美文网首页
读完就带你入门CSRF

读完就带你入门CSRF

作者: Qug_ | 来源:发表于2018-10-12 15:34 被阅读42次

    前言:不想读完的,可以理解这一句话,“如果你能理解XSS攻击的话,那么你一定认同XSS攻击是利用盗取的高权限cookie来进行的,相较而言CSRF并不干偷盗之事,而是借刀杀人”,这是我自己的感想,不认同的也不强求


    CSRF(cross-site request forgery),跨站请求伪造,算了算了,概念性的我就不多说了,都能百度到,下面我直接说重点吧。

    CSRF的攻击原理是什么,简单说就是利用了高权限帐号(如管理员)的登录状态或者授权状态去做一些后台操作,但实际这些状态并没有被我们直接获取到(获取那是XSS干的事)。

    GET方式演示CSRF攻击

    我们这里假设有个网站test.com,包含一个登录页面(login.php)和一个付款页面(pay.php)

    login.php:

    <?php
        setcookie('uid', 1, time()+86400);
        echo "your uid is {$_COOKIE['uid']}";
    

    pay.php:

    <?php
       //身份验证
        if (!isset($_COOKIE['uid']) || $_COOKIE['uid']< 0) {  
            die('login error!');
        }
       //金额获取   
        if (!isset($_GET['money'])) {
            die('no money');
        }   
       //收款人获取
        if (!isset($_GET['to_who'])) {
            die('nobody');
        }   
        $uid = $_COOKIE['uid']; 
        $money = $_GET['money'];
        $to_who = $_GET['to_who'];
       //。。。。。。
       //此处应该还有相关DB操作,略去
        echo "transfer {$money} yuan to {$to_who}!";
    

    打开login.php,模拟登录,可以看到登录成功:

    your uid is 1
    

    登录完成后我们打开pay.php进行转账,转1000元给father,GET请求构造:http://test.com/pay.php?money=1000&to_who=father

    访问得到转账成功的响应:

    transfer 1000 yuan to father!
    

    以上是用户正常操作,这时黑客发现了该网站的CSRF漏洞,于是立刻伪造了一个页面,页面上预置了一个UC震惊部的超链接,超链接指向http://test.com/pay.php?money=1000&to_who=hacker

    <html>
        <head>
            <meta charset="utf-8">
        </head>
        <body>
            <a href="http://test.com/pay.php?money=1000&to_who=hacker" taget="_blank">震惊!男人看了会沉默,女人看了会流泪!不转不是中国人!<a/>
        </body> 
    </html>
    

    如上,收款人被篡改成了黑客,如果我们是中国人,就一定会毫不犹豫的点击链接,因为不转不是中国人!!然后,然后。。。我们就把自己账户的1000元开心的转给了黑客。

    为什么会出现这种情况,我们在别的网站点击链接居然能扣自己账户的钱?

    点击链接前,我们已经登录了信任网站test.com,而这个这个链接是我们自己发送的,test.com会识别当前已经登录,然后转账,网站无法判断到底是谁让我们点击的。

    从上面这个实例可知,完成CSRF攻击流程:

    1、用户登录了信任的网站A,并且保存登录状态

    2、黑客找出网站A没有防御的链接,通过社会工程学伪装,诱导点击。

    3、只要登录状态保持,用户主动访问目标链接,则攻击成功。

    有人说那每次访问其他网站,把之前的网站都注销。是的,这个办法可以,但这么做这现实吗?我们需要注销许多常用的网站,下次登录又要输入用户名和密码,极其反人类。这肯定不是最佳办法,防御措施应该让程序员考虑,用户别乱点链接是最重要的。


    以上演示了GET方式攻击,有人说那我把method改为POST吧,其实稍微动动脑也知道不行,POST请求我们同样可以伪造,隐藏表单的方式我们见多不怪了,所以仅仅依靠简单的POST传输依旧无济于事。

    如此一来,不管哪种访问方式都可能受到攻击。所以,这并不是GET和POST谁更安全的问题,POST只是提高了攻击门槛和成本。

    划重点,那么CSRF能够攻击的根本原因是:服务器无法识别你的来源是否可靠


    最后,我们聊一聊前辈是如何防御CSRF攻击的:

    防御的方法有很多:

    1、比如加上验证码。但这么做很繁琐,并且影响用户体验。

    2、比如转账需要二次密码验证,现在很多银行就这么搞的。

    3、确认来源是否可靠(推荐)

    1和2都是同一个思路,那就是验证请求合法性,从这一思路出发,前辈想出了下面几种方法:

    验证HTTP Referer 字段

    HTTP协议里面定义了一个访问来源的字段,这个字段叫Referer。黑客伪造的链接或表单是在其他网站上,所以我们可以判断Referer是否为自身网站,如果是,则允许访问,如果不是,则拒绝访问。

    但是这种方法是有缺陷的,上面实验尝试过,如果对方在QQ上发送给你一个链接呢?点击的时候属于主动点击,此时一样没有Referer。程序会把它归属为安全请求,那么就被绕过了。并且如果某些低版本的浏览器存在漏洞(比如IE6),Referer很有可能被篡改,所以这个方法并非十全十美。

    服务端验证请求的token一致性

    CSRF攻击的核心原理就是利用用户验证信息储存cookie中,发送请求,使得服务器无法判断真伪,而token之所以能够拦截,就是因为它是CSRF攻击过程中几乎不可能伪造的东西。

    实现原理:在服务端生成一个随机的token,加入到HTTP请求参数中,服务器拦截请求,查看发送的token和服务端的是否一致,若一致,则允许请求;若不一致,则拒绝请求。

    注意:一定要生成唯一的或者随机性较大的token。如果token可以被爆破,一样可以伪造请求,进行攻击。

    参考文章:https://blog.csdn.net/li741350149/article/details/62887524

    Ajax防御CSRF

    实际上Ajax防御的思想也可以利用上面的token验证方式。

    IBM上一篇文章说Ajax防御时,在 HTTP 头中自定义属性并验证token。

    它是这么说的:

    把 token 以参数的形式置于 HTTP 请求之中,而是把它放到 HTTP 头中自定义的属性里。通过 XMLHttpRequest 这个类,可以一次性给所有该类请求加上 csrftoken 这个 HTTP 头属性,并把 token 值放入其中。这样解决了上种方法在请求中加入 token 的不便,同时,通过 XMLHttpRequest 请求的地址不会被记录到浏览器的地址栏,也不用担心 token 会透过 Referer 泄露到其他网站中去。
    

    总结

    CSRF防御原则:

    • GET方式不能用于更新资源的操作
    • POST方式请求加上随机token验证

    相关文章

      网友评论

          本文标题:读完就带你入门CSRF

          本文链接:https://www.haomeiwen.com/subject/stdgaftx.html