最近发生大量的安全攻击事件,这些事件对于项目方来说具有重大影响。攻击事件的发生主要原因之一是业务逻辑设计不当,其中可能存在漏洞或弱点,被黑客利用进行攻击。另外,价格操控也是导致安全攻击事件的因素之一,黑客可能通过操纵价格或市场行为来实施攻击。

本篇文章我们一起来盘点一下近期常见攻击都有些什么特点,以及项目方如何避免这些问题。

一、业务逻辑设计不当

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余额进行价格计算,调用外部函数获取价格也需要考虑其是否能被操控。项目方也可以与专业的安全合作伙伴合作,及时发现并应对潜在的安全威胁。

希望对您有帮助!

Logo

一起探索未来云端世界的核心,云原生技术专区带您领略创新、高效和可扩展的云计算解决方案,引领您在数字化时代的成功之路。

更多推荐