文章总结: 本文深入剖析本地大模型文件格式GGUF的安全隐患,揭示其解析器存在整数溢出导致的RCE风险,及内嵌Jinja2模板引发的供应链投毒与Prompt劫持威胁。文章提供了Fuzzing与静态审计的挖掘链路及复现证据,建议采用安全算术、模板白名单及CI/CD门禁等工程化治理清单,强调逻辑数据分离以增强防御能力。 综合评分: 96 文章分类: AI安全,漏洞分析,供应链安全,二进制安全,安全建设
GGML_GGUF 文件格式漏洞深度解读与挖掘思路
原创
马努
黑伞安全
2026年1月12日 12:01 北京
全网 GGUF 漏洞挖掘体系综述
从内存破坏、模板投毒到供应链治理
导读
- • 阅读目标:理解 GGUF 格式的双重安全风险(解析器内存破坏 vs 模板逻辑投毒)
- • 适用人群:安全研究员、AI 基础设施工程师、模型运维人员
- • 核心收获:掌握从 Fuzzing 到静态审计的完整挖掘链路,获取工程化防御清单
- • 复现成本:中(需 C/C++ 基础与 ASAN 调试环境)
- • 风险等级:高(RCE + 供应链劫持)
摘要
本文深入剖析本地大模型推理生态中的核心文件格式 GGUF 存在的安全隐患。研究指出,GGUF 不仅是静态权重的载体,更因内嵌元数据与图灵完备的 Jinja2 模板而成为“活跃”的攻击面。通过解析器路径,攻击者可利用整数溢出(CVE-2024-25664 等)触发堆缓冲区溢出,实现远程代码执行(RCE)[1];通过模板路径,攻击者可在量化模型中植入恶意逻辑,利用 Hugging Face 的展示盲区实施供应链投毒与 Prompt 劫持[2]。
本文基于 Databricks、Cisco Talos 及 Pillar Security 的公开研究成果,提供了漏洞复现证据(ASAN 日志、PoC 片段)与挖掘方法论(Sanitizers、FormatFuzzer、静态审计)。最后,针对企业级应用,提出了包含 CI/CD 门禁、安全算术检查及模板白名单在内的工程治理清单,并探讨了“逻辑与数据分离”的未来演进方向。
术语小卡
- • GGUF:二进制模型格式,支持 mmap 直接加载,追求推理效率。
- • Chat Template:基于 Jinja2 的对话模板,定义 Prompt 结构,含逻辑控制。
- • Wraparound:整数回绕,N × Size 溢出导致分配变小,引发堆溢出。
- • Checked Arithmetic:使用
__builtin_mul_overflow等防止算术溢出的安全编程范式。 - • Reproducible Builds:可复现构建,确保产物与源一致,提升供应链可验证性。
本文贡献
- • 双轨风险模型:系统性拆解解析器 RCE 与模板投毒的攻击面。
- • 证据链复核:集成 Talos ASAN 日志与 Databricks PoC,验证溢出机理[1]。
- • 结构化 Fuzz:提出基于 010 Editor 模板的格式化 Fuzzing 流程[3]。
- • 模板治理:构建“签名—白名单—透明化”的模板安全生命周期[2]。
- • 工程门禁:量化安全算术与 CI/CD 阈值,避免回归与漏检。
背景与问题陈述
随着 llama.cpp 等本地推理引擎的普及,GGUF 已成为 Hugging Face 上最流行的模型分发格式之一[1]。社区为了适配不同档次的硬件,衍生出 Q2_K、Q4_K_M、Q8_0 等繁杂的量化版本。这种“同一模型、多种文件”的生态现状,使得单一源头审计变得极其困难,任何一个量化变体都可能成为攻击者的载体。
现有防线存在盲区:ProtectAI、JFrog 等扫描工具主要侧重 Pickle 反序列化与传统恶意代码特征,往往忽略 GGUF 内部的模板逻辑。这创造了一个危险真空地带:攻击者可以发布一个通过静态扫描的 GGUF 文件,却在推理时通过渲染恶意模板执行 Prompt 注入或钓鱼攻击[2]。
历史一再证明:当文件格式开始承载逻辑时,它就不再是纯粹的数据。Google Project Zero 的 Mateusz Jurczyk 在“Effective File Format Fuzzing”中指出,任何复杂的解析器都是潜在攻击面[3]。GGUF 正处于这一演进的最新节点,它不仅包含张量数据,还封装了复杂的 KV 元数据和活跃的 Chat Template 逻辑。
攻击面框架:解析器路径 vs 模板路径
可控输入风险矩阵
| 关键字段 | 数据类型 | 操作类型 | 典型后果(CVE) |
| — | — | — | — |
| n_kv | uint64 | malloc(n_kv * sizeof(kv)) | 整数回绕导致堆溢出(CVE-2024-25664)[1] |
| str.len | uint64 | calloc(len + 1) | 分配过小导致堆越界写(CVE-2024-25665)[1] |
| arr.n | uint64 | 批量分配/循环写入 | 批量越界写(CVE-2024-25667)[1] |
| GGUF_TYPE_SIZE[idx] | Index | 数组索引查表 | 索引越界,获取错误 Size 导致溢出[1] |
| n_tensors | uint64 | malloc(n_tensors * sizeof(info)) | 分配回绕,循环越界(CVE-2024-25666)[1] |
解析器路径(Memory)
机理:利用整数溢出导致分配大小远小于实际写入量。
// 危险模式
size_t size = count * sizeof(Item);
void* ptr = malloc(size); // 溢出后 size 变小
// 循环按 count 写入,堆破坏
影响:RCE、DoS。
模板路径(Logic)
机理:在 GGUF 元数据中注入恶意 Jinja2 模板。由于量化模型常有独立元数据,攻击者可进行“供应链错位”投毒[2]。
隐蔽触发示例:
- • HTML 上下文:仅当用户请求生成网页/代码时注入恶意 JS。
- • 登录诱导:检测到“login”关键词时伪造密码框。
证据与复现要点
内存破坏:源码与日志对照
Databricks 与 Talos 的发现揭示了 gguf_init_from_file 中的致命缺陷[1][4]。下列对照展示漏洞代码与 ASAN 现场:
// 1. 读取 n_kv (攻击者可控: 0x55...5a)
fread(&ctx->n_kv, ...);
// 2. 乘法回绕 (Wraparound)
// 0x55...5a * 48 = 0xE0 (高位截断)
size_t size = ctx->n_kv * sizeof(gguf_kv);
ctx->kv = malloc(size); // 分配极小堆块
// 3. 越界写入
for (i = 0; i < ctx->n_kv; ++i) {
ctx->kv[i] = ...; // 远超分配范围,触发 Heap Overflow
}
==3991119==ERROR: AddressSanitizer: heap-buffer-overflow
WRITE of size 8 at 0x610000000200 thread T0
#0 gguf_fread_str ggml.c:18658
#1 gguf_init_from_file ggml.c:18796
#2 llama_model_loader ...
0x610000000200 is located 0 bytes to the right of 192-byte region
allocated by thread T0 here:
#0 __interceptor_malloc ...
#1 gguf_init_from_file ...
复现 Checklist:
- • 编译参数:
-fsanitize=address,undefined -g -O1。 - • 触发用例:将 Header 中
n_kv设为0x555555555555555a。 - • 最小退出条件:PoC 文件 payload 后立即截断(EOF),确保
malloc已执行、fread失败暴露 ASAN 报警。
模板投毒:Hugging Face UI 盲区
攻击者准备仓库
文件1:clean_model.fp16.gguf(干净模板)
文件2:poisoned_model.q4_k_m.gguf(恶意模板)
Hugging Face UI 仅扫描文件1,显示“安全”
用户为省显存下载 Q4 版本
结果:用户获得恶意模板
核查步骤:逐个读取 GGUF 头部、提取 tokenizer.chat_template 字段,进行差分比对(见“实战案例:模板差异审计”)。
实战案例:从 PoC 到工程复现
案例 1:解析器整数溢出(CVE-2024-25664)
目标:构造极小 GGUF 文件,使 n_kv 极大但文件体积极小,欺骗分配器。
失败与坑位:文件过短会直接触发 EOF 返回 NULL,未执行到 malloc。需保证 Magic/Version 合法、payload 足以进入分配,再以 EOF 终止。
修复代码片段(Checked Arithmetic):
// 修复前
// ctx->kv = malloc(ctx->header.n_kv * sizeof(struct gguf_kv));
// 修复后 (使用 __builtin_mul_overflow)
size_t size_kv;
if (__builtin_mul_overflow(ctx->header.n_kv, sizeof(struct gguf_kv), &size_kv)) {
return NULL; // 溢出检测
}
ctx->kv = malloc(size_kv);
案例 2:模板差异审计(Template Diff)
目标:验证同仓库下 FP16 原版与 Q4 量化版模板是否一致。
# 伪代码:提取并比较两个 GGUF 文件的模板字段
def extract_template(gguf_path):
reader = GGUFReader(gguf_path)
return reader.get_field("tokenizer.chat_template")
t1 = extract_template("model-fp16.gguf")
t2 = extract_template("model-q4_k_m.gguf")
if t1 != t2:
print("[ALERT] Template Mismatch Detected!")
print(diff(t1, t2))
else:
print("[PASS] Templates are identical.")
审计结果:实战中发现多个社区量化模型为适配特定工具擅改 System Prompt,虽未必恶意,但证明供应链不透明。
研究方法:Sanitizers、Fuzz 与静态审计
动态检测(Sanitizers)与 Harness
编写极简 Harness 提高 Fuzz 吞吐率,避免加载完整运行时,仅保留解析逻辑:
#include "ggml.h"
// 编译:gcc -g -O1 -fsanitize=address,undefined harness.c ggml.c -o harness
int main(int argc, char **argv) {
if (argc < 2) return 1;
struct gguf_init_params params = {
.no_alloc = true, // 仅解析元数据,不分配张量内存
.ctx = NULL,
};
struct gguf_context * ctx = gguf_init_from_file(argv[1], params);
if (ctx) gguf_free(ctx);
return 0;
}
格式 Fuzzing(FormatFuzzer)
- • 解析模板:使用 010 Editor 的
gguf.bt理解文件结构[3]。 - • 变异策略:重点变异
n_kv、n_tensors、str.len,尝试边界值(UINT64_MAX)。 - • 覆盖度度量:关注异常路径(Error Handling)的覆盖率,确保错误处理逻辑被充分测试。
静态审计规则集(Semgrep)
| 漏洞模式 | Semgrep 逻辑 |
| — | — |
| Malloc Overflow | malloc($X * $Y) 且无 mul_overflow 检查 |
| Calloc Overflow | calloc($LEN + 1) (LEN 为最大值时回绕) |
| Unchecked Return | fread(...) 未检查返回值即使用数据 |
| Index OOB | TypeSize[$IDX] 来自文件且未检查范围 |
防御与治理(工程落地清单)
模板治理流程
- 开始流程 → 系统启动模板安全检查流程。
- 模型导入 → 用户或系统尝试加载GGUF模型文件。
- 签名校验 → 系统检查模型是否具备可信的数字签名:
- 若签名不可信 → 直接拦截阻断,流程结束。
- 若签名可信 → 进入下一步白/黑名单检查。
- 白/黑名单检查 → 系统根据预设名单对模型进行归类:
- 若模型在白名单中 → 系统展示工具信息,允许用户加载,流程结束。
- 若模型在黑名单中 → 直接拦截阻断,流程结束。
- 若模型不在任何名单中(未知) → 进入沙箱/隔离环境进行安全分析。
- 沙箱/隔离分析 → 在受控环境中对模型进行动态行为监控。
- 人工审计 → 安全人员对隔离环境中的模型行为进行手动审查。
- 加入白名单 → 若人工审计确认模型安全,将其加入白名单。
- 展示工具信息 → 系统向用户展示模型相关信息。
- 用户加载 → 用户正常加载并使用模型。
- 流程结束 → 安全检查完成。
工程防御清单
- • 安全算术:所有分配长度计算强制使用
__builtin_mul_overflow检查。 - • 默认禁用:推理工具默认不信任 GGUF 内嵌模板,除非显式 override 或加入白名单。
- • CI/CD 门禁:ASAN 回归测试必须 100% 通过;Fuzzing 每周至少运行 100 核心小时。
- • 透明度披露:发布模型时提供《模板完整性报告》,列出模板哈希与签名。
红队演练与蓝队对策
红队视角(Attack)
- • 触发词埋设:选择高频词(”login”、”help”)或长尾词(特定报错代码)。
- • 文件欺骗:利用文件列表顺序,将正常文件置顶,恶意文件混入量化列表。
- • 混淆技术:使用 Jinja2 编码特性(如十六进制)隐藏恶意 payload。
蓝队视角(Defense)
- • 静态扫描:建立规则库扫描常见 Web 攻击特征(
<script>、iframe)。 - • 动态审计:使用自动化 Harness 发送触发词集,监控渲染结果是否包含 HTML 标签。
- • 仓库差分:自动脚本拉取所有 GGUF 变体,计算模板哈希相似度。
复现与回归工程手册
| 环节 | 规范与标准 |
| — | — |
| 环境基线 | GCC/Clang 最新版;开启 ASAN/UBSAN;覆盖 x86_64 与 ARM64 双架构 |
| 样本库管理 | 建立 corpus/ 目录,命名规范 cve-{id}-{field}-overflow.gguf;强制版本化管理 |
| CI 集成 | Pre-commit 阶段 Sanitizer 快扫;Nightly 阶段长时 Fuzzing |
| 输出物 | 周报包含:新增 Crash 数、修复率、模板差分命中数、覆盖率变化 |
跨格式对比与研究议程
安全没有银弹。GGUF 在性能上无可匹敌,但安全性仍需补课。
| 格式 | RCE 风险 | 逻辑/Prompt 风险 | 签名/验证链 | 生态工具成熟度 | | — | — | — | — | — | | Pickle | 极高(设计缺陷) | 高 | 无标准 | 高(PyTorch 原生) | | SafeTensors | 极低(纯张量) | 低 | 支持 Hash | 中(HF 推广) | | ONNX | 中(解析器) | 中(图逻辑) | 支持 | 高(工业标准) | | GGUF | 高(C 解析器) | 极高(内嵌模板) | 社区依赖(弱) | 极高(量化推理标准) |
观点小结:未来核心在于“逻辑与数据分离”。理想状态下,GGUF 回归纯数据容器(类似 SafeTensors),将 Chat Template、Tokenization 逻辑剥离为独立、可审计的代码文件。然而,鉴于 llama.cpp“单文件分发”的巨大便利,这一拆分面临用户习惯阻力。短期内,“可验证量化”(Verifiable Quantization)——证明 Q4 模型确实源自特定 FP16 模型且无篡改——是工程攻坚方向。
总结与行动建议
GGUF 的兴起标志着“模型即代码”时代的到来,但也暴露了 AI 基础设施在传统二进制安全与供应链安全上的双重短板。对于安全从业者,这既是挑战也是机遇。
读者行动项:
- • 立即行动(Now):启用 ASAN/UBSAN;审计现有 GGUF 库,提取并比对模板。
- • 近期计划(Next Week):建立模板白名单与签名流程;固化加载器基线;集成 Semgrep 规则。
- • 中期目标(Next Month):推进逻辑-数据分离的内部方案与可验证量化实验。
引用与致谢
- 1. Databricks. GGML GGUF File Format Vulnerabilities. https://www.databricks.com/blog/ggml-gguf-file-format-vulnerabilities
- 2. Pillar Security. LLM Backdoors at the Inference Level: The Threat of Poisoned Templates. https://pillar.security/blog/llm-backdoors-at-the-inference-level-the-threat-of-poisoned-templates
- 3. Mateusz Jurczyk. Effective File Format Fuzzing – Thoughts, Techniques and Results (BlackHat EU 2016). https://blackhat.com/docs/eu-16/materials/eu-16-Jurczyk-Effective-File-Format-Fuzzing-Thoughts-Techniques-And-Results.pdf
- 4. Cisco Talos. TALOS-2024-1912 Heap-based buffer overflow in GGUF string array parsing (llama.cpp). https://talosintelligence.com/vulnerability_reports/TALOS-2024-1912
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:黑伞安全 马努《GGML_GGUF 文件格式漏洞深度解读与挖掘思路》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。











评论