作者:Nedo_zou | 来源:互联网 | 2024-11-11 13:19
篇首语:本文由编程笔记#小编为大家整理,主要介绍了DVWA笔记系列-CSRF相关的知识,希望对你有一定的参考价值。 0x01 CSRF 简介 跨站请求伪造(英语:Cross-site request
篇首语:本文由编程笔记#小编为大家整理,主要介绍了DVWA笔记系列-CSRF相关的知识,希望对你有一定的参考价值。
0x01 CSRF 简介
跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。
跟跨网站脚本(XSS)相比,XSS 利用的是用户对指定网站的信任,CSRF 利用的是网站对用户网页浏览器的信任。
0x02 CSRF 原理
CSRF攻击原理如下:
首先正常的用户输入口令登陆了网站A(被攻击站点)
网站A(被攻击站点)判断该用户口令合法,生产COOKIE保存在浏览器中
用户在没关闭网站A的情况下,访问了网站B的攻击页面(攻击者站点)
网站B(攻击者站点)利用网站A留在浏览器的COOKIE,访问网站A的某个URL,并偷偷做了该URL能做的事情
CSRF攻击原理图:
0x03 DVWA-CSRF-LOW
说完原理,我们直接看DVWA中CSRF的代码吧,下面是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( ''
. ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '' );
// Feedback for the user
echo "Password Changed.
";
}
else {
// Issue with passwords matching
echo "Passwords did not match.
";
}
((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
?>
LOW级别的代码很简单,没有Referer也没有token校验,只是单纯的比较一下两次输入的密码一不一样,我们可以直接利用Burp实现制造一个CSRF页面,如下图,首先点击右键:
构造成功,得到html代码,接着我们直接把他复制到服务器上,保存为一个html文件,在诱使别人点击,即可以实现CSRF攻击。
0x04 DVWA-CSRF-Medium
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( ''
. ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '' );
// Feedback for the user
echo "Password Changed.
";
}
else {
// Issue with passwords matching
echo "Passwords did not match.
";
}
}
else {
// Didn't come from a trusted source
echo "That request didn't look correct.
";
}
((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
?>
Medium级别在Low级别的基础上了加了HTTP_REFERER校验与服务器校验,具体代码如下:
if( stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false )
stripos() 函数查找字符串在另一字符串中第一次出现的位置(不区分大小写),即该行代码具体作用是判断服务器名是否在Referer字段中。
我们来看burp截取的数据包:
红线部分即为后端加的REFERER字段,如果是黑盒测试的话,我们可以先把REFERER字段后面的值去除,在发送该数据包,然后判断服务器是否校验REFERER的值。但之前我们以前审计了该密码重置的代码。我们知道服务端代码只用stripos()函数来判断服务器名是否在返回的REFERER字段中。这样的话,我们绕过他的检验就很简单了,我们可以这样构造攻击URL:
http://攻击者IP/192.168.203.141.html
我们在BURP中尝试一下,下面是我修改过后的数据包:
GET /DVWA-master/DVWA-master/vulnerabilities/csrf/?password_new=huangguohua&password_cOnf=huangguohua&Change=Change HTTP/1.1
Host: 192.168.203.141
Proxy-Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: http://127.0.0.1/192.168.203.141.html
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
COOKIE: security=medium; PHPSESSID=45uteveeouuha9l5hn39uh1151
发现可以,成功绕过
我们先按Low级别上面讲的,先构造好CSRF页面:
诱使用户点击:
攻击成功。
0x05 结束语
High级别的增加Token校验和session校验,单纯的只是CSRF是不行的,要打组合拳,要通过XSS+CSRF组合才行,这里就不细说了。