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

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

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

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

工具目录

分类

查看所有分类
Loading categories
AWS-Tough-Library-Multiple-CVEs — 0.20.0 之前版本存在的 tough 问题(多个 CVE) | Kitploit
工具/GitHubGitHub/murataydemir/aws-tough-library-multiple-cves
漏洞分析供应链安全论文与研究学习与教育
GitHubmurataydemir/aws-tough-library-multiple-cves

AWS-Tough-Library-Multiple-CVEs

0.20.0 之前版本存在的 tough 问题(多个 CVE)

查看仓库

最受欢迎

查看全部 →

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

探索所有工具

浏览我们的工具集合

查看所有工具 →
131年前尚未审核
分享

AWS Tough 库多个 CVE


2025 年 3 月,AWS Labs 的 Tough 库(TUF – The Update Framework 的 Rust 客户端实现)披露了多个安全漏洞。这些问题分别跟踪为 CVE-2025-2885、CVE-2025-2886、CVE-2025-2887 和 CVE-2025-2888,并已在 Tough 0.20.0 版本 中修复。安全工程师可以使用本文档了解每个漏洞的技术细节、代码库中的根本原因以及解决这些问题的补丁。强烈建议所有 Tough < 0.20.0 的用户升级到 v0.20.0 或更高版本。

CVE-2025-2885:缺少顺序根版本验证

Tough 在更新过程中未能按顺序验证 Root metadata 版本。控制仓库(或具备中间人能力)的攻击者可以提供带有意外版本号的根元数据文件,导致客户端获取并信任错误的版本。本质上,Tough 并未确保新根元数据的版本恰好比先前信任的版本大 1,这违反了 TUF 对连续信任链的要求。这可能导致 回滚或混搭攻击,即旧(但签名正确)的根被当作最新版本接受,从而可能重新引入已退役的签名密钥或过期的信任。

  • 公告: GitHub Security Advisory GHSA-5vmp-m5v2-hx47 (CVE-2025-2885)
  • 受影响的代码: tough/src/lib.rs 中 Tough 对根元数据的更新逻辑。有漏洞的实现仅检查新根的版本不低于旧版本,而不是要求它为下一个顺序版本。这一遗漏违反了 TUF 规范中客户端必须按顺序下载中间根版本(不允许跳过版本)的规则。

有漏洞的实现: 在 0.19.x 及更早版本中,下载新的 root.json 后,Tough 验证了签名,但并未严格执行版本连续性。它允许新根版本为任意 >= 受信任版本的值。例如,如果当前受信任的根是版本 N,Tough 会接受声称版本为 N+2 或更高(只要签名有效)的新根,从而跳过 N+1。下面的代码片段说明了修复前的检查:```rust // (Prior to fix) Allow new root version to be >= old version – too permissive ensure!(root.signed.version <= new_root.signed.version, error::OlderMetadataSnafu { role: RoleType::Root, current_version: root.signed.version, new_version: new_root.signed.version });

root@kitploit:~
攻击者可以通过提供<b>一个版本号更高但实际上是旧密钥集的根元数据</b>来利用这一点。Tough 会将其视为更新并接受,进而[信任使用过期密钥签名的内容](https://github.com/advisories/GHSA-5vmp-m5v2-hx47#:~:text=The%20tough%20client%20will%20trust,with%20a%20previous%20root%20role)。

<b>修复实现:</b>补丁代码(Tough 0.20.0 中)明确要求新根版本的版本号恰好比旧版本大 1,参见 [提交 0eeb60a](https://github.com/awslabs/tough/commit/0eeb60aefe27f00b65730634b788a1aafb8bf3c6)。它还确保新版本更高(防止相同或降低)并阻止任何大于 +1 的跳变:```rust
// (Fixed in v0.20.0) Enforce sequential root version update (new_version == old_version + 1)
ensure!(
    root.signed.version < new_root.signed.version && 
    root.signed.version.get() + 1 == new_root.signed.version.get(),
    error::OlderMetadataSnafu { 
        role: RoleType::Root, 
        current_version: root.signed.version, 
        new_version: new_root.signed.version 
    }
);

