CSRF漏洞(原理、DVWA实验、修复建议)

目录

1 介绍CSRF漏洞

2 CSRF漏洞的原理

3 DVWA CSRF实验过程

3.1 low级别

3.2 medium级别

相关函数说明

3.3 high级别

3.4 impossible级别

4 CSRF漏洞修复建议


1 介绍CSRF漏洞

CSRF (Cross -site request forgery,跨站请求伪造)也被称为One Click Attack或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,XSS利用站点内的信任用户,而CSRF则通过伪装成受信任用户请求受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)也难以防范,所以被认为比XSS更具
危险性。CSRF漏洞经常被用来制作蠕虫攻击、刷SEO流量等。

2 CSRF漏洞的原理

其实可以这样理解CSRF:攻击者利用目标用户的身份,以目标用户的名义执行某些非法操作。CSRF能够做的事情包括:以目标用户的名义发送邮件、发消息,盗取目标用户的账号,甚至购买商品、虚拟货币转账,这会泄露个人隐私并威胁到了目标用户的财产安全。
举个例子,你想给某位用户转账100元,那么单击"转账” 按钮后,发出的HTTP请求会与http://www.xxbank.com/pay.php?user=xx&money=100类似。而攻击者构造链接(http://www.xxbank.com/pay.php?user=hack&money=100),当目标用户访问了该URL后,就会自动向Hack账号转账100元,而且这只涉及目标用户的操作,攻击者并没有获取目标用户的cookie或其他信息。
CSRF的攻击过程有以下两个重点。

  • 目标用户已经登录了网站,能够执行网站的功能。
  • 目标用户访问了攻击者构造的URL。

3 DVWA CSRF实验过程

CSRF漏洞(原理、DVWA实验、修复建议)_第1张图片

3.1 low级别

' . ((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); } ?>

可以看到,服务器收到修改密码的请求后,会检查参数password_new与password_conf是否相同,如果相同,就会修改密码,并没有任何的防CSRF机制(当然服务器对请求的发送者是做了身份验证的,是检查的cookie,只是这里的代码没有体现)。

于是直接构造链接访问即可。http://192.168.1.100/dvwa/vulnerabilities/csrf/?password_new=password&password_conf=password&Change=Change#

CSRF漏洞(原理、DVWA实验、修复建议)_第2张图片

3.2 medium级别


' . ((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); } ?>

相关函数说明

int eregi(string pattern, string string)
检查string中是否含有pattern(不区分大小写),如果有返回True,反之False。
可以看到,Medium级别的代码检查了保留变量 HTTP_REFERER(http包头的Referer参数的值,表示来源地址)中是否包含SERVER_NAME(http包头的Host参数,及要访问的主机名,这里是192.168.1.100),希望通过这种机制抵御CSRF攻击。

referer头信息可以用burp suite的截断功能修改
CSRF漏洞(原理、DVWA实验、修复建议)_第3张图片
CSRF漏洞(原理、DVWA实验、修复建议)_第4张图片

CSRF漏洞(原理、DVWA实验、修复建议)_第5张图片

3.3 high级别

' . ((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); } // Generate Anti-CSRF token generateSessionToken(); ?>

可以看到,High级别的代码加入了Anti-CSRF token机制,用户每次访问改密页面时,服务器会返回一个随机的token,向服务器发起请求时,需要提交token参数,而服务器在收到请求时,会优先检查token,只有token正确,才会处理客户端的请求。

CSRF漏洞(原理、DVWA实验、修复建议)_第6张图片
后续:https://www.jianshu.com/p/4eed0faaf0ca

或者:https://www.freebuf.com/articles/web/118352.html

3.4 impossible级别


prepare( 'SELECT password FROM users WHERE user = (:user) AND password = (:password) LIMIT 1;' );
    $data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR );
    $data->bindParam( ':password', $pass_curr, PDO::PARAM_STR );
    $data->execute();

    // Do both new passwords match and does the current password match the user?
    if( ( $pass_new == $pass_conf ) && ( $data->rowCount() == 1 ) ) {
        // It does!
        $pass_new = stripslashes( $pass_new );
        $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 database with new password
        $data = $db->prepare( 'UPDATE users SET password = (:password) WHERE user = (:user);' );
        $data->bindParam( ':password', $pass_new, PDO::PARAM_STR );
        $data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR );
        $data->execute();

        // Feedback for the user
        echo "
Password Changed.
"; } else { // Issue with passwords matching echo "
Passwords did not match or current password incorrect.
"; } } // Generate Anti-CSRF token generateSessionToken(); ?>

可以看到,Impossible级别的代码利用PDO技术防御SQL注入,至于防护CSRF,则要求用户输入原始密码(简单粗暴),攻击者在不知道原始密码的情况下,无论如何都无法进行CSRF攻击。

4 CSRF漏洞修复建议

 

  • 验证请求的Referer值,如果Referer是以自己的网站开头的域名,则说明该请求来自网站自己,是合法的。如果Referer是其他网站域名或空白,就有可能是CSRF攻击,那么服务器应拒绝该请求,但是此方法存在被绕过的可能。
  • CSRF攻击之所以能够成功,是因为攻击者可以伪造用户的请求,由此可知,抵御CSRF攻击的关键在于:在请求中放入攻击者不能伪造的信息。例如可以在HTTP请求中以参数的形式加入一个随机产生的token,并在服务器端验证token,如果请求中没有token或者token的内容不正确,则认为该请求可能是CSRF攻击从而拒绝该请求。
     

你可能感兴趣的:(渗透测试)