在去中心化金融(DeFi)领域中存在着大量的安全风险,这些风险可能对用户、平台和整个金融生态系统造成严重的危害。我们总结了三种 DeFi 安全风险,并通过分析最近发生的真实安全事件来阐述黑客攻击的过程以及相应的解决方案。
价格操纵风险
智能合约漏洞风险
用户操作风险
1. 价格操纵风险
在 DeFi 中,价格操纵风险是指恶意行为者试图通过操纵资产的价格来获利或影响市场的行为。这种操纵可能会导致市场价格的不正常变动,给其他参与者带来损失。以下,我们总结了价格操纵风险在 DeFi 中可能出现的三种情况:
闪电贷攻击
三明治攻击
预言机攻击
1.1 闪电贷攻击
闪电贷攻击是一种在 DeFi 应用中出现的攻击方式。它利用了闪电贷这种无需提供抵押品即可借贷的金融操作。攻击者通过闪电贷借入大量资金,并在同一笔交易中进行一系列操作,以实施欺诈行为。
ShidoGlobal 闪电贷攻击事件
2023 年 6 月 23 日,在 BSC(币安智能链)上发生了 ShidoGlobal 闪电贷攻击事件。攻击者通过锁定和索取机制,以及两个池之间的价格差异来实现代币的套利,成功窃取了 976 个 WBNB。
Attack Tx:
攻击者如何实施闪电贷攻击?
攻击者借取了 40 个 WBNB 的闪电贷。
攻击者将 39 个 WBNB 交换成了 10, 436, 972, 685, 676, 390, 697 个 Shido Inu:SHIDO 代币(小数点后 9 位),并存入了 PancakeSwap V2:SHIDO-WBNB 池中。这一步操作增加了 Shido Inu:SHIDO 代币在该池中的供应量,导致该代币价格下降。
攻击者接着依次调用了 ShidoLock.lockTokens 和 ShidoLock.claimTokens,将 10, 436, 972, 685.676390697 个 Shido Inu:SHIDO 代币(小数点后 9 位)转换成了 10, 436, 986, 704, 133, 494, 387, 000, 000, 000 个 SHIDO 代币(小数点后 18 位)。
当攻击者调用 ShidoLock 合约中的 lockTokens 函数时,他们将 10, 436, 972, 685.676390697 个 Shido Inu:SHIDO 代币锁定在合约中。这意味着这些代币无法被转移或交易,直到特定的条件满足。通过锁定代币,攻击者可以在一定程度上维持代币的价格稳定。
攻击者调用 claimTokens 函数,将锁定的代币转换成了 10, 436, 986, 704, 133, 494, 387, 000, 000, 000 个 SHIDO 代币。这一步实际上是将 SHIDO 代币的小数位数从 9 位增加到 18 位,增加了代币的总供应量。
通过锁定和索取机制,PancakeSwap V2:SHIDO-WBNB 池和 PancakeSwap V2:SHIDO 28 池之间存在价格差异。具体来说,由于 SHIDO 代币在 PancakeSwap V2:SHIDO-WBNB 池中的供应量增加,导致价格下降。而在 PancakeSwap V2:SHIDO 28 池中,由于供应量没有增加,价格相对较高。攻击者利用这种价格差异,在两个池之间进行代币交换,以更有利的价格将 10, 436, 986, 704, 133, 494, 387, 000, 000, 000 个 SHIDO 代币(小数点后 18 位)交换成了 1, 016 个 WBNB。
最后,攻击者偿还了 40 个 WBNB 的闪电贷,并获得了约 976 个 WBNB 的利润。
限制闪电贷功能
限制闪电贷功能和引入闪电贷手续费是减少闪电贷攻击和操纵风险的一种常见方法。
限制闪电贷功能:可以对闪电贷功能进行限制,例如设置最小借贷金额、借贷时间限制等。这样可以减少攻击者利用闪电贷进行攻击的机会。
引入闪电贷手续费:可以向借贷者收取一定的手续费。这样可以增加攻击的成本,使攻击者在进行闪电贷攻击时面临更高的风险和成本。
在上述示例代码中,我们设置了一些限制条件来限制闪电贷功能的使用,例如最小借贷金额、最大借贷金额和借贷时间。在执行闪电贷操作之前,我们先计算并收取一定比例的手续费。
1.2 三明治攻击
三明治攻击(Sandwich Attack)是一种在去中心化交易所(DEX)中利用信息不对称的攻击方式。攻击者通过在两个交易之间插入恶意交易,从而利用价格差异来获取利润。
CurveFinance 三明治攻击事件
2023 年 8 月 2 日,Hypernative systems 对 Curve Finance 发起三明治攻击。攻击者通过在添加流动性和移除流动性的两个交易之间插入恶意交易,赚取 36.8 K USDT。
Attack Tx:
攻击者如何实施三明治攻击?
攻击者从多个资金来源获得巨额闪电贷款,包括 wstETH、WETH 和 USDT。
攻击者向 3 pool 提供 155, 000, 000 USDT 流动性并获得 3 CRV LP 代币。3 CRV 是 Curve TriPool(Curve DAI/USDC/USDT 矿池)的 LP 代币,即在该攻击事件中受到损害的矿池。
攻击者从池中移除(几乎全部)DAI 和 USDC 流动性,并销毁 3 CRV LP 代币。此时,该池几乎完全是 USDT,这暂时使其比 DAI 和 USDC 便宜得多。
调用 UnderlyingBurner 合约 execute()函数,继续向 Curve DAI/USDC/USDT 矿池中添加流动性。UnderlyingBurner 主要持有 USDT,添加的 DAI:USDC:USDT 数量是 100, 000: 100, 000: 227, 079, 039, 776 。这导致该矿池更加不平衡,USDT 的相对数量更高,价值更低。
攻击者将他持有的 DAI 和 USDC 添加到 Curve DAI/USDC/USDT 矿池中并享受溢价,这意味着获得更高数量的 3 CRV LP 代币。
攻击者通过销毁其 3 CRV LP 代币并提取 USDT 流动性。
攻击者偿还闪贷并保留 36.8 K USDT 的利润。
在这个过程中,恶意交易指的是攻击者从 Curve DAI/USDC/USDT 矿池中移除大量的 DAI 和 USDC 流动性,并销毁 3 CRV LP 代币的交易。这个交易使得该矿池变得非常不平衡,USDT 的相对数量更高,从而导致其价值更低。
另外两笔交易指的是攻击者添加流动性和提取流动性的交易。攻击者利用价格差异,通过添加自己持有的 DAI 和 USDC 流动性到 Curve DAI/USDC/USDT 矿池,并在溢价时将其提取出来,获得更高数量的 3 CRV LP 代币。
这样,攻击者通过三明治攻击将恶意交易与另外两笔交易包装在一起,低价购买 USDT 流动性,然后高价出售获取利润。
限制交易顺序
当涉及到防止三明治攻击时,代码实现可能会涉及复杂的智能合约和交易逻辑。以下是一个简化的示例,展示了如何通过限制交易顺序和引入交易延迟来预防三明治攻击。
在这个例子中,我们假设有一个智能合约 SandwichAttackPrevention,用于管理用户的余额和交易操作。为了防止三明治攻击,我们引入了两个主要的防御机制。
首先,在 allowTransaction 函数中,只有合约的拥有者才能将 isTransactionAllowed 设置为 true,从而允许用户执行交易。这样可以确保交易按照正确的顺序执行,而不允许攻击者在两个交易之间插入恶意交易。
其次,在 executeTransaction 函数中,我们引入了交易延迟的概念。只有在当前区块时间超过设定的延迟时间后,用户才能执行交易。这样可以给其他用户足够的时间来执行交易并更新价格,从而减少攻击者利用价格差异的机会。
1.3 预言机攻击
价格预言机是一种提供加密货币实时价格信息的数据源。这些信息对于许多 DeFi 协议的正常运行至关重要。预言机攻击是指攻击者人为地改变预言机提供的数据,目的是从基于操纵价格的交易中获利。
Rodeo Finance 预言机攻击事件
Rodeo 是一个 DeFi 平台,提供价格预言机服务。2023 年 7 月 11 日,价格预言机操纵导致黑客从 Rodeo 协议中窃取了约 472 ETH(约 88.8 万美元)。
Attack Tx:
价格预言机如何被操纵?
Rodeo Finance 攻击事件的关键在于 Rodeo TWAP Oracle。该预言机用于跟踪 ETH 和 unshETH 之间的价格比率。
分析攻击交易:攻击过程始于攻击者执行一个经过精心计划的交易。攻击者利用对平台架构和时间加权平均价格(TWAP)预言机潜在漏洞的深入理解,发起了这次攻击。
操纵 TWAP 预言机:攻击者能够使用与未配置的策略地址相关联的 earn 函数,强制交换 USDC 为 unshETH。这种操纵有效地绕过了由于有缺陷的 unshETH 价格预言机而导致的滑点控制。实质上,earn 函数被强制从 USDC 换成 WETH,再换成 unshETH。
计算 TWAP 价格:TWAP 价格是通过对最后四个更新的价格进行平均计算得出的,每个更新间隔为 45 分钟。然而,有缺陷的价格预言机返回了一个被操纵的价格,导致智能合约认为该持仓是健康的。
开仓杠杆头寸:攻击者通过三明治攻击操纵 TWAP 预言机,然后通过从投资者合约调用 earn 函数来开设杠杆头寸。他们借入了价值 40 万美元的 USDC。
交换资产:攻击者将借入的资产与底层的 CamelotDEX 池进行交换,同时将其准备好的 unshETH 卖回给池子。
绕过执行验证:合约通常会验证操作是否有效。然而,由于攻击者控制了这个策略,他们轻松绕过了这个检查。这使得攻击者能够通过将准备好的 unshETH 卖回给池子来利用被操纵的头寸,有效地从平台中提取流动性。
转移被盗资金:攻击者将被盗资金从 Arbitrum 转移到 Ethereum,将 285 个 ETH 换成 unshETH,然后将它们转移到 Arbitrum 以继续攻击。这部分价值 150 个 ETH 的被盗资金随后被转移到了 Tornado Cash,一个专注于隐私的以太坊混币服务。剩余的 371.2 个 ETH(约价值 701, 679 美元)仍然被攻击者控制的地址持有。
这次攻击的一个重大漏洞是 Rodeo TWAP Oracle 的执行存在缺陷。预言机依赖于 WETH/unshETH 交易对的储备,该交易对的流动性较低,因此价格波动很大。
基于多个预言机来计算价格
确保价格查询的可靠性,一个可靠的预言机应该使用多个预言机或聚合喂价来计算价格,而不仅仅依赖代币对比率。特别是在矿池流动性较差的情况下,这种多样化的定价信息来源可以提高价格数据的准确性,并使攻击者更难操纵数据。
为了实现这一目标,一个可能的解决方案是使用去中心化预言机,例如 Chainlink。Chainlink 预言机可以从各种数据源收集数据,并使用区块链技术验证和确认数据的准确性。通过使用多个数据源,Chainlink 减少了单点故障的可能性,并且更难以被攻击者操纵数据。
以下是一个使用 Chainlink 聚合器合约获取价格数据的示例代码:
在上述代码中,我们使用了一个AggregatorV3Interface类型的数组来存储多个预言机的实例。构造函数接受一个预言机地址数组作为参数,并将每个地址实例化为一个AggregatorV3Interface对象。
getLatestPrice 函数用于获取多个数据源的最新价格数据。它遍历 priceFeeds 数组,并通过调用每个预言机的 latestRoundData 函数来获取价格数据。所有的价格数据被存储在一个 int 类型的数组中,并返回给调用者。
通过这种方式,我们可以从多个数据源获取价格数据,并确保价格查询更准确地反映资产价格。
2. 智能合约漏洞风险
智能合约漏洞智能合约漏洞是指在以太坊或其他智能合约平台上编写的代码中存在的安全漏洞或错误。DeFi 的核心是基于智能合约的金融协议,因此智能合约漏洞可能导致用户资金的丢失、操纵市场行为或其他恶意行为。
识别这些漏洞至关重要,我们的审计涵盖了各种潜在问题。这包括但不限于可重入漏洞、访问控制漏洞、整数溢出漏洞和业务逻辑漏洞。我们全面的审计服务旨在加强您的智能合约的安全性,并保护免受这些风险的影响。
以下,以访问控制漏洞举例,说明智能合约漏洞对 DeFi 的影响。
LeetSwap 访问控制漏洞
LeetSwap 遭受了攻击,损失超过了 340 ETH。根本原因在于 LeetSwap V2 Pair 合约存在访问控制漏洞, _transferFeesSupportingTaxTokens 函数可见性为 public。
Attack Tx:
Vulnerable Contract:
https://basescan.org/address/0x94dac4a3ce998143aa119c05460731da80ad90cf
攻击者调用了 _transferFeesSupportingTaxTokens 函数来操纵池子,攻击流程如下:
用 WETH 兑换另一个代币 A。
调用 _transferFeesSupportingTaxTokens 函数来转移代币 A,并随后调用 sync 函数,导致代币 A 的价格上涨。
用代币 A 兑换 更多的 WETH 并清空池子。
解决方案
为了修复 _transferFeesSupportingTaxTokens 函数的访问控制漏洞,应该将函数可见性更改为 private 或 internal。将函数声明为 private,只有合约内部的其他函数能够调用它。将函数声明为 internal,可以被继承该合约的合约访问。其他合约继承 LeetSwap V2 Pair 合约时,可以通过 super 关键字调用_transferFeesSupportingTaxTokens 函数。而外部用户无法直接访问该函数,提高了合约的安全性。
需要根据具体的合约逻辑和需求来决定如何更改函数的可见性,确保在提高安全性的同时不影响合约的正常运行。
智能合约审计是识别和预防漏洞的重要步骤。在Salus,我们拥有一支由经验丰富的智能合约开发人员和审计专家组成的团队,可以帮助您增强合约的安全性。我们的专业知识使我们能够准确定位潜在的弱点,并确保您的项目的安全性和可靠性。
3. 用户操作风险
在 DeFi 领域中,用户操作风险是指用户在使用 DeFi 平台时,由于自身的操作失误、安全意识不足或不谨慎的行为而导致资金损失的风险。以下是一些常见的用户操作风险:
点击恶意链接:用户可能会误点击恶意链接,导致恶意软件或病毒感染其设备,攻击者可以利用这些恶意软件来获取用户的敏感信息或控制其钱包。
使用不安全的钱包:如果用户选择使用不安全的钱包应用程序或硬件钱包,攻击者可能会利用这些漏洞来窃取用户的私钥或操作权限。
泄露私钥:用户如果在未加密的环境中泄露私钥,或者将私钥存储在不安全的地方,那么攻击者可能会轻易获取用户的私钥并进而控制其资金。
不谨慎的交易操作:用户在进行交易时,如果没有仔细检查交易细节(如目标地址、交易数量等),可能会导致资金发送到错误的地址或发送错误的数量。
为了减少用户操作风险,以下是一些建议:
提高安全意识:了解常见的网络钓鱼、恶意软件和诈骗手段,并学习如何识别和避免它们。保持警惕,并仔细检查与 DeFi 有关的链接和应用。
使用安全钱包:选择使用经过安全审计和有良好声誉的钱包应用程序或硬件钱包。确保钱包应用程序和固件是最新版本,并遵循最佳的安全实践。
备份和保护私钥:将私钥存储在安全的地方,并使用强密码加密。定期备份私钥,并将其存储在离线、安全的地方,以防止意外数据丢失。
仔细检查交易细节:在执行任何交易之前,仔细检查交易细节,确保目标地址、交易数量等都是正确的。双重检查可以避免由于疏忽导致的资金损失。
4. 总结
请注意,针对以上每一种攻击和漏洞的解决方案只是简单的示例,并不能完全防止相对应的攻击,或者修复相对应的漏洞。如果您对智能合约审计感兴趣,请联系我们,我们将与您合作,为您提供专业的审计服务,确保您的合约安全可靠。我们致力于为您提供优质的服务和全面的技术支持,以确保您的智能合约在安全和可靠的环境中运行。