zoukankan      html  css  js  c++  java
  • PHP代码审计学习(8)——CSRF漏洞

    CSRF

      跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。跟(XSS)相比,XSS 利用的是用户对指定网站的信任,CSRF 利用的是网站对用户网页浏览器的信任。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性

    攻击思路

      CSRF(Cross-site request forgery)跨站请求伪造:攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的。

      一个典型的CSRF攻击有着如下的流程:

    受害者登录a.com,并保留了登录凭证(Cookie)。
    攻击者引诱受害者访问了b.com。
    b.com 向 a.com 发送了一个请求:a.com/act=xx。浏览器会默认携带a.com的Cookie。
    a.com接收到请求后,对请求进行验证,并确认是受害者的凭证,误以为是受害者自己发送的请求。
    a.com以受害者的名义执行了act=xx。
    攻击完成,攻击者在受害者不知情的情况下,冒充受害者,让a.com执行了自己定义的操作。

    挖掘思路

      CSRF主要是越权操作,出现的位置自然就是要有权限控制的地方,所以在黑盒审计的时候,多注意管理后台、交易管理,用户操作等地方,找交互页面抓包查看token头,若没有删referer再提交是否返回一致,若一致则有可能有CSRF。

      在白盒的时候,就看核心代码有没有验证referer和token,若核心文件没有则去功能点找

    案例

      直接上DVWA的源码(我太菜了不会写这个场景)

    <?php
    
    if( isset( $_GET[ 'Change' ] ) ) {
        // 获取用户的输入
        $pass_new  = $_GET[ 'password_new' ];
        $pass_conf = $_GET[ 'password_conf' ];
    
        // 确认两次输入的密码是否相同,相同就更新数据库内的信息
        if( $pass_new == $pass_conf ) {
            // 以下两段代码都是防止SQL注入的
            $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 );
    
            // 更新数据库内的信息,具体函数作用以及对代码的理解,在暴力破解那里我写过的,这里就不写了
            $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>' );
    
            // 修改成功,返回信息给用户
            echo "<pre>Password Changed.</pre>";
        }
        else {
            // 两次输入的密码不同,所以返回信息给用户
            echo "<pre>Passwords did not match.</pre>";
        }
    
        ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
    }
    
    ?>

      可以看到,服务器收到修改密码的请求后,会检查参数password_newpassword_conf是否相同,如果相同,就会修改密码,并没有任何的防CSRF机制

      抓一下包

     

       构造http://192.168.43.167/DVWA/vulnerabilities/csrf/?password_new=123456&password_conf=123456&Change=Change#

      当受害者点击了这个链接,他的密码就会被改成password,这样就完成了一次CSRF攻击,当然这种很明显,可以使用BP自带的POC攻击

       诱导受害者使用浏览器访问生成的html文件,点击submit,会发现密码修改成功。用户密码变成了123456

    防御

      1、将cookie设置为HttpOnly 

      CRSF攻击很大程度上是利用了浏览器的cookie,为了防止站内的XSS漏洞盗取cookie,需要在cookie中设置"HttpOnly"属性,这样通过程序(js、applet等)无法读取到cookie信息。避免了攻击者伪造cookie的情况出现。服务端的CSRF方式方法很多样,但总的思想都是一致的,就是在客户端页面增加伪随机数。  

      2、Cookie Hashing(所有表单都包含同一个伪随机值)

        这可能是最简单的解决方案了,因为攻击者不能获得第三方的Cookie(理论上),所以表单中的数据也就构造失败了

      3、验证码

      这个方案的思路是:每次的用户提交都需要用户在表单中填写一个图片上的随机字符串,厄....这个方案可以完全解决CSRF,但个人觉得在易用性方面似乎不是太好,还有听闻是验证码图片的使用涉及了一个被称为MHTML的Bug,可能在某些版本的微软IE中受影响。

      在业界目前防御 CSRF 攻击主要有三种策略:验证 HTTP Referer 字段;在请求地址中添加 token 并验证;在 HTTP 头中自定义属性并验证。

    参考

      https://www.freebuf.com/articles/web/118352.html

  • 相关阅读:
    12 Essential Bootstrap Tools for Web Designers
    S.O.L.I.D 是面向对象设计(OOD)和面向对象编程(OOP)中的几个重要编码原则
    cocos2d3.0rc编译android工程
    Android和iOS中Cocos2dx的横屏竖屏设置
    cocos2d-x 3.0rc开发指南:Windows下Android环境搭建
    C#第一个windows窗体应用程序
    程序员技术练级攻略
    11个强大的Visual Studio调试小技巧
    Model--汇总
    UIView---汇总
  • 原文地址:https://www.cnblogs.com/Lee-404/p/13210083.html
Copyright © 2011-2022 走看看