Jarvis Network闪电贷重入攻击事件分析

  • 事件概述:2023年1月15日,Jarvis Network因闪电贷重入攻击损失663,101枚MATIC,攻击者利用合约逻辑漏洞操纵价格计算。

  • 攻击核心

    • 漏洞触发于remove_liquidity函数,攻击者通过重入(转账回调)在self.D(关键价格计算变量)更新前获取异常价格。
    • 重入前后同一函数返回值差异巨大(如从1,002增至10,091),导致借贷资金被高估10倍。
  • 技术细节

    • 流程缺陷:合约执行顺序为“销毁LP→转账→更新self.D”,攻击者在转账后通过回调重入其他合约借贷,利用未更新的self.D值套利。
    • 重入锁失效:尽管remove_liquidity使用@nonreentrant防止直接重入,但跨合约调用绕过限制。
  • 根本原因

    • 价格计算依赖的self.D变量在外部调用后更新,违反“Checks-Effects-Interactions”安全规范。
    • 价格源单一且未实时同步,加剧漏洞影响。
  • 安全建议

    • 关键变量修改应置于外部调用前。
    • 采用多数据源验证价格,严格遵循“检查→更新→交互”的编码逻辑。
总结

根据NUMEN链上监控显示,Jan-15-2023 05:43:37 PM +UTC时间,Jarvis_Network项目遭到攻击,损失663101个MATIC。
具体tx如下:
https://polygonscan.com/tx/0x0053490215baf541362fc78be0de98e3147f40223238d5b12512b3e26c0a2c2f

Jarvis Network闪电贷重入攻击事件分析

根据调用栈分析,交易中涉及到很多代币转账,所以调用栈很长,我们分析发现在调用过程中存在重入的逻辑。在重入的过程中发现重入前和重入后,对同一个合约的同一个函数调用,传入参数也一样,但是返回值差别很大。 
重入前:1002157321772769944
重入后:10091002696492234934 

Jarvis Network闪电贷重入攻击事件分析

重入发生在remove_liquidity,这个函数在(https://polygonscan.com/address/0xfb6fe7802ba9290ef8b00ca16af4bc26eb663a28#code)这个合约中。remove_liquidity这个函数在移除流动性的时候会把用户添加的代币返回给用户,由于polygon和evm是同构链,所以在matic转账给合约的时候会进入到合约的重入。详细分析调用栈中重入的部分。

Jarvis Network闪电贷重入攻击事件分析

首先看getUnderlyingPrice(https://polygonscan.com/address/0xcc6aa628516bb46391b05b16e5058c877461cc76#code)上面是逻辑合约,但是不开源。

Jarvis Network闪电贷重入攻击事件分析

Jarvis Network闪电贷重入攻击事件分析

根据插槽得到v1=0xe7cea2f6d7b120174bf3a9bc98efaf1ff72c997d,wtoken=0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270。所以进入if分支,然后通过插槽查到_oracles[v1]=0xacf3e1c6f2d6ff12b8aee44413d6834774b3f7a3,继续进入里面的else分支后调用0xacf3e1c6f2d6ff12b8aee44413d6834774b3f7a3合约的getUnderlyingPrice函数。0xacf3e1c6f2d6ff12b8aee44413d6834774b3f7a3对应的逻辑合约是0x3803527dcd92ac3e72a0a164db82734daba47fac,这个合约也没有开源

Jarvis Network闪电贷重入攻击事件分析

Jarvis Network闪电贷重入攻击事件分析

这个是一些内置的计算,因为攻击涉及到重入,考虑到一定是重入前和重入后的一些变量是转账发生之后计算的,这部分代码不涉及到外部变量,所以问题应该不在这。除此之外还调用了0x9de。

Jarvis Network闪电贷重入攻击事件分析

varg0是传入的代币地址,也就是0xe7cea2f6d7b120174bf3a9bc98efaf1ff72c997d。对应的_poolOf[v0]是0xfb6fe7802ba9290ef8b00ca16af4bc26eb663a28。进入这个合约分析get_virtual_price函数。对应代码如下:

Jarvis Network闪电贷重入攻击事件分析

self.token还是0xe7cea2f6d7b120174bf3a9bc98efaf1ff72c997d,除数是这个代币的总发行量

Jarvis Network闪电贷重入攻击事件分析

看到D会影响get_xcp的返回。因为重入发生在remove_liquidity,所以分析remove_liquidity函数。详细代码如下:

Jarvis Network闪电贷重入攻击事件分析

调用前后get_virtual_price返回值变化。

Jarvis Network闪电贷重入攻击事件分析

self.D的更改在转账之后。攻击者在移除流动性的时候,matic转移到攻击者合约,回调fallback时候先查了一下0xe7cea2f6d7b120174bf3a9bc98efaf1ff72c997d价格,由于self.D更新在转账之后,所以导致之前的价格获取错误。

移除流动性方法流程:1)销毁用户LP;2)发送给用户质押资金;3)更新self.D。 

self.D用于价格计算,添加流动性时也对self.D更新,并且攻击者此次流动性资金较大。根据self.D计算公式self.D = D - D * amount / total_supply,amount和total_supply近乎相等,正常计算时,self.D值会小很多。 

但由于攻击者在2)进行了重入,并且比原始价格增高了10倍进行借贷,正是因为self.D值在添加流动性时增大,而移除流动性时未及时更新。 

这里remove_liquidity 移除流动性方法虽然添加了@nonreentrant('lock')来防止重入该方法,但由于攻击者重入进入其他合约借贷资金,这里重入锁并不能奏效。

总结: 

本次攻击主要是因为变量修改逻辑在外部调用之后,导致价格获取出现异常,并且跨合约重入使得重入锁不能奏效,NUMEN实验室提醒项目方代码要经过严格的安全审计,变量修改要放在外部调用之前并且价格获取采用多数据源的方式,代码逻辑遵循先判断,后写入变量,再进行外部调用的编码规范(Checks-Effects-Interactions)会使项目更加安全稳定。NUMEN拥有专业的安全团队,为WEB3生态保驾护航

分享至:

作者:Numen Cyber

本文为PANews入驻专栏作者的观点,不代表PANews立场,不承担法律责任。

文章及观点也不构成投资意见

图片来源:Numen Cyber如有侵权,请联系作者删除。

关注PANews官方账号,一起穿越牛熊
推荐阅读
30分钟前
2小时前
2小时前
2小时前
2小时前
3小时前

热门文章

行业要闻
市场热点
精选读物

精选专题

App内阅读