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等复杂过程变得安全简单。