安全审计必看 | 近期Web3常见的攻击都有什么特点,项目方如何避免这些问题?
摘要: 我们一起来盘点一下近期常见攻击都有些什么特点,以及项目方如何避免这些问题。
本文作者:Beosin安全研究专家Sivan
上一篇文章我们介绍了近期区块链生态中发生的骗局类资金安全问题,包括后门以及貔貅盘。除了这些骗局事件,近期安全事件也对整个区块链生态造成了巨大的影响。
最近发生大量的安全攻击事件,这些事件对于项目方来说具有重大影响。攻击事件的发生主要原因之一是业务逻辑设计不当,其中可能存在漏洞或弱点,被黑客利用进行攻击。另外,价格操控也是导致安全攻击事件的因素之一,黑客可能通过操纵价格或市场行为来实施攻击。
本篇文章我们一起来盘点一下近期常见攻击都有些什么特点,以及项目方如何避免这些问题。
一、业务逻辑设计不当
Pair代币意外销毁
近期因为业务逻辑设计不当发生的安全事件,大多都是由于pair代币余额异常导致的。
一些代币项目,会在业务设计中添加交易手续费或代币通缩的功能,也就是在代币转移过程中,会收取相关比例的手续费或者直接销毁部分转移的代币。这本是一个项目的创收或激励用户持有代币或其他有助于项目发展的业务逻辑,但如果代码设计不够完善,便会出现严重的问题。
例如,在转账过程中,有些项目进行额外代币扣除时,没考虑到pair意外扣除将导致严重后果。该类项目的转账函数逻辑一般是发送方和接收方进行正常的代币转移,并且额外扣除某个地址部分费用,用于手续费或销毁。但额外扣除地址为pair时,会导致pair中其中一个代币余额通过非交易的方式变少,k值异常变化,从而使用少量代币便能兑换出大量另一个代币。
以下列项目代码为例:
该代币合约中存在意外销毁pair余额的问题,当代币转移发起者不是pair合约时,会进行更新池子的操作,该更新池子的方式是将pair的代币余额扣除交易金额的1%,再更新储备量。黑客可以通过调用transfer函数自己给自己转账,反复操作,将会使得pair中的一个代币消耗得极少,最后利用极少代币将pair中大量的价值币兑换出来。
以下是真实安全事件过程:
首先使用2555枚WBNB兑换了1390亿枚Bamboo代币;
不断通过transfer将代币发送给自己,导致pair中Bamboo代币异常减小;
使用139B枚Bamboo代币兑换回2772枚WBNB,完成攻击。
再以另一个意外销毁pair代币的例子说明一下,如下图代码。合约会判断当前交易类型,如果为2(to地址为pair合约,相当于卖币),合约会记录一个交易量的20%作为销毁数量,后续可以调用goDead()函数将pair中这个累积数量销毁,该功能对稳定币价能起部分作用。
但是合约没考虑到一些特殊情况,例如直接向pair里面转币,这时会使得合约误以为用户是在卖币,这部分币可以通过pair的skim函数全部提取出来。相当于pair没有任何变化,再次调用goDead()函数时,却能使得pair中的代币意外减少,重复操作,便能耗尽pair其中一种代币。
以下同样是真实安全事件过程:
不停通过transfer与skim操作,将amountToDead值控制得异常大。
调用goDead()函数将pair中的代币销毁掉。
使用少量代币兑换了大量的USDT。
总结:
代币的transfer函数一定要认真设计代币转移逻辑,一定要避免pair余额意外扣除的情况,pair余额仅在添加流动性、移除流动性以及交易过程中才能改变,并且改变数量尽量不要大于或小于传入数量,才能保障pair资金健康。
二、价格操控问题
对于价格操控的攻击事件,主要是由于项目方合约在获取价格的时候没有考虑到价格被意外控制的情况。特别是对于存在两个逆向计算的业务逻辑函数,如stake&unstake、deposit&withdraw等,两种操作一般都使用相同的参数但相反的计算逻辑。
而在这两种操作之间,如果能通过其他函数或合约将其中的部分或全部参数进行不对等的控制,那么两种操作之间便可能存在价格差,从而导致资产被盗。
1、只读重入
重入一直是区块链生态中最常见也是危害最大的漏洞之一。在以太坊最开始盛行的时候,重入攻击大多是因为以太坊转账调用的目标函数fallback()中再次发起了对该项目合约的调用,此时项目合约变量还未更新,可以绕过相关检查,如DAO事件。
随着以太坊生态越来越丰富,各个项目方更加注重这一方面的防护以及solidity0.8.0版本之后对溢出的主动检查,现在更多的攻击事件是通过重入来控制某些价格或参数,来达到攻击的目的。
例如近期发生频繁的只读重入,便是通过重入前后变量未修改完全,使得重入中调用的计算价格的函数出现异常,从而导致资产被盗。
有兴趣的读者可以参考如下链接:安全审计必备知识 | 难以防范的“只读重入攻击”是什么?
2、Pair余额依赖
Pair可以最直观的表现出代币价格变化,也是最准确的价格获取渠道,但pair中的价格是瞬时价格,并且可以通过大量代币兑换来控制,导致瞬间暴涨或暴跌。如果依赖pair中的价格作为业务中的参数参与计算,那么便可能导致异常的结果。
如下代码,burnForEth函数通过依赖pair中能兑换出的数量来作为本合约发送给调用者的ETH数量,该数量是通过pair中两种代币余额来进行计算。正常情况下这是一个最准确的价格,但是如果提前使用ETH将pair中的另一个代币大量兑换出来,会导致ETH在该pair中的价格暴跌,从而计算出能兑换的ETH就会异常大,使得合约给调用者发送更多的ETH。最后,调用者通过pair将ETH兑换回来,使价格恢复正常。
以下是真实安全事件过程:
攻击者使用闪电贷的ETH将大量WAX代币兑换出来,导致WAX价格暴涨。
攻击者不断调用burnForEth函数,销毁WAX来取出ETH,此时使用的WAX价格时暴涨过后的,可以获得更多的ETH。
最后,攻击者将ETH兑换出来,归还闪电贷并获利。
总结:
安全事件一直都是区块链生态最大的威胁之一,需要项目方时刻保持警惕。对于需要计算价格的业务逻辑要有严格的流程把控,尽量避免直接使用pair余额进行价格计算,调用外部函数获取价格也需要考虑其是否能被操控。项目方也可以与专业的安全合作伙伴合作,及时发现并应对潜在的安全威胁。
Beosin作为一家全球领先的区块链安全公司,在全球10多个国家和地区设立了分部,业务涵盖项目上线前的代码安全审计、项目运行时的安全风险监控、预警与阻断、虚拟货币被盗资产追回、安全合规KYT/AML等“一站式”区块链安全产品+服务,目前已为全球3000多个区块链企业提供安全技术服务,审计智能合约超过3000份,欢迎点击公众号留言框,与我们联系。
评论(0)
Oh! no
您是否确认要删除该条评论吗?