主页 > 最新版官网imtoken > 你绕过了以太坊合约的安全弱点III

你绕过了以太坊合约的安全弱点III

最新版官网imtoken 2023-07-16 05:14:48

摘要:过年之前,最后说一下以太坊安全的特点。 以太坊通过硬分叉解决了这个问题。 合约所有者利用函数的异常处理和调用堆栈大小限制进行攻击。 结论 通过对这几个问题的参考文献的研究,我们看到了以太坊合约设计中的一些弱点。

新年前,我们最后来谈一谈以太坊安全性的特点。

无法修复错误

合约一旦在区块链上发布,就无法修改。 相应地,合约中的任何错误都没有机会被纠正。 如果希望能够修改bug,合约编写者需要在编写合约时预留一些修改或终止合约的代码。 但是,保留修改后门的方法是有争议的,因为在以太坊的愿景中,一旦部署了智能合约,其设置就应该是不可更改的。

形式上,因为bug无法修改,可能会导致一些很严重的攻击,没有办法弥补。 DAO 攻击是唯一的例外。 以太坊通过硬分叉解决了这个问题。 但这种做法并没有得到整个社区的认可,因为它违背了“代码即法律”的原则。

调用堆栈大小限制

一个合约每次调用另一个合约,调用栈都会增加一帧。 上限为1024,当达到这个上限时erc20是以太坊链吗,下次调用会触发异常。 如果攻击者首先让他的调用栈只差一帧就被填满,然后调用受害者合约的函数,那么在受害者函数执行过程中的任何调用都会导致执行失败。 如果受害函数没有正确处理执行成功或失败,可能会导致意想不到的结果。 在本文的其余部分,我们将通过一个例子来说明这一点。

为了解决这个问题,在以太坊的一次升级中,规定每次通过call或delegatecall调用合约函数时,最多只能将剩余gas的63/64分配给被调用函数。 只能容纳大约470万瓦斯。 也就是说,如果调用者一开始投入了一个gas,经过10层递归调用,最里面的函数至多有(63/64)^10*a个gas。 因此,调用深度不能超过 1024 。 在下面的攻击案例中,假设没有这样的补丁。

时间限制

大量应用程序使用时间限制来确定何时允许某些操作。 例如,在 ERC 20 合约中,从某个时刻开始,允许用户使用以太币购买代币。

在智能合约的执行过程中,当前时间取自给定交易所在区块的区块时间戳。 因此,一个区块中的所有交易都使用相同的时间戳执行。 这个设置保证了智能合约在每个矿工中的执行结果是一致的。

但是这种设置也可能会导致一些攻击,因为矿工在选择时间戳时有一定的自主权,这可能会为一些攻击埋下后门。

攻击政府合约

GovernMental 是一种“庞氏游戏”类型的合约。 严格来说不能叫作弊,因为庞氏骗局的规则是公开写在合约里的。 在这个合约中,每个人都通过向合约转入一笔钱来加入庞氏骗局游戏。 合约通过两个数组记录参与者的地址和每个参与者转账的金额。 如果最后一个人加入后12小时没有下一个人加入,那么最后一个人可以得到所有的好处。 (这个设定是不是有点像大名鼎鼎的Fomo3D?值得注意的是,Fomo3D出现的时间晚于本文。)

以下是政府合同的简化版本

在这个合约中,参与者可以通过 invest() 函数投资以太币并加入游戏。 合约维护一个名为 jackpot 的变量,它表示如果将来没有人加入,获胜者将获得多少以太币。 新参与者必须在头奖中投入超过一半的以太币。 同时,新参与者投入的以太币将有一半添加到头奖中。 如果一分钟内没有新的参与者,则最后一个人获得头奖中的以太币,合约所有者拿走剩余的钱(留下 1 以太币作为下一轮的启动资金)。 需要注意的是,这里并没有在最后分发钱的时候检查通过send()函数转账是否成功。

这个简化版的合约有几个可以攻击的点。

攻击一个

这种攻击来自合约所有者本身,目的是为了防止原来的游戏赢家拿到钱。 合约所有者利用 send() 函数的异常处理和调用堆栈大小限制进行攻击。

攻击方式是提前进行大量的递归调用,使得在执行resetInvestment()时,调用栈达到上限,无法再向游戏赢家和合约所有者发送send()函数执行。 合同所有者和游戏获胜者都没有得到钱,钱保留在合同中,但重置合同状态的代码将照常执行。 只要再正常进行一轮游戏,合约所有者就可以将本应属于上一轮游戏获胜者的钱收入囊中。

攻击二

这种攻击方式来自于矿工。 矿工可以通过拒绝将其他人的交易与政府合约打包在一起,让他们想要的人成为合约博弈的赢家。 并且,攻击矿工在打包区块时可以任意决定交易顺序,影响谁是这个区块之后的lastInvestor。

如前所述,每个新参与者需要投入的以太币数量不能少于合约中头奖中以太币数量的一半。 一个人在发起交易时看到的头奖价值可能与交易执行时的头奖价值不同。 因此,这个人可能认为他在发起交易时投入的以太币数量符合要求。 但在执行过程中,由于头奖价值发生变化,成为无效交易。 这就是上一篇文章中提到的不可预知状态问题。

此外,矿工有权决定区块时间戳。 合约执行时,判断是否可以执行resetInvestment,就是读取矿工确定的区块时间戳。 通过影响区块时间戳,游戏结果也会受到影响。

结语

通过对这几个问题参考文献[1]的研究,我们看到了以太坊Solidity合约在设计上的一些弱点。 虽然这些弱点不叫漏洞erc20是以太坊链吗,但是如果你不理解这几点,在写合约的时候没有充分考虑,你可能会写出有安全问题的合约。

参考:

[1] Atzei、Nicola、Massimo Bartoletti 和 Tiziana Cimoli。 “对以太坊智能合约 (sok) 攻击的调查。” 安全和信任原则。 斯普林格,柏林,海德堡,2017 年。164-186。

--

Conflux致力于打造下一代高性能DAPP公链平台