原文链接:https://pwning.mirror.xyz/
我的区块链冒险旅程!这一次,我披露了 Moonbeam 的一个关键设计缺陷,保护了DeFi 项目中面临风险的1亿多美元资产,从而保护了Moonbeam 网络。我获得了他们的最高奖励—— Immunefi bug赏金计划,100万美元,以及 Moonwell 的5万美元奖金(我猜这也是奖金最高的十大bug 奖金之一吧?)
在报告了 Aurora 引擎中的 bug 之后,我开始考虑原生合约的委托调用的其他潜在的误用。委托调用delegatecall
的最初目的是提供一种机制,通过这种机制,一个智能合约可以共享和重用另一个合约的代码,从而避免重复代码存储的开销。原生合约通常是预构建的合约,它实现了作为原始 EVM 扩展的特殊函数。
现在,棘手的部分是: 如果委托调用delegatecall
原生合约,您可能能够执行一些意想不到的函数,甚至是特权函数!但是,这些合约的开发人员可能没有意识到函数的实际用户可能是其他人。 在 Aurora 错误的例子中,原生合约只是假定调用者始终是一个魔术地址,因此硬编码的日志发射器会导致恶意withdrawal漏洞。
还有什么假设可能是错误的?执行委托调用delegatecall
时,调用上下文将从前一个上下文继承,包括 msg.sender
和 msg.value
。** 从原生合约的角度来看,调用 delegatecall 的合约是透明的: 它的调用者将被视为真正的用户。因此,如果调用了恶意合约,它可以模拟其调用方对本机合约进行操作!
“Moonbeam ”和“Moonriver ” (“月光”和“月河”)都是与 EVM 兼容的平台。在moonbeam运行时,Moonbeam 和Moonriver 之间有一些预编译的合约。
Balance ERC-20预编译提供了一个 ERC-20接口,用于处理原生令牌(MOVR & GLMR)余额。Erc20BalancesPreedit 的实现位于 moonbeam/precompiles/balances-erc20/src/lib.rs 中。
设计人员没有考虑 EVM 中delegatecall
的使用。恶意合约可以将其 msg.sender
传递给预编译合约以模拟其调用方。在这个场景中,预编译合约没有办法计算出实际的调用方。攻击者可以增加受害者的允许值,也可以立即转移可用的余额。
在 Asset ERC-20预编译中也存在类似的问题,它提供了可互操作令牌(xcKSM、 xcDOT、 …)的 ERC-20原生实现。Erc20AssetsPrepileSet 的实现位于 moonbeam/prepiles/asset-erc20/src/lib.rs 中。
但是,在这种情况下,设计人员确实考虑了 EVM 中委托调用delegatecall
的使用。测试中的 ERC20Instance
合约已经实现了牢固有效性测试用例,其中包括 approve_delegate()
、 approve_delegate()
和 transferFrom_delegate()
。很不幸(或者,对我们来说,很幸运!),结果是设计逻辑不能正常工作,所以他们删除了相关的代码在他们的补丁。
这里有一个可以在两种情况下重用的简单exploit : 原生令牌的资产地址是0x0000000000000000000000000000000000000000000000000000000000802,本地令牌的资产地址可以是0xFFFFFFFF1FcaCBd218EDc0EbA20Fc2308C778080。
Exploit.sol:
我们该怎么处理这个设计缺陷呢?基本思想是让某人触发您的恶意合约,例如,在 POC 合约中调用 trap()
。
我们怎样才能说服用户援引一些可疑的合约呢?空投!UNIH 令牌背后的黑客已经演示了钓鱼的crypto-native解决方案!任何想要在 uniswap 中出售空投令牌的用户都必须调用恶意令牌合约来批准 DEX 使用他们的余额。由于 RUNE 令牌的脆弱设计,其中只检查 tx.source
而不是 msg.sender
是否获得批准,所有的 RUNE 令牌都可能被木马合约窃取。
钓鱼的想法是创造性的,但它强烈限制了漏洞的潜在损害。我们想找个更好的受害者
谁是穷黑客最好的朋友?闪电贷款提供者!他们持有大量的金钱,并调用您的合约回调,因为你希望!在闪电贷款回调,他们被迫批准您未来的转移他们的资产令牌,即使他们是完美的合约!
一些 DEX 对支持对任意合约的回调,例如 MoonRiver 上的 SolarBeamonMoonbeamStellaSwap。由于闪电贷款的支持,xcKSM 和 stKSM 之间的稳定互换对也很脆弱。如果一个令牌可以从交易对中抽出,那么另一个令牌可以在一次swap中被移出,所有的流动性将被清算。
现在,完美的写合约变成了完美的受害者。当我报告的时候,最富有的脆弱合约是:
这些代币价值约1260万美元,即使是10% 的潜在损失也已经超过100万美元,这是 Moonbeam 提供的最高赏金奖励。但是,真正的黑客不会因为一些微不足道的成就而停止攻击,还会有更疯狂的受害者吗?
原生MOVR 令牌(Moonriver上)和 GLMR (在Moonbeam)等价于以太坊上的 ETH。要在 DeFi 协议中使用,它们必须包装在与 ERC-20兼容的令牌合约中,就像 WETH
一样。
Balance ERC-20预编译提供了本机令牌的本机包装器。没有任何已部署的协议使用它,因为官方封装的令牌 WMOVR 和 WGLMR 被更广泛地采用。通过利用 Balance ERC-20预编译的漏洞,我们能够从任何用户那里窃取本机令牌余额,如果它调用恶意合约的话。与资产 ERC-20预编译令牌不同,例如 xcKSM 和 xcDOT 是由 DEXes 直接使用的,MOVR 和 GLMR 余额很少被智能合约使用。
大多数非零余额的合约都是多大号钱包,与外部拥有的账户没有太大区别。唯一的例外,我们的一线希望,是Moonwell项目的 MGlimmer 合约。
Moonwell 项目是 Moonriver 上最主要的 DeFi 协议。它有近2亿美元的供应和1亿美元可供借贷(在我报告的时候)。MGlimmer 或 Moonwell: mMOVR 令牌是处理针对 MOVR 的贷款和借款的特定合约,它的余额中有本地 MOVR。
最酷的是,当它把余额转移给用户时,它会把目的地作为一个合约来调用!这里有一个简单的漏洞,获得批准花费所有余额的 MGlimmer。
GlimmerExploit.sol:
脆弱合约中存储的余额不会太多(现在是几千 MOVR)。不过,你在合约中存入的任何金额都将被视为本贷款协议中的抵押品。通过重复存款-> 借款-> 转移所有回-> 离开坏账程序,利用可以进一步武器化。所有可借用的资产都可以被抽干!
如果任何一个黑客拿走了所有1亿美元的可借资产和1200万美元的 DEX 对易损令牌,那么它绝对可以跻身 DeFi 历史上的前10大抢劫案!关于这些漏洞的另一个令人惊讶的事实是,实际的攻击可以是超级隐秘的,只保留未经授权的特权,而不是立即窃取。由于合约本身是完美无瑕的,这些 DeFi 项目的开发人员几乎不可能发现哪里出了问题!
每个人都在熊市中挣扎。我不想伤害任何人,我想帮助他们,尤其是当他们是如此努力工作的团队。因此,我尽力帮助项目团队了解根本原因,并加快修补过程。
这里的情况一开始非常复杂。缺陷在区块链系统的深层核心,但受害者是建立在它之上的 DeFi 协议。一些协议可能有紧急出口来暂停和升级它们的契约,而其他的则是不可变的。
最终的补丁必须由Moonbeam 团队完成,但最大的受害者Moonwell井可以在Moonbeam团队行动之前缓解这个漏洞。我注意到Moonbeam 和Moonwell 都在Immunefi上启动了他们的赏金项目,所以我和Immunefi的团队讨论了潜在的特殊情况(没有透露项目的具体名称)。在意识到其他项目,比如 uniswap 风格的 DEXes,不能真正做任何有用的事情之后,我决定不向他们报告,以尽量减少泄露关键信息的风险。由于只有资产 ERC-20问题可能是 Moonwell 团队的一个问题,我必须将 Moonbeam 的报告分成两部分,只有必要的信息和独家的 Glimmer 利用 POC 提交给他们。
我特别照顾了Moonbeam 团队即使他们可能不知道。我花了额外的时间学习他们的代码库,并编写了两个完整的测试用例(600 + LOC) ,以防他们需要更多的根本原因解释。我询问了 PureStake 团队discord ,以确保一旦第一个工程师上班,我就提交报告。幸运的是,它工作了: 他们开始处理这个问题在星期五和完成补丁之前的周末没有任何询问!
这是隐藏在基于区块链的智能合约核心设计的最后一个意想不到的缺陷吗?当然不是!对于每一个代表来说,在黑暗中还隐藏着另一个更加疯狂的问题。总有其他更奇异的问题等着我!.和我一起在我的旅程中,因为我发现这些bug,把他们推向光明,使区块链更安全的每个人!