此更改确保客户端按顺序(N, N+1, N+2, ...)下载并应用根元数据,而不会跳过。如果遇到版本不是恰好为 old_version+1 的根元数据文件,Tough 现在会将其视为潜在攻击并中止更新。

  • 根本原因:缺少顺序版本检查(CWE-1288:完整性校验值验证不当)。代码仅防止新根比当前根旧,但没有防止意外的版本跳跃。
  • 修复措施:升级到包含该补丁的 tough = 0.20.0。确保基于 Tough 的任何分支或自定义更新器都实施相同的严格检查。此外,还建议审计更新历史日志中是否存在可疑的根版本跳跃,以作为检测尝试利用的指标。

CVE-2025-2886:终止委派未得到遵守

Tough 错误地处理了 TUF 所定义的 “终止”委派目标角色。在 TUF 仓库中,委派可以被标记为 terminating,这意味着如果目标查找到达该委派且未在其中找到目标,则搜索应停止(而不应继续到其他较低优先级的委派)。(参见此处)由于逻辑错误,Tough 未能终止搜索——即使本应停止,它仍会继续搜索后续委派。这可能允许控制较低优先级委派的攻击者为原本不应由其控制的目标提供内容,从而绕过预期的信任边界。

  • 安全公告:GitHub 安全公告 GHSA-v4wr-j3w6-mxqc(CVE-2025-2886)
  • 受影响代码:tough/src/editor/targets.rs 中的目标查找算法(以及相关的委派解析代码)。存在漏洞的代码没有正确处理委派上的 terminating 标志。在遍历委派查找目标时,即使当前委派被标记为 terminating 且没有匹配项,Tough 仍会继续到下一个委派,这与 TUF 规范相反。

易受攻击的实现:在 Tough <0.20.0 中,find_target() 逻辑只是递归或循环遍历所有可能的委派角色,直到找到目标或全部耗尽。当遇到 terminating 角色时,它不会设置任何标志或跳出循环。旧行为伪代码如下:```rust for role in delegation_chain { if role.has_target(target) { return target_metadata; } // Missing: if role is terminating and target not found, should break. // Tough erroneously continues to next delegation. }

root@kitploit:~
这意味着,较低优先级的委托(在遇到其上方的终止委托后本应被忽略)仍可能被查询,并提供恶意目标文件​

<b>修复后的实现:</b> 修补后的版本引入了一种机制来跟踪终止并适当地停止搜索。当遇到不含目标的终止委托时,Tough 现在会[立即跳出搜索循环](https://github.com/awslabs/tough/commit/598111f88105a707ee68b0fa06c52da7176ea96a#:~:text=%2F%2F%20we%20encountered%20a%20terminating,so%20we%20stop%20iterating%20immediately)。在更新后的代码中,当命中终止角色时,会设置一个布尔标志(例如 `terminated`),并将其向调用栈上层传播。例如:```rust
// If a terminating delegation was reached (and we didn't find the target there), stop searching further
if role.terminating && !permissive {
    // Mark that we encountered a terminating delegation
    *terminated = true;
    break;
}

此外,递归的 find_target 调用现在会携带一个 terminated 标志,以确保一旦发出终止信号,较高级别的循环中便不再考虑其他委托​。Tough 的 RepositoryEditor::delegate_role 及相关结构也已更新,以存储 terminating 属性并将其传递给搜索逻辑。

  • 根本原因: 代码存在逻辑缺陷,未实现终止委托(terminating delegation)语义(CWE-284:不当访问控制——低优先级角色可能覆盖预期限制)​。本质上,在终止委托上缺少 break,导致未经授权的目标数据被纳入考虑。
  • 影响: 客户端可能获取到由错误角色拥有的目标——具体而言,如果项目将一部分目标委托给另一方(并将该委托标记为终止委托以限制覆盖范围),该方仍可为范围之外的目标提供任意内容。这会破坏 TUF 仓库中的信任层级。
  • 修复建议: 升级到正确实现终止委托处理的 tough 0.20.0+。如果你维护的是分支或自定义客户端,请确保你的目标查找在遇到终止委托时会停止。安全测试人员只应在旧版本上尝试委托滥用场景;已修补版本会正确忽略恶意的低优先级响应。

