继承变量覆盖及构造函数失配,竟然会导致这些漏洞

安全,区块链领域举足轻重的话题。本期咱们聊聊,由于名称书写、声明语句、继承中变量覆盖等细节问题引起的巨大安全隐患。 「区块链大本营」携手「成都链安科技」团队重磅推出「合约安全漏洞解析连载」,以讲故事的方式,带你回顾区块链安全走过的历程;分析漏洞背后的玄机。让开发者在趣味中学习,写出更加牢固的合约,且防患于未然。 当然,这些文章并不是专为开发者而作的,即使你不是开发者,当你读完本连载,相信再有安全问题爆出时,你会有全新的理解。

引子: 《易》曰:‘君子慎始,差若毫厘,缪以千里。’ - 《礼记·经解》

上回讲到:

机制依赖参数主导

矿工操纵投机取巧

区块参数作为区块属性的数据,对于挖掘区块的矿工来说,并不具有完全的随机性,因此将其作为随机数生成的依据是有局限性和危险性的。而以太坊本身又没有提供类似于传统语言的rand()函数,所以随机数生成的来源,尽量来源于区块链外部或者利用新的信任模型RanDAO来完成。随机数生成作为目前以太坊游戏的核心,在原理的定制上直接决定了项目质量和项目寿命。

本回咱们来聊聊:

继承变量名同实不同

构造函数名异失其义

广义的名字,指明了一个特定的人或物,将其与相似的其他人或物区别开来。我们把名字作为对一个人或物的称呼,初次了解人或物,我们都会先尝试记住他们的名字。

计算机也是如此,在区块链开发,合约的编写当中,我们给予不同函数、不同变量以不同的名字,程序才能按照编写的意愿调用和执行。正确书写名称、正确声明函数自然就成为智能合约安全开发的基础。

然而,这样的问题在区块链发展到近期依然屡次出现,导致安全事件的发生,例如Morphtoken, B2X, DoubleOrNothinglmpl等多个合约中出现的Owned合约构造函数Owned大小写问题。

本期咱们就来聊聊由于名称书写,声明语句,继承中变量覆盖等细节问题引起的巨大安全隐患。

01

基础知识

Solidity中的构造函数

Solidity的使用与面向对象编程语言非常相似。构造函数(constructor)用于初始化合约对象。一个合约的构造函数的方法名与合约的名字相同,在合约创建时,对于状态变量的数据初始化操作是通过调用构造函数完成的,一般包括:设置代币名称、标识符、发币、将所有代币发送给owner,注意此调用仅存在于合约部署时。此外,合约的所有者(owner)的设置一般也放在构造函数当中。因此,构造函数相当于合约启动的引擎

以太坊solidity0.4.22引入了新的构造函数声明形式constructor(),该函数引入的目的是避免编程人员在编写构造函数时的命名错误。

Solidity中的继承

Solidity支持多继承和多态,其原理是代码拷贝。换句话说,继承的写法总是能够写成一个单独的合约。当一个合约从多个合约继承时,只有一个合约(子类)会被部署到链上,而其他的代码都会被拷贝到这个单一的合约当中去。

02

因小失大

MorphToken出现的安全漏洞只是因为在构造函数中Owned大小写没有注意Owned写成的owned,使owned函数失去构造函数仅在部署时才能调用的特殊性,导致任何账户都能调用,来实现更改owner变量,转移合约所有权的恶性事件。攻击者在初次刺探时可能以为要黑构造函数可能相当于打李逵,结果细看之后发现对方不过是个李鬼。

继承的情况有许多种,在合约继承中出现的漏洞是因为:子类重新定义的变量继承父类的函数,而且还取了同样的名字来方便理解,而其实调用父类函数并不会操作子类的这个变量。开发者认为函数操作的是子合约的变量,没想到操作的父合约的变量。这个失误还曾被当作蜜罐手段伪装成漏洞吸引想要改变合约权限、偷取合约内资金的玩家上钩。

03

构造函数失配漏洞

上面讲到如果构造函数在声明时出错,变成了一个普通函数,那么,合约将存在重大安全风险。我们构造函数失配的情况分为两大类:

一、构造函数名和合约名不一致

  • 案例合约:

在这个合约中,ownerWallet和合约的函数名不一致,变成了普通的函数,导致用户可以执行此函数,变成合约的owner,然后取出合约地址下的Ether。

  • 漏洞修复

Solidity 0.4.22提出了构造函数的新的写法constructor() public {},如果可能,推荐这种写法,如果版本低于0.4.22,那么一定要着重检测构造函数的名称是否和合约名相同

二、constructor声明形式错误

  • 案例合约

其中,owned合约的function constructor()函数的功能是将创建者地址赋予owner,用于后续的身份验证。但是,在使用constructor声明构造函数时,开发者错误的在其前面添加了一个function关键字,导致其变成一个名为constructor普通的函数。任意账户地址都可以调用constructor()函数,并修改owner的值,导致合约管理权限被盗用。

  • 漏洞修复

Solidity 0.4.22 提出的新的构造函数的完整声明形式如下,注意:constructor前无function

04

合约继承中的变量覆盖漏洞

这里我们拿Owned合约做一个简单的例子。

