客服QQ:872490018

BCH 升级攻击事件安全分析

5 月 15 日 BCH 升级遭到攻击,慢雾安全团队及时跟进,并在社区里注意到相关分析工作,通过交流将此分析文完整转载于此。这是一场真实攻击,从行为上分析来看确实预谋已久,但 BCH 响应很及时,成功化解了一场安全危机。

BCH 升级攻击事件安全分析-碳链


BCH 的 5 月 15日 升级遭到攻击,导致节点报出 too many sigops 错误。经分析,攻击载荷为一个精确构造的 P2SH Transaction,利用了 BCH 去年 11 月升级引入的 OP_CHECKDATASIG 操作码。

攻击导致了矿工节点无法打包,BCH 方面通过类似于空块攻击的方式,紧急挖出十个空块以触发滚动检查点保证升级。攻击发生约 1 小时后,BCH 矿池上线紧急修复后的代码成功继续出块。

不过同时也有人观察到,在 582698 区块高度,有矿工挖出了哈希结尾为 6bf418af 的区块,大小 139369 字节。但随后该区块被 10 分钟后 BTC.top 挖出的哈希结尾为 449e2bb4 区块所重组。或许是一次误伤,不过可见 BCH 对于升级防守之严密。

攻击原理分析

攻击载荷


捕捉到的攻击载荷 TXID 为

4c83ab55623633c86ec711b3d68ccdea506b228178ff1533f287ab744b006c44

其内容点击阅读原文查看。

该攻击载荷由 1334 个 Input 构成,每一个 Input 均是 P2SH 格式。

其内容为

OP_FALSE OP_IF OP_CHECKDATASIG OP_CHECKDATASIG OP_CHECKDATASIG OP_CHECKDATASIG OP_CHECKDATASIG OP_CHECKDATASIG OP_CHECKDATASIG OP_CHECKDATASIG OP_CHECKDATASIG OP_CHECKDATASIG OP_CHECKDATASIG OP_CHECKDATASIG OP_CHECKDATASIG OP_CHECKDATASIG OP_14 OP_CHECKDATASIG OP_ENDIF OP_TRUE

可见其中包含 15 个 OP_CHECKDATASIG

该攻击载荷利用了一个 CORE 曾经帮 ABC 修复,但未完全修复的漏洞,制造了组块和验证之间的差异,从而导致矿工组出的区块不被节点接受。

漏洞背景

OP_CHECKDATASIG 是一种椭圆曲线签名校验指令(SigOP),这类指令由于需要进行椭圆曲线运算,执行开销远高于其他指令。因此在节点代码中,对于这类指令的数量做出了限制,以避免拒绝服务攻击。

相关代码位置:

https://github.com/Bitcoin-ABC/bitcoin-abc/blob/f27da0752c0a3b7382df54a65ca3cf1c3629aad4/src/consensus/consensus.h#L27

static const uint64_t MAX_TX_SIGOPS_COUNT = 20000;

即,单个 Transaction 中 SigOP 的数量不能超过 20000。

漏洞原理

细心的话,你已经发现了,攻击载荷的 SigOP 数量为 1334 * 15 = 20010,这个攻击载荷 TX 会被节点拒绝,报错即是 too many sigops,这是导致节点拒绝包含该 TX 的区块的原因。

相关代码位置:

https://github.com/Bitcoin-ABC/bitcoin-abc/blob/f27da0752c0a3b7382df54a65ca3cf1c3629aad4/src/validation.cpp#L1936

if (nSigOpsCount > nMaxSigOpsCount) {    return state.DoS(100, error("ConnectBlock(): too many sigops"),                     REJECT_INVALID, "bad-blk-sigops");}

然而在组块时为什么没有拒绝这个 TX 呢?我们可以在 Bitcoin-ABC 的补丁中发现端倪。

补丁位置:https://reviews.bitcoinabc.org/D3053

相关代码位置:

https://github.com/Bitcoin-ABC/bitcoin-abc/blob/f27da0752c0a3b7382df54a65ca3cf1c3629aad4/src/validation.cpp#L592

// 原代码int64_t nSigOpsCount = GetTransactionSigOpCount(tx, view, STANDARD_SCRIPT_VERIFY_FLAGS);
// 补丁代码int64_t nSigOpsCount = GetTransactionSigOpCount(tx, view, STANDARD_CHECKDATASIG_VERIFY_FLAGS);

所在的函数为:AcceptToMemoryPoolWorker

可见原代码组块过程中在计算 Transaction 中的 SigOP 数量时,错误地使用了 STANDARD_SCRIPT_VERIFY_FLAGS,而非 STANDARD_CHECKDATASIG_VERIFY_FLAGS。

这两个标志有什么区别呢?

在 policy 中我们可以找到他们。

相关代码位置:

https://github.com/Bitcoin-ABC/bitcoin-abc/blob/f27da0752c0a3b7382df54a65ca3cf1c3629aad4/src/policy/policy.h#L108

static const uint32_t STANDARD_CHECKDATASIG_VERIFY_FLAGS =    STANDARD_SCRIPT_VERIFY_FLAGS | SCRIPT_ENABLE_CHECKDATASIG;

所以我们可以见到,当仅使用了 STANDARD_SCRIPT_VERIFY_FLAGS 时,计算脚本中 SigOP 数量时,是不包含 OP_CHECKDATASIG 的。所以这个包含 20010 个 SigOP 的攻击载荷,在组块时,统计出来的 SigOP 数量为零。

因此,攻击载荷会在矿工组块的时候被包含进区块中,然而,由于其他代码正确地统计了 SigOP,节点会拒绝该区块,这导致了 BCH 无法出块。

总结

攻击者利用了 BCH 引入 OP_CHECKDATASIG 时产生的,又未完全修复的漏洞,巧妙地构造了攻击载荷。攻击者应该高度了解客户端代码,并熟悉 OP_CHECKDATASIG 漏洞。



BCH 升级攻击事件安全分析-碳链

慢雾导航


慢雾科技官网

https://www.slowmist.com/


慢雾区官网

https://slowmist.io/


慢雾 GitHub

https://github.com/slowmist


Telegram

https://t.me/slowmistteam


Twitter

https://twitter.com/@slowmist_team


Medium

https://medium.com/@slowmist


币乎

https://bihu.com/people/586104


知识星球

https://t.zsxq.com/Q3zNvvF

*文章为作者独立观点,不代表碳链立场
本文由 慢雾科技 授权 碳链 发表,并经碳链编辑。转载此文章须经作者同意,并请附上出处(碳链)及本页链接。原文链接http://www.itanlian.com/chainnews/3626.html
发表评论
坐等沙发
相关文章
烦立停:过度营销的孙宇晨输给了一个结石
烦立停:过度营销的孙宇晨输给了一个结石
除了USDT,还能用什么,传说中的“USDT暴雷”是否成真?
除了USDT,还能用什么,传说中的“USDT暴…
牛津级Token经济体系:落地应用进行时
牛津级Token经济体系:落地应用进行时
区块链安全入门笔记(六) | 慢雾科普
区块链安全入门笔记(六) | 慢雾科普
公开透明,慢雾智能合约安全审计证书开放查询
公开透明,慢雾智能合约安全审计证书开…
CFTC迎来新主席,他如何看待数字货币?
CFTC迎来新主席,他如何看待数字货币?
慢雾科技
SlowMist-Team 作者
我还没有学会写个人说明!
  • 文章

    79

  • 评论

    0

广告赞助

复制代码