CVE-2025-2887:委托目标的回滚检测不完整

Tough 用于检测快照元数据中的回滚攻击的逻辑并不完整。具体而言,在更新 Snapshot 角色时,Tough 应验证所有先前见过的目标元数据(包括委托目标)在新快照中仍然存在,且未发生版本回退。(参见此处)Tough 确实对顶层 targets.json 执行了此检查,但未能对委托的目标元数据文件执行同样检查。这一缺陷可能允许攻击者在未被发现的情况下删除或回退仓库快照元数据中的委托目标文件,导致客户端将过期(或缺失)的委托目标文件当作最新版本接受​。

  • 安全公告: GitHub 安全公告 GHSA-q6r9-r9pw-4cf7(CVE-2025-2887)
  • 受影响代码: tough/src/lib.rs 中的快照更新验证(加载/应用新 Snapshot 元数据的函数)。存在漏洞的代码只检查了快照中主 targets.json 角色的连续性,但未遍历快照元数据中列出的委托角色以执行类似检查。

存在漏洞的实现: 在 Tough <0.20.0 中,客户端在获取新的 snapshot.json 后,会确保 root 和 snapshot 角色未被回滚,并专门确保 targets.json 仍然存在。它还会验证新快照中 targets.json 的版本是否 >= 先前版本。然而,如果快照包含委托目标(例如 projects.json、user.json 委托元数据),客户端不会验证这些内容。例如,原始代码大致如下:```rust // Pseudo-code of original snapshot rollback check (simplified) if let Some(old_targets_meta) = old_snapshot.meta.get("targets.json") { let new_targets_meta = new_snapshot.meta.get("targets.json").unwrap(); ensure!(new_targets_meta.version >= old_targets_meta.version, ...); } // (No checks for delegated target roles like "projects.json", "user.json", etc.)

root@kitploit:~
这意味着如果拥有仓库访问权限的攻击者<b>删除了某个委派元数据文件,或将其回滚到较旧版本</b>,Tough 的客户端将不会察觉——只要主要的 targets.json 仍然完好。客户端随后可能会从该委派中下载过时的目标,却不知道它本应作为回滚而被拒绝。

<b>已修复的实现:</b>版本 0.20.0 增加了对<b>快照元数据中列出的每个角色</b>的全面检查。新代码遍历旧快照元数据中的每个条目(包括所有委派的目标角色),并确保每个条目满足两点:(1) 该角色仍存在于新快照中,以及 (2) 其版本号未降低。如果任何角色在新快照中缺失,或其版本号低于之前,更新将被拒绝,视为潜在的回滚攻击​。例如:```rust
for (name, old_meta) in &old_snapshot.signed.meta {
    // 1. Role must appear in new snapshot
    ensure!(
        snapshot.signed.meta.contains_key(name),
        error::SnapshotRoleMissingSnafu { role: name, old_version: old_snapshot.signed.version, new_version: snapshot.signed.version }
    );
    // 2. Role’s version must not decrease
    let new_meta = snapshot.signed.meta.get(name).unwrap();
    ensure!(
        old_meta.version <= new_meta.version,
        error::SnapshotRoleRollbackSnafu { role: name, old_role_version: old_meta.version, new_role_version: new_meta.version, … }
    );
}

通过遍历 所有角色(name 代表每个元数据文件名,如 targets.json、delegated-role.json 等),客户端将捕获任何被删除或回退的委托目标元数据。如果某个角色消失或其版本回退,将触发 SnapshotRoleMissing 和 SnapshotRoleRollback 错误。(如果角色消失或其版本回退)。值得注意的是,Tough 现在还明确确保快照中至少包含 targets.json 条目(否则会抛出 SnapshotTargetsMetaMissing 错误),作为健全性检查。

  • 根本原因: 验证不完整 – Tough 未将回滚检查统一应用于委托目标角色。这是一个 安全控制的部分实现,留下了攻击者可能利用的缺口(CWE-352:授权中缺少关键步骤;概念上属于完整性验证问题的一部分)。代码仅保护顶层目标,错误地假设委托角色不会回退。
  • 影响: 能够操纵仓库的攻击者可以隐藏更新或重新引入旧的委托目标数据,而不会被客户端检测到。例如,他们可能提供一个由已被攻破的密钥签名的旧委托目标文件,而由于 Tough 未检查该文件的版本,该文件会被接受。在实践中,这可能导致客户端 获取过时内容,或错过对委托目标的关键撤销。(参见 此处)
  • 修复方案: 使用 tough v0.20.0+,该版本实现了完整的快照回滚检查。如果自行维护更新程序,请确保对于快照中列出的 每个受信任的元数据文件,新快照也以 >= 先前版本的版本号列出该文件。还建议对仓库更新中的任何 委托目标移除 启用日志记录或审计,因为这些操作应属罕见;如果意外发生,可能表明存在恶意活动。