调用useEmergencyCode函数,只会更改TestBank合约中的owner,并不会更改Owned中的owner,onlyOwner中的owner仍是合约的部署者地址。

换句话说,TestBank合约中的owner与Owned中的owner是不一样的两个变量。根据上面提到的Solidity原理的解释:对于EVM来说,每个Storage 变量都会有一个唯一标识的slot id。在这里,虽然都叫做owner,但是从bytecode的角度来看,他们都是由不同的slot id来确定的,因此也和变量的名字没有什么关系。

关于Storage变量以及slot的相关知识我们也曾在漏洞连载分析第七期存储器局部变量未初始化中讲到过,在此就不赘述。

05

失之毫厘,差之千里

正确记住对方的名字,在社交礼仪中是非常重要的一点,代表着对他人的尊重。

在合约编写的过程中,规范书写,正确声明,辨析不同变量也是对代码的尊重,更是对工作的尊重。在做到这份尊重的同时,也能带来项目质量和资金安全的提升,当大部分开发者都做到这一点,这个产业的良性循环也就慢慢启动。

本回结语

蔺相如,司马相如,名相如,实不相如;

魏无忌,长孙无忌,人无忌,尔勿无忌。

引用:

[1]: Solidity原理(一):继承(Inheritance):

https://blog.csdn.net/Programmer_CJC/article/details/80042261

[2]: 以太坊蜜罐智能合约分析:

https://paper.seebug.org/631/

[3]: Solidity语法---以太坊智能合约生命周期:

https://www.jianshu.com/p/61e2d9e31aab

[4]: 深入理解Solidity:

https://solidity-cn.readthedocs.io/zh/develop/solidity-in-depth.html

[5]: 注意!3份合约又存在Owner权限被盗问题——低级错误不容忽视:

https://mp.weixin.qq.com/s/xPwhanev-cjHhc104Wmpug

相关阅读:

杨霞 成都链安科技CEO,创始人。电子科技大学副教授,最早研究区块链形式化验证的专家。一直为航空航天、军事领域提供形式化验证服务。主持国家核高基、装发重大软件课题等近10项国家课题。CC国际安全标准成员、CCF区块链专委会委员。发表学术论文30多篇,申请20多项专利。是成都链安科技有限公司创始人之一,该公司专注于区块链安全领域,其核心技术为形式化验证。

原文发布于微信公众号 - 区块链大本营(blockchain_camp)

原文发表时间:2018-10-11

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

了解与实现“工作量证明”的源头 Hashcash

让我们来看看 Hashcash 的思路:一封要证明其合法性的电子邮件需要附带一些对字符串的 hash 值来证明其耗费了一定的时间/资源运行了某个算法(Hashc...

43411
来自专栏司想君

前端也要学系列:设计模式之装饰者模式

今天我们来讲另外一个非常实用的设计模式:装饰者模式。这个名字听上去有些莫名其妙,不着急,我们先来记住它的一个别名:包装器模式。

922
来自专栏java工会

一分钟搞明白java8中的lambda|文末红包

2305
来自专栏web前端教室

javascript ES6 初次相见

JS的ES6网上也热炒了好久了, 我一直也没怎么太细看, 今天想起来就写个东西, 也为分享,也为学习。 我喜欢接地气一点,所以网上的那些新名词我就不写了, 就写...

1927
来自专栏月牙寂

[以太坊源代码分析]III. 挖矿和共识算法的奥秘

1.待挖掘区块需要组装 在Ethereum 代码中,名为miner的包(package)负责向外提供一个“挖矿”得到的新区块,其主要结构体的UML关系图如下...

4528
来自专栏懂啵的蟒络空间

哈希现金(Hashcash)与“工作量证明”

“哈希现金(Hashcash)是一种用于防止垃圾电子邮件和拒绝服务攻击的工作量证明系统,最近以其在比特币(以及其他加密货币)挖矿算法中的应用而闻名,由Adam ...

54910
来自专栏区块链大本营

当智能合约安全遇见《海上钢琴师》,自由与限制应是怎样的关系?

自1995年尼克萨博第一次提出智能合约理念以来,智能合约的功能延展越来越迅速,代码逻辑功能也越来越复杂。

873
来自专栏一个会写诗的程序员的博客

在 Java 9 的JShell中 跟Kotlin 的REPL中尽情体验函数式编程乐趣吧《Kotlin极简教程》正式上架:

相比之下, 我们不得不说,Java 8,9中的 Stream API 还是有点啰嗦,绕来绕去。不如Kotlin来得直截了当,简单优雅。

901
来自专栏Janti

项目心得:广度遍历搜索部门处理业务

部门树节点 平常在做后台管理系统的时候,多多少少都会涉及部门管理,部门有上下级,所以架构会呈现出树形,下图是一个简单的部门节点图: ? 这个和平时的二叉树很像,...

3178
来自专栏区块链大本营

程序员们,快来找漏洞啊!找到就赏15ETH

在以太坊上递归检索动态数组或链接列表可能会造成很严重的安全问题,因为攻击者可能会增加它们的大小以使得智能合约出现异常。

1132

扫码关注云+社区

领取腾讯云代金券