在过去一周(2026/08/10 - 2026/08/16)中,共有5起值得关注的安全事件,总损失约为4700万美元。
| 日期 | 事件 | 类型 | 预估损失 |
|---|---|---|---|
| 2026/08/10 | Coinsbuy | 私钥泄露 | ~$7.9M |
| 2026/08/10 | 未知巨鲸钱包 | 私钥泄露 | ~$25M |
| 2026/08/12 | Harmony | 验证问题 | 未知* |
| 2026/08/13 | Kite | 私钥泄露 | ~$14M |
| 2026/08/15 | Fox | 业务逻辑缺陷 | ~$117K |
*Harmony报告称,其确认的首波铸币事件涉及40亿枚 ONE,而更广泛的重建分析显示,约有3.01万亿枚 ONE 被伪造,其中约2.385万亿枚 ONE 被转移 [1]。按事件发生前的价格(约0.001183美元)计算,被伪造的数量名义价值约为35.6亿美元,但这一数字约为 ONE 总供应量的200倍,远超该代币的市值,因此既不可实现,也未被确认为已实现损失。此后,Harmony已将链回滚至攻击前的检查点,丢弃了伪造的状态 [2]。因此,Harmony事件被排除在总损失统计之外。
入选理由
- Harmony:入选原因是链实现层面的重放保护缺陷导致Harmony生态系统中出现了大规模的未授权原生代币发行。在调查过程中还发现了一个单独的预质押(pre-staking)法定人数验证薄弱点,但其在此次攻击中所起的作用尚未得到确认。
Best Security Auditor for Web3
Validate design, code, and business logic before launch
每周焦点:Harmony
本周之所以聚焦Harmony,是因为该漏洞存在于链实现本身,而非应用合约层面,这是一种影响异常巨大的失效模式,因为它能够导致整个第一层区块链的基础资产被无限膨胀。
2026年8月12日,分片式第一层区块链Harmony因跨分片收据重放缺陷,遭受了其原生代币 ONE 的未授权铸造攻击。目标分片在识别某一收据是否已被消费时,所使用的字段并未被源委员会的签名所覆盖,因此攻击者可以仅通过篡改这些字段,重新提交一份真实的、此前已被记入贷方的收据,使其再次被记入贷方,而源分片却没有相应的借方扣款记录。Harmony正在核对确认的首波40亿枚 ONE 铸币事件,与更大范围重建分析所得出的约3.01万亿枚 ONE 被伪造、约2.385万亿枚 ONE 被某个伪造铸币钱包转移的数据之间的关系;这些数字均未被确认为已实现损失,最终影响仍取决于回滚和交易所对账的结果 [1][2]。在调查过程中,Harmony还发现了一个单独的预质押法定人数验证缺陷,但尚未确认此次攻击是否依赖该缺陷。
背景
Harmony是一个分片式第一层区块链。每个分片都维护自己独立的状态,因此源分片无法直接修改目标分片上的账户。为了在分片之间转移价值,Harmony采用了一种异步的、基于收据的设计:源分片扣除发送方的余额并生成一份跨分片收据,随后目标分片再将其记入接收方的账户。
跨分片收据记录了转账本身的信息:
type CXReceipt struct {
TxHash common.Hash
From common.Address
To *common.Address
ShardID uint32
ToShardID uint32
Amount *big.Int
}
目标分片并不会信任一份裸收据。该收据被包裹在 CXReceiptsProof 中传输,其中携带了Merkle证明、源区块头以及源委员会针对该区块头的提交签名:
type CXMerkleProof struct {
BlockNum *big.Int
BlockHash common.Hash
ShardID uint32
CXReceiptHash common.Hash
ShardIDs []uint32
CXShardHashes []common.Hash
}
type CXReceiptsProof struct {
Receipts CXReceipts
MerkleProof *CXMerkleProof
Header *block.Header
CommitSig []byte
CommitBitmap []byte
}
正常的验证路径会根据已签名的源区块头及其委员会签名对证明进行校验:
VerifyIncomingReceipts()
-> IsSpent()
-> ValidateCXReceiptsProof()
-> VerifyHeaderSignature()
-> verifySignature()
-> DecodeSigBitmap()
-> IsQuorumAchievedByMask()
-> aggSig.VerifyHash()
由于源分片只会执行一次借方扣款,目标分片必须确保每份跨分片收据只被消费一次。
漏洞分析
跨分片结算路径存在两个问题:一个是识别已消费收据方式中的重放保护薄弱点,另一个是预质押法定人数验证薄弱点。
跨分片收据重放
重放保护机制会记录并查找某份收据的“已消费”标记,但其所用的键值来源于Merkle证明中的两个可变字段:
CXMerkleProof.ShardID
CXMerkleProof.BlockNum
Bloom硬分叉在第2964纪元(2026年7月13日)加强了主网上的这一机制,该机制由 IsCXMerkleProofReplayFixEpoch 进行门控 [3]:对于其已签名的 Header.Epoch() 处于该纪元或之后的证明,IsSpent() 和 WriteCXReceiptsProofSpent() 会改为从已签名的源区块头(Header.ShardID 和 Header.Number)中派生已消费标记的键值,而不再使用前述两个字段。然而,这种更强的键值方式并未被追溯应用——对于其 Header.Epoch() 早于该硬分叉的证明,这两个函数仍保留了旧版的回退逻辑,继续使用 MerkleProof.ShardID 和 MerkleProof.BlockNum,而 ValidateCXReceiptsProof() 对于这些纪元,从未将这两个字段与已签名的区块头绑定起来。
这两个字段处于提交签名的覆盖范围之外,该签名仅覆盖源 Header。若篡改 Header,将无法通过 VerifyHeaderSignature() 的验证;但篡改 MerkleProof.ShardID 或 MerkleProof.BlockNum 则完全不会触发任何检查——既不会触发区块头签名检查,对于这些纪元而言,也不会触发证明验证检查,因为验证从未将这两个字段与 Header 绑定。由于旧版已消费标记的键值来源于这些未经身份验证的字段,一份收据在重放保护机制中的身份标识,与用于验证证明其余部分真实性的签名脱钩了:两份携带相同已签名区块头和收据、但 MerkleProof.ShardID 或 MerkleProof.BlockNum 值不同的证明,在已消费状态跟踪机制看来会被视为彼此独立的两份不同证明。

