两则JSON CSRF实例
最近面试被问到JSON CSRF,还刚好挖过他们家SRC两个实际案例,当时挖洞的时候也特地去查过JSON CSRF的资料,可面试的时候怎么也没想起来,遂翻出以前SRC的报告记录一下再整理下JSON CSRF的利用方法
JSON CSRF
所谓JSON CSRF和普通CSRF的不同及利用难点在于
POST的包体为JSON格式,而不是键值对,一般HTML表单无法构造
Content-Type 头一般需要设置为 application/json,HTML表单同样无法构造
使用XMLHttpRequest、fetch能构造出JSON请求,并且能设置Content-Type,但是无法跨域
所以在服务端严格校验JSON格式和Content-Type的情况下,目前的解决方案我只找到利用Flash的跨域与307跳转(具体见参考文章),但Flash无疑已经过时了,某些浏览器也默认禁止了Flash运行。所以我挖到的两个”JSON CSRF”应该都不算严格意义上的JSON CSRF,而是寻找到了其他绕过的方式
未验证Content-Type头且未严格校验JSON格式案例
直接复制当时报告中的描述了
对关注列表取消关注再关注时可抓到关注请求包,经测试url中的_signature参数无校验作用。csrf_token存于cookie, 无效。所以可构造CSRF,但是这里是JSON格式请求包,用XMLHttpRequest构造的话存在跨域问题无法解决
但是发现服务器对JSON数据有容错性,即JSON数据后多了个等号依旧能正常识别,而且服务器不校验Content-Type头,故构造一般的html表单,name为JSON数据即可
严格验证Content-Type头和JSON格式案例
直接创建日程放入payload即可收获一个self xss,但selfx没用,然后发现没有csrftoken及referer和orgin的验证,可配合CSRF
但由于body是JSON格式(如下),而且服务器对JSON没有容错性,也会验证Content-Type,一般的CSRF表单无法构造
1 | {"title":"<script>alert(1)</script>","type":1,"timezone":"Asia/Shanghai","isAllDay": "1","reminders":[{"minutes":60}],"description":"","rrule":"","start":1588465800,"end":1588469400,"hasAlarm":1} |
然后手动修改参数为键值对形式,Content-Type为application/x-www-form-urlencoded,服务端依旧可以正常识别,还有问题的就是"reminders": [{"minutes":60}]
是一个数组对象,反复测试发现可以这样构造reminders[][minutes]=60
1 | title=<script>alert(1);</script>&type=1&timezone=Asia/Shanghai&isAllDay=0&reminders[][minutes]=60&description=&rrule=&start=158847840&hasAlarm=1 |
然后用burp自动生成CSRF POC,但是失败,没发现原因,自己手工构造后测试发现网页返回错误,最后才发现网站是用的PUT请求
用表单只能构造GET/POST请求,仿佛又要放弃了,但是最后查阅资料多次测试下,发现加入_method=PUT即可,最后POC如下
1 | <html> |