前言
在最近挖洞的时候,老是碰到 POST 传参采用 JSON 格式,而不是传统的parameter=value
的格式,之前也没接触过,所以也不知道该怎么搞,所以打算学习一下,此文作为一个笔记梳理。
前提知识
一般采用 Json
格式传输参数时,请求包中都有 Content-Type
头,一般服务器也会验证 Content-Type
值是否为 application/json
,当服务器验证 Content-Type
时,若不符合要求,则会抛出异常,导致传输的数据失效
当简单的采用表单传输简单参数时,Content-Type
值为:x-www-form-urlencoded
,传输的数据会被 URL 编码,传输文件时值为:form-data
给表单添加 enctype="text/plain"
属性时,Content-type
值为:text/plain
在使用 XMLHttpRequest
跨域发起请求时,浏览器首先会先进行一次 OPTIONS
预请求,查看目标网站是否支持跨域,如果支持,则浏览器会进行下一步,发送真实请求,否则会直接报错
突破限制的方法
下面统一假设 POST 传输的参数为:{"title":"Json_CSRF","content":"xxxxxxx","time":"2020-07-20"}
服务端不验证 Content-Type
的情况
- 特殊的表单,即构造一个键值对
Json_CSRF
传输的数据变成了:{"title":"Json_CSRF","content":"xxxxxxx","time":"2020-07-20","test":"=test"}
且请求头中:Content-Type: text/plain
,当服务器后端严格校验 Content-Type
头时,该方法也就差不多没用了
- 利用 JS 中的
XMLHttpRequest
,即 XHR,该方法要求目标网站支持跨域
Json_CSRF
首先,浏览器会发起一个 OPTION
请求,查询目标网站是否支持跨域
如果目标响应包中有 Access-Control-Allow-Credentials: true
代表允许携带 cookie
,
有Access-Control-Allow-Origin:http://mysite.com
或者为 Access-Control-Allow-Origin:*
,即代表支持跨域
浏览器便会携带 cookie
发起真实请求
注意:实际上百度并不支持跨域,此处只是为了方便演示
当目标网站不支持跨域,则浏览器将不会发起请求,导致该方法失效
当然,除了 XMLHttpRequest
,fetch
也是一样的
服务端验证 Content-Type
的情况
可惜,现在是个浏览器都会询问用户是否开启 flash,此举难以成功,而且不久,flash 就会被废弃