一个有点意思的以太坊智能合约蜜罐

admin 2021年12月22日01:47:25评论117 views字数 7236阅读24分7秒阅读模式
本文转自先知社区:https://xz.aliyun.com/t/7225
作者:啦啦0咯咯


一篇以前写的文,现在修改补充了些许,发了上来

前言

以太坊中的智能合约蜜罐相对于互联网蜜罐的目的有着本质的区别:后者着重在于诱导攻击,然后做检测分析,来收集攻击手法与漏洞;而前者更像是一场赌博的骗局,利用种种方法,诱导目标转账进入合约,完成韭菜收割。但是这个蜜罐的名词也是挺恰当的,就也这么叫了。

有趣的是智能合约蜜罐其目标锁定在智能合约开发者,智能合约代码审计人员,略懂区块链技术的信息安全人员(emmmm)

通常而言智能合约蜜罐的欺骗性在于区块链漏洞,逻辑漏洞;又或是赌博合约。
此处介绍的是利用第三方组件导致的智能合约蜜罐。

智能合约蜜罐的奇特组件——区块链浏览器

蜜罐合约地址:0xcEA86636608BaCB632DfD1606A0dC1728b625387

一个有点意思的以太坊智能合约蜜罐

我们可以通过Etherscan浏览器看到该合约的外部交易,内部调用,代码,代码abi等信息

智能合约代码分析

先来看关键的智能合约代码

