在过去一周(2026/07/27 - 2026/08/02),共有 2 起值得关注的重大安全事件,合计造成约 8800 万美元的损失。
| 日期 | 事件 | 类型 | 预估损失 |
|---|---|---|---|
| 2026/07/29 | LULA | 业务逻辑缺陷 | ~57.8万美元 |
| 2026/07/30 | COLDCARD | 熵生成缺陷 | ~1,370 BTC (~8800万美元)* |
* COLDCARD 的损失因确认方式不同而有所差异:图中所示的约 1,370 BTC(约 8800 万美元)是可公开验证的链上最低数额(coldcardwatch.com);私下渠道的核对数据(Galaxy Research,通过与 73 名受害者的沟通所得)显示损失更高,约为 1,596 BTC,若计入疑似但未确认的资金转出,最高可达约 2,055 BTC(约 1.3 亿美元)。
选择理由
- LULA:一个可以转移 AMM 交易对余额并强制触发储备重新同步的特权代币函数,通过价格操纵演变为可重复利用的流动性抽取手段。
- COLDCARD:钱包固件中的构建与集成错误,悄然将种子生成过程导向了确定性的软件回退方案,破坏了熵的保证,使种子恢复从理论上不可行的问题变成了一个离线搜索问题,进而升级为大规模资金损失。
Best Security Auditor for Web3
Validate design, code, and business logic before launch
本周焦点:COLDCARD
我们选择 COLDCARD 作为本周焦点,因为一个钱包熵值漏洞造成了本期最大规模的损失。其根本原因——一个构建保护机制仅检查配置宏是否存在而非是否被启用——正是功能测试无法察觉的那类隐蔽集成错误,这一教训适用于任何链上安全依赖链下随机性的系统。
COLDCARD 是一款比特币硬件钱包,其 2021 年发布的固件使用确定性软件源而非预期的硬件随机数生成器(RNG)来生成钱包种子 [1][2]。该缺陷直到 2026 年 7 月下旬才被大规模利用,受影响的钱包从 7 月 30 日起在链上被分批清空:公开确认的损失总计至少 1,370 BTC(按 8 月 5 日 64,099 美元的价格计算约为 8800 万美元)[3],而私下确认的报告显示这一数字可能高达约 1,596 BTC [4]。根本原因是一个构建与配置错误,将种子生成导向了软件回退方案,而非预期的硬件 RNG。对于受影响的设备而言,这使得种子恢复从密码学上不可行的问题变成了一个离线搜索问题。
背景
COLDCARD 是一款比特币硬件钱包。钱包的私钥和地址都是从单一的秘密值——其种子——推导出来的,因此任何自托管钱包的安全性都取决于该种子的两个属性:保密性,以及生成时的不可预测性。硬件钱包的存在主要是为了保护第一个属性;而本次事件是第二个属性的失效。BIP-39 种子助记词是人类可读的,但其不可预测性要求背后的安全属性,仍然是用于生成它的随机字节的熵。如果这些字节可以被复现,那么种子也就可以被复现。可以这样理解:一个保险箱的密码是通过掷骰子决定的,如果骰子是被做过手脚的,那么无论锁有多坚固,只要知道其中的偏差规律,保险箱对任何人都是敞开的。
对于钱包而言,"被做过手脚的骰子"意味着一个弱随机数生成器。硬件钱包本应从其安全微控制器上的硬件真随机数生成器(TRNG)中获取种子熵,因为软件伪随机数生成器(PRNG)是确定性的:只要知道其内部状态和调用历史,其输出就可以被精确复现。如果生成器的输出是可预测的,那么其候选范围就可以被枚举,并与地址、xpub 或公钥等公开钱包数据进行比对,这就将种子恢复从密码学上不可行的问题,变成了一个离线搜索问题。
COLDCARD 的固件暴露了两个独立的 RNG 接口。MicroPython 提供了一个 STM32 平台层,暴露了钱包加密库所期望的全局 rng_get() 符号,而 COLDCARD 同时也维护着自己的板级硬件 RNG 封装。这两个接口都旨在提供硬件熵,钱包的加密库通过固件构建时解析的单一全局 RNG 符号来访问其中之一。
漏洞分析
根本原因在于围绕 MICROPY_HW_ENABLE_RNG 配置宏的一个构建与集成错误。COLDCARD 的生产板级配置将该宏设置为 0,因为固件原本打算使用自己的板级硬件 RNG 封装,而非 MicroPython 的硬件 RNG 实现。然而,钱包生成路径已被迁移至使用 ngu.random.bytes(32),而加密库的 STM32 路径最终依赖于由 MicroPython 解析的全局 rng_get() 符号。
问题链条如下:
generate_seed()
-> ngu.random.bytes(32)
-> libngu CHIP_TRNG_32()
-> rng_get()
-> MicroPython STM32 RNG module
-> Yasmarang software fallback because MICROPY_HW_ENABLE_RNG == 0
板级配置禁用了 MicroPython 的硬件 RNG 分支:
// We have our own version of this code.
#define MICROPY_HW_ENABLE_RNG (0)
加密库仍然将该宏视为硬件 RNG 存在的充分证明 [5],因为它在调用 rng_get() 之前仅检查该宏是否存在:
extern uint32_t rng_get(void);
#define CHIP_TRNG_32() rng_get()
#ifndef MICROPY_HW_ENABLE_RNG
#error "get a HW TRNG plz"
#endif
这个防护检查遗漏了危险的情形:一个被定义为 0 的宏仍然是"已定义"的,因此 #ifndef 检查会通过,构建也会成功。由于 MicroPython 是根据该宏的值而非其是否存在来选择 RNG 实现的,MICROPY_HW_ENABLE_RNG == 0 使得 rng_get() 被导向了软件回退分支,而非 COLDCARD 的板级封装 [6]:
#if MICROPY_HW_ENABLE_RNG
// STM32 hardware RNG
#else
// Yasmarang software fallback
#endif
后果因设备代际而异。对于 Mk2/Mk3 固件 v4.0.0-v4.1.9,Block 的分析 [7] 指出,没有任何密码学熵被加入到 ngu.random 中,因此一旦回退状态和调用历史已知,钱包生成就可能变为确定性的(Coinkite 的公告 [2] 将 Mk2/Mk3 的受影响范围界定得略窄一些,为 v4.0.1-v4.1.9)。对于 Mk4/Q/Mk5,安全元件材料虽经过哈希处理,但只有四个字节被传入 ngu.random.reseed(),这使得安全重新播种被限制在一个单一的 32 位状态字内,其可搜索空间远小于用户预期的钱包熵。对最终的 32 个随机字节进行哈希处理并不能增加结果的熵;它只是对一个本已有限的候选集合进行了变换。
攻击分析
与智能合约漏洞利用不同,此次事件并没有单一的链上攻击交易可供追溯。这是一次离线种子恢复问题,随后引发了链上资金清空。前提条件是受影响用户通过存在漏洞的 ngu.random.bytes(32) 路径生成了其钱包种子,因此其种子材料依赖于一个可复现的软件回退状态,而非完整的硬件熵。第二个(推断出的)前提条件是,受影响的钱包可以仅凭种子推导得出:一个强壮且唯一的 BIP-39 密语(passphrase)会通过 PBKDF2 混入独立的、用户提供的熵,而这部分并未受到 RNG 漏洞的影响,这使得设置了此类密语的钱包不在纯种子枚举的范围之内;而此次清空事件的规模表明,大多数受影响用户并未设置此类密语。据此,恢复过程很可能分为三个步骤:
- 攻击者利用设备元数据、启动时序、RTC/SysTick 假设以及可能的 RNG 调用历史,对候选 RNG 状态进行约束或枚举。
- 对于每一个候选状态,攻击者推导出候选钱包种子,并在离线状态下将其与地址、xpub 或生成的公钥等公开钱包数据进行比对。
- 一旦某个候选项与真实钱包匹配,攻击者便恢复出种子,重建私钥,并将相关的 BTC 转出清空。
在链上,此次盗窃表现为从 7 月 30 日开始的一波地址清空。独立的链上启发式追踪 [3] 识别出多波资金转移,从 4,580 个已验证地址中共转出至少 1,370 BTC(按 8 月 5 日 64,099 美元的 BTC 价格计算约为 8800 万美元),这是一个经过验证的最低数额,而非总数。与此同时,一个私下渠道 [4](通过与 73 名受害者的沟通得到确认)显示,该数字可能高达约 1,596 BTC,若计入疑似但未确认的资金转出,则可能进一步升至 2,055 BTC(约 1.3 亿美元)。
结论
COLDCARD 事件是一次熵生成失效事件:由于一个构建保护机制仅检查配置宏是否存在而非是否被启用,安全关键的种子生成 API 悄然被解析到了一个确定性的软件 PRNG 回退方案,而非预期的硬件 RNG。对于受影响的设备而言,这使得种子恢复从密码学上不可行的问题变成了一个离线搜索问题,最终导致超过 1,370 BTC [3] 在多波清空中被转出(私下渠道的统计数字则显示约为 1,596 至 2,055 BTC [4])。
其核心的工程失误在于,发布的固件从未验证其最关键的安全 API 是否真正连接到了预期的硬件 RNG。以下三项做法本可以发现该问题:针对密码学熵的构建保护机制必须同时检查宏是否存在以及宏的取值;熵回退机制必须采用失败即关闭(fail closed)的方式,而不是悄然替换为软件 PRNG;对最终固件镜像的验证应涵盖符号来源和端到端的熵流,而不仅仅是代码能否编译通过。受影响的种子无法就地修复;其资金应转移至基于已修复固件创建的新钱包,而设置一个强壮且唯一的密语可以在不修复种子本身的情况下降低即时风险 [2]。
这种失效模式值得特别强调:此类随机性漏洞对功能测试而言是不可见的,因为每一个生成的种子单独来看都是有效的。缺陷并不在于任何单一的输出,而在于产生这些输出的源头:由于该源头是可预测且可复现的,这些种子整体上便落入了一个狭小的、可枚举的范围之内。链下密钥生成组件理应受到一流的安全审查。
参考资料
- [1] BlockSec Phalcon 发布的警报,将 COLDCARD 钱包资金清空事件与种子生成随机性薄弱问题联系起来
- [2] Coinkite,关于熵问题的技术深度剖析
- [3] coldcardwatch.com,Coldcard 资金清空追踪:链上被清空地址的追踪与方法论
- [4] Galaxy Research,COLDCARD 黑客事件损失估算(通过受害者报告确认约 1,596 BTC)
- [5] libngu,STM32 RNG 路径引用了全局的
rng_get(),且仅通过#ifndef MICROPY_HW_ENABLE_RNG进行保护 - [6] Coldcard MicroPython,当硬件 RNG 被禁用时,
rng_get()会回退至 Yasmarang - [7] Block Engineering,COLDCARD 固件中可预测的 RNG 回退与 32 位重新播种问题
本周更多事件
LULA
LULA 是 BNB Chain 上的一种 BEP-20 代币,于 2026 年 7 月 29 日因其代币合约中的一个业务逻辑缺陷损失约 57.8 万美元。一条攻击者可触及的路径能够触发其特权函数 recycle(),使 Rental 合约可以直接从 PancakeSwap V2 交易对中转出 LULA,随后调用 sync(),将交易对的储备更新为被操纵后的余额。攻击者反复触发 recycle(),将交易对中的 LULA 储备压缩至接近于零,然后用少量 LULA 换回了该交易对中几乎全部的 USDT [1]。
背景
LULA 是 BNB Chain 上的一种 BEP-20 代币,采用基于租赁的团队奖励机制。符合条件的地址会在 Rental 合约中累积待发放的团队奖励,并通过 claimTeamReward() 进行领取。在领取流程中,Rental 合约会调用代币的 recycle() 函数,以获取用于奖励发放的 LULA。recycle() 并非任意用户可调用;只有 Rental 合约被授权执行该函数。
claimTeamReward() 入口函数包含一个"仅限 EOA"的检查。它支持来自外部账户(msg.sender == tx.origin)的直接调用,同时也通过检查委托代码前缀来支持 EIP-7702 委托调用。

