零时科技 || H2O 攻击事件分析

我们监测到一起针对 BNB Smart Chain 链上项目 H2O 攻击事件,此次攻击共造成 22,000 USD 的损失。

登链封面(事件).jpg

<!--StartFragment-->

背景介绍

2025年3月14日,我们监测到一起针对 BNB Smart Chain 链上项目 H2O 攻击事件,攻击hash为:

https\://bscscan.com/tx/0x729c502a7dfd5332a9bdbcacec97137899ecc82c17d0797b9686a7f9f6005cb7

https\://bscscan.com/tx/0x994abe7906a4a955c103071221e5eaa734a30dccdcdaac63496ece2b698a0fc3

被攻击的项目为 H2O ,攻击共造成 22,000 USD 的损失。 

<!--EndFragment-->

<!--StartFragment-->

攻击及事件分析

在第一次攻击中,攻击者首先从 PancakeSwapV3 Pool 中利用 flashloan 贷了 100,000 USDT 作为攻击的初始资金。

<!--EndFragment-->

1.png

<!--StartFragment-->

随后,用贷来的初始资金在 USDT-H2O 的 PancakeSwap Pair 中兑换了 66,439,209 H2O。

<!--EndFragment-->

2.png

<!--StartFragment-->

攻击者随后频繁将 H2O 转给 PancakeSwap Pair USDT-H2O ,然后使得 Pair 中 USDT reserve 和H2O reserve 不平衡,随后利用 skim 平衡 Pair 中的 reserve0 和 reserve1 来实施攻击。H2O 的漏洞出现在 transfer 函数中,我们可以看到 transfer 函数的具体实现。

<!--EndFragment-->

3.png

<!--StartFragment-->

问题具体出现在函数中,当 from 为 PancakeSwap Pair 时,调用 _calulate 函数。由于攻击者利用 Pair 的 Reserve0 和 Reserve1 不平衡,调用 skim 给自身 transfer ,所以该 transfer 的 sender 为 Pair address 。接下来,我们看一下该函数的具体实现。 

<!--EndFragment-->

4.png

<!--StartFragment-->

这个函数的逻辑很简单根据合约自身持有的 H2O 代币余额动态设定奖励费率(1%-5%,余额越少费率越低),通过链上随机数向用户按比例分发 H2 或 O2 代币;当用户持有至少 10 H2 和 5 O2时,可销毁 2:1 比例的代币(模拟化学反应 2H₂+O₂→2H₂O ),兑换合约中的 H2O 代币,实际兑换量受合约余额限制。

合约生成链上随机数的逻辑如下:

<!--EndFragment-->

5.png

<!--StartFragment-->

根据 blocktime , blocknumber 和 msg.sender 的 keccak256 来计算。在第一次攻击中,由于攻击者没有 H2 Token 和 O2 Token ,所以在此次攻击中获得了 169,731,921 O2 Token 。接下来,只要攻击者使得 getRandomOnchain()%2 == 1 即可完成攻击,随后攻击者又进行了三次尝试,但是前两次 getRandomOnchain()%2 均为0,导致攻击失败,第四次才真正完成攻击。 

<!--EndFragment-->

6.png

<!--StartFragment-->

在第四次攻击时,攻击者首先从 PancakeSwapV3 Pool 中利用 flashloan 贷了 100,000 USDT 作为攻击的初始资金,

<!--EndFragment-->

7.png

<!--StartFragment-->

随后,用贷来的初始资金在 USDT-H2O 的 PancakeSwap Pair 中兑换了 66,439,209 H2O。

<!--EndFragment-->

8.png

<!--StartFragment-->

攻击者随后频繁将 H2O 转给 PancakeSwap Pair USDT-H2O ,然后使得 Pair 中 USDT reserve 和 H2O reserve 不平衡,随后利用 skim 平衡 Pair 中的 reserve0 和 reserve1 来实施攻击。 

<!--EndFragment-->

9.png

<!--StartFragment-->

根据我们上述的分析可知,此次攻击中 getRandomOnchain()%2 为1,所以 H2O 会 mint H2Token 。又因为攻击者利用第一次攻击时,getRandomOnchain()%2 为 0,所以获得 mint 的大量 O2 Token 。所以,H2O burn 了 H2 和 O2 后将自身的 H2O 转给攻击者。

最后,攻击者用凭空的来的 H2O 兑换了 122,820 USDT 。归还完 100,000 USDT 的 flashloan 和 50 USDT 的利息,最终获利 22,770 USDT 。

<!--EndFragment-->

<!--StartFragment-->

总结

本次漏洞成因主要是因为 H20 Token 合约设计从 PancakeSwap Pair 上买入的经济模型时,在修改 ERC20 transfer 函数没有考虑到 skim 也可以达到相同目的,导致攻击者利用 skim 凭空获得大量激励。建议项目方在设计经济模型、价格计算机制和代码运行逻辑时要多方验证,合约上线前审计时尽量选择多个审计公司交叉审计。

<!--EndFragment-->

点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
零时科技
零时科技
0xbD0b...A354
专注区块链生态安全