Jarvis Network闪贷及重入攻击分析

UTC时间2023年1月15日下午05:43:37,根据Numen的链上监测,Jarvis_Network项目遭到攻击,损失663101个MATIC。

image.png UTC时间2023年1月15日下午05:43:37,根据Numen的链上监测,Jarvis_Network项目遭到攻击,损失663101个MATIC。具体交易可查看https://polygonscan.com/tx/0x0053490215baf541362fc78be0de98e3147f40223238d5b12512b3e26c0a2c2f

image.png

通过对调用栈的分析,该笔交易涉及到多次token转账,导致调用栈较长。我们的分析表明调用过程中存在可重入逻辑。重入过程显示,同一个合约的同一个函数调用,传入参数相同,但重入前后返回值差异很大。

image.png

image.png

重入发生在https://polygonscan.com/address/0xfb6fe7802ba9290ef8b00ca16af4bc26eb663a28 合约的 remove_liquidity 函数中。remove_liquidity 函数在移除流动性时将代币返回给用户。由于 Polygon 和 EVM 是同构链,当向 MATIC 合约转入代币时,它进入了合约重入。对调用堆栈的可重入部分进行了详细分析。

image.png

分析的第一个合约是 getUnderlyingPrice :https://polygonscan.com/address/0xcc6aa628516bb46391b05b16e5058c877461cc76 这是一个合乎逻辑的合约,但不是开源的。

image.png

image.png 根据slot,我们得到v1 = 0xe7cea2f6d7b120174bf3a9bc98efaf1ff72c997d和wtoken = 0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270。然后我们进入if分支,通过slot找到_oracles[v1] = 0xacf3e1c6f2d6ff12b8aee44413d6834774b3f7a3。我们继续进入里面的else分支,调用0xacf3e1c6f2d6ff12b8aee44413d6834774b3f7a3合约的getUnderlyingPrice函数。0xacf3e1c6f2d6ff12b8aee44413d6834774b3f7a3对应的逻辑合约是0x3803527dcd92ac3e72a0a164db82734daba47fac,这个合约也没有开源。

image.png

image.png

攻击涉及内置计算,因为它涉及重入,并且一些变量必须在传输发生后计算。这部分代码没有涉及到外部变量,所以问题应该不在这里。其中,函数 0x9de 被调用。

image.png

变量 varg0 是传入的令牌地址,即 0xe7cea2f6d7b120174bf3a9bc98efaf1ff72c997d。对应的_poolOf[v0]为0xfb6fe7802ba9290ef8b00ca16af4bc26eb663a28。然后分析这个合约的get_virtual_price函数。该函数的代码如下:

image.png

变量self.token还是0xe7cea2f6d7b120174bf3a9bc98efaf1ff72c997d,除数就是这个token的总流通量。

image.png

观察到变量D影响了get_xcp的返回值,重入发生在 remove_liquidity 函数中,然后进行分析。该函数的详细代码如下:

image.png

注意到调用前后 get_virtual_price 返回值的变化。 image.png

image.png

self.D的变化发生在transfer之后,当攻击者移除流动性时,MATIC 将转移到攻击者的合约中,fallback回调时,首先检查 0xe7cea2f6d7b120174bf3a9bc98efaf1ff72c997d 的价格,由于self.D在转账后更新,导致之前的价格获取错误。

去除流动性的过程如下:

  1. 销毁用户的LP
  2. 发送用户的抵押资金
  3. 更新self.D变量。

Self.D 用于计算价格,并且在增加流动性时也会更新。然而,在这种情况下,攻击者拥有更多的流动资金。根据self.D的计算公式self.D = D - D * amount / total_supply,正常情况下计算self.D的值会比较小,amount和total_supply几乎相等。

然而,由于攻击者重新进入并在原始价格的基础上增加了 10 倍的借贷,所以 self.D 的价值在流动性增加时增加,而在移除时没有及时更新。

remove_liquidity 方法包括一个不可重入锁('lock')以防止该方法被重新进入,但是当攻击者重新进入另一个合约以借入资金时该锁不起作用。

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

1 条评论

请先 登录 后评论
Polaris_tow
Polaris_tow
0x215B...F2F1
欢迎一起学习哦,web3世界的守护者! 交流群:741631068 可以加v:zz15842945138 twitter:https://twitter.com/Polaris_tow