JSON解析差异-风险研究
字数 1724 2025-08-22 12:22:24
JSON解析差异与安全风险研究
1. JSON解析差异概述
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,广泛应用于客户端与服务器之间的数据传输。然而,由于缺乏严格的规范定义,不同JSON解析器在处理相同JSON文档时可能存在差异,从而导致潜在的安全风险。
1.1 问题根源
- 规范不严格:官方JSON RFC(如8259)对一些细节提供了宽泛的规则
- 多种解析规范共存:
- IETF JSON RFC (8259及之前版本)
- ECMAScript标准
- JSON5(扩展规范,添加注释、无引号字符串等便利功能)
- HJSON(类似JSON5但有不同设计选择)
2. 主要解析差异类型及安全风险
2.1 重复键处理差异
示例:
{
"a": 1,
"a": 2
}
不同解析器处理方式:
- Python(jsonschema):以后出现的键值为准(a=2)
- Go(jsonparser):以先出现的键值为准(a=1)
安全风险:
- 当系统使用多个解析器时(如前端用Go,后端用Python),可能导致业务逻辑绕过
- 实验案例:利用Python Flask作为代理校验层,Go处理实际计算逻辑,通过重复键绕过校验
2.2 字符截断与Unicode处理差异
示例payload:
{
"test": 1,
"test\\ud800": 2
}
不同解析器处理方式:
- Python 2.x:可能将非法Unicode字符截断,导致两个键被视为相同
- Python 3.x:更严格的Unicode处理
安全风险:
- 权限绕过:通过特殊Unicode字符创建"superadmin"等效权限
- 实验案例:使用
superadmin\ud888创建具有管理员权限的用户
2.3 注释处理差异
示例:
{
"description": "Duplicate with comments",
"test": 2,
"extra": /*,
"test": 1,
"extra2": */
}
不同解析器处理方式:
- GoJay:忽略注释,保留原始结构
- JSON-iterator(Java):将注释部分解析为字符串值
2.4 数字类型处理差异
大数处理问题
RFC说明:RFC明确指出大数解析可能存在不一致问题
示例:
{
"qty": 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
}
不同解析器处理方式:
- Python:保持原值
- Go:可能解析为0
安全风险:
- 数值校验绕过:大数被解析为0导致业务逻辑错误
- 实验案例:商品数量使用极大值,后端解析为0导致免费购买
无穷大与NaN处理
RFC说明:官方RFC不支持正负无穷大和NaN
示例:
{
"test": 1.0e4096
}
不同语言处理:
- PHP:
0 == "Infinity"返回true,可能导致逻辑绕过
3. JSON序列化风险
不同语言/库在序列化时对重复键的处理不同:
- JSON-iterator(Java):
- 内存中:保留第一个值
- 序列化输出:保留最后一个值
- rapidjson(C++):
- 内存中:保留最后一个值
- 序列化输出:保留所有键值对
4. 防御措施
4.1 对于JSON SDK开发者
- 严格按照RFC定义规范实现
- 明确处理边界情况:
- 重复键
- 非法Unicode字符
- 注释
- 大数和特殊数值
4.2 对于普通开发者(使用方)
-
解析器盘点:
- 识别系统中使用的所有JSON解析器
- 了解它们的特性和差异
-
输入验证:
- 使用JSON Schema进行强校验
- 示例Schema:
{ "type": "object", "properties": { "orderId": { "type": "number", "maximum": 10 }, "cart": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "number", "minimum": 0, "exclusiveMaximum": 9 }, "qty": { "type": "integer", "minimum": 1 } }, "required": ["id", "qty"] } } }, "required": ["orderId", "cart"] }
-
统一解析器:
- 尽量在整个系统中使用相同的JSON解析器
- 如果必须使用多个解析器,确保它们的行为一致
-
安全测试:
- 对JSON处理逻辑进行模糊测试
- 特别测试边界情况:
- 重复键
- 特殊字符
- 极大/极小数值
- 非法Unicode
5. 历史相关CVE
历史上许多安全漏洞都源于JSON解析差异,包括但不限于:
- 权限绕过漏洞
- 业务逻辑绕过漏洞
- 数据篡改漏洞
6. 实验复现资源
- BishopFox/json-interop-vuln-labs
- Lab1: 重复键处理差异利用
- Lab2: Unicode字符截断利用
7. 总结
JSON解析差异可能导致严重的安全问题,特别是在微服务架构中,不同服务可能使用不同的JSON解析器。开发者应当:
- 充分了解使用的JSON解析器的特性
- 实施严格的输入验证
- 在整个系统中保持解析行为的一致性
- 对JSON处理逻辑进行全面的安全测试
通过规范JSON处理流程和加强安全防护,可以有效降低因解析差异导致的安全风险。