据@FatMan报道,Mirror Protocol 遭受了黑客攻击。这篇博客对此有很好的报道。在这篇短文中,我们将使用攻击交易来详细说明这是如何发生的。

免责声明:本文基于公开交易以及我们对 Mirror Protocol 和 Terra 生态系统的理解。如果有任何不准确之处,请告知我们。欢迎对本博客提出任何意见。
1. 攻击
1.1. 准备
该交易用于准备攻击。
步骤 1: 在此交易中,攻击者首先向锁定合约发送了 100,000 USTC。这并非开仓的必要条件,但对攻击至关重要。

步骤 2: 之后,攻击者通过存入 10 USTC 作为抵押品并指定抵押率 (collateral_ratio) 为 2.5 来开仓。

指定了 short_params,以便铸币合约将铸造的 mAssets(即 mETH)进行出售,并将获得的 USTC 添加到仓位的锁定金额中。
步骤 2.1: 让我们一步一步地了解交易。首先,将调用 open_position 函数来打开一个 ID 为 43186 的空头仓位。

步骤 2.2: 由于添加了可选的 short_params,合约将首先根据当前 ETH 价格铸造 0.001208 mETH,然后通过在 mETH-UST Pair 中进行兑换来出售。

步骤 2.3: 0.001208 mETH 将被兑换成 4.06582 USTC。兑换的 USTC 在扣除相关费用(例如税费)后将发送到锁定合约。这是因为开仓的仓位只能在一段时间后解锁。

步骤 2.4: 接着将调用 lock_position_funds_hook。在此函数中,通过查询 current_balance 并将 current_balance 与 locked_funds 进行比较来计算 position_locked_amount。

然而,正如我们在步骤 1 中看到的,100,000 USTC 已直接转入锁定合约,因此 locked_amount 将约为 100,004 USTC,而不是 4 USTC。

步骤 2.5: 最后,将调用 increase_short_token 来记录 sLP 代币。

至此,攻击者通过直接向锁定合约发送 100,000 USTC 并以 10 USTC 作为抵押品,开了一个仓位。该仓位的锁定金额约为 100,004 USTC,并可在一段时间后解锁。攻击者通过发送 1,000 到 100,000 USTC,开立了许多此类仓位。

1.2. 攻击
Mirror Protocol 不会检查仓位 ID 的重复性。在这种情况下,攻击者可以反复提交许多重复的仓位 ID 来解锁一个仓位中的锁定金额。
该交易是攻击交易。 例如,对于仓位 ID 43186,攻击者重复了 437 次。

由于原始合约代码没有检查重复性,在这次单次函数调用中,约有 43.7M (437 * 0.1M)USTC 被解锁。

请注意,其他仓位也通过相同的机制被解锁。
2. Bug 修复
该漏洞已在此提交中修复。

具体来说,unlockable_positions 是一个包含待解锁仓位 ID 的向量。在原始代码中,没有检查 unlockable_positions 中是否存在重复的 ID。修补后的代码添加了对仓位 ID 重复性的检查。
3. 结论
正如 @FatMan 和其他社区成员指出的那样,此 bug 已存在数月并在野外被利用。我们认为,对已被利用的漏洞进行悄无声息的修复并不是一种好的安全实践。此外,我们也认为高知名度的 DeFi 项目应该部署一些守门员,主动监控其应用程序的状态,并在出现异常情况时发出警报。



