引子:“庖人虽不治庖,尸、祝不越樽俎而代之矣。”?--《庄子·逍遥游》
古时候,有一位杰出的领袖名叫唐尧。
他所治理的地区人们安居乐业,但是他听闻隐士许由十分有才干,便萌生了将领导权让给许由的想法。但是许由拒绝了,并说出了这样一段话“鹪鹩巢于深林,不过一枝。”
至此,后人也用越俎代庖一词来表达越权的含义。
“越俎代庖”
在智能合约的实现中存在着访问权限,如果权限设置不合理,很容易造成智能合约被攻击,严重的还会造成巨大的经济损失。
成都链安-安全实验室对于智能合约安全有着丰富的经验和积累,但随着区块链技术越来越受重视,智能合约的数量也越来越多,随之而来的智能合约被攻击事件也越来越多,也让我们感受到了“让区块链更安全”的企业使命是多么的重要,但是一己之力难于对抗所有的威胁。
接下来,我们将会把自己的安全经验积累通过与智能合约CTF靶场ethernaut相结合,通过技术连载的方式向广大智能合约开发者普及在开发过程中,如何实现更安全的代码。
工行发放首单基于智能合约的数字人民币供应链贷款:金色财经报道,工商银行上海市分行成功实现了数字人民币智能合约在供应链金融场景的创新试点应用,发放首单基于智能合约的数字人民币供应链贷款,开辟了“数字人民币+供应链金融”的合作新模式。[2023/2/11 12:01:10]
现在我们就来聊一聊ethernaut靶场的第一题Fallback,
代码函数“越俎代庖”的事件。
一、权限漏洞简介
越权漏洞是指在智能合约中,因函数可见性设置不合理或函数缺乏有效的验证导致本不能调用某一函数的用户通过直接或者绕过验证的方式成功调用该函数。
该漏洞可被单独利用,也可能结合其他漏洞进行组合攻击,利用方式简单,漏洞影响视存在漏洞的函数而定,可能对合约造成毁灭性打击。
二、Fallback“越俎代庖”
漏洞原理详细分析
2.1合约中的“俎”与“庖”
DFI.money:所有YFII Vault V2产品均已通过第三方智能合约审计:DFI.money(原YFII)官方发推表示,所有YFII Vault V2产品均已通过第三方智能合约审计。[2020/9/27]
如何理解合约中的“俎”与“庖”呢?先来看一段合约代码,如下图所示:
图1
这一段合约代码出自ethernaut靶场的第一题Fallback。针对于靶场中的问题,解题思路是通过调用回调函数function()payablepublic来触发owner=msg.sender;,使得合约的所有者变成调用者。
题目非常的简单,只要向此合约发起一笔交易,且满足require的条件就可触发fallback函数。
正常情况下,在对一个合约调用中,如果没有其他函数与给定的函数标识符匹配,或者没有提供附加数据,那么fallback函数会被执行。一般是作为转入以太币的默认操作。所以智能合约开发时一般是不需要将owner=msg.sender写到fallback函数中的。
声音 | 央行穆长春:央行数字货币会加载有利于货币职能的智能合约:中国人民银行支付结算司副司长穆长春在中国金融四十人论坛上表示,中国央行数字货币是可以加载智能合约的。在此需要强调的一点是,央行数字货币依然是具有无限法偿特性的货币,它是对M0的替代。它所具有的货币职能(交易媒介、价值储藏、计账单位)决定其如果加载了超出其货币职能的智能合约,就会使其退化成有价票证,降低可使用程度,会对人民币国际化产生不利影响,因此,我们会加载有利于货币职能的智能合约,但对于超过货币职能的智能合约还是会保持比较审慎的态度。[2019/8/10]
如下图所示:
图2
然而,在这里本不该被用户调用的owner=msg.sender被调用了,导致权限控制不当,产生了越权,“俎”与“庖”就这样发生了接下来的故事。
2.2相关安全事件
2.2.1Bancor合约事件
2020年6月18日,Bancornetwork被爆出存在漏洞。
量子链帅初:智能合约和Dapp现阶段是空中楼阁:量子链创始人帅初今日表达了一些对数字货币的思考:1.数字货币背后的核心理念是节点在网络上有对等的权利,因此我们把它叫做对等网络。2.网络的接入门槛对网络的拓展性非常重要,无门槛接入成就了比特币早期的发展。3.对等的意义在于人人有权利知道并校验网络的所有交易,因此网络没有欺诈,信任可以建立。4.现阶段的智能合约和Dapp基本上是空中楼阁,行业不能承受之重,如果这两个有问题的概念不能完善,3年后不会再有人再提起。5.数字货币也许会开启世界范围内的金融启蒙运动,真正教育大家,投资是有风险的。6.闸门已开,全世界最聪明的人才定会前赴后继的涌入,技术和媒体也都是一种杠杠,技术无限放大,积累财富;媒体作为杠杆,只是追逐热点,吸引大众流量,也会无限放大人性、幻象、假象。7.运行在全世界前1%的人的大脑中的共识,决定了剩下99%的共识,现阶段也决定了我们所有人的未来。[2018/6/1]
漏洞产生的原因是合约中存在一个public的safeTransferFrom方法,使得攻击者可以直接调用此方法授权给Bancornetwork合约的代币转出到任意账户。
其关于转账和授权的三个函数权限均为public,这使得任何用户都能对其进行调用。本次事件涉及资金50W余美元。
详细代码如下图所示:
以太坊竞争对手RSK发布比特币智能合约平台:以太坊竞争对手RSK实验室已经宣布:比特币智能合约平台主网于周一正式上线。该公司声称获得了90%的比特币哈希算力的支持,用于RSK侧链挖矿。且鼓励所有开发者在测试阶段参与寻找bug的奖励计划。[2017/12/5]
图3
权限为public的safeTransferFrom方法这个“奸臣”并没有得到Bancor合约“国王”的许可,直接夺走了“国家”的“财政大权”。
幸而Bancornetwork团队和白帽首先发现了此问题,并对资金进行了转移。在后续也对该漏洞进行了修复,才得以避免损失。
详细分析见
而同样的事件也在另外一个合约中上演,接下来我们将介绍6月底的VETH合约漏洞事件。
2.2.2VETH项目事件
2020年6月30,VETH项目被爆出漏洞。本次事件中“越俎代庖”的主角则是合约中的changeExcluded函数的external修饰符。
external修饰符使得任何人都可以调用changeExcluded函数来绕过transferFrom函数内部的授权转账额度检查,将合约的VETH代币盗走。
此次事件,攻击者利用此漏洞盗走919299个VETH后大量抛售,导致VETH代币价值瞬间流失。
详细见涉及到的合约代码如下图所示:
图4
通过以上两个案例,相信大家已经意识到了合约中“越俎代庖”事件的严重影响,那么如何在合约代码编写的过程中有效的区分“俎”与“庖”呢?
2.3“俎”、“庖”信息大揭秘
针对越权事件,首先需要合约开发人员了解函数可见性。
函数的可见性,一共有external、public、internal和private四种:
-External
外部函数作为合约接口的一部分,意味着我们可以从其他合约和交易中调用。一个外部函数f不能从内部调用。当收到大量数据的时候,外部函数有时候会更有效率,因为数据不会从calldata复制到内存.
-Public
public函数是合约接口的一部分,可以在内部或通过消息调用。对于public状态变量,会自动生成一个getter函数。
-Internal
这些函数和状态变量只能是内部访问,不使用this调用。
-Private
private函数和状态变量仅在当前定义它们的合约中使用,并且不能被派生合约使用。
开发人员在构造一个函数时,应当遵循这些可见性进行开发,要明确哪些函数是可以由用户调用的“俎”,而哪些又是合约中不能任意替代的“庖”,以最小原则进行分配。
比如一个函数safeTransfer在设计时是用于转账操作的,用户可以通过调用此函数,转账此合约发行的代币。我们使用public和external都可以满足需求,但就安全的角度,我们应当使用external,避免合约内对此函数进行调用,造成不可预期的风险。
如存在有一个safeTransferFrom函数,用户可以通过授权给此合约其他代币,将其他代币转移到一个指定地址的,当_token等于合约本身时,就会以合约本身的身份调用sadeTransfer函数,即而将合约内的钱转到其他地址。
图5
然而只是遵循函数可见性是远远不够的,函数的可见性,只是区分了合约内部、继承合约和外部这三个界限,远远不能满足我们的需求。
想要达到较为完善的权限管理,我们应当引入“角色”的概念,如:管理员、普通用户、特权用户等。在合约中存储这些角色的地址,通过判断地址或标志变量来进行权限的控制。
如下图所示:
图6
通过修饰器对这些不同的“角色”进行管理,如使用onlyOwner修饰器,限制特定的地址才可调用此函数。对应“角色”的权限管理。使用修饰器的方式,可以更加清晰的判断出是否存在纰漏。
三、安全总结
就链上现状来看,智能合约权限管理错误造成的漏洞比比皆是,其中不乏很多“著名项目”,而此类漏洞造成的损失也是巨大的。
成都链安安全团队依据多年合约审计和链上分析安全经验给出以下几点建议:
1、遵循权限最小化开发原则,在设计函数时应当就规划好可见性。
2、建立角色机制,使用修饰器对各函数进行权限管理,避免纰漏。
3、上线前一定找专业机构做好代码审计,正所谓“一人一个脑,做事没商讨;十人十个脑,办法一大套”。
郑重声明: 本文版权归原作者所有, 转载文章仅为传播更多信息之目的, 如作者信息标记有误, 请第一时间联系我们修改或删除, 多谢。