背景
根据Numen链上监控显示,Mar-15-2023 03:16:02 AM +UTC,Ethereum、Binance、Polygon链上Poolz遭到攻击,共损失2,805,805枚MEE,525,134枚ESNC,774,997枚DON,2,007,504,238枚ASW,6,510,689枚KMON,2,521,065枚POOLZ,35,976,107枚DCD,760,845枚PORTX,252,153,413枚ECIO,35,975,489枚WOD,29,032,394枚SIP,61,856,885枚MNZ,465,116枚EBA,157,696枚GEMG,202,442枚WANA,223,500枚KXA,82,067枚MSTR,1,717,102枚CHRP,822,631枚CVZ,37,053枚CHIM,8,577,867枚QZA,总价值约665000美元。攻击者已将部分Token兑换为BNB,目前资金暂未转出。
攻击者地址:0x190Cd736F5825ff0Ae0141B5C9cb7Fcd042cef2a
攻击者合约:0x058bae36467a9fc5e1045dbdffc2fd65b91c2203
其中一笔攻击交易:
0x39718b03ae346dfe0210b1057cf9f0c378d9ab943512264f06249ae14030c5d5
攻击流程
1. 攻击者先通过pancakeswap兑换了一下mnz代币。
2. 攻击者调用CreateMassPools,主要问题就存在于这个函数。
正常功能是用户可以批量创建池子,然后提供初始流动性。再通过CreatePool把池子创建出来,并用一个mapping记录池子属性,如下图所示。
问题出在getArraySum函数。TransferInToken给池子建立流动性,amount通过getArraySum控制。
通过传入的_StartAmount数组遍历,然后进行累加。然后通过调用栈看到[115792089237316195423570985008687907853269984665640502182660492372007802789937,61856797091635905326850000]。数组累加超过uint256,即返回1。但是CreatePool中做的记录是通过_StartAmount来实现的。所以攻击者转入了1个token,但_StartAmount是个大数。
3.黑客调用withdraw提币,完成攻击。
总结
此次事件,攻击者获利的根本原因是算数溢出。为了防止此类问题,Numen建议使用 Solidity 的高版本进行编译,以便在编译过程中自动进行溢出检查。另外,您也可以在低版本 Solidity 中使用 OpenZeppelin 的 SafeMath 库来解决整数溢出问题。