Solidity安全之delegatecall 的滥用问题
摘要: Soildity 作为编写智能合约的语言,已经被广泛的应用。但同时,开发者和用户也得到了惨痛的教训,智能合约的安全问题层出不穷。因此,我们总结了一些常见的Solidity安全问题。前车之鉴,后车之师,希望后来者能有所警惕。
Soildity 作为编写智能合约的语言,已经被广泛的应用。但同时,开发者和用户也得到了惨痛的教训,智能合约的安全问题层出不穷。因此,我们总结了一些常见的Solidity安全问题。前车之鉴,后车之师,希望后来者能有所警惕。
delegatecall 「滥用」问题
在 Solidity 中提供了delegatecall函数来实现合约之间相互调用及交互。各种调用,导致了delegatecall函数被合约开发者“滥用”,甚至“肆无忌惮”提供任意调用“功能”,导致了各种安全漏洞及风险。
Delegatecall是一种常用的调用函数,它的特点是调用后内置变量 msg 的值不会修改为调用者,但执行环境为调用者的运行环境。
代码分析
在智能合约的开发过程中,合约的相互调用是经常发生的。开发者为了实现某些功能会调用另一个合约的函数。比如下面的例子,调用一个合约 A 的 test() 函数,这是一个正常安全的调用。
但是在实际开发过程中,开发者为了兼顾代码的灵活性,往往会有下面这种写法:
这将引起任意 public 函数调用的问题:合约中的 delegatecall 的调用地址和调用的字符序列都由用户传入,那么完全可以调用任意地址的函数。
相关事件
7 月 19 日,Parity发布安全警报,警告其钱包软件1. 5 版本及之后的版本存在一个漏洞。据该公司的报告,确认有153,000ETH(大约价值 3000 万美元)被盗。
因为initWallet函数是公开函数( public function) , 攻击者调用initWallet,重新初始化钱包会把之前合约钱包所有者覆盖, 即可改变钱包所有者。
漏洞代码:
攻击过程技术分析还原:
第一步:成为合约的owner
通过往这个合约地址转账一个value = 0 ,msg.data.length > 0 的交易, 执行到_walletLibrary.delegatecall的分支,该函数能无条件的调用合约内的任何一个函数,黑客调用了一个叫做 initWallet的函数:
这个函数再次调用initMultiowned函数:
不幸的是,initWallet没有检查以防止攻击者在合同初始化后调用到initMultiowned, 这个函数使得这个合约的所有者被改为攻击者,相当于从unix中获得了root权限。
第二步: 转账, 剩下的事情就很清晰了,通过调用execute函数转账到黑客的地址:
第一个参数: address to= 0xb3764761e297d6f121e79c32a65829cd1ddb4d32, 转账额度116779808c03e4140000是为以Wei为单位的的eth,即 82189000000000000000000,可以通过如下的代码获得具体数值。
作为已经有过被利用先例的漏洞,开发者在智能合约在部署前必须通过严格的审计和测试,在编写时使用delegatecall要更加小心。
评论(0)
Oh! no
您是否确认要删除该条评论吗?