预质押法定人数检查
第二个缺陷影响了预质押阶段的法定人数验证机制。uniformVerifier.IsQuorumAchievedByMask() 逻辑将阈值与
len(mask.Publics)
进行比较,将其视为签名者的数量。但 mask.Publics 实际上是某个分片和纪元下委员会公钥的完整列表,而并非真正签名的验证者集合;后者是由签名者位图(signer bitmap)来表示的。因此,即使签名者位图为空,也仍可能满足法定人数阈值,因为该检查衡量的是委员会规模,而非位图中被启用的比特位数量。再结合一个恒等(全零)聚合BLS签名,这一缺陷可能使一个预质押时代的源区块头看起来携带了足够的法定人数验证。

攻击分析
攻击者从一份真实的、已经处理过的跨分片收据入手,该收据来自硬分叉之前的某个源分片区块,随后攻击者通过仅篡改其未经身份验证的证明标识字段来重放该收据。被伪造的 ONE 被铸造进了四个攻击者钱包。以下分析基于交易 0xf3d4e8b1...8242c7f 和 0x9a756ef9...b0a4d678。
-
步骤一:攻击者获取了一份来自硬分叉之前源分片区块的有效历史
CXReceiptsProof。该证明包含有效的收据、有效的源区块头以及有效的源委员会提交签名。 -
步骤二:目标分片已经消费过这份收据一次,并写入了其已消费标记,该标记的键值来源于Merkle证明字段。
-
步骤三:攻击者仅篡改了未经身份验证的证明标识字段,而已签名的区块头以及所有受签名覆盖的字段均保持不变:
MerkleProof.ShardID MerkleProof.BlockNum -
步骤四:被篡改的证明作为一笔传入收据,被提交到目标分片随后的一个区块中。
IsSpent()从被篡改的字段中派生出已消费标记的键值,未能找到此前记录的标记,因此该收据看起来尚未被消费。 -
步骤五:
ValidateCXReceiptsProof()仍然接受了该证明,因为被篡改的标识字段并未处于签名覆盖范围之内,而每一个受身份验证保护的字段均保持不变:区块头哈希和传出收据哈希、Merkle证明区块哈希和收据哈希、收据集合哈希,以及提交签名和位图。 -
步骤六:
ApplyIncomingReceipt()在目标分片上被执行,并通过db.AddBalance(*cx.To, cx.Amount)再次将资金记入接收方账户。由于原始的跨分片交易此前已经执行过一次,源分片上没有发生相应的借方扣款,从而导致目标分片上产生了原生代币ONE的通货膨胀。
结论
该项目所确认的根本原因,是一个协议层面的重放保护失效问题:跨分片收据的已消费状态身份标识,来源于未经身份验证的证明字段,而非已签名的源区块头,因此一份已经处理过的收据能够被再次记入贷方。Harmony还确认了一个单独的预质押法定人数验证缺陷,但公开披露的信息并未确定攻击者在此次事件中是否利用了该缺陷。
相关补丁已修复了这两个漏洞 [4][5][6]。更广泛地说,一个链实现必须对其用于识别已消费状态的每一个字段进行身份验证,并且必须以实际签名的验证者数量作为判断法定人数的依据,而不是以完整委员会成员数作为依据。
参考文献
- [1] Harmony事件更新
- [2] Harmony回滚方案
- [3] Harmony Bloom硬分叉(PR #5053)
- [4] 提交61afbf6:修复CX收据已消费标记键值
- [5] 提交7515262:修复法定人数位图计数逻辑
- [6] Harmony PR #5101
关于BlockSec
BlockSec是一家全栈式区块链安全与加密合规服务提供商。我们构建的产品和服务,帮助客户在协议与平台的完整生命周期内执行代码审计(包括智能合约、区块链及钱包)、实时拦截攻击、分析安全事件、追踪非法资金,并满足反洗钱/反恐怖融资(AML/CFT)合规义务。
BlockSec已在多个知名会议上发表了多篇区块链安全论文,报告了多起DeFi应用的零日攻击,成功拦截多起黑客攻击、挽回超过2000万美元的损失,并为价值数十亿美元的加密资产保驾护航。



