Solana上租金小偷的故事
最近,发生了一起租金盗窃案。 该机器人从 Solana 生态系统中未初始化的账户中窃取资金,索取租金并从中获利。 Solend 团队在尝试攻击正在开发的新无许可池时注意到了该机器人(需要明确的是,存储在主要 Solend 协议中的资金完全不受影响)。 让我们通过对其中一个未经许可池的攻击进行案例研究,深入了解租金盗窃的运作方式。
介绍
最近,发生了一起租金盗窃案。
该机器人从 Solana 生态系统中未初始化的账户中窃取资金,索取租金并从中获利。
Solend 团队在尝试攻击正在开发的新无许可池时注意到了该机器人(需要明确的是,存储在主要 Solend 协议中的资金完全不受影响)。
让我们通过对其中一个未经许可池的攻击进行案例研究,深入了解租金盗窃的运作方式。
背景
要了解此漏洞是如何运作的,我们首先必须了解一下 Solana 中租金的运作方式。
由于账户可以存储每个验证者需要下载的数据,因此 Solana 根据数据量收取一定的租金。然而,只要账户余额不低于阈值,足以支付两年租金的账户就被视为免租金。幸运的是,租金非常便宜,因此豁免账户租金并不难。
因此,在创建新帐户时,大多数程序都需要将一些 SOL 转入新帐户以使其免租。
漏洞利用
通过调用 init_reserve
函数将新储备(也称为资产)添加到 Solend 池中,该函数创建 6 个新帐户来存储有关储备的数据:
- 储备详细信息——存储有关储备的信息,例如流动性薄荷、薄荷小数、预言机、配置等。
- 储备流动性代币账户——持有存入的代币
- 费用接收者代币账户——将收取借入费用的账户
- 储备抵押品铸币账户——存款收据代币,也称为
cTokens
- 储备抵押代币账户——持有用户的抵押代币
- 创建者抵押代币账户 — 创建者的
cToken
账户
帐户创建和初始化通常在同一交易中完成。然而,由于 Solana 的交易大小限制为 1232 字节,这 6 个账户的创建和初始化必须分为 2 个交易:创建和初始化。以下是对 init_reserve
的调用假设的样子:
注意到有什么不对劲吗?在两次交易之间,该帐户有租金,但没有所有者。这就是租金窃贼进来抢夺帐户及其租金的地方:
由于两次交易之间存在大约 40 秒(50 个槽)的窗口,因此此类攻击非常一致。
幸运的是,租金相对便宜,因此整个攻击每次迭代仅提取约 0.0082 SOL(4 个代币账户,每个账户价值约 0.002 SOL),在撰写本文时约为 28 美分。
尽管损失了成本,但这还是很烦人的……
例子
让我们看一下其中一个攻击。
交易1:
(……更多帐户被截断)
开发商创建了几个帐户并转移了足够的 SOL 以使它们免租金。这发生在插槽 136,580,113 中。
(……更多帐户被截断)
如前所述,攻击者获得了新创建帐户的所有权。这发生在槽 136,580,154,即初始交易后的 41 个槽(29 秒)。
交易2:
开发人员尝试取得该帐户的所有权,但由于攻击者取得了该帐户的所有权,因此失败并出现错误“帐户或令牌已在使用中”。这发生在 136,580,167 号槽中,即攻击者交易后 13 个槽(9 秒)。两个 Solend 事务之间总共有 54 个时隙间隙(38 秒)。
(……更多帐户被截断)
现在攻击已经结束,攻击者关闭账户,将租金转给自己。此次攻击期间被盗的总金额为 0.00815212 SOL。
影响
盗租攻击不会偷走太多钱。
他们只能偶尔赚取少量利润,因为 Solana 租金便宜,而且只有少数大型服务将帐户创建和初始化分开。此外,该策略的扩展性不佳,因为这种非原子帐户创建相对较少。
然而,即使金钱影响很小,它仍然令人讨厌。交易将失败并需要重新进行,从而影响可用性。
解决方案
作为临时权宜之计,Solend 重构了他们的代码库,将事务之间的 40 秒延迟降低到 15 秒左右(20 个槽),从而使攻击变得更加困难和不一致。
作为一种更持久的解决方案,Solend 实现了一个链上程序来处理帐户创建,允许他们将所有相关指令放入一个交易中。
本文由SlerfTools翻译,转载请注明出处。
SlerfTools是专为Solana设计的工具箱,致力于简化区块链操作,提供无编程全可视化界面,使发币、管理流动性和无代码创建Dapp等复杂过程变得安全简单。