TrueUSD与Compound漏洞分析:多重入口点的安全风险

本文详细分析了TrueUSD稳定币在Compound协议中的安全漏洞,该漏洞由于TUSD存在两个交互入口点,可能导致数百万美元资金面临风险。文章深入探讨了漏洞原理、利用方式及修复方案,为智能合约开发者提供重要安全启示。

TrueUSD ↔ Compound 漏洞分析

TrueUSD(TUSD)是以太坊区块链上的一种稳定币。直到最近,它拥有多个入口点,这可能给各种协议带来问题。我们在审计Compound的cToken合约时发现了这样的问题。这个存在数百万美元风险的漏洞已被Compound和OpenZeppelin缓解,详细说明可在此处找到。

问题根源

一个合约怎么可能有多个入口点?实际上,单个合约确实不能。在TUSD的情况下,实际上有两个不同的合约都与相同的余额进行交互。本质上,TUSD的真实实现位于地址0x0000000000085d4780b73119b644ae5ecd22b376,而次要入口点0x8dd5fbce2f6a956c3022ba3663759011dd51e73e只是将所有调用转发给主合约。从外部角度来看,这意味着与其中一个合约交互会影响两个合约的余额。在大多数情况下,这不是问题,因为你只需向合约提供一个地址而忽略另一个。但是,如果你与两者都交互,就可能会遇到问题。

与任意合约交互的危险

为什么开发人员会想要与同一代币的两个不同地址交互?当然他们不会。实际上,与次要地址交互从来就没有意义,因为成本更高而结果相同。因此,没有善意的理由调用次要合约。但是,如果你的合约可以调用任意地址,这就可能被滥用。在Compound的具体案例中,以下函数容易受到这种攻击:

正如你所见,可以提供实现transfer和balanceOf函数的任意合约地址。有趣的是,添加此函数只是为了让意外将代币转移到合约的用户能够取回它们。

那么,我们如何利用这个函数?让我们仔细看看它。首先,我们确保要清理的代币不是CToken合约的基础代币。接下来,我们检查合约的余额,并将其可能拥有的任何资金转移给管理员。回想一下,TUSD有两个入口点——如果基础代币是主要的TUSD地址,但我们使用次要地址调用此函数,require条件将通过。因此,合约会将其全部基础余额转移给管理员地址。幸运的是,开发人员有先见之明,至少将代币转移给管理员,否则这种利用会更加严重。

如何滥用此漏洞

最初,似乎我们只能将基础资金转移给管理员。这将有效地禁用合约,因为不能再借入或提取资金,至少在资金归还之前是这样。虽然有害,但这更像是一种破坏性利用,对攻击者无利可图。缺少资金还会影响什么?cTUSD代币的汇率计算如下:

TUSD/cTUSD的汇率定义为: (总现金 + 总借款 - 总储备)/ 总供应量

这里,总现金是合约中的TUSD总额,总借款是从合约借出的TUSD金额,总储备是属于协议的金额。最后,总供应量是已铸造的cTUSD总额。

如果所有基础代币都被转移走,汇率会发生什么变化?这意味着总现金将为0,TUSD与cTUSD的比率将下降,因此cTUSD的价值将突然急剧下降。之后,当资金归还时,汇率将突然跳回初始值。攻击者如何获利?有几种选择:

  • 清算以TUSD作为贷款抵押品的用户
  • 借入TUSD,执行攻击,然后偿还更少的TUSD
  • 执行攻击,然后铸造cTUSD。当资金返还给合约时,赎回cTUSD获利

目前,TUSD不能用作抵押品,因此第一种攻击无效。

在我们发现此漏洞时,第二种攻击将产生合约中TUSD约12%的利润,约为310万美元。自那时起,合约中的资金量只增不减。

如何避免此问题

在我们的审计期间,我们将sweepToken函数置于管理员权限之后。由于资金无论如何都会转移给管理员,他们的参与是必要的,因此他们不妨自己执行调用。当然,这可能并非所有情况下的正确修复方法。更普遍适用的修复方法可能是:

本质上,我们做的是检查合约的基础余额在清理前后保持不变。由于跨合约调用,这确实会产生额外成本,但意味着我们永远不必担心任何其他具有多个入口点的代币。

结论

与此同时,次要的TUSD合约已被禁用,因此该代币现在只有一个入口点。当然,这并不意味着此漏洞永远不会再次出现,因为可能还有更多具有多个入口点的代币。例如,Tether USD(USDT)在升级合约时未来可能启用次要入口点。因此,在调用任意合约时应格外小心。如果调用者可以指定任何符合所需接口的合约,你应该预期任何事情都可能发生。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计