以 Kadena 智能合约为例,简析如何规避重入攻击和跨函数攻击
在这篇文章中,我们将简要地解释重入和跨函数重入之间的区别,以及图灵不完备性如何能够防止一些这样的攻击。
其中我们将提供一个跨函数重入利用的案例,该案例中Kadena区块链使用的是编程语言Pact,但图灵不完备性并未防止该恶意利用的发生。
事件简介Kadena区块链旨在实现比其他L1链更高的可扩展性、安全性和可用性。其开发了一种新的语言用以编写智能合约:Pact。
这种语言是人类可读的,且易于形式化验证,并具备可提高安全性的图灵不完备性。
这里提到的图灵不完备性意味着Pact无法做到图灵完备编程语言(如Solidity或Haskell)所能做到的那些事——看起来好像是个劣势,但其实智能合约编程,哪怕是最复杂的DeFi协议也很少会需要用到图灵完备性。
图灵不完备性最重要的一点是没有无界递归。虽然这确实大大减少了攻击面,但一些「经典」攻击是无法被100%避免的,接下来我们就会讲述跨函数重入的问题。
经典重入攻击重入攻击是非常常见的安全问题。这个问题不仅很难被开发者发现,也很难被审计师审查出其会导致的所有潜在后果。
重入攻击取决于函数在进行外部调用之前和之后执行的特定任务的顺序。
如果一个合约调用了一个不受信任的外部合约,攻击者可以让它一次又一次地重复这个函数调用,形成一个递归调用。而如果重新输入的函数执行重要的任务(如更新账户的余额),那这可能就会导致灾难性的后果。
下方是一个简化的例子。
我们把易受攻击的合约称为unsafe合约,把恶意的合约称为Attack合约。
1. 攻击者调用unsafe合约,以将资金转移到Attack合约中。
2. 收到调用之后,unsafe合约首先检查攻击者是否有资金,然后将资金转移到Attack合约。
3. 收到资金后,Attack合约执行回退函数,在它能够更新余额之前回调到不安全的合约,从而重新启动该过程。
因为这种攻击是通过无界递归调用进行的,所以如果语言不是图灵完备的,攻击就不可能进行。
跨函数重入跨函数重入类似于经典的重入攻击,除了重入的函数与进行外部调用的函数功能不同。这种重入攻击通常更难被发现——因为在复杂的协议中,组合的可能性太多,无法手动测试每个可能的结果。
这就引出了我们的概念证明:使用Pact语言进行简单的跨函数重入攻击。
-
Pact模块中的简单跨函数重入
正如我们在下方代码片段中看到的,合约中的函数对另一个实现特定接口的合约进行外部调用。这允许重入一个设计好的攻击合约。Pact中的功能是内置函数,可授予用户权限来执行敏感任务。以下代码仅供说明之用,并非取自真实案例合约。
- 星际资讯
免责声明:投资有风险,入市须谨慎。本资讯不作为投资建议。