DVWA之CSRF(跨站请求伪造攻击)

目录

Low

Middle

High

Impossible


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

$GLOBALS :引用全局作用域中可用的全部变量。$GLOBALS 这种全局变量用于在 PHP 脚本中的任意位置访问全局变量(从函数或方法中均可)。PHP 在名为 $GLOBALS[index] 的数组中存储了所有全局变量。变量的名字就是数组的键。

从源代码可以看出这里只是对用户输入的两个密码进行判断,看是否相等。不相等就提示密码不匹配。

相等的话,查看有没有设置数据库连接的全局变量和其是否为一个对象。如果是的话,用mysqli_real_escape_string()函数去转义一些字符,如果不是的话输出错误。

是同一个对象的话,再用md5进行加密,再更新数据库。

知道了这些之后,我们第一次尝试两次秘密不一致看看。

DVWA之CSRF(跨站请求伪造攻击)_第1张图片

可以看到顶部的URL是:http://127.0.0.1/vulnerabilities/csrf/?password_new=123&password_conf=124&Change=Change#

很明显,这就是修改密码的链接。

我们打开另一个页面,在顶部URL中自己输入如下的

http://127.0.0.1/vulnerabilities/csrf/?password_new=abc&password_conf=abc&Change=Change#

可以看到,直接跳转到了密码成功的页面了

DVWA之CSRF(跨站请求伪造攻击)_第2张图片

Middle

源代码:

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

Middle类型的代码在Low级别的基础上,加上了对用户请求头的中的Referer字段进行验证

 if( stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false )

即用户的请求头中的Referer字段必须包含了服务器的名字。关于Http Referer字段,详情:验证 HTTP Referer 字段 

当我们再打开另一个页面,在顶部URL中自己输入如下的时,

http://127.0.0.1/vulnerabilities/csrf/?password_new=abc&password_conf=abc&Change=Change#

它会报错,提示你Http Referer字段没有定义索引

DVWA之CSRF(跨站请求伪造攻击)_第3张图片

 这次我们先正常的访问这个完整,然后用burpsuite进行抓包,如图可以看到Referer字段

DVWA之CSRF(跨站请求伪造攻击)_第4张图片

然后,我们打开另一个页面,在顶部URL中自己输入如下的链接,用burpsuite进行抓包

http://127.0.0.1/vulnerabilities/csrf/?password_new=abc&password_conf=abc&Change=Change#

可以看到,当我们直接打开另一个页面,直接输入URL的时候,请求包的头中并没有Referer字段,所以不能修改成功。

 那我们可以自己加一个Referer字段,然后值只要设置成包含了主机头127.0.0.1就行了

DVWA之CSRF(跨站请求伪造攻击)_第5张图片

可以看到,已经成功修改密码了

DVWA之CSRF(跨站请求伪造攻击)_第6张图片

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正确,才会处理客户端的请求。这里因为对请求的token进行了验证,所以比上两个等级的更加的安全。关于 token 抵御CSRF攻击,详情:在请求地址中添加 token 并验证

因为该请求是get请求,所以token验证会被放在请求URL中,我们随便输入密码验证一下,可以看到,在请求的URL中最末尾加入了token。

DVWA之CSRF(跨站请求伪造攻击)_第7张图片

所以现在要想进行CSRF攻击就必须获取到用户的token,而要想获取到 token 就必须利用用户的 cookie 值去访问修改密码的页面,然后截取服务器返回的token值。然后再利用CSRF漏洞构造URL进行密码的修改。

我们尝试利用下面的代码去构造一个页面,诱使用户点击,当用户点击该链接的这一刻,该代码会偷偷的访问修改用户密码的页面,然后获取到服务器返回的 token ,然后再构造修改密码的表单,加上我们获取到服务器的token值,向服务器发送修改密码的请求。




    
    
    


    
    

这一切看起来是那么的天衣无缝,无懈可击。可是,我们忘记了浏览器最重要的一个策略——同源策略。由于我们框架ifame要访问的链接是 http://192.168.10.14/dvwa/vulnerabilities/csrf ,这是漏洞网站服务器的链接。而我们的脚本执行的位置是我们自己搭的一个服务器,所以我们的攻击脚本是不可能跨域取到改密界面中的user_token。关于同源策略和跨域问题:浏览器同源策略和跨域的实现方法

由于这里跨域是不能实现的,所以我们之前的想法以失败告终了。

在这里,我们要想获取到用户的token,并提交修改密码的表单的话,就必须得把我们的攻击脚本注入到目标服务器中 。而要想注入到目标服务器,同时得发挥作用,获取用户的 token修改密码的话,就得和XSS漏洞一起结合实现了。

我们将如下代码通过存储型XSS插入到数据库中,这语句会弹出用户的token

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级别修改密码需要输入之前的密码,黑客无法知道用户之前的密码,所以无法进行CSRF攻击。

你可能感兴趣的:(DVWA)