Solana上租金小偷的故事

最近,发生了一起租金盗窃案。 该机器人从 Solana 生态系统中未初始化的账户中窃取资金,索取租金并从中获利。 Solend 团队在尝试攻击正在开发的新无许可池时注意到了该机器人(需要明确的是,存储在主要 Solend 协议中的资金完全不受影响)。 让我们通过对其中一个未经许可池的攻击进行案例研究,深入了解租金盗窃的运作方式。

介绍

最近,发生了一起租金盗窃案。

该机器人从 Solana 生态系统中未初始化的账户中窃取资金,索取租金并从中获利。

Solend 团队在尝试攻击正在开发的新无许可池时注意到了该机器人(需要明确的是,存储在主要 Solend 协议中的资金完全不受影响)。

让我们通过对其中一个未经许可池的攻击进行案例研究,深入了解租金盗窃的运作方式。

背景

要了解此漏洞是如何运作的,我们首先必须了解一下 Solana 中租金的运作方式。

由于账户可以存储每个验证者需要下载的数据,因此 Solana 根据数据量收取一定的租金。然而,只要账户余额不低于阈值,足以支付两年租金的账户就被视为免租金。幸运的是,租金非常便宜,因此豁免账户租金并不难。

因此,在创建新帐户时,大多数程序都需要将一些 SOL 转入新帐户以使其免租。

漏洞利用

通过调用 init_reserve 函数将新储备(也称为资产)添加到 Solend 池中,该函数创建 6 个新帐户来存储有关储备的数据:

  1. 储备详细信息——存储有关储备的信息,例如流动性薄荷、薄荷小数、预言机、配置等。
  2. 储备流动性代币账户——持有存入的代币
  3. 费用接收者代币账户——将收取借入费用的账户
  4. 储备抵押品铸币账户——存款收据代币,也称为cTokens
  5. 储备抵押代币账户——持有用户的抵押代币
  6. 创建者抵押代币账户 — 创建者的 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 实现了一个链上程序来处理帐户创建,允许他们将所有相关指令放入一个交易中。

💡
原文链接:solend

本文由SlerfTools翻译,转载请注明出处。

SlerfTools专为Solana设计的工具箱,致力于简化区块链操作,提供无编程全可视化界面,使发币管理流动性无代码创建Dapp等复杂过程变得安全简单。