回首Delegatecall漏洞下的Parity多重签名合约
摘要: 黑客通过 delegatecall 调用 initWallet 函数, initWallet 没有检查以防止攻击者在合同初始化后调用到 initMultiowned ,可以将Parity Wallet库合约变为常规多sig钱包并成为它的所有者。
事件回顾
2017年7月19日,Parity Multisig 电子钱包合约被爆出漏洞,攻击者从三个高安全的多重签名合约中窃取到超过15万以太坊(约3000万美元)。
首先我们先来简单了解一下Parity 钱包:
这个钱包的特点有几个:
第一个是它因为是重新写的代码,所以跑起来更快,占用系统的资源更少。
第二个特点是它的同步功能做得更好,所以其他钱包很久不能同步的的时候,它还是能够很快同步。
第三个特点,它虽然是一个全节点钱包,但是它把那些很早的区块只留下了区块头,其他内容删减了,所以同步好的区块的大小也就几个G,而如果是用以太坊的官方全节点钱包,光区块大概就得有40个G。
第四个特点,这个对ICO特别有用,就是它能够设置定时发送交易,能够在到达某个区块数的时候自动发送转账交易。
这个钱包不好的地方在于它对发送代币的支持不太好。不过这个问题可以通过把它的地址导入 imToken 来实现代币的方便发送。
漏洞缘由:
delegatecall的含义:
.delegatecall(...) returns (bool):issue low-level DELEGATECALL, returns false on failure, forwards all available gas, adjustable。 call与delegatecall的功能类似,区别仅在于后者仅使用给定地址的代码,其它信息则使用当前合约(如存储,余额等等),函数的设计目的是为了使用存储在另一个合约的库代码。
所以开发者在提供这样的库时,就要如何安排存储来达到这样的目的。
注意delegatecall是危险函数,他可以完全操作当前合约的状态。
黑客通过 delegatecall 调用 initWallet 函数, initWallet 没有检查以防止攻击者在合同初始化后调用到 initMultiowned ,可以将Parity Wallet库合约变为常规多sig钱包并成为它的所有者。意思就是漏洞使得黑客能通过 library 库函数,让自己成为多个 Parity 钱包的新主人,然后调用转账函数把钱转走。
访问控制问题在所有程序中都很常见,而不仅仅是智能合约。
事实上,人们经常通过其公共或外部功能访问合约的功能。
尽管不安全的可视性设置会给攻击者直接访问合约的私有价值或逻辑的方式,但访问控制旁路有时更加微妙。
这些漏洞可能发生在合约使用已弃用tx.origin的验证调用者时,长时间处理大型授权逻辑require并delegatecall在代理库或代理合约中鲁莽使用。
具体分析:
1、 initWallet 函数可以改变合约的 owner 。
2、 代码里使用了 delegatecall() 函数,导致所有 public 函数对所有人可见。包括 initWallet 函数。而且 initWallet 函数也没有作任何防护措施。
3、 攻击者先获取owner权限,将调用函数的指令放在Data中。
4、 然后执行execute获取所有 funds:
防范方法
1、谨慎使用 delegatecall() 函数。
2、明确函数可见性,默认情况下为public类型,为防止外部调用函数被内部调用应使用 external。
3、加强权限控制。敏感函数应设置 onlyOwner 等修饰器。
(作者:区块链安全档案,内容来自链得得内容开放平台“得得号”;本文仅代表作者观点,不代表链得得官方立场)
评论(0)
Oh! no
您是否确认要删除该条评论吗?