一、JSON简介
JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation)。
JSON是用来传输和存储数据的,其作用类似于XML,但是JSON 比 XML 更小、更快,更易解析。
以下请求报文是以JSON格式传输数据(其请求体是JSON格式的数据,其作用是上传PDF文件):
POST /uploadPdf HTTP/1.1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/109.0 Accept-Encoding: gzip, deflate Content-Type: application/json;charset=utf-8 Content-Length: 862 Connection: close Cookie: R2iL9iJ4SFWJDpYY4pb_YfduHmFfKzpsNWiL-XZeXx7-5aTw24asso6HFj1 {"basic":{"token":"eyJhbGciOiJITUFDU0hBMjU2IiwidmVyIjoiMS4xIn0="},"data":{"dataType":"book","name":"渗透测试.pdf"}}
二、JSON语法简单介绍
1、JSON语法
数据在名称/值对中
数据由逗号分隔
大括号保存对象
中括号保存数组
2、JSON值
JSON 值可以是:
数字(整数或浮点数):{“age”:30 }
字符串(在双引号中) :{“uname”:“yang”}
逻辑值(true 或 false):{“flag”:true }
数组(在中括号中):{“sites”:[{“name”:“yang”},{“name”:“ming”}]}
对象(在大括号中)JSON 对象在大括号({})中书写: null { “runoob”:null }
例子:
{ "users": { "user": [ { "id": "1", "username": "admin", "passwd": "admin888" }, { "id": "2", "username": "root", "passwd": "root123" }, { "id": "3", "username": "system", "passwd": "system456" } ] } }
三、JSON注入
1、何为JSON注入?
JSON注入是指应用程序所解析的JSON数据来源于不可信赖的数据源,程序没有对这些不可信赖的数据进行验证、过滤,如果应用程序使用未经验证的输入构造 JSON,则可以更改 JSON 数据的语义。在相对理想的情况下,攻击者可能会插入无关的元素,导致应用程序在解析 JSON数据时抛出异常。
简单点来说就是,攻击者可以在JSON数据内任意插入特殊符号,破坏JSON结构,从而导致JSON数据无法被解析。
2、JSON注入的类型
在我看来,JSON注入主要分为两种类型,分别为:
- 通过插入特殊符号“””、“\”来破坏JSON结构,从而导致JSON数据无法被解析。
- JSON数据后面拼接逻辑判断等注入语句,从而导致攻击者可以恶意查询后台/数据库数据(思路和SQL注入是一样的)。
下面将对上述两个方面进行详细讲解。
2.1 插入特殊符号导致JSON结构被破坏
我们来看一下这个语句(上述例子):
"data":{"dataType":"book","name":"渗透测试.pdf"}
这是一个正常的JSON语句,但是如果我们把上传的PDF文件的名称修改为“渗透测试”.pdf”(就是在名称里面添加了特殊符号“””),这时候语句就会变成:
"data":{"dataType":"book","name":"渗透测试".pdf"}
这时候JSON语句的结构就会被破坏,从而导致该语句无法被服务器解析。
同样的,我们可以把“””改为“\”,这时候JSON语句变为:
"data":{"dataType":"book","name":"渗透测试\.pdf"}
这时候JSON语句的结构也会被破坏,因为“\”会把后面的“””转义,从而导致该语句无法被服务器解析。
由于 JSON 是根据引号、冒号、逗号和花括号区分各字符意义的,所以我们可以想方设法地在JSON语句中插入上述符号来达到破坏JSON结构的目的。
2.2 拼接注入语句,非法查询后台/数据库数据
这种情况的思路和SQL注入是一样的。
如下是后台的PHP代码:
<?php header('content-type:text/html;charset=utf-8'); if(isset($_POST['json'])){ $json_str=$_POST['json']; $json=json_decode($json_str); if(!$json){ die('JSON文档格式有误,请检查'); } $username=$json->username; //$passwd=$json->passwd; $mysqli=new mysqli(); $mysqli->connect('localhost','root','root'); if($mysqli->connect_errno){ die('数据库连接失败:'.$mysqli->connect_error); } $mysqli->select_db('user'); if($mysqli->errno){ dir('打开数据库失败:'.$mysqli->error); } $mysqli->set_charset('utf-8'); $sql="SELECT username,paawd FROM users WHERE username='{$username}'"; $result=$mysqli->query($sql); if(!$result){ die('执行SQL语句失败:'.$mysqli->error); }else if($result->num_rows==0){ die('查询结果为空'); }else { $array1=$result->fetch_all(MYSQLI_ASSOC); echo "用户名:{$array1[0]['username']},密码:{$array1[0]['paawd']}"; } $result->free(); $mysqli->close(); } ?>
按照SQL注入的思路进行注入:
四、JSON注入的危害
1、攻击者可以利用JSON注入漏洞在JSON数据中插入元素,从而允许JSON数据对业务非常关键的值执行恶意操作,严重的可能导致XSS和动态解析代码。
2、非法查询后台/数据库数据。
五、JSON注入防护
1、对关键符号进行转义:“””转义为“\””,“\”转义为“\\”。
2、根据业务实际需求对数据进行合理过滤和安全校验,尽量限制用户输入特殊符号,在条件允许的情况下,最好禁止用户输入任何特殊符号。
3、使用后端编程语言的第三方组件,如Java的JSON-lib.jar。