内容简介:区块链安全咨询公司曲速未来表示:Solidity作为一种用于编写以太坊智能合约的图灵完备的语言,除了常见语言特性以外,还提供了调用/继承其他合约的功能。在call、delegatecall、callcode三个函数来实现合约之间相互调用及交互。本文为作者“区块链安全档案”,原创文章,转载时请保留本声明及附带文章链接。 内容仅供读者参考,并非投资建议,本网站将保留所有法律权益。
2018-09-14 19:32 区块链 技术
941 收藏
区块链安全咨询公司曲速未来表示:Solidity作为一种用于编写以太坊智能合约的图灵完备的语言,除了常见语言特性以外,还提供了调用/继承其他合约的功能。在call、delegatecall、callcode三个函数来实现合约之间相互调用及交互。
前言
区块链安全咨询公司 曲速未来 表示:Solidity作为一种用于编写以太坊智能合约的图灵完备的语言,除了常见语言特性以外,还提供了调用/继承其他合约的功能。在call、delegatecall、callcode三个函数来实现合约之间相互调用及交互。正是因为这些灵活各种调用,也导致了这些函数被合约开发者“滥用”,甚至“肆无忌惮”提供任意调用“功能”,导致了各种安全漏洞及风险。
上述代码就是一个典型的存在call注入问题直接导致重入漏洞的demo。
2016年7月,The DAO被攻击者使用重入漏洞取走了所有代币,损失超过60亿,直接导致了eth的硬分叉,影响深远。
2017年7月20日,Parity Multisig电子钱包版本1.5 的漏洞被发现,使得攻击者从三个高安全的多重签名合约中窃取到超过15万ETH ,其事件原因是由于未做限制的 delegatecall 函数调用了合约初始化函数导致合约拥有者被修改。
2018年6月16日,有人在先知大会上提到了一种新的攻击场景——call注⼊,主要介绍了利用对call调用处理不当,配合一定的应用场景的一种攻击手段。
接着于 2018年6月20日,ATN代币团队发布《ATN抵御黑客攻击的报告》,报告指出黑客利用call注入攻击漏洞修改合约拥有者,然后给自己发行代币,从而造成 ATN 代币增发。
Solidity 的三种调用函数
在Solidity中,call函数簇可以实现跨合约的函数调用功能,其中包括call、delegatecall和callcode三种方式。
以下是Solidity中call函数簇的调用模型:
这些函数提供了灵活的方式与合约进行交互,并且可以接受任何长度、任何类型的参数,其传入的参数会被填充至32字节最后拼接为一个字符串序列,由EVM解析执行。
在函数调用的过程中,Solidity中的内置变量msg会随着调用的发起而改变,msg保存了调用方的信息包括:调用发起的地址,交易金额,被调用函数字符序列等。
三种调用方式的异同点
call: 最常用的调用方式,调用后内置变量msg的值会修改为调用者,执行环境为被调用者的运行环境(合约的 storage)。
delegatecall: 调用后内置变量msg的值不会修改为调用者,但执行环境为调用者的运行环境。
callcode: 调用后内置变量msg的值会修改为调用者,但执行环境为调用者的运行环境。
delegatecall滥用问题
delegatecall: 调用后内置变量msg的值不会修改为调用者,但执行环境为调用者的运行环境。
原理
在智能合约的开发过程中,合约的相互调用是经常发生的。开发者为了实现某些功能会调用另一个合约的函数。比如下面的例子,调用一个合约A的test()函数,这是一个正常安全的调用。
但是在实际开发过程中,开发者为了兼顾代码的灵活性,往往会有下面这种写法:
这将引起任意 public 函数调用的问题:合约中的delegatecall的调用地址和调用的字符序列都由用户传入,那么完全可以调用任意地址的函数。
除此之外,由于delegatecall的执行环境为调用者环境,当调用者和被调用者有相同变量时,如果被调用的函数对变量值进行修改,那么修改的是调用者中的变量。
call 安全问题
call: 最常用的调用方式,调用后内置变量msg的值会修改为调用者,执行环境为被调用者的运行环境。
call注入是一种新的攻击场景,原因是对call调用处理不当,配合一定的应用场景的一种攻击手段。
call 注入原理
call 调用修改 msg.sender 值
通常情况下合约通过call来执行来相互调用执行,由于call在相互调用过程中内置变量msg会随着调用方的改变而改变,这就成为了一个安全隐患,在特定的应用场景下将引发安全问题。
外部用户通过call函数再调用合约函数:
高度自由的 call 调用
在某些应用场景下,调用函数可以由用户指定;下面是call函数的调用方式:
从上面可以看出,call函数拥有极大的自由度:
1.对于一个指定合约地址的call调用,可以调用该合约下的任意函数
2.如果call调用的合约地址由用户指定,那么可以调用任意合约的任意函数
为了便于理解,可以将智能合约中的call函数类比为其他语言中的eval函数,call函数相当于给用户提供了随意调用合约函数的入口,如果合约中有函数以msg.sender作为关键变量,那么就会引发安全问题。
call 函数簇调用自动忽略多余参数
call函数簇在调用函数的过程中,会自动忽略多余的参数,这又额外增加了call函数簇调用的自由度。下面的例子演示call自动忽略多余参数:
例子中test()函数仅接收一个uint256的参数,但在callFunc()中传入了三个参数,由于call自动忽略多余参数,所以成功调用了test()函数。
callcode 安全问题
callcode: 调用后内置变量msg的值会修改为调用者,但执行环境为调用者的运行环境。
由于callcode同时包含了call和delegatecall 的特性,通过上文对call和delegatecall的安全问题进行了分析和举例,可以得出的结论是call和delegatecall存在的安全问题将同时存在于callcode中,这里不再进行详细的分析。
总结
针对文中所提到的安全隐患,区块链安全咨询公司 曲速未来 建议:
1.call、callcode、delegatecall调用的自由度极大,并且call会发生msg值的改变,需要谨慎的使用这些底层的函数;同时在使用时,需要对调用的合约地址、可调用的函数做严格的限制。
2.call与callcode调用会改变msg的值,会修改msg.sender为调用者合约的地址,所以在合约中不能轻易将合约本身的地址作为可信地址。
3.delegatecall与callcode会拷贝目标代码到自己的环境中执行,所以调用的函数应该做严格的限制,避开调用任意函数的隐患。
4.智能合约在部署前必须通过严格的审计和测试。
本文内容由 曲速未来安全咨询公司编译,转载请注明。 曲速未来提供包括主链安全、交易所安全、交易所钱包安全、DAPP开发安全、智能合约开发安全等相关区块链安全咨询服务。
本文为作者“区块链安全档案”,原创文章,转载时请保留本声明及附带文章链接。 内容仅供读者参考,并非投资建议,本网站将保留所有法律权益。
以上所述就是小编给大家介绍的《曲速未来 :以太坊智能合约编码安全之Call注入》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Learn Python the Hard Way
Zed A. Shaw / Addison-Wesley Professional / 2013-10-11 / USD 39.99
Master Python and become a programmer-even if you never thought you could! This breakthrough book and CD can help practically anyone get started in programming. It's called "The Hard Way," but it's re......一起来看看 《Learn Python the Hard Way》 这本书的介绍吧!