在自动做市商(AMM)中,一个交易对根据其存储的储备来为交易定价,而这些储备通过交易对的 sync() 函数进行更新,该函数会将储备设置为交易对当前的代币余额。储备通常反映真实的交易活动,因为它们会随着交易和流动性事件而变动,但交易对的代币余额也可以通过直接转账来改变,而 sync() 会将当时交易对中存在的任何余额——无论是否被操纵——直接复制到存储的储备中。
漏洞分析
根本原因在于 LULA.recycle() 允许 Rental 合约直接将 LULA 从 PancakeSwap V2 交易对中转出,随后调用 sync(),将交易对的储备更新为被操纵后的余额 [1]。

由于 sync() 会将储备设置为交易对中剩余的任何 LULA 余额,这条特权路径可以在不影响 USDT 一侧的情况下,将交易对的 LULA 储备任意压低。一旦 LULA 储备接近于零,交易对就会将少量的 LULA 定价为几乎值该交易对全部的 USDT。
攻击分析
以下分析基于交易 0xa219ab9...411d7c。
- 第一步:攻击者通过积累约 1.9705 亿 USDT 为此次操纵提供资金。这些资金来自多个闪电贷及借贷来源,包括 Moolah/Lista、Aave V3、Venus、PancakeSwap V3、PancakeSwap Vault、Uniswap V4 PoolManager 以及 Uniswap V3。
- 第二步:攻击者使用这约 1.9705 亿 USDT,通过 PancakeSwap V2 路由器执行了一笔大额的
USDT -> LULA交换。这将交易对的 LULA 储备从约 800 万 LULA 大幅降低至 24,022 LULA,同时将 USDT 一侧的数额提高到约 1.9764 亿 USDT。 - 第三步:攻击者通过多个 EIP-7702 钱包调用了奖励领取路径。每个钱包都在 Rental 合约上调用
claimTeamReward(),进而触发LULA.recycle(),将交易对的 LULA 储备从 24,022 LULA 压缩至 0.004 LULA,而此时该交易对仍持有极大量的 USDT。 - 第四步:攻击者通过路由器执行了最后一笔 PancakeSwap V2 交易,仅向交易对中投入约 4,749 LULA,换出约 1.9764 亿 USDT。
- 第五步:攻击者偿还了所有闪电贷,最终获利约 57.8 万美元。
结论
BNB Chain 上的 LULA 代币因其代币合约中的一个业务逻辑缺陷而遭受约 57.8 万美元的损失:一条攻击者可触及的路径能够触发其特权函数 recycle(),使 Rental 合约可以直接从 PancakeSwap V2 交易对中转出 LULA,随后调用 sync(),将交易对的储备重新同步为被操纵后的余额。攻击者反复触发这一过程以扭曲交易对的价格,并用少量 LULA 换回该交易对中几乎全部的 USDT。
代币合约绝不应暴露一条能够转移 AMM 交易对余额并强制触发储备重新同步的特权路径,因为这样做等于将价格控制权交给了任何能够触及该路径的人。与 AMM 交易对集成的代币,必须确保交易对储备的变动始终与真实的、由市场驱动的余额变化相绑定,而任何读取资金池储备用于定价的逻辑,都应将其视为可被操纵的数据,而非权威数据。
参考资料
关于 BlockSec
BlockSec 是一家提供全栈区块链安全与加密合规服务的供应商。我们打造的产品与服务,可帮助客户执行代码审计(涵盖智能合约、区块链及钱包)、实时拦截攻击、分析安全事件、追踪非法资金,并满足反洗钱/反恐怖融资(AML/CFT)合规要求,覆盖协议与平台的完整生命周期。
BlockSec 已在多个知名会议上发表了多篇区块链安全论文,报告了多起 DeFi 应用的零日攻击,成功拦截多起黑客攻击并挽回超过 2000 万美元的资金损失,累计守护了数十亿美元的加密资产安全。
-
官方 Twitter 账号:https://twitter.com/BlockSecTeam