CVE-2025-2888: 回滚时的时间戳元数据缓存不当

Tough 错误地处理了 Timestamp 角色中检测到的回滚。TUF 中的 Timestamp 角色会定期签署最新的快照元数据版本,以帮助客户端检测是否看到一个较旧的快照(即回滚)。Tough 确实对时间戳中包含的快照版本执行了回滚检查,但仅在将新的时间戳元数据缓存到本地之后才执行。如果检测到回滚,Tough 会拒绝更新,但已经将无效时间戳作为“最新”版本持久化在其缓存中。这意味着恶意时间戳(带有过时的快照版本)可能污染客户端的缓存。随后,合法的更新在 Tough 看来可能像是回滚(因为缓存中的时间戳所指示的快照版本高于新版本),从而阻止有效的更新。

  • 公告: GitHub 安全公告 GHSA-76g3-38jv-wxh4 (CVE-2025-2888)
  • 受影响代码: tough/src/lib.rs 中的时间戳更新逻辑(加载新 timestamp.json 的函数)。核心问题是一个 操作顺序错误:Tough 在完全验证内部快照版本不早于之前所见版本之前,就已用新的 Timestamp 元数据更新了本地缓存/状态。

存在漏洞的实现: 在 Tough <0.20.0 中,当获取到新的 timestamp.json 时,客户端会解析并将其写入缓存(将其标记为当前受信任的时间戳),然后对快照版本执行回滚检查。如果新时间戳中的快照版本低于先前记录的快照版本(表示回滚尝试),Tough 会记录错误并拒绝该更新周期 – 但缓存中已经保存了“坏”时间戳。在该错误路径中,缓存条目不会被移除。因此,客户端对“受信任”时间戳的记录可能变成这个过时的记录。

例如,假设最后已知的快照版本为 5。攻击者可以提供一份 Timestamp 元数据(带有更高的时间戳版本号),该元数据签署的是快照版本 4。Tough 会接受该时间戳文件(将其缓存),然后发现快照 4 < 5 并在更新过程中报错退出 – 但现在其缓存显示“最新时间戳指示快照 4”。当接下来出现正确的时间戳(快照 5 或 6)时,Tough 会将快照 5 与缓存的快照 4 视为又一次回滚(因为它错误地将缓存中的快照版本 4 作为基线),从而连有效更新也拒绝。AWS 公告描述了这一循环:“客户端会缓存时间戳元数据,尽管在检测到回滚时该元数据已被正确拒绝……导致 tough 随后无法消费有效更新。”

