org.json与参数走私浅析
字数 2139 2025-10-01 14:05:52

org.json 解析特性与参数走私漏洞分析

一、org.json 库概述

org.json 是 Java Web 生态中一个轻量级的 JSON 构造和解析工具包,提供简洁的 API 进行 JSON 序列化与反序列化操作。该库还支持 JSON 与 XML、HTTP headers、Cookies 等格式的相互转换。

基本使用示例

JSONObject jsonobj = new JSONObject("{'name':'test','age':20}");
String name = jsonobj.getString("name");

二、org.json 解析过程深度分析

2.1 解析入口

通过 new JSONObject(String json) 构造方法进行 JSON 字符串解析,首先调用 nextClean() 方法获取下一个有效字符。

2.2 初始检查

  • 检查 JSON 字符串是否以左花括号 { 开头
  • 不符合格式要求时抛出 JSONException 异常

2.3 nextClean() 方法功能

从输入流中跳过所有空白字符(空格、制表符、换行符等),定位到第一个有效字符。

2.4 主解析循环

通过 while 循环对 JSON 字符串逐个字符读取,根据不同情况进行处理:

  1. case '\u0000':遇到 null 字符时抛出异常
  2. case '}':遇到右花括号时结束解析
  3. default:处理键值对(核心解析逻辑)

2.5 键值对解析流程

  1. 使用 nextSimpleValue() 方法解析键名
  2. 检查下一个字符是否为冒号 :,否则抛出异常
  3. 检查键名重复性,发现重复键时抛出 syntaxError 异常
  4. 使用 nextValue() 方法解析属性值
  5. 将解析结果存储到当前 JSONObject 中

2.6 值解析机制

nextValue() 方法处理以下情况:

  • 嵌套 JSON 对象
  • Array 数组
  • 其他类型通过 nextSimpleValue() 处理

2.7 nextSimpleValue 方法解析逻辑

分两种情况处理属性值:

情况一:引号开头的内容

  • 单/双引号开头时调用 nextString() 方法
  • 处理转义字符(\n、\t 等)和普通字符
  • 支持 Unicode 字符处理
  • 遇到匹配的结束引号时停止

情况二:非引号开头的内容

  • 构造 StringBuilder
  • 循环读取字符直到遇到 JSON 结构分隔符或控制字符
  • 回退一个字符
  • 调用 stringToValue() 方法清理字符串并转换为对应 JSON 值

2.8 stringToValue 方法处理规则

对获取的内容进行规整处理:

  • 检查字符串是否为空
  • 判断是否为布尔值 "true" 或 "false"
  • 判断是否为 "null"
  • 检查是否为数字(仅处理 0-9 和负号 - 情况)
  • 根据检查结果返回对应类型的值

三、org.json 解析特性总结

  1. 宽松的解析策略:允许属性不使用双引号包裹,支持单引号
  2. 重复键处理:不支持重复键,发现时会抛出异常
  3. 类型转换特性:对数字型输入有特殊处理规则
  4. Unicode 支持:完整支持 Unicode 字符处理

四、参数走私漏洞案例分析

4.1 漏洞场景

Web 应用 User 实体包含 roleId 属性(String 类型),认证拦截器对请求 JSON Body 中的 roleId 字段进行拦截:

JSONObject jsonObj = new JSONObject(body);
if (jsonObj.getString("roleId").equals("1")) {
    // 鉴权逻辑,限制 roleId 更新操作
}

后端接口使用 Fastjson 进行参数解析,存在解析器差异。

4.2 漏洞原理

Fastjson 解析特性

  • JSONScanner 会对以正号(+)、负号(-)或数字开头的字符串识别为数值
  • 示例:{"value":+1} 解析后值为数字 1

org.json 解析特性

  • 对非引号包裹的内容,只有 0-9 和负号(-)才会被识别为数字
  • 正号(+)开头的内容会被原样输出为字符串

4.3 漏洞利用

构造攻击载荷

String body = "{\"roleId\":+1}";
JSONObject jsonobj = new JSONObject(body);
System.out.println("org.json parse result:" + jsonobj.getString("roleId"));
// 输出结果: "+1" (字符串)

User userByFastjson = com.alibaba.fastjson.JSONObject.parseObject(body, User.class);
System.out.println("fastjson parse result:" + userByFastjson.getRoleId());
// 输出结果: "1" (数字)

绕过效果

  • org.json 将 +1 解析为字符串 "+1"
  • Fastjson 将 +1 解析为数字 1
  • 成功绕过鉴权检查

4.4 其他攻击向量

Unicode 空字符利用

  • json-c 对空字符会做截断处理
  • org.json 库会保留 Unicode 空字符
  • 通过在属性中增加 Unicode 空字符,结合重复 key 手法实现绕过

分号解析差异

  • org.json 和 Gson 将分号 ; 识别为键值以外的分隔符
  • 部分 JSON 解析组件会错误解析进入兜底逻辑
  • 可能由于解析差异导致参数走私风险

五、防护建议

  1. 统一解析库:前后端使用相同的 JSON 解析库
  2. 严格输入验证:对输入数据进行严格类型和格式检查
  3. 安全配置:配置解析库使用严格模式
  4. 代码审计:重点关注多解析器共存场景
  5. 边界防护:在网关层进行有效的数据过滤和验证

六、总结

org.json 库的宽松解析特性与其它 JSON 解析库的差异可能导致参数走私漏洞。特别是在多解析器共存的环境中,解析差异可能被利用来绕过安全检测。开发人员应充分了解所使用的 JSON 解析库的特性,避免因解析差异导致的安全问题。在安全审计过程中,需要特别关注解析器差异可能带来的参数走私风险。

通过本文分析,我们深入了解了 org.json 的解析机制和可能存在的安全风险,为安全开发和代码审计提供了重要参考。

org.json 解析特性与参数走私漏洞分析 一、org.json 库概述 org.json 是 Java Web 生态中一个轻量级的 JSON 构造和解析工具包,提供简洁的 API 进行 JSON 序列化与反序列化操作。该库还支持 JSON 与 XML、HTTP headers、Cookies 等格式的相互转换。 基本使用示例 二、org.json 解析过程深度分析 2.1 解析入口 通过 new JSONObject(String json) 构造方法进行 JSON 字符串解析,首先调用 nextClean() 方法获取下一个有效字符。 2.2 初始检查 检查 JSON 字符串是否以左花括号 { 开头 不符合格式要求时抛出 JSONException 异常 2.3 nextClean() 方法功能 从输入流中跳过所有空白字符(空格、制表符、换行符等),定位到第一个有效字符。 2.4 主解析循环 通过 while 循环对 JSON 字符串逐个字符读取,根据不同情况进行处理: case '\u0000' :遇到 null 字符时抛出异常 case '}' :遇到右花括号时结束解析 default :处理键值对(核心解析逻辑) 2.5 键值对解析流程 使用 nextSimpleValue() 方法解析键名 检查下一个字符是否为冒号 : ,否则抛出异常 检查键名重复性,发现重复键时抛出 syntaxError 异常 使用 nextValue() 方法解析属性值 将解析结果存储到当前 JSONObject 中 2.6 值解析机制 nextValue() 方法处理以下情况: 嵌套 JSON 对象 Array 数组 其他类型通过 nextSimpleValue() 处理 2.7 nextSimpleValue 方法解析逻辑 分两种情况处理属性值: 情况一:引号开头的内容 单/双引号开头时调用 nextString() 方法 处理转义字符(\n、\t 等)和普通字符 支持 Unicode 字符处理 遇到匹配的结束引号时停止 情况二:非引号开头的内容 构造 StringBuilder 循环读取字符直到遇到 JSON 结构分隔符或控制字符 回退一个字符 调用 stringToValue() 方法清理字符串并转换为对应 JSON 值 2.8 stringToValue 方法处理规则 对获取的内容进行规整处理: 检查字符串是否为空 判断是否为布尔值 "true" 或 "false" 判断是否为 "null" 检查是否为数字(仅处理 0-9 和负号 - 情况) 根据检查结果返回对应类型的值 三、org.json 解析特性总结 宽松的解析策略 :允许属性不使用双引号包裹,支持单引号 重复键处理 :不支持重复键,发现时会抛出异常 类型转换特性 :对数字型输入有特殊处理规则 Unicode 支持 :完整支持 Unicode 字符处理 四、参数走私漏洞案例分析 4.1 漏洞场景 Web 应用 User 实体包含 roleId 属性(String 类型),认证拦截器对请求 JSON Body 中的 roleId 字段进行拦截: 后端接口使用 Fastjson 进行参数解析,存在解析器差异。 4.2 漏洞原理 Fastjson 解析特性 JSONScanner 会对以正号(+)、负号(-)或数字开头的字符串识别为数值 示例: {"value":+1} 解析后值为数字 1 org.json 解析特性 对非引号包裹的内容,只有 0-9 和负号(-)才会被识别为数字 正号(+)开头的内容会被原样输出为字符串 4.3 漏洞利用 构造攻击载荷 绕过效果 org.json 将 +1 解析为字符串 "+1" Fastjson 将 +1 解析为数字 1 成功绕过鉴权检查 4.4 其他攻击向量 Unicode 空字符利用 json-c 对空字符会做截断处理 org.json 库会保留 Unicode 空字符 通过在属性中增加 Unicode 空字符,结合重复 key 手法实现绕过 分号解析差异 org.json 和 Gson 将分号 ; 识别为键值以外的分隔符 部分 JSON 解析组件会错误解析进入兜底逻辑 可能由于解析差异导致参数走私风险 五、防护建议 统一解析库 :前后端使用相同的 JSON 解析库 严格输入验证 :对输入数据进行严格类型和格式检查 安全配置 :配置解析库使用严格模式 代码审计 :重点关注多解析器共存场景 边界防护 :在网关层进行有效的数据过滤和验证 六、总结 org.json 库的宽松解析特性与其它 JSON 解析库的差异可能导致参数走私漏洞。特别是在多解析器共存的环境中,解析差异可能被利用来绕过安全检测。开发人员应充分了解所使用的 JSON 解析库的特性,避免因解析差异导致的安全问题。在安全审计过程中,需要特别关注解析器差异可能带来的参数走私风险。 通过本文分析,我们深入了解了 org.json 的解析机制和可能存在的安全风险,为安全开发和代码审计提供了重要参考。