zoukankan      html  css  js  c++  java
  • CSRF 漏洞测试

    CSRF简介

    CSRF中文名:跨站请求伪造,英文译为:Cross-site request forgery,CSRF攻击就是attacker(攻击者)利用victim(受害者)尚未失效的身份认证信息(cookie、session等),以某种方式诱骗victim点击attacker精心制作的恶意链接或者访问包含恶意攻击代码的页面,当victim触发成功之后,恶意代码会被执行,浏览器默默的向目标service发出请求加载着victim尚未失效的身份认证信息,导致victim替attacker完成了非法操作比如:在某些论坛上发布大量的恶意言论、网站用户密码被恶意篡改、账户金额被盗取、删除网站个人信息~~~~~

    漏洞测试

    通过DVWA平台,对CSRF漏洞进行测试,让大家走进CSRF的世界

    环境:dvwa服务IP      :192.168.43.146

               attacker服务IP :192.168.43.150

    low level

    查看源码:

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

    代码审计之后发现:网站没有对CSRF做出防范,只对网站进行了SQL防御(通过mysqli_real_escape_string()函数的过滤作用,将用户传入的数据中的特殊字符进行转义,有效预防了attacker对网站的SQL注入攻击)

    mysqli_real_escape_string()函数详细介绍:

    定义和用法
    mysql_real_escape_string() 函数转义 SQL 语句中使用的字符串中的特殊字符。
    
    下列字符受影响:
    
    x00
    
    
    
    
    
    '
    "
    x1a
    如果成功,则该函数返回被转义的字符串。如果失败,则返回 false。
    
    语法
    mysql_real_escape_string(string,connection)
    
    参数         描述
    string         必需。规定要转义的字符串。
    connection     可选。规定 MySQL 连接。如果未规定,则使用上一个连接。
    
    //有效预防了数据库攻击

    既然网站没有对CSRF保护那么attacker就可以直接进行攻击

    用户正常修改密码:

    用户非正常修改密码:

    attacker制作含有恶意攻击代码网页

    恶意代码:

    <iframe hidden src="http://192.168.43.146/dvwa/vulnerabilities/csrf/?password_new=attacker&password_conf=attacker&Change=Change#"></iframe>

    attacker将代码嵌入自己的钓鱼网页中,当victim受害者被诱导访问该网页时,恶意代码就会自动被浏览器所执行并携带着victim未失效的身份认证信息向目标服务器发出请求,而victim却毫无察觉,自己的用户密码已经被attacker恶意篡改

    victim被attacker诱导浏览自己网站上的图片(恶意代码就隐藏在该网页中)

    你会发现该网站一切好像很正常&很美好,但自己却不知道已经被攻击了,网站密码已经被修改为attacker

    此时victim再去登陆时会发现自己已经login不上了

    medium level

    查看源码:

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

    代码审计发现:该网站进行了referer字段检测,该字段限制了不是同一个域的不能跨域访问,attacker要想进行CSRF攻击只要绕过if条件就可以,接下来分析该if条件

    if( stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false )
    
    $_SERVER[ 'HTTP_REFERER' ] 获取网页请求的来源URL
    
    $_SERVER[ 'SERVER_NAME' ] 获取目标服务器的域名
    
    $_SERVER[ 'HTTP_REFERER' ]和$_SERVER[ 'SERVER_NAME' ]通过stripos()进行匹配,查看$_SERVER[ 'SERVER_NAME' ]字符串是否包含在$_SERVER[ 'HTTP_REFERER' ]中,从而判断用户的服务请求是否是跨域请求,若是跨域请求则会被目标服务器所拒绝访问
    
    attacker可以有两种方法进行绕过:
    
    第一种:将网页的名字改为$_SERVER[ 'SERVER_NAME' ].html
    第二种:添加网页父目录包含$_SERVER[ 'SERVER_NAME' ]

    在这里使用第一种方法进行绕过:

    victim浏览该网页,恶意代码被成功执行,victim的网站密码被恶意篡改

    high level

    查看源码:

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

    代码审计发现:该网站进行了user_token的检测

    user_token:

    当用户每次访问修改用户密码页面时,服务器会先返回一个随机的token,接下来当用户向服务器发起修改密码请求时,需要提交user_token,当请求到达服务器时,服务器会优先检查token,判断客户端的token和服务端的token是否匹配,若不匹配,服务器则会拒绝客户端的请求

    在这里attacker是不能伪造token的,因为token是一个很长的随机数,attacker要想CSRF攻击成功,只有通过利用网站的XSS漏洞获取用户的token

    XSS利用代码获取user_token:

    <iframe src="../csrf" onload=alert(document.getElementsByName('user_token'))></iframe>

    有关XSS的利用可以查看笔者的这篇文章(https://www.cnblogs.com/qftm/p/10317166.html)

    利用user_token进行CSRF攻击

    构造恶意代码:

    victim浏览存在恶意攻击的网页

    攻击成功

    impossible level

    查看源码:

    <?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();
    
    ?> 
    代码审计发现:用户修改网站密码不仅需要user_token的验证还需要用户输入当前密码进行验证,因此,attacker不能对用户进行CSRF攻击

    总结

    学过CSRF和XSS之后,你可能会有疑惑,它们两个一样吗,不用多说,相信大家看名字就知道不一样

    CSRF攻击是直接利用用户尚未失效的cookie,并伪造特殊的请求对用户造成危害的一种攻击手段

    XSS攻击是直接盗取用户的cookie,所造成的一种攻击手段

    两者看似相似,当又有一些不一样的地方

  • 相关阅读:
    softmax和cross_entropy
    python初始化list列表(1维、2维)
    奥卡姆剃刀 (Occam Razor)
    何谓超参数?
    面试干货!21个必知数据科学面试题和答案
    计算广告算法到底要做什么?
    推荐系统的常用算法
    推荐系统常见面试题2
    推荐系统算法面试题
    mysql-面试题
  • 原文地址:https://www.cnblogs.com/qftm/p/10317162.html
Copyright © 2011-2022 走看看