修复后的实现: 此修复确保在缓存新时间戳之前执行回滚检查,并添加了对时间戳内容的更严格验证。在 Tough 0.20.0 中,修改了 load_timestamp() 函数,强制要求在完成更新前验证 Timestamp 元数据格式正确且其快照版本不低于之前受信任的快照版本。具体来说,代码现在检查:(a) 时间戳元数据只有一个条目(必须仅针对 snapshot.json),(b) 该条目存在且可解析,以及 (c) 内部的快照版本 >= 旧的快照版本。(参见 此处)只有通过这些验证后,新时间戳才被视为受信任。关键的新增逻辑如下所示:```rust // Ensure the timestamp meta contains exactly one entry (the snapshot) ensure!(timestamp.signed.meta.len() == 1, error::TimestampMetaLengthSnafu { … }); let snapshot_meta = timestamp.signed.meta.get("snapshot.json"); ensure!(snapshot_meta.is_some(), error::MissingSnapshotMetaSnafu { … });

// If we have a previously trusted timestamp (old_timestamp): if let Some(old_timestamp) = old_timestamp_opt { // Check that the snapshot version in the new timestamp >= old snapshot version let old_snapshot_meta = old_timestamp.signed.meta.get("snapshot.json").unwrap(); ensure!( old_snapshot_meta.version <= snapshot_meta.unwrap().version, error::OlderSnapshotInTimestampSnafu { // details: new snapshot vs old snapshot versions snapshot_new: snapshot_meta.unwrap().version, snapshot_old: old_snapshot_meta.version, timestamp_new: timestamp.signed.version, timestamp_old: old_timestamp.signed.version } ); }

root@kitploit:~
通过此更改,如果新时间戳的快照版本低于之前见过的快照版本,`ensure!` 将在新时间戳被保存为受信任<b>之前</b>失败。将引发错误 `OlderSnapshotInTimestamp` 以中止更新。因此,当检测到回滚时,Tough 会将旧的(正确的)时间戳保留在缓存中,而错误的时间戳永远不会被缓存为受信任。这防止了被拒绝的时间戳更新污染未来更新的情况。

- <b>根本原因:</b> <b>不当的更新顺序</b>(CWE-367:检查时间与使用时间竞争条件,在元数据验证的上下文中)。Tough 对时间戳中快照回滚的检查发生在错误的时间点——即在副作用(缓存)已经发生之后。此外,未完全验证时间戳内容(长度)使逻辑变得脆弱​
- <b>影响:</b> 恶意时间戳(具有较低的快照版本)可能暂时欺骗客户端,导致其存储错误状态。这会导致更新机制中的拒绝服务:客户端此后会将真实更新视为无效(错误的回滚检测)。不会直接执行代码或窃取数据,但<b>持续更新</b>失败可能同样危险(例如,阻止安全补丁应用)。(参见[此处](https://github.com/advisories/GHSA-76g3-38jv-wxh4#:~:text=If%20the%20tough%20client%20successfully,client%20from%20consuming%20valid%20updates))
- <b>修复方案:</b> 升级到 tough <b>0.20.0+</b>。已修补的版本可以安全地处理时间戳回滚事件。如果观察到因该错误导致的更新失败,则可能需要在用修复后的客户端重试更新之前<b>清除缓存的元数据</b>(以移除任何被污染的时间戳)。作为一般实践,客户端应始终在信任或缓存元数据之前对其进行验证——此问题恰恰凸显了这一原则。

参考文献:
- [AWS 安全公告 AWS-2025-007](https://aws.amazon.com/security/security-bulletins/AWS-2025-007/) – <i>tough 的问题,0.20.0 之前的版本(多个 CVE)​</i>
- [GitHub 公告数据库中关于 CVE-2025-2885 的条目](https://github.com/advisories/GHSA-5vmp-m5v2-hx47)
- [GitHub 公告数据库中关于 CVE-2025-2886 的条目](https://github.com/advisories/GHSA-v4wr-j3w6-mxqc)
- [GitHub 公告数据库中关于 CVE-2025-2887 的条目](https://github.com/advisories/GHSA-q6r9-r9pw-4cf7)
- [GitHub 公告数据库中关于 CVE-2025-2888 的条目](https://github.com/advisories/GHSA-76g3-38jv-wxh4)
- Tough v0.20.0 补丁提交:
    - 根版本修复提交 | [`awslabs/tough@​0eeb60a`](https://github.com/awslabs/tough/commit/0eeb60aefe27f00b65730634b788a1aafb8bf3c6)
    - 终止委派修复提交 | [`awslabs/tough@598111f`](https://github.com/awslabs/tough/commit/598111f88105a707ee68b0fa06c52da7176ea96a)
    - 快照回滚修复提交 | [`awslabs/tough@3345151`](https://github.com/awslabs/tough/commit/3345151a87c358d1ce43aeb7e8b3ebea5ebdbab4)
    - 时间戳回滚修复提交 | [`awslabs/tough@9b400e1`](https://github.com/awslabs/tough/commit/9b400e1c8b7d6b9ab8009104fa7fe5884db05f18)
下载工具