[区块链安全-Ethernaut]区块链智能合约安全实战-连载中

准备

随着区块链技术的逐渐推广,区块链安全也逐渐成为研究的热点。在其中,又以智能智能合约安全最为突出。Ethernaut正是入门研究区块链智能合约安全的好工具。

  • 首先,应确保安装Metamask,如果可以使用Google Extension可以直接安装,否则可以使用FireFox安装
  • 新建账号,并连接到RinkeBy Test Network(需要在Setting - Advanced里启用Show test networks,并在网络中进行切换)
    [区块链安全-Ethernaut]区块链智能合约安全实战-连载中_第1张图片
  • 访问Faucet并获取测试币,每天都有0.1Eth的额度

现在就可以开始Ethernaut的探索之旅了!


0. Hello Ethernaut

本节比较简单,所以我将更关注整体过程,介绍Ethernaut的实例创建等等,自己也梳理一下,所以会更详细一些。

准备工作

进入Hello Ethernaut,会自动提示连接Metamask钱包,连接后,示意图如下:
成功连接Metamask
按F12打开开发者工具,在console界面就可以进行智能合约的交互。

[区块链安全-Ethernaut]区块链智能合约安全实战-连载中_第2张图片

创建实例并分析

单击 Get New Instance 以创建新的合约实例。

可以看出我们实际上是通过与合约0xD991431D8b033ddCb84dAD257f4821E9d5b38C33交互以创建实例。在辅导参数中,调用0xdfc86b17方法,附带地址为0x4e73b858fd5d7a5fc1c3455061de52a53f35d966作为参数。实际上,所有关卡创建实例时都会向0xD991431D8b033ddCb84dAD257f4821E9d5b38C33,附带的地址则是用来表明所处的关卡,如本例URL地址也为
https://ethernaut.openzeppelin.com/level/0x4E73b858fD5D7A5fc1c3455061dE52a53F35d966

[区块链安全-Ethernaut]区块链智能合约安全实战-连载中_第3张图片
实例已经成功生成,主合约交易截图如下:

主合约交易截图
进入交易详情,查看内部交易,发现合约之间产生了调用。第一笔是由主合约调用关卡合约,第二笔是由关卡合约创建合约实例,其中实例地址为0x87DeA53b8cbF340FAa77C833B92612F49fE3B822

[区块链安全-Ethernaut]区块链智能合约安全实战-连载中_第4张图片
回到页面来看,可以确认生成实例的确为0x87DeA53b8cbF340FAa77C833B92612F49fE3B822
[区块链安全-Ethernaut]区块链智能合约安全实战-连载中_第5张图片
下面我们将进行合约的交互以完成本关卡。

合约交互

此时,在console界面可以通过playercontract分别查看用户当前账户和被创建合约实例。player代表用户钱包账户地址,而contract则包含合约实例abiaddress、以及方法信息。

[区块链安全-Ethernaut]区块链智能合约安全实战-连载中_第6张图片
按照提示要求输入await contract.info() ,得到结果'You will find what you need in info1().'
await contract.info()

输入await contract.info1(),得到结果'Try info2(), but with "hello" as a parameter.'
await contract.info1()`

输入await contract.info2('hello'),得到结果'The property infoNum holds the number of the next info method to call.
await contract.info2('hello')
输入await contract.infoNum(),得到infoNum参数值为42(Word中的首位)。这就是下一步要调用的函数(info42)。
[区块链安全-Ethernaut]区块链智能合约安全实战-连载中_第7张图片
输入await contract.info42(),得到结果'theMethodName is the name of the next method.,即下一步应当调用theMethodName

await contract.info42()
输入await contract.theMethodName(),得到结果'The method name is method7123949.

await contract.theMethodName()
输入await contract.method7123949(),得到结果'If you know the password, submit it to authenticate().
await contract.method7123949()
所以通过password()可以获取密码ethernaut0,并将其提交到authenticate(string)
[区块链安全-Ethernaut]区块链智能合约安全实战-连载中_第8张图片
注意当在进行authenticate()函数时,Metamask会弹出交易确认,这是因为该函数改变了合约内部的状态(以实现对关卡成功的检查工作),而其他先前调用的函数却没有(为View)。
[区块链安全-Ethernaut]区块链智能合约安全实战-连载中_第9张图片
此时,本关卡已经完成。可以选择Sumbit Instance进行提交,同样要签名完成交易

[区块链安全-Ethernaut]区块链智能合约安全实战-连载中_第10张图片
在此之后,Console页面弹出成功提示,本关卡完成!

[区块链安全-Ethernaut]区块链智能合约安全实战-连载中_第11张图片

总结

本题比较简单,更多的是要熟悉ethernaut的操作和原理。


1. Fallback

创建实例并分析

根据先前的步骤,创建合约实例,其合约地址为0xe0D053252d87F16F7f080E545ef2F3C157EA8d0E
本关卡要求获得合约的所有权并清空余额
观察其源代码,找到合约所有权变更的入口。找到两个,分别是contribute()receive(),其代码如下:

  function contribute() public payable {
    require(msg.value < 0.001 ether);
    contributions[msg.sender] += msg.value;
    if(contributions[msg.sender] > contributions[owner]) {
      owner = msg.sender;
    }
  }
  receive() external payable {
    require(msg.value > 0 && contributions[msg.sender] > 0);
    owner = msg.sender;
  }

按照contribute()的逻辑,当用户随调用发送小于0.001 ether其总贡献额超过了owner,即可获得合约的所有权。这个过程看似简单,但是通过以下constructor()函数可以看出,在创建时,owner的创建额为1000 ether,所以这种方法不是很实用。

  constructor() public {
    owner = msg.sender;
    contributions[msg.sender] = 1000 * (1 ether);
  }

再考虑receive()函数,根据其逻辑,当用户发送任意ether,且在此之前已有贡献(已调用过contribute()函数),即可获得合约所有权。receive()类似于fallback(),当用户发送代币但没有指定函数对应时(如sendTransaction()),会调用该方法。
在获取所有权后,再调用withdraw函数既可以清空合约余额。

合约交互

使用contract命令,查看合约abi及对外函数情况。

[区块链安全-Ethernaut]区块链智能合约安全实战-连载中_第12张图片
调用await contract.contribute({value:1}),向合约发送1单位Wei。

[区块链安全-Ethernaut]区块链智能合约安全实战-连载中_第13张图片
此时,调用await contract.getContribution()查看用户贡献,发现贡献度为1,满足调用receiver()默认函数的最低要求。

[区块链安全-Ethernaut]区块链智能合约安全实战-连载中_第14张图片
使用await contract.sendTransaction({value:1})构造转账交易发送给合约,
[区块链安全-Ethernaut]区块链智能合约安全实战-连载中_第15张图片
调用await contract.owner() === player 确认合约所有者已经变更。
await contract.owner()  === player
最后调用await contract.withdraw()取出余额。
[区块链安全-Ethernaut]区块链智能合约安全实战-连载中_第16张图片
提交实例,显示关卡成功!

[区块链安全-Ethernaut]区块链智能合约安全实战-连载中_第17张图片

总结

本关卡也算比较简单,主要需要分析代码内部的逻辑,理解fallback()receive的原理。


你可能感兴趣的:(区块链智能合约安全)