据慢雾MistEye系统安全预警,2023年10月7日,Avalanche链上社交协议StarsArena遭攻击,损失约290万美元。慢雾安全团队简析该攻击事件并将结果分享如下。慢雾StarsArena被黑相关信息攻击者地址:https://snowtrace.io/address/0xa2ebf3fcd757e9be1e58b643b6b5077d11b4ad7a攻击合约:https://snowtrace.io/address/0x7f283edc5ec7163de234e6a97fdfb16ff2d2c7achttps://snowtrace.io/address/dd9afc0e3c43951659c8ebe7aef9ee40879863ea攻击交易:https://snowtrace.io/tx/0x4f37ffecdad598f53b8d5a2d9df98e3c00fbda4328585eb9947a412b5fe17ac5攻击核心攻击者利用重入漏洞,篡改自己存款份额所对应的价格。随后在卖出时,又因该恶意操纵的价格计算依赖,导致类似的价格操控。通过精确计算重入时更新的份额价格,攻击者窃取了合约中的资金。
交易分析我们可以发现攻击交易中存在一笔重入调用,我们通过反编译代码逐步分析调用方式。攻击者先创建攻击合约(0x7f283和0xdd9af),通过攻击合约调用StarsArena:Shares合约的0xe9ccf3a3方法,然后存入1枚AVAX代币。根据反编译后的代码一步步跟踪,攻击者首先用的0xe9ccf3a3方法是一个类似于存款的函数,其中会调用0x326c和0x2058方法。0x326c方法仅作为参数返回的调用,而0x2058方法类似于一个处理某种代币购买或交换的函数,该方法通过0xe9ccf3a3所传入的AVAX代币数额及地址来进行下一步操作及份额和费用的计算。跟进0x2058方法第92行的调用逻辑,可以发现0x1a9b方法为一个计算函数,计算出的结果是一个类似于价格的值,其返回值为新计算出的v24/0xde0b6b3a7640000或者是_initialPrice。
之后的109行,110行及116行的0x307c和0x30ef方法中就存在low-levelcall的调用,而0x30ef的call还是对varg1也就是传入的0xdd9af攻击合约地址的外部调用。函数没有防重入锁的约束,并且在执行完外部调用后,此方法才会向下执行之后的if判断来更新field0.length及field0参数。毫无疑问,重入就是在此处发生的。我们再来看攻击者在重入调用中构造的数据。重入外部调用的是0x5632b2e4方法,并传入攻击者所构造的的4个参数,这些参数通过进制转化153005ce00为91000000000。
正如上面讲到的,对0x5632b2e4方法的外部调用是执行在if(varg0==_getMyShares[address(varg1)][msg.sender])判断之前。这时field0.lengt值为0,并未更新。攻击者正好通过这个方式绕过0x5632b2e4方法中的判断,将msg.sender也就是攻击合约0xdd9af的以下4个参数状态都修改为了外部调用是时构造的数据。通过以上操作之后,攻击者调用了sellShares来卖出自己的份额,获得了266,102.97278枚AVAX。深入sellShares函数,函数起先就调用了0x1a9b方法,而在之前的0x2058方法中就曾存在调用,是处理某种代币购买或交换的函数。
我们可以发现,在0x1a9b方法中的0x2329方法会更新owner_9f[varg0],而这个参数在重入时就已经被修改为攻击者所构造的91000000000。回到0x1a9b方法中,根据之前恶意构造的值重新计算(计算数额见注释)。经过以上计算,新计算出的份额所对应的价格发生了改变,计算出的结果为274,333.061476814e18。再经过一系列的费用收取过后,攻击者在没有修改份额的情况下使用恶意构造操纵的价格,卖出份额,成功获利。慢雾StarsArena被黑总结本次攻击的核心在于重入攻击所造成的价格计算依赖更新,进而导致了类似恶意价格操控。慢雾安全团队建议项目方应尽可能在经过多家安全公司审计后,再进行合约的部署发布;同时在编码时应尽可能满足Checks-Effects-Interactions编码规范,添加防重入锁。