pragma solidity ^0.4.20;
contract QUESTION{ //玩家 输入答案字符串开始玩游戏 function Play(string _response) external payable{ //需要该玩家地址不为智能合约地址 require(msg.sender == tx.origin); //如果答案的sha256哈希=答案hash 并且 传入的押金超过1ether if(responseHash == keccak256(_response) && msg.value>1 ether) { //给该玩家转账该智能合约所有的钱 msg.sender.transfer(this.balance); } }
string public question;
address questionSender;
bytes32 responseHash;
//开始游戏,传入题目和答案的字符串 function StartGame(string _question,string _response) public payable{ //如果答案hash没有被赋值 if(responseHash==0x0) { //计算sha256赋值答案hash responseHash = keccak256(_response); //赋值题目字符串 question = _question; //赋值题目发送者的地址,为调用者的地址 questionSender = msg.sender; } }
function StopGame() public payable{ //需要调用者等于题目发送者 require(msg.sender==questionSender); //给调用者转账所有eth msg.sender.transfer(this.balance); }
//更新一个新的问题,传入题目字符串,答案hash function NewQuestion(string _question, bytes32 _responseHash) public payable{ //需要调用者等于题目发送者 require(msg.sender==questionSender); //更新题目 question = _question; //更新答案hash responseHash = _responseHash; }
//该智能合约fallback函数可以接受钱 function() public payable{}}

很简单的一个合约,大致就是猜答案:hash符合就给所有钱

这是明显存在漏洞的智能合约:

  1. 在区块链上的交易调用都是可见的,我们可以在区块链浏览器中看到(相当于是默认允许中间人攻击的监听)。在Etherscan中可以直接解密。而在函数的StartGame函数中,response是直接明文传入然后再进行hash存储,即问题设置的答案完全可以被知道

  2. Play()只允许由用户账户调用,而不允许由合约账户调用(require(msg.sender == tx.origin);)。这意味着当答题者发布交易调用Play(),问题的部署者可能会在交易池中一直监听。当监听到Play()交易时,问题部署者用更高的gasprice提交newQuestion函数去修改答案。从而使答题者的答案错误,完成欺骗。但是这种攻击较为繁琐,也具有一定风险。

也有一些奇怪的地方。

疑点1

  • NewQuestion(string _question, bytes32 _responseHash)是用responseHash设置答案。

  • StartGame(string _question,string _response)却是用respon明文设置答案

既然有函数知道用responseHash传入,也就代表着开发者应该是意识到了这个问题。这里是故意为之还是萌新犯蠢?

疑点2

  • if(responseHash==0x0) 其他地方用require作为异常抛出,唯独这里用if做判断,将会不抛出异常。代码风格有点不统一。

Etherscan区块链浏览器上的交易分析

由于这是一个已经收网成功的蜜罐合约,我们队区块链浏览器上已经产生的交易进行分析,看看这个蜜罐钓鱼的过程。

Etherscan上的交易记录:0xCEA86636608BACB632DFD1606A0DC1728B625387

包括:4个外部交易,1个内部交易

一个有点意思的以太坊智能合约蜜罐

一个有点意思的以太坊智能合约蜜罐

在2020.02.14去看Etherscan,会发现交易不会直接帮我们解析出调用过程的参数,但是可以用下面介绍了另一种方法得到解析。

按照时间线排序分析

外部交易0xf9f25d... 0x8F1F6FEb78BA90ad003E1B7408caA164aD90830d地址创建合约(创建合约)

外部交易0x41365... 创建者使用交易调用合约函数Startgame(),带上1.03Ether(部署问题和答案,从结果来看,这应该是一个抛饵行为)

一个有点意思的以太坊智能合约蜜罐


外部交易0xcb589e... 受害者使用交易调用合约函数Play(),没有value,即没有带钱(受害者试探,由于没有带钱是不会通过if判断的)


一个有点意思的以太坊智能合约蜜罐


外部交易0x8486f4... 受害者使用交易调用合约函数Play(),带上1.05Ether的钱(受害者上钩,提交了1Ether以上的钱,讲道理按照逻辑这里应该获得合约返回的亲,但是并没有这笔交易)


一个有点意思的以太坊智能合约蜜罐


内部调用0xb68f60... 合约把所有钱转账给了另一个合约0x4B2838d9326bD5126F0573D9b5c71C0626Ab28f2(创建者收网,暴露出了一个合约地址)


一个有点意思的以太坊智能合约蜜罐

我们得到两个地址,我们给他取个别名:
钓鱼者:0x8F1F6FEb78BA90ad003E1B7408caA164aD90830d
还引出了一个奇怪的创建者收网用的智能合约:
钓鱼中间合约:0x4B2838d9326bD5126F0573D9b5c71C0626Ab28f2

总体流程总结如下:

一个有点意思的以太坊智能合约蜜罐


尝试分析中间智能合约

尝试在Etherscan中查看0x4B2838d9326bD5126F0573D9b5c71C0626Ab28f2钓鱼中间合约

发现该智能合约源码不公开,由0x78d39cDf39e80498237BC330e752DaBd8f90AC2f(从转钱结果推断,取名为钓鱼者小号)进行创建,并且该地址对钓鱼中间合约进行了几次调用。就触发了0xcEA86636608BaCB632DfD1606A0dC1728b625387(钓鱼合约)给该中间智能合约转钱。

但是拥有钓鱼合约源码的我们可以知道,只有对合约的Stopgame()函数产生调用,该智能合约才会对外转钱。中间合约肯定调用了钓鱼合约,才导致钓鱼合约会给中间合约转钱

其中一定有一些我们通过区块链浏览器看不见的调用在发生。

而钓鱼合约运行不在我们预期之内,就是因为这些看不见的调用。

寻找缺失的版图

四处寻找有没有能显示这些预计之外的调用的区块链浏览器。

  • 与Etherscan结果类似的Tokenview:https://tokenview.com/cn/eth/address/0xcea86636608bacb632dfd1606a0dc1728b625387
    4个外部交易,2个call调用(多了一个外部call调用,但是只是把合约创建又分作外部调用,又分作内部调用)

然后就找到了完全暴露的智能合约内部call调用etherchain:https://www.etherchain.org/account/cea86636608bacb632dfd1606a0dc1728b625387

一个合约创建,3个外部交易,4个call调用

真实交易分析

在完整的调用分析前,重新理一下相关地址:

命名 地址
钓鱼者 0x8F1F6FEb78BA90ad003E1B7408caA164aD90830d
钓鱼者创建鱼钩智能合约 0xcEA86636608BaCB632DfD1606A0dC1728b625387
钓鱼者小号 0x78d39cDf39e80498237BC330e752DaBd8f90AC2f
钓鱼中间智能合约 0x4B2838d9326bD5126F0573D9b5c71C0626Ab28f2


一个有点意思的以太坊智能合约蜜罐


与原先Etherscan交易对比可知,与之前相比多了3个call调用,均是由中间智能合约发起。(交易调用时间顺序整体是下面的条目时间早,但是同一区块的条目,上面的时间早)

下面的两个call调用发生在部署智能合约之后,部署者调用StartGame之前,受害者输入答案之前。应该就是我们之前疏忽的关键调用。

这两个call调用都是属于一笔之前没有出现过的交易0x1754a4ecaecff5e6f3d6fd6384f80e00535fa50318de369b57fbb4dc2495defa中

在Etherscan中查看该笔交易,

由于这样看到的交易的input是钓鱼者小号调用钓鱼中间合约的input。我们想看到的两个call调用在虚拟机调用层面,才能查看。

查看Tools&Utilities -> Parity Trace 查看智能合约中函数调用栈的情况。(虽然Etherchain也有Parity Trace,但是Etherscan较为友好,Etherscan作为用的最多的区块链浏览器也是有原因的)

有三个调用栈:

第一个调用是钓鱼者小号0x78d39c...对于中间合约的调用。不管。

第二个调用:

一个有点意思的以太坊智能合约蜜罐


第三个调用:

一个有点意思的以太坊智能合约蜜罐


都对钓鱼合约进行了调用。

关注其中input数据到底调用了什么,利用ethereum-input-decoder解密

  • 从Etherscan中钓鱼智能合约的code中获取abi填入,填入input

第二个调用:调用StartGame,传入问题,答案

一个有点意思的以太坊智能合约蜜罐


第三个调用:调用NewQuestion,传入问题,答案hash

一个有点意思的以太坊智能合约蜜罐


可以看出,其实真正的答案是先用了StartGame设定,再NewQuestion修改。
之后我们看到的钓鱼者的StartGame调用,由于if(responseHash==0x0)验证不通过,不会对智能合约答案造成影响,只是一个烟雾弹。

同理看一下多出来的上面的那个call调用(在受害者上钩之后):
交易:https://etherscan.io/tx/0xb86f60ff9a075a30aa4008c1cd70ed15f424d141c4de5b3afbadd9d7a18f97b4
函数调用情况:https://etherscan.io/vmtrace?txhash=0xb86f60ff9a075a30aa4008c1cd70ed15f424d141c4de5b3afbadd9d7a18f97b4&type=parity

一个有点意思的以太坊智能合约蜜罐


一个有点意思的以太坊智能合约蜜罐


利用中间钓鱼合约完成收网。

真实交易时间线

  1. block:5806406 | 钓鱼小号部署中间合约(钓鱼准备)

  2. block:5873826 | 钓鱼者创建钓鱼合约(准备出发钓鱼)

  3. block:5873890 | 钓鱼小号控制中间合约调用钓鱼合约StartGame()函数,传入问题,sZs答案(钓鱼准备ing)

  4. block:5873890 | 钓鱼小号控制中间合约调用钓鱼合约newQuestion()函数,传入问题,一个答案hash(钓鱼准备ing)

  5. block:5873943 | 钓鱼者使用交易调用钓鱼合约Startgame(),传入问题,带上1.03Ether(烟雾弹+抛饵)

  6. block:5881051 | 受害者使用交易调用合约函数Play(),没有带钱(鱼儿试探)

  7. block:5881054 | 受害者使用交易调用合约函数Play(),带上1.05Ether的钱(鱼儿上钩)

  8. block:5881321 | 钓鱼小号控制中间合约调用钓鱼合约StopGame()函数,撤回钱

至此完美完成了一次智能合约蜜罐攻击,一次利用以太坊最流行区块链浏览器Ethersacn的缺陷,打一个信息差的蜜罐钓鱼

流程图如下:

一个有点意思的以太坊智能合约蜜罐


再读智能合约代码

再回过头去去看看似乎萌新弱鸡的代码,处处用心险恶

之前疑点1:

  • NewQuestion(string _question, bytes32 _responseHash)是用responseHash设置答案。

  • StartGame(string _question,string _response)却是用respon明文设置答案

StartGame用于钓鱼,NewQuestion用于传递真实答案,即使被发现了Etherscan以太坊浏览器存在该不会完全显示call调用的问题也不能被破解。

之前疑点2:

  • if(responseHash==0x0) 其他地方用require这里用if

如果这个地方也用require就会导致用于诱惑别人的钓鱼者StartGame调用报错失败,而引起别人怀疑。

假设是我们

那么假设我们不知道Etherscan有隐藏调用的情况,是否就肯定会上当受骗呢?

其实也不是的,因为智能合约的存储空间,我们也是可以读取的。我们可以直接读取智能合约中的变量值(不管是public还是不是public)从而意识到情况不对。

web3.eth.getStorageAt("0xcEA86636608BaCB632DfD1606A0dC1728b625387"0function(x,y){alert(y)});0x0000000000000000000
0x00000000000000000000000000000000000000000000000000000000000000d1 //string的长度 string question0x0000000000000000000000004b2838d9326bd5126f0573d9b5c71c0626ab28f2 //提问者的地址 address questionSender0x684ff0e88cefc2b7ff23228e02c9a10cc9b5b2e67e12b259a9bca644e19d2b8f //答案hash bytes32 responseHash0x0000000000000000000000000000000000000000000000000000000000000000

可以发现提问者地址不等于我们所知的调用StartGame钓鱼者的地址

答案hash也与我们的答案hash不符合

小结

  1. Etherscan、BTC.com 比特大陆、Tokenview 上仅涉及ETH转账或 Token 转账的交易,Etherscan不会显示不关乎转账的外部合同的调用。

  2. Etherchain 和 blockchair 可以查看所有调用

  3. 在 Etherscan 查看交易中点击 工具&实用程序 Parity追溯。可以查看交易内部虚拟机层面 智能合约中的调用传递的数据等。(Etherchain中也有这个功能只是包装不到位)

类似合约

从2018年3月份至2018年10月份的都有,最长等待鱼儿上钩的时间有100天

游戏停止,骗币成功:https://etherscan.io/address/0xce6B1AFf0fE66da643D7A9A64d4747293628D667#code

游戏停止,骗币成功:https://etherscan.io/address/0xFf45211eBdfc7EBCC458E584bcEc4EAC19d6A624#code

游戏停止,骗币失败: https://etherscan.io/address/0x4bc53ead2ae82e0c723ee8e3d7bacfb1fafea1ce#code

游戏停止,骗币失败: https://etherscan.io/address/0x3B048ab84ddd61C2FfE89EDe66D68ef27661C0f2

游戏停止,骗币失败: https://etherscan.io/address/0x5ccfcDC1c88134993F48a898AE8E9E35853B2068#code

参考

https://medium.com/quantstamp/exploiting-the-interface-of-etherscan-for-ethereum-attacks-17b72d2897e0
https://paper.seebug.org/671/


实操推荐:以太坊和智能合约(复制链接至PC端体验吧)

https://www.hetianlab.com/expc.do?ec=ECIDe0f3-5b8c-42cf-9e00-dbaf891ad3d5&pk_campaign=weixin-wemedia#stu

通过该实验了解以太坊和智能合约的基础知识,了解智能合约的部署流程。

一个有点意思的以太坊智能合约蜜罐

“阅读原文”

体验免费靶场

本文始发于微信公众号(合天网安实验室):一个有点意思的以太坊智能合约蜜罐

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2021年12月22日01:47:25
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   一个有点意思的以太坊智能合约蜜罐http://cn-sec.com/archives/454531.html

发表评论

匿名网友 填写信息