RSS Feed
更好更安全的互联网
  • MIMIC Defense CTF 2019 final writeup

    2019-05-31

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

    上周有幸去南京参加了强网杯拟态挑战赛,运气比较好拿了第二名,只是可惜是最后8分钟被爆了,差一点儿真是有点儿可惜。

    有关于拟态的观念我会在后面讲防火墙黑盒攻击的 writeup 时再详细写,抛开拟态不谈,赛宁这次引入的比赛模式我觉得还蛮有趣的,白盒排位赛的排名决定你是不是能挑战白盒拟态,这样的多线并行挑战考验的除了你的实际水平,也给比赛本身平添了一些有趣的色彩(虽然我们是被这个设定坑了),虽然我还没想到这种模式如何应用在普通的ctf赛场上,但起码也是一个有趣的思路不是吗。

    Web 白盒

    sqlcms

    这题其实相对比赛中的其他题目来说,就显得有些太简单了,当时如果不是因为我们是第一轮挑战白盒的队伍,浪费了 30 分钟时间,否则抢个前三血应该是没啥问题。

    简单测试就发现,过滤了以下符号

    此外还有一些字符串的过滤

    还有一些躺枪的(因为有or)

    总结起来就是,未知表名、不能使用逗号、不能截断的时间盲注。其实实际技巧没什么新意,已经是玩剩下的东西了,具体直接看 exp 吧

    ezweb

    这题觉得非常有意思,我喜欢这个出题思路,下面我们来一起整理下整个题目的思路。

    首先是打开页面就是简单粗暴的登录,用户名只把.换成了_,然后就直接存入了 session 中。

    当我们在用户名中插入/的时候,我们就会发现爆了无法打开文件的错误,/被识别为路径分割,然后 sqlite 又没有太高的权限去创建文件夹,所以就报错了,于是我们就得到了。

    如果用户名被直接拼接到了数据库名字中,将.转化为_

    直接访问相应的路径,就可以下载到自己的 db 文件,直接本地打开就可以看到其中的数据。

    image.png-103.9kB

    数据库里很明显由 filename 做主键,后面的数据是序列化之后的字符串,主要有两个点,一个是 file_type ,这代表文件上传之后,服务端会检查文件的类型,然后做相应的操作,其次还会保存相应的文件路径。

    抛开这边的数据库以后,我们再从黑盒这边继续分析。

    当你上传文件的时候,文件名是 md5(全文件名)+最后一个.后的后缀拼接。

    对于后缀的检查,如果点后为 ph 跟任何字符都会转为 mimic 。

    多传几次可以发现,后端的 file_type 是由前端上传时设置的 content-type 决定的,但后端类型只有4种,其中 text 会直接展现文件内容, image 会把文件路径传入 img 标签展示出来,zip 会展示压缩包里的内容,other 只会展示文件信息。

    其中最特别的就是 zip ,简单测试可以发现,不但会展示 zip 的内容,还会在uploads/{md5(filename)}中解压 zip 中的内容。

    测试发现,服务端限制了软连接,但是却允许跨目录,我们可以在压缩包中加入../../a,这个文件就会被解压到根目录,但可惜文件后缀仍然收到之前对 ph 的过滤,我们没办法写入任何 php 文件。

    按照常规思路来说,我们一般会选择上传.htaccess.user.ini,但很神奇的是,.htaccess因为 apache 有设置无法访问,不知道是不是写进去了。.user.ini成功写入了。但是两种方式都没生效。

    于是只能思考别的利用方式,这时候我们会想到数据被储存在sqlite中。

    如果我们可以把 sqlite 文件中数据修改,然后将文件上传到服务端,我们不就能实现任意文件读取吗。

    image.png-142.6kB

    这里我直接读了 flag ,正常操作应该是要先读代码,然后反序列化 getshell

    最后拿到 flag

    拟态防火墙

    两次参加拟态比赛,再加上简单了解过拟态的原理,我大概可以还原目前拟态防御的原理,也逐渐佐证拟态防御的缺陷。

    下面是我在攻击拟态防火墙时,探测到的后端结构,大概是这样的(不保证完全准确):

    image.png-33.8kB

    其中 Web 服务的执行体中,有 3 种服务端,分别为 nginx、apache 和 lighttpd 这3 种。

    Web 的执行体非常简陋,其形态更像是负载均衡的感觉,不知道是不是裁决机中规则没设置还是 Web 的裁决本身就有问题。

    而防火墙的执行体就更诡异了,据现场反馈说,防火墙的执行体是开了2个,因为反馈不一致,所以返回到裁决机的时候会导致互判错误...这种反馈尤其让我疑惑,这里的问题我在下面实际的漏洞中继续解释。

    配合防火墙的漏洞,我们下面逐渐佐证和分析拟态的缺点。

    我首先把攻击的过程分为两个部分,1是拿到 Web 服务执行体的 webshell,2是触发修改访问控制权限(比赛中攻击得分的要求)。

    GetShell

    首先我不得不说真的是运气站在了我这头,第一界强网杯拟态挑战赛举办的时候我也参加了比赛,当时的比赛规则没这么复杂,其中有两道拟态 Web 题目,其中一道没被攻破的就是今年的原题,拟态防火墙,使用的也是天融信的 Web 管理界面。

    一年前虽然没日下来,但是幸运的是,一年前和一年后的攻击得分目标不一致,再加上去年赛后我本身也研究过,导致今年看到这个题的时候,开局我就走在了前面。具体可以看下面这篇 wp 。

    https://mp.weixin.qq.com/s/cfEqcb8YX8EuidFlqgSHqg

    由于去年我研究的时候已经是赛后了,所以我并没有实际测试过,时至今日,我也不能肯定今年和去年是不是同一份代码。不过这不影响我们可以简单了解架构。

    https://github.com/YSheldon/ThinkPHP3.0.2_NGTP

    然后仔细阅读代码,代码结构为 Thinkphp3.2 架构,其中部分代码和远端不一致,所以只能尝试攻击。

    在3.2中,Thinkphp 有一些危险函数操作,比如 display,display 可以直接将文件include 进来,如果函数参数可控,我们又能上传文件,那么我们就可以 getshell。

    全局审计代码之后我们发现在/application/home/Controller/CommonControler.class.php

    image.png-289.1kB

    如果我们能让 type 返回为 html ,就可以控制 display 函数。

    搜索 type 可得$this->getAcceptType();

    只要将请求头中的 accept 设置好就可以了。

    然后我们需要找一个文件上传,在UserController.class.php moduleImport函数里

    这里的上传只能传到/tmp目录下,而且不可以跨目录,所以我们直接传文件上去。

    紧接着然后使用之前的文件包含直接包含该文件

    上传文件的时候要注意 seesion 和 token ,token 可以从首页登陆页面获得。

    至此我们成功获得了 webshell 。这里拿到 webshell 之后就会进入一段神奇的发现。

    首先,服务端除了/usr以外没有任何的目录,其中/usr/中除了3个服务端,也没有任何多余的东西。换言之就是没有/bin,也就是说并没有一个linux的基本环境,这里我把他理解为执行体,在他的外层还有别的代码来联通别的执行体。

    由于没有/bin,导致服务端不能执行system函数,这大大影响了我的攻击效率,这可能也是我被反超的一个原因...

    继续使用php eval shell,我们发现后端3个执行体分别为nginx\apache\lighthttpd,实际上来说都是在同一个文件夹下

    由于 Web 的服务器可以随便攻击,有趣的是,在未知情况下,服务端会被重置,但神奇的是,一次一般只会重置3个服务端的一部分,这里也没有拟态裁决的判定,只要单纯的刷新就可以进入不同的后端,其感觉就好像是负载均衡一样。

    这样我不禁怀疑起服务端的完成方式,大概像裁决机是被设定拼接在某个部分之前的,其裁决的内容也有所设定,到这里我们暂时把服务端架构更换。

    image.png-31.9kB

    阅读服务端代码

    在拿到 shell 之后,主办方强调 Web 服务和题目无关,需要修改后端的访问控制权限,由于本地的代码和远程差异太大,所以首先要拿到远端的代码。

    /conf/menu.php中可以获得相应功能的路由表。

    其中设置防火墙访问控制权限的路由为?c=Policy/Interview&a=control_show',

    然后直接读远端的代码/Controller/Policy/interviewController.class.php

    其操作相关为

    直接访问这个路由发现权限不够,跟入getPrivilege

    一直跟到 checklogin

    发现对 cookie 中的 loginkey 操作直接对比了 auth_id ,id 值直接盲猜为1,于是绕过权限控制

    添加相应的 cookie ,就可以直接操作访问控制页面的所有操作,但是后端有拟态防御,所以访问 500.

    至此,我无意中触发了拟态扰动...这完全是在我心理预期之外的触发,在我的理解中,我以为是我的参数配置错误,或者是这个 api 还需要添加策略组,然后再修改。由于我无法肯定问题出在了哪,所以我一直试图想要看到这个策略修改页面,并正在为之努力。(我认为我应该是在正常的操作功能,不会触发拟态扰动...)

    ps:这里膜@zsx和@超威蓝猫,因为我无法加载 jquery ,所以我看不到那个修改配置的页面是什么样的,但 ROIS 直接用 js 获取页面内容渲染...

    在仔细分析拟态的原理之后,我觉得如果这个功能可以被正常修改(在不被拟态拦截的情况下),那么我们就肯定触发了所有的执行体(不可能只影响其中一台)。

    那么我们反向思考过来,既然无法修改,就说明这个配置在裁决机背设置为白名单了,一旦修改就会直接拦截并返回 500!

    所以我们当时重新思考了拟态防火墙的结构...我们发现,因为Web服务作为防火墙的管理端,在防火墙的配置中,至少应该有裁决机的 ip ,搞不好可以直接获取防火墙的 ip 。

    image.png-45.3kB

    这时候如果我们直接向后端ip构造socket请求,那么我们就能造成一次降维打击

    只是可惜,因为没有 system shell ,再加上不知道为什么蚁剑和菜刀有问题,我们只能花时间一个一个文件去翻,结果就是花了大量的时间还没找到(远程的那份代码和我本地差异太大了),赛后想来,如果当场写一个脚本说不定就保住第一了2333

    关于拟态

    在几次和拟态防御的较量中,拟态防御现在的形态模式也逐渐清晰了起来,从最开始的测信道攻击、ddos攻击无法防御,以及关键的业务落地代价太大问题。逐渐到业务逻辑漏洞的防御缺陷。

    拟态防御本身的问题越来越清晰起来,其最关键的业务落地代价太大问题,在现在的拟态防御中,逐渐使用放弃一些安全压力的方式来缓解,现在的拟态防御更针对倾向于组件级安全问题的防御。假设在部分高防需求场景下,拟态作为安全生态的一环,如果可以通过配置的方式,将拟态与传统的Waf、防火墙的手段相结合,不得不承认,在一定程度上,拟态的确放大了安全防御中的一部分短板。拟态防御的后续发展怎么走,还是挺令人期待的。


    Paper

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

    作者:吴烦恼 | Categories:技术分享 | Tags:
  • 如何打造自己的PoC框架-Pocsuite3-框架篇

    2019-05-15

    作者:w7ay@知道创宇404实验室
    English version: https://paper.seebug.org/914/
    相关阅读:如何打造自己的PoC框架-Pocsuite3-使用篇

    本节笔者将按照Pocsuite框架结构以及工程化实践,来实现一款自己的PoC框架。为了开一个好头,我们先取一个好听的名字,想威武霸气一些可以取上古神器之类的,诸如轩辕夏禹赤霄干将,若怀着对游戏的热爱也可以有山丘之王(Mountain King)剑圣(BladeMaster)月之女神(Priess Of the moon)。由于笔者比较懒,我们就取一个朴素的名字:AirPoc,中文名叫它"空气炮"吧。

    名称取好了,我们还要幻想一下大饼。这里请充分发挥想象力,幻想它的功能,你要记住,没有我们实现不了的功能,如果有,打死产品manager即可。

    这里不妨开下脑洞,为了组建兔子安全联盟,我们计划开发一款基于区块链的PoC验证框架AirPoc,限定只对"兔子安全联盟”范围内的网站进行安全检查,由一个AirPoc节点检查出了存在漏洞的地址,将URL和PoC共享到区块中,再由随机的其他节点验证,验证成功则获得"空气币",而被检测到的网站所有者则需要支付"空气币"作为报酬。

    虽然只是暂时的幻想,但是产品小哥哥也略带激动整理出了我们需要的功能。

    1. 使用简单,不要有太多的命令,可以跨平台使用
    2. 人多力量大,能让更多人参与进来的
    3. 能简单操作就能内置到其他产品上
    4. 验证速度与验证准确率极高!
    5. 我也不知道什么好,总之你跑起来能出东西就行!

    当然,这位产品小哥哥可能怕被打,没有将分布式,区块链的概念加入进来。

    具体细节

    下面就由笔者来具体实现由笔者兼职的产品manager随便一想(挖坑)的东西。我们逐一分析问题,并给出最后的解决方案。

    说到使用简单,我们就任性的选择使用Python了,不信你看看Python之父的头发。在安装了Python之后,也可以一份代码多处使用,但为了足够的简单与原生,我们决定尽量少使用Python的第三方包。而目前Python最新版为3.7,我们就以此为例。

    国外的众多开源安全项目都有不少人参与,像Metasploit

    image-20190425142853330

    Sqlmap

    image-20190425142829862

    Routersploit

    image-20190425142732368

    能贡献一份代码到上面可能是安全研究人员最想做的事情吧。

    所以笔者有个想法是AirPoc的PoC仓库可以开源到GitHub,并且能够在线调用上面的PoC,这样也不会为了PoC的更新而烦恼了。

    内置到其他产品也更是容易,如果是Python类的软件,可以直接把AirPoc当做包来调用,如果其他软件,AirPoc可以开放一个RPC接口提供使用,如果不想要Python的环境,也可以通过pyinstaller之类的工具打包,我们的设计原则是尽量不依赖其他第三方库,所以也会避免很多奇奇怪怪的问题。

    想要实现验证速度与验证准确率极高,我们要做好多线程或协程的并发模型,这里我们会在后面在详细叙述。

    最后,"我也不知道什么好,总之你跑起来能出东西就行!",如果上面的事情我们都做好了,这个应该就是水到渠成的了~

    AirPoc的框架

    在完成这个"宏伟计划"之前,我们也需要设计一下整体的代码框架。作为一名代码洁癖患者,一个良好的代码结构,是万里长征的第一步。我们建立如下的目录结构,env是虚拟环境,建立两个目录libpocslib用于存储之后的相关核心文件,pocs用于存储poc文件,和一个文件main.py用作初始入口。

    就像盖大楼需要打好地基,接下来完成基础框架,我们可以先不用写具体的功能,但是了解作为"地基"的函数的意义。如下,在main.py文件中如下代码,一个初始的框架就完成了。

     

    image-20190429110505553

    但是,正如你所见,版本号和我的比特币钱包的数字竟然差不多,我们还要给它加些料。

    单例模式

    在我们软件的初始化的工程中,我们需要得到很多环境相关的信息。比如当前执行的路径是哪?poc目录在哪?我们输出结果文件输出到哪个路径等等。

    它们有一个共同的特定是,它们只需要加载一次,在后面使用中直接拿来用就行了。这种模式在软件设计模式中有一个单独的名词,"单例模式"。

    幸运的是python的模块就是天然的单例模式,因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,就会直接加载 .pyc 文件,而不会再次执行模块代码。因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。

    我们在lib目录里面新建一个data.py用于存储这些信息。同时将版本信息也放到这里来。

     

    为了更好的来表示这些常量,我们用PEP8标准里的规范,统一约定用大写和下划线来表示常量。为了说明与之前的区别,我们象征性的将VERSION减一个0,来表达我们的比特币又增长了10倍。

    动态加载

    在解决完我们相关的环境问题后,我们在看看如何动态加载模块。在具体细节里我们说过,我们期望PoC能够从本地或者远程网站(如GitHub)上加载。

    这里又得分成两种情况,如果是通过文件路径加载动态加载的模块,可以直接用__import__()来加载,但是如果要远程加载,可能就又会复杂一点,根据python的相关文档,我们要自己实现"查找器"与"加载器" https://docs.python.org/zh-cn/3/reference/import.html

    当然,你也可以从远程保存到本地后,按照本地加载模式进行加载。但是Pocsuite已经有完整的加载器代码了,我们可以直接拿来用。

    新建lib/loader.py文件

     

    具体如何实现的我们可以不用关心,我们只需要知道,其中我们可以用load_string_to_module来从源码中加载模块了。如果你有兴趣了解具体的实现,可以参考上面的python官方文档。

    规则的制定

    从文件或者远程加载好模块后,就可以准备运行的相关事宜了。我们需要对PoC做一个规则的统一约定,让程序更好的调用它们。

    你可以将规则定义的详细,也可以一切从简,主要是看使用场景。而前面也提到,为了保护"安全联盟"的安全问题,所以我们需要PoC更够比较简单的快速编写。

    同时我们还需要考虑如果PoC需要多个参数如何处理?笔者的规则是这样定义的。

     

    在PoC文件中定义一个verify函数用作验证使用,arg作为普通的参数传递,当需要传递较多的参数时,从kwargs中接收。在PoC验证成功后,也只需要返回一个字典即可,如果验证失败,返回FalseNone即可。字典内容由PoC编写者制定,给予编写者最大的灵活空间。

    但是注意!PoC的质量就需要依靠编写者的维护。

    V0.01

    我们最终要实现的目标是,设置好目标,程序自动加载指定的一个或多个PoC或全部的PoC,逐个检测目标。剩下的部分就是怎样将这些功能串联在一起了。

    前面我们已经实现了AirPoc的基础框架,现在只需要在其基础上具体实现功能即可。

    为了测试的方便,我们先在pocs目录下按照之前定义的规则建立两个简陋的PoC。

    image-20190429164121695

    image-20190429164143909

    现在,main.py中的代码如下

     

    我们的版本也来到了0.01,它已经是一个"成熟的”能自己跑PoC的框架了。

    image-20190429172118745

    多线程模型

    为了让我们的框架运行得更快一点,我们使用多线程来处理每个PoC,因为我们处理的任务大多是I/O密集型任务,所以我们也不用太纠结python是不是伪线程这个问题。

    多线程模型中最简单的一种是生产者/消费者的模型,启动多个线程来共同消费一个队列就行了。新建lib/threads.py

     

    值得注意的一点是,我们并没有使用Python线程中推荐的join()来阻塞线程,因为使用join()的话,python将无法响应用户输入的消息了,会导致Ctrl+C退出时没有任何响应,所以以while循环的方式来阻塞线程。

    接着将主程序改造成多线程的模式,将原start()中的"消费者"提取出来,单独用作一个函数,用队列接收数据即可。如下

     

    另外,线程数量是我们可配置的,我们将它改成从配置中读取。

     

    再次运行,会发现比以前快很多!

    image-20190430102952036

    统一网络请求

    这是我们整个框架的最后一个部分,如何来统一网络请求。有时我们需要让我们的PoC框架发出的网络请求中统一一下代理,UA头等等的设置,这需要我们框架进行统一的处理。在实现我们的目的之前,我们还需要在框架里做一个约定,约定我们的网络请求都需要统一使用requests来进行发包。开始时我们说到,我们会尽量不使用第三方模块,但是requests模块实在太好用了,我们将它排除在外...

    Python语言动态的机制,我们可以很容易在使用一个函数之前Hook它,将它原始的方法重定向到我们自定义的方法中,这是我们能够统一网络请求的一个前提。

     

    image-20190430112557108

    通过hook一个函数来达到我们自己的目的。

    像sqlmap这类工具,基于python内置的urllib模块,但是有大量的代码都在处理在了网络请求方面,甚至为了处理chunked发包的问题,hook重写了更底层的httplib库。

    pocsuite为了统一调度网络请求,hook了requests模块的相关方法。我们可以具体参考其中的代码。

    pocsuite3/lib/request/patch/__init__.py代码很清晰的说明了hook的函数

     

    如果你看过requests的源码,会知道这里面的重点是看它如何hook seesion函数的。

    pocsuite3/lib/request/patch/hook_request.py

     

    它重写了session_request函数的方法,让其中可以自定义我们自定义的文件头等信息。上述代码可能需要你看过requests才会对他有所理解,不过没关系,我们还是以拿来主义的精神直接用即可。

    为了达到此目的以及更好的优化框架结构,我们还需要做一些小调整。

    新建lib/requests.py

     

    同时在config中预留requests的接口

    image-20190430115617047

    以及init的时候执行我们的hook。

    image-20190430115652364

    我们新编写一个PoC,用这个网站测试一下 最后的效果 http://www.httpbin.org/get

    pocs/poc.py

     

    image-20190430130417913

    效果很好,但是如果加上https的网站,就有一个警告信息。

    image-20190430130730241

    同样参考Pocsuite的方法禁用掉warning信息

     

    最后有仪式感的将版本号变更为0.1,AirPoc的框架部分大体完成了。

    最后

    AirPoc的很多结构思想都来源于Pocsuite,如果直接阅读Pocsuite,也许能收获很多东西。目前AirPoc v0.1基础框架已经差不多完成了,已经可以从本地加载一个或多个PoC,进行批量测试。后面我们再尝试些更好玩的,如何验证无回显的情况,如何生成shellcode,以及如何操作回连的shell,敬请期待下节《功能篇》~。

    AirPoc下载:https://images.seebug.org/archive/airpoc.zip


    Paper

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

    作者:吴烦恼 | Categories:安全研究技术分享 | Tags:
  • WebLogic RCE(CVE-2019-2725)漏洞之旅

    2019-05-05

    作者:Badcode@知道创宇404实验室
    时间:2019年4月30日
    English version: https://paper.seebug.org/910/

    417

    2019年4月17日,CNVD 发布《关于Oracle WebLogic wls9-async组件存在反序列化远程命令执行漏洞的安全公告》,公告指出部分版本WebLogic中默认包含的wls9_async_response包,为WebLogic Server提供异步通讯服务。由于该WAR包在反序列化处理输入信息时存在缺陷,攻击者可以发送精心构造的恶意 HTTP 请求,获得目标服务器的权限,在未授权的情况下远程执行命令。

    418

    2019年4月18日,开始应急。因为这个漏洞当时属于0day,也没有补丁可以参考,只能参考公告内容一步一步来看了。首先看到公告里提到的wls9_async_response.war包,看下web.xml里的url。

    看到/AsyncResponseService,尝试访问一下,404。之后看到weblogic.xmlweblogic-webservices.xml

    访问下_async/AsyncResponseService

    可以正常访问,再结合公告中的漏洞处置建议,禁止 /_async/* 路径的URL访问,可以大概率猜测,漏洞入口在这里。

    weblogic-webservices.xml中有一个类,weblogic.wsee.async.AsyncResponseBean,跟进去这个类,发现在wseeclient.jar里面

    而后我在这个类里面的方法下断点,然后构造一个普通的SOAP消息,发送。

    断点没有debug到。最后我把wsee/async所有类的所有方法都下了断点,重新发送消息,成功在AsyncResponseHandler类中的handleRequest拦截到了。

    继续流程,String var2 = (String)var1.getProperty("weblogic.wsee.addressing.RelatesTo");这个步骤一直取不到值,导致流程结束。为了解决这个问题,翻了不少资料,最后找到一个类似的例子,可以使用<ads:RelatesTo>test</ads:RelatesTo>weblogic.wsee.addressing.RelatesTo赋值。

     

    之后流程就能够继续下去了,我一直以为漏洞的关键点在这里,因为这个wsee.async下面的几个类中有readObject方法,我一直尝试着通过AsyncResponseHandler跳到readObject方法,而后就卡在这里,后面的流程就不写了,对这个漏洞来说是错的,上面写的这些猜测和流程都是正确的。

    419

    2019年4月19日,和我一起应急的师傅给我发了一张截图。

    看到这截图里面的RelatesTo,我还以为之前的推测没有错,只是没有构造好。

    全局搜索UnitOfWorkChangeSet这个类,之后在这个类中下断点。

    根据截图,构造一个类似的,然后发送

    在这个类中debug到了。

    看到了日思夜想的readObject,有了反序列的点,自然要找利用链了,目前 WebLogic 下面 commoncollections 相关的利用链已经是无法使用了,WebLoigc 依赖的common-collections版本已经升级了,先找个Jdk7u21测试一下,将生成的 payload 转换成 byte,发送。

    可以看到,成功地执行了命令。但是这个利用链限制太大了,基本没啥用。我想起去年应急过的一个WebLogic 反序列漏洞,CVE-2018-3191,既然jdk7u21都不受黑名单限制,想来CVE-2018-3191也是一样可以利用的。

    猜测没有错误,CVE-2018-3191也是能够利用的,这个漏洞也终于有点"危害"了。和 pyn3rd 师傅讨论一下有没有其他利用链,仔细翻下黑名单,除了CVE-2018-3191,就只有新的jython利用链(CVE-2019-2645)了,由 Matthias Kaiser大佬提交的,但是目前这个还有没有公开,所以这个利用链也没法使用。

    有了正确答案,就可以看下之前的猜测哪里出了问题。

    回到AsyncResponseHandler类中的handleRequesthandleRequest的上一步,HandlerIterator类中的handleRequest方法

    会遍历this.handlers,然后调用每个handlerhandleRequest去处理用户传入的SOAP Message。

    可以看到,AsyncResponseHandler仅仅只是21个handler之中的一个,而weblogic.wsee.addressing.RelatesTo的赋值就是在ServerAddressingHandler中完成的,有兴趣的可以去跟一下。这里面有一个非常重要的handler--WorkAreaServerHandler,看名字可能觉得眼熟,看到里面的handleRequest方法可能就不淡定了。

    之后的流程就和CVE-2017-10271是一样的了,关于这个漏洞的分析可以参考廖师傅的文章

    跟到这里就可以看出来了,这个url只是CVE-2017-10271漏洞的另外一个入口而已。这也是后期导致假PoC泛滥的一个原因。整个流程大概如下:

    那么问题来了,这个PoC是如何绕过CVE-2017-10271的黑名单的呢?

    首先来看一下CVE-2017-10271的补丁,会将传入的数据先调用validate校验,通过之后才交给XMLDecoder

     

    可以看到,objectnewmethod这些标签都被拦截了,遇到直接抛出错误。void标签后面只能跟indexarray标签后面可以跟class属性,但是类型只能是byte类型的。其中,过滤object标签是CVE-2017-3506的补丁,剩下的过滤是针对CVE-2017-10271的补丁。

    如果仔细看了黑名单的,就不难发现,外面流传的很多PoC都是假的,就是新url入口+老的payload,这样的组合是没有办法绕过这个黑名单的。

    绕过这个黑名单的关键是class标签,可以从官方的文档来了解一下这个标签。

    class标签可以表示一个类的实例,也就是说可以使用class标签来创建任意类的实例。而class标签又不在WebLogic 的黑名单之内,这才是这个漏洞最根本的原因。4月26日,Oracle 发布这个漏洞的补丁,过滤了class标签也证实了这点。

    既然漏洞的原因是绕过了CVE-2017-10271的黑名单,那么wls-wsat.war也是应该受影响的。

    测试一下,没有问题。

    这说明,CNVD的公告写的影响组件不全,漏洞处置建议也写的不全面,要通过访问策略控制禁止 /_async/* 及 /wls-wsat/* 路径的URL访问才行,之后我们也同步给了CNVD,CNVD发了第二次通告

    421

    2019年4月21日,准备构造出这个漏洞的检测PoC,能够使用class标签来创建类的实例,我首先考虑的是构造java.net.Socket,这也引出了一个JDK版本的坑。我测试的是jdk6,参考之前的PoC,可以这么构造

    ceye成功接收到请求,也说明Socket实例创建成功了。

    我把上面的检测PoC在 jdk 7上测试,竟然失败了,一直爆找不到java.net.Socket这个类错误,让我一度以为这个漏洞只能在 jdk 6 下面触发,后来仔细对比,发现是换行符的问题,也就是这样写才对。

    不带换行符的在6和7下面都能生成实例。其实这个问题在最早测试 CVE-2018-3191 payload的时候就已经发生过,pyn3rd师傅问我xml payload是怎么生成的,我说用的拼接,直接System.out.println输出的,都带了换行符,我因为当时跑weblogic的jdk是jdk6,所以没有问题,但是 pyn3rd 师傅的环境是 jdk7 的,没测试成功,只觉得是PoC写法不同造成的问题,后来师傅自己解决了,这里也没沟通,埋下了一个大坑,导致我后面踩进去了。

    422

    2019年4月22日,pyn3rd 师傅测试 WebLogic 12.1.3没成功,发现是12的版本没有oracle.toplink.internal.sessions.UnitOfWorkChangeSet这个类,所以没办法利用。尝试着构造新的exp,目前的情况是,能够创建类的实例,但是调用不了方法。自然想起com.sun.rowset.JdbcRowSetImpl这个类。

    这个是CVE-2017-10271的一种触发方法。之前的黑名单提过,void标签后面只能跟index,所以上面这个payload肯定会被黑名单拦截。尝试使用class标签重写上面的payload。

    构造的过程中,在跟底层代码的时候,发现 jdk 6和 jdk 7处理标签的方式不同。

    jdk 6使用的是com.sun.beans.ObjectHandler

    能用的有stringclassnullvoidarrayjavaobject和一些基本类型标签(如int)。

    jdk7 使用的是com.sun.beans.decoder.DocumentHandler

    可以看到,和jdk6差异不小,例如,jdk 6不支持newproperty等标签。

    我在用jdk 6 的标签构造的时候,一直没构造成功,直到我看到jdk 7 的源码里面的property,这不就是我想要的么,而且这个标签还不在 WebLogic 的黑名单内。所以重写上面的payload如下

    可以看到,没有触发黑名单,成功的执行了命令,而且没有依赖 WebLogic 内部的包,10.3.6和12.1.3都可以通用。遗憾的是,这个payload的打不了 jdk 6的,因为 jdk 6 不支持 property标签。期望有大佬能写出6也能用的。

    423

    2019年4月23日,在CNVD发出通告,各大安全公司发出漏洞预警之后,之前提过的新url+老payload的这种模式的PoC和exp纷纷出炉。不仅是国内,国外也很热闹,很多人表示测试成功,但是都是在无补丁的情况下测试的。Oracle 官网下载的 WebLogic 都是没有安装补丁的,Oracle的补丁是单独收费的,如果安装了 CVE-2017-10271 的补丁,这些PoC和exp都是没有办法触发的,绕过不了黑名单。

    426

    2019年4月26日,Oracle 官方发布紧急补丁,并为该漏洞分配编号CVE-2019-2725。

    427

    2019年4月27日,pyn3rd 师傅说12.1.3版本的exp也有人弄出来了,用的是org.slf4j.ext.EventData

     

    看下这个类的构造方法,直接将传入的xml交给XMLdecoder处理,太粗暴了...

    相当于经过了两次XMLdecode,所以外层用<class>绕过,内层直接标记为纯文本,绕过第一次过滤,第二次 XMLdecode不经过WebLogic 黑名单,直接被JDK解析反序列化执行。

    这种exp也是最完美的,没有jdk版本限制,不需要外连,可惜的是只能打12.1.3版本。

    430

    2019年4月30日,在其他大佬手中看到了这个漏洞的其他利用方式,没有 weblogic和 jdk的版本限制,比上面的几种利用方式都更完善。这种利用方式我之前也看到过,就是Tenable 发的演示视频,当时没想明白,看了大佬的利用方式之后,才明白自己忽略了什么。构造方式可以参考CVE-2017-17485,我之前构造exp的时候也没有往这方面想,这或许就是黑哥说的积累不够吧。

    总结

    • 针对这次漏洞,Oracle 也是打破了常规更新,在漏洞预警后不久就发布了补丁,仍然是使用黑名单的方式修复。(吐槽一下,这么修复,这个功能还能用么?)
    • 此次的漏洞事件中,也看到了安全圈的乱象,漏洞都没有经过完全的验证,就直接发错误的分析文章和假PoC,误导大众。
    • 在这个漏洞应急的过程中,从无到有,从缺到圆,踩了很多坑,也学习到了很多姿势,也看到了自己和大佬的差距。最后感谢漏洞应急过程中几位师傅的交流和指点。

    参考链接

     

    Paper

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

    作者:吴烦恼 | Categories:安全研究技术分享 | Tags:
  • WebLogic CVE-2019-2647、CVE-2019-2648、CVE-2019-2649、CVE-2019-2650 XXE漏洞分析

    2019-05-05

    作者:Longofo@知道创宇404实验室
    时间:2019年4月26日

    Oracle发布了4月份的补丁,详情见链接(https://www.oracle.com/technetwork/security-advisory/cpuapr2019-5072813.html#AppendixFMW)

    @xxlegend 在《Weblogic CVE-2019-2647等相关XXE漏洞分析》分析了其中的一个XXE漏洞点,并给出了PoC。刚入手java不久,本着学习的目的,自己尝试分析了其他几个点的XXE并构造了PoC。下面的分析我尽量描述自己思考以及PoC构造过程,新手真的会踩很多莫名其妙的坑。感谢在复现与分析过程中为我提供帮助的小伙伴@Badcode,没有他的帮助我可能环境搭起来都会花费一大半时间。

    补丁分析,找到漏洞点

    根据JAVA常见XXE写法与防御方式(参考https://blog.spoock.com/2018/10/23/java-xxe/),通过对比补丁,发现新补丁以下四处进行了setFeature操作:

    应该就是对应的四个CVE了,其中ForeignRecoveryContext@xxlegend大佬已经分析过了,这里就不再分析了,下面主要是分析下其他三个点

    分析环境

    • Windows 10
    • WebLogic 10.3.6.0
    • Jdk160_29(WebLogic 10.3.6.0自带的JDK)

    WsrmServerPayloadContext 漏洞点分析

    WsrmServerPayloadContext修复后的代码如下:

    可以看到进行了setFeature操作防止xxe攻击,而未打补丁之前是没有进行setFeature操作的

    readExternal在反序列化对象时会被调用,与之对应的writeExternal在序列化对象时会被调用,看下writeExternal的逻辑:

    var1就是this.formENdpt,注意var5.serialize可以传入三种类型的对象,var1.getEndptElement()返回的是Element对象,先尝试新建一个项目构造一下PoC:

    结构如下

    test.xml内容如下,my.dtd暂时为空就行,先测试能否接收到请求:

    运行PoC,生成的反序列化数据xxe,使用十六进制查看器打开:

    发现DOCTYPE无法被引入

    我尝试了下面几种方法:

    • 在上面说到var5.serialize可以传入Document对象,测试了下,的确可以,但是如何使getEndptElement返回一个Document对象呢?
      • 尝试了自己创建一个EndpointReference类,修改getEndptElement返回对象,内容和原始内容一样,但是在反序列化时找不到我创建的类,原因是自己建的类package与原来的不同,所以失败了
      • 尝试像Python那样动态替换一个类的方法,貌似Java好像做不到...
    • 尝试了一个暴力的方法,替换Jar包中的类。首先复制出Weblogic的modules文件夹与wlserver_10.3\server\lib文件夹到另一个目录,将wlserver_10.3\server\lib\weblogic.jar解压,将WsrmServerPayloadContext.class类删除,重新压缩为weblogic.Jar,然后新建一个项目,引入需要的Jar文件(moduleswlserver_10.3\server\lib中所有的Jar包),然后新建一个与WsrmServerPayloadContext.class同样的包名,在其中新建WsrmServerPayloadContext.class类,复制原来的内容进行修改(修改只是为了生成能触发xml解析的数据,对readExternal反序列化没有影响)。WsrmServerPayloadContext.class修改的内容如下:
    • 经过测试第二种方式是可行的,但是好像过程略复杂。然后尝试了下新建一个与原始WsrmServerPayloadContext.class类同样的包名,然后进行修改,修改内容与第二种方式一样测试这种方式也是可行的,比第二种方式操作起来方便些

    构造新的PoC:

     

    查看下新生成的xxe十六进制:

    DOCTYPE被写入了

    测试下,使用T3协议脚本向WebLogic 7001端口发送序列化数据:

    漂亮,接收到请求了,接下来就是尝试下到底能不能读取到文件了

    构造的test.xml如下:

    my.dtd如下(my.dtd在使用PoC生成反序列化数据的时候先清空,然后,不然在dbBuilder.parse时会报错无法生成正常的反序列化数据,至于为什么,只有自己测试下才会明白):

    运行PoC生成反序列化数据,测下发现请求都接收不到了...,好吧,查看下十六进制:

    %dtd;%send;居然不见了...,可能是因为DOM解析器的原因,my.dtd内容为空,数据没有被引用。

    尝试debug看下:

    可以看到%dtd;%send;确实是被处理掉了

    测试下正常的加载外部数据,my.dtd改为如下:

    gen.xml为:

    debug看下:

    可以看到%dtd;%send;被my.dtd里面的内容替换了。debug大致看了xml解析过程,中间有一个EntityScanner,会检测xml中的ENTITY,并且会判断是否加载了外部资源,如果加载了就外部资源加载进来,后面会将实体引用替换为实体申明的内容。也就是说,我们构造的反序列化数据中的xml数据,已经被解析过一次了,而需要的是没有被解析过的数据,让目标去解析。

    所以我尝试修改了十六进制如下,使得xml修改成没有被解析的形式:

    运行PoC测试下,

    居然成功了,一开始以为反序列化生成的xml数据那块还会进行校验,不然反序列化不了,直接修改数据是不行的,没想到直接修改就可以了

    UnknownMsgHeader 漏洞点分析

    WsrmServerPayloadContext差不多,PoC构造也是新建包然后替换,就不详细分析了,只说下类修改的地方与PoC构造

    新建UnknownMsgHeader类,修改writeExternal

    PoC如下:

     

     

    运行PoC测试下(生成的步骤与第一个漏洞点一样),使用T3协议脚本向WebLogic 7001端口发送序列化数据:

    WsrmSequenceContext 漏洞点分析

    这个类看似需要构造的东西挺多的,readExternalwriteExternal的逻辑也比前两个复杂些,但是PoC构造也很容易

    新建WsrmSequenceContext类,修改

    PoC如下:

     

     

    测试下,使用T3协议脚本向WebLogic 7001端口发送序列化数据:

    最后

    好了,分析完成了。第一次分析Java的漏洞,还有很多不足的地方,但是分析的过程中也学到了很多,就算是一个看似很简单的点,如果不熟悉Java的一特性,会花费较长的时间去折腾。所以,一步一步走吧,不要太急躁,还有很多东西要学。

     

    Paper

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

    作者:吴烦恼 | Categories:安全研究技术分享 | Tags:
  • 如何打造自己的PoC框架-Pocsuite3-使用篇

    2019-04-25

    作者:w7ay@知道创宇404实验室
    Engilish version: https://paper.seebug.org/905/

    相比于无聊的用法介绍,我更想说一下Pocsuite3为什么会有这些功能以及是如何实现的。如果你也想制造一款类似的工具,Pocsuite3的一些思想或许能够帮助到你。本文同时也是记录Pocsuite3开发过程中的一些思考与理解。

    简介

    Pocsuite 是由知道创宇404实验室打造的一款开源的远程漏洞测试框架。它是知道创宇安全研究团队发展的基石,是团队发展至今一直维护的一个项目,保障了我们的 Web 安全研究能力的领先。

    你可以直接使用 Pocsuite 进行漏洞的验证与利用;你也可以基于 Pocsuite 进行 PoC/Exp 的开发,因为它也是一个 PoC 开发框架;同时,你还可以在你的漏洞测试工具里直接集成 Pocsuite,它也提供标准的调用类。

    Pocsuite3是完全由Python3编写,支持Windows/Linux/Mac OSX等系统,在原Pocsuite的基础上进行了整体的重写与升级,使整个框架更具有操作性和灵活性。

    巨人的肩膀

    Pocsuite3在编写时参考了很多市面上的开源框架以及流行成熟的框架,在代码工程结构上参考了Sqlmap,Pocsuite-console模式则参照了routersploit与metasploit,所以PoC的代码格式和以前有些差别(但是尽量克制了大的改动)。Pocsuite3也提供了非常简单的接口调用,可以集成到其他安全工具内部。

    下载

    Pip 安装

    安装有两种,pip和直接运行源码。

    将使用Pocsuite3最新版。

    执行

    检验安装效果。

    源码安装

    如果你自信能折腾的话,可以下载源码使用,这也是我们推荐的方式,因为pip的更新可能会慢于github,

    同时需要安装两个依赖

    如果同时也是Windows系统,除了上面的依赖还需要安装一个

    最后

    检验安装效果。

    另外需要注意的是,两种安装方式只可以取其一,不可同时安装。建议使用源码安装的方式。

    一般使用帮助

    大多数情况,-h可以帮助你了解Pocsuite支持的功能。

    一个简单的测试

    将使用ZoomEye搜索ecshop并使用ecshop_rce.py探测,指定线程数量为5

    Pocsuite的运行模式默认是verify验证模式,此时对目标影响最小,也有attackshell模式,对目标进行相关攻击与shell反弹(当然需要PoC的支持,Pocsuite的PoC编写格式预留了这三种模式的接口,并且有很多内置API帮助实现这三种接口)

    Shell模式

    Pocsuite3新增加了shell模式的设定,当你选择了此函数,Pocsuite3将会监听一个端口,并等待目标的反连。我们提供了各种语言用于反连的payload,以及用于生成在Windows/Linux平台下可执行的shellcode。

    从配置文件运行

    有时候命令行命令太多,有些参数的重用性比较高,Pocsuite也提供了从配置文件中运行的方法。

    我们以redis未授权访问漏洞为例,我们修改这个文件pocsuite.ini

    线程也调整一下,RUN!

    由于开启了comparsion参数,我们可以看到更多的信息

    1

    如果你同时还是Zoomeye VIP,搜集目标的同时也能够识别出蜜罐信息。目前只有通过Zoomeye接口获取的数据才能有蜜罐的标识。Shodan、Censys暂未开放相关API接口。

    插件系统

    Pocsuite支持了插件系统,按照加载目标(targets),加载PoC(pocs),结果处理(results)分为三种类型插件。

    Targets插件

    除了本身可以使用-u-f加载本地的目标之外,你可以编写一个targets类型插件从任何你想加载的地方加载目标(eg:Zoomeye、Shodan)甚至从网页上,redis,都可以。Pocsuite3内置了四种目标加载插件。

    从上文可以看出,如果使用了搜索dork—dork—dork_zoomeye—dork_shodan—dork_censys,相关插件将自动加载,无需手动指定。

    Pocs插件

    原来只能通过从seebug中调用插件,现在将这种方式抽离出来作为插件,将允许从任何能够访问的地方调用,甚至写一个插件在github上维护一个仓库调用都行。

    Demo:

    https://github.com/knownsec/pocsuite3/blob/master/pocsuite3/plugins/poc_from_redis.py

    https://github.com/knownsec/pocsuite3/blob/master/pocsuite3/plugins/poc_from_seebug.py

    Results-plugin

    Results插件允许对扫描的结果进行处理,可以参考内置的两个插件,保存结果为html与保存结果为txt。Results插件的结果是实时的,具体可以看plugins/file_record.py的实现方式。

    https://github.com/knownsec/pocsuite3/blob/master/pocsuite3/plugins/html_report.py

    https://github.com/knownsec/pocsuite3/blob/master/pocsuite3/plugins/file_record.py

    调用插件

    通过--plugins在后面指定插件名称,多个插件可以用,分割。例如--plugins html_report将会生成HTML报表格式文档。

    内置API

    基于我们漏洞应急的积累,基本上Pocsuite内置的API接口可以做到PoC编写的全覆盖了。很多API接口我们下一章再说,这里说两个比较有趣的案例。

    Shellcode生成支持

    在一些特殊的Linux和Windows环境下,想得到反弹shell条件比较困难。为此我们制作了用于在Windows/Linux x86 x64环境下的用于反弹的shellcode,并制作了接口支持,你在只需要拥有命令执行权限下便可以自动将shellcode写入到目标机器以及执行反弹shell命令。Demo Poc:https://github.com/knownsec/pocsuite3/blob/master/pocsuite3/pocs/thinkphp_rce2.py

    HTTP服务内置

    如果你们还对Hacking Jenkins Part 2 - Abusing Meta Programming for Unauthenticated RCE! 有印象。多么完美的漏洞,但是在编写PoC的时候我们遇到了困难,verify模式我们可以轻松用Ceye来识别,但是attack模式与shell模式我们就必须要制作自己的Jar并将它上传到服务器上面!

    为此我们制作Jar格式打包的API以及HTTP服务API,在后面的众多越来越难以自动化的PoC编写中,会发现它是如此好用。

    附 Jenkins Abusing Meta Programming for Unauthenticated RCE(CVE-2019-1003000) with Pocsuite3 演示视频。

    https://www.youtube.com/watch?v=5P7WWlqYt4U

    自定义参数传递

    随着编程人员的安全意识逐渐提高,会发现以前一条链接就可以获取RCE的时代已经过去了。越来越多的漏洞转向需要一定"权限"才能触发。为此,我们需要在Pocsuite3预留参数接口。

    在尽量保持原有PoC格式的前提下,我们增加了一个_options方法,用于指定用户传递的参数。DemoPoc: https://github.com/knownsec/pocsuite3/blob/master/tests/login_demo.py

    我们定义了在Poc中需要传递usernamepassword两个参数,为了使用的方便,可以直接在命令行模式下如下

    是的,就是这么简单。可能你会问如果PoC中定义的参数与Pocsuite自带的参数名冲突了如何解决?我们的解决办法是不允许定义冲突的参数名,Pocsuite在启动时就会检查,如果有冲突的参数名会提示你修改PoC中的自定义参数名称。

    Console模式

    在某些情况下,我们也考虑到了可交互的命令模式(黑客的仪式感)。并且它完全能兼容命令行模式下的PoC,如果你在Linux或Mac下使用它,将得到更好的体验。

    一些Tips:

    • 在此模式下多用help可以明白更多
    • 加载PoC插件时,可以直接use + 数字,更简单方便,当然输入完整路径也可以,按下Tab会自动补全。
    • 有一些命令别名没有在help中显示,作为彩蛋等待使用者发现~image-20190424141427790

    API 通用集成

    我们鼓励也支持将Pocsuite3作为安全产品中的一部分。只需要将Pocsuite3作为模块导入到你的项目中就能轻松使用。后面我们也会详细说明Pocsuite3是如何做到这一点的。

    pocsuite3.api将Pocsuite中所有接口暴露出来,不管是写PoC还是集成到自己的环境,只需要使用这就可以。一个简单调用Demo。

     

    最后

    一个功能完备的框架并不只是一个可以批量处理任务的引擎,很多东西需要在实战中积累并以最好的方式实现出来(俗称踩坑)。在打造自己的PoC框架过程中,一定要清楚自己需要的是什么,以及用何种方式将它优雅的解决?下篇将具体谈谈Pocsuite3中的框架结构。


    Paper

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

    作者:吴烦恼 | Categories:安全研究技术分享 | Tags:
  • 【ZoomEye专题报告】DDoS 反射放大攻击全球探测分析

    2019-04-24

    作者:知道创宇404实验室
    ZoomEye专题:https://www.zoomeye.org/topic?id=Global-Detection-and-Analysis-of-Amplified-Reflection-DDoS-Attacks
    PDF 版本:下载
    English Version: https://paper.seebug.org/899/

    1.更新情况

    版本 时间 描述
    第一版 2017/08/07 完成第一轮数据统计,输出报告,完善文档格式
    第二版 2017/08/14 完成第二轮数据统计,输出报告,完善文档格式
    第三版 2017/11/15 完成第三轮数据统计,在第二轮的基础上增加对cldap的探测
    第四版 2018/03/05 完成第四轮数据统计,在第三轮的基础上增加对Memcached的探测

    2.概述

    DDos攻击是一种耗尽资源的网络攻击方式,攻击者通过大流量攻击,有针对性的漏洞攻击等耗尽目标主机的资源来达到拒绝服务的目的。

    反射放大攻击是一种具有巨大攻击力的DDoS攻击方式。攻击者只需要付出少量的代价,即可对需要攻击的目标产生巨大的流量,对网络带宽资源(网络层)、连接资源(传输层)和计算机资源(应用层)造成巨大的压力,2016年10月美国Dyn公司的DNS服务器遭受DDoS攻击,导致美国大范围断网。事后的攻击流量分析显示,DNS反射放大攻击与SYN洪水攻击是作为本次造成美国断网的拒绝服务攻击的主力。由于反射放大攻击危害大,成本低,溯源难,被黑色产业从业者所喜爱。

    在2017年8月3日到2017年8月6日期间ZoomEye网络空间探测引擎对全网进行第一轮的探测,统计可被利用进行DDoS反射放大攻击的主机数,发布了《DDoS反射放大攻击全球探测分析-第一版》,之后在2017年8月11日到2017年8月13日期间ZoomEye网络空间探测引擎再次对全网进行了探测,发布了《DDoS反射放大攻击全球探测分析-第二版》。之后在2017年11月13日到2017年11月15日期间,ZoomEye网络空间探测引擎探测到了另一个活动频繁的攻击——CLDAP DDoS反射放大攻击,随后对DDoS反射放大攻击进行了第三轮的探测,发布了《DDoS反射放大攻击全球探测分析-第三版》。

    随后在2018年3月1日,ZoomEye又探测到在网络空间中频繁活动Memcached DRDoS, 进行第四轮对DDoS反射放大攻击的探测。

    3.第四轮放大攻击数据分析

    [注:下面数据统计均基于第四轮 2018/03/05]

    第四轮探测,ZoomEye网络空间探测引擎在对前面两轮6种DDoS攻击的探测的基础上,增加了对Memcached攻击的探测。

    3.1.CHARGEN

    通过ZoomEye网络空间探测引擎获取到9万(95,010)台主机开放了19端口。然后对这9万主机进行放大倍率的探测,实际上只有1万(10,122)台主机开启了19点端口,占总数的10.65%。在开启了19端口的主机中,有6千(6,485)台主机的放大倍数能够达到10倍以上,占总数的64.07%,剩下的主机的放大倍数主要集中在2倍。相关数据如图3.1-1所示:

    对放大倍数达到10以上的主机流量进行统计,我们总共发送了870KB(891,693 byte)的请求流量,得到了71M(74,497,401 byte)响应流量,产生了83倍的放大流量。假设一台主机1分钟内可以成功响应100个请求数据包,计算得到攻击流量有947Mbits/s。本轮探测对最大放大倍数进行了统计,得到了Chargen协议单次请求响应最高能放大319倍流量。

    上面的数据和之前两次的的数据进行比较,Chargen DDoS攻击的危害并没有减小,反而有增大的趋势。

    根据ZoomEye网络空间探测引擎的探测结果,对可利用的Chargen主机进行全球分布统计,见图3.1-2:

    3.1-2 Chargen协议19端口可利用主机全球分布图从图中可以看出仍然是韩国具有最多数量的可被利用进行DDos反射放大攻击的主机,我国排在第二 。下面,对我国各省份的情况进行统计,如图3.1-3所示:

    3-1.3 Chargen协议19端口可利用主机全国分布图

    3.2.NTP

    通过ZoomEye网络空间探测引擎获取到14万(147,526)台开启了UDP 123端口的主机。利用这些数据进行放大倍率探测,实际上只有1千(1,723)台主机开启了UDP 123端口,占总数的1.17%,放大倍数大于10的主机只有4台,占有响应主机总数的0.23%,具体数量见图3.2-1所示:

    和上一次探测的结果相比,利用NTP进行反射DDoS攻击的隐患基本消除,不管是NTP服务器的总量还是可被利用服务器数量,都大幅度下降,尤其是本次探测中,只发现4台可被利用的NTP服务器,而且这4台皆位于日本。我国未被探测到可被利用的NTP服务器。

    3.3.DNS

    通过Zoomeye网络空间探测引擎获取到2千万(21,261,177)台UDP 53端口相关的主机,对这些主机进行放大倍率探测,实际上只有384万(3,847,687)台主机开启了53端口,占了扫描总数的18.1%。在开启了53端口的主机中,有3万(31,999)台主机放大倍数在10倍以上,只占总数的0.83%,而放大倍数为1的主机有277万(2,776,027)台,具体数据见图3.3-1:

    和上一版的数据相比,互联网上DNS服务器的和可被利用的DNS服务器数量均处于下降状态。

    下面,再来看看这3万台放大倍数大于10的主机全球分布情况,如图3.3-2所示,可以看到,和上一轮相比,数量排名没啥变化,仍然是美国排在第一位。我们又对可利用主机在我国的分布情况进行了统计,如图3.3-3所示,和上一轮相比,湖北省的DNS服务器数量有了明显的提高。

    3.3-2 DNS协议53端口可利用主机全球分布图

    3.3-3 DNS协议53端口可利用主机全国分布图

    3.4.SNMP

    通过Zoomeye网络空间探测引擎获取到1千万(11,681,422)台UDP 161端口相关的主机,对这些主机进行放大倍率探测,实际上有167万(1,677,616)台主机开启了161端口,占了扫描总数的14.36%。在开启了161端口的主机中,有61万(617,980)台主机放大倍数在10倍以上,占了总数的36.84%,具体数据见图3.4-1:

    本次探测得到的数据和前一轮的数据相比较,探测到的SNMP主机数增加,而可利用的主机数却呈下降状态。

    下面,再来看看这61万台放大倍数大于10的主机全球分布情况,如图3.4-2所示,可以看到,我国的主机量上升到了第二位。我们又对可利用主机在我国的分布情况进行了统计,如图3.4-3所示,台湾,北京,黑龙江仍然是受影响最深的几个省份之一。

    3.4-2 SNMP协议161端口可利用主机全球分布图

    3.4-3 SNMP协议161端口可利用主机全国分布图

    3.5.SSDP

    通过Zoomeye网络空间探测引擎获取到3千万(32,522,480)台UDP 1900端口相关的主机,对这些主机进行放大倍率探测,实际上有60万(609,014)台主机开启了1900端口,占了扫描总数的1.87%。在开启了1900端口的主机中,有57万(572,936)台主机放大倍数在10倍以上,占了总数的94.08%,具体数据见图3.5-1:

    下面,再来看看这57万台放大倍数大于10的主机全球分布情况,如图3.5-2所示,和上一轮探测的数据相比,没有明显的变化。 再对我国的数据进行统计,如图3.5-3所示,台湾仍是我国可被利用的主机数最多的省份,远远超过我国的其他省份。

    3.5-2 SSDP协议1900端口可利用主机全球分布图

    3.5-3 SSDP协议1900端口可利用主机全国分布图

    3.6.CLDAP

    通过Zoomeye网络空间探测引擎获取到40万(403,855)台UDP 389端口相关的主机,对这些主机进行放大倍率探测,实际上有1万(17,725)台主机开启了389端口,占了扫描总数的4.39%。在开启了389端口的主机中,有1万(17,645)台主机放大倍数在10倍以上,占了总数的99.55%,具体数据见图3.6-1:

    下面,再来看看这2万台放大倍数大于10的主机全球分布情况,如图3.5-2所示,可以看到,美国仍然是可被利用的CLDAP服务器数量最多的国家,我国依旧排第三位。我们又对可利用主机在我国的分布情况进行了统计,如图3.5-3所示,台湾依然是我国可被利用的主机数最多的省份,和香港一起远远超过我国的其他省份地区。

    3.6-2 LDAP协议389端口可利用主机全球分布图

    3.6-3 LDAP协议389端口可利用主机全国分布图

    3.7.Memcached

    Memcached是一个自由开源的,高性能,分布式内存对象缓存系统。Memcached是以LiveJournal旗下Danga Interactive公司的Brad Fitzpatric为首开发的一款软件。现在已成为mixi、hatena、Facebook、Vox、LiveJournal等众多服务中提高Web应用扩展性的重要因素。Memcached是一种基于内存的key-value存储,用来存储小块的任意数据(字符串、对象)。这些数据可以是数据库调用、API调用或者是页面渲染的结果。Memcached简洁而强大。它的简洁设计便于快速开发,减轻开发难度,解决了大数据量缓存的很多问题。它的API兼容大部分流行的开发语言。本质上,它是一个简洁的key-value存储系统。一般的使用目的是,通过缓存数据库查询结果,减少数据库访问次数,以提高动态Web应用的速度、提高可扩展性。

    Memcached Server在默认情况下同时开启了TCP/UDP 11211端口,并且无需认证既可使用Memcached的储存服务。2018年3月2日,ZoomEye对全网开启了UDP 11211端口,并且无需认证的Memcached进行探测,共得到14142个目标,并对这些目标进行全球分布统计,如图3.7-1所示:

    3.7-1 Memcached可被利用主机全球分布图从上图中可以明显的看出我国对安全问题的重视程度和国外仍然有较大的差距。在14142个有效目标中,有11368个目标的IP地址位于我国。下面再对我国的目标进行全国分布统计,如图3.7-2所示:

    3.7-2 Memcached可被利用主机全国分布图Memcached未开启认证的情况下,任何人都可以访问Memcached服务器,储存键值对,然后可以通过key来获取value。所以,为了摸清出全球Memcache可利用的情况,我们在Memcached储存一个key为1byte的,value为1kb的数据,然后我们再通过该key获取到value,这样就产生了将近1000倍的放大效果。Memcached在默认情况下还会开启UDP端口,所以这就导致了Memcached可以被利用来进行DDoS放射放大攻击。而Memcached能放大多少倍取决于:

    1. Memcached服务器带宽
    2. Memcached能储存的值的最大长度

    利用自己的服务器进行一个测试,首先让能利用的Memcached储存一个1kb长度的值,然后同时向所有目标获取值,能收到886Mbit/s的流量,如图3.7-3所示:

    3.7-3 流量统计图

    4.总结

    和前面三轮探测的数据相比,在第四轮的探测中,变化最大的是NTP服务,当前互联网的NTP服务器已经没办法造成大流量的DDoS反射放大攻击了。与之相比,其他协议也或多或少的降低了可被利用的主机数量 。DDoS反射放大攻击仍然危害巨大,DDoS防御仍然刻不容缓。 从这次ZoomEye探测到的数据中,再和公网上的Memcached服务进行对比:

    4-4 ZoomEye探测11211端口数量在ZoomEye的数据库中,开启11211端口的目标有54万,其中美国有23万,中国有13万的目标,但是开启了UDP 11211端口的数据中,总量只有14142,其中美国有1070的目标,中国有11368个目标主机。

    从这些数据对比中,可以看出美国对此类的安全事件有非常快的响应速度,中国和美国的差距还很大。

    从放大效果来看,虽然可利用的目标已经缩减到1万的量级,但是仍然能造成大流量的DDos攻击。

    对于Memcached的用户,我们建议关闭其UDP端口,并且启用SASL 认证,对于运营商,建议在路由器上增加的uRPF(Unicast Reverse Path Forwarding)机制,该机制是一种单播反向路由查找技术,用于防止基于源地址欺骗的网络攻击行为,利用该机制能使得UDP反射攻击失效。

    5.参考链接

    1.Stupidly Simple DDoS Protocol (SSDP) generates 100 Gbps DDoS.
    https://blog.cloudflare.com/ssdp-100gbps/
    2.基于SNMP的反射攻击的理论及其实现.
    http://drops.xmd5.com/static/drops/tips-2106.html
    3.基于Memcached分布式系统DRDoS拒绝服务攻击技术研究.
    https://paper.seebug.org/535/
    4.ZoomEye Chargen dork.
    https://www.zoomeye.org/searchResult?q=port%3A19
    5.ZoomEye NTP dork.
    https://www.zoomeye.org/searchResult?q=port%3A123
    6.ZoomEye DNS dork.
    https://www.zoomeye.org/searchResult?q=port%3A53
    7.ZoomEye SNMP dork.
    https://www.zoomeye.org/searchResult?q=port%3A161
    8.ZoomEye LDAP dork.
    https://www.zoomeye.org/searchResult?q=port%3A389
    9.ZoomEye SSDP dork.
    https://www.zoomeye.org/searchResult?q=port%3A1900
    10.ZoomEye Memcached dork.
    https://www.zoomeye.org/searchResult?q=port%3A11211

     

    Paper

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

    作者:吴烦恼 | Categories:安全研究 | Tags:
  • Drupal 1-click to RCE 分析

    2019-04-22

    作者:LoRexxar'@知道创宇404实验室
    时间:2019年4月19日

    2019年4月11日,zdi博客公开了一篇A SERIES OF UNFORTUNATE IMAGES: DRUPAL 1-CLICK TO RCE EXPLOIT CHAIN DETAILED.

    整个漏洞的各个部分没什么特别的,巧妙的是,攻击者使用了3个漏洞+几个小trick,把所有的漏洞链接起来却成了一个还不错的利用链,现在我们就来一起看看整个漏洞.

    无后缀文件写入

    在Drupal的机制中,设定了这样一条规则。

    用户上传的图片文件名将会被保留,如果出现文件名相同的情况,那么文件名后面就会被跟上_0,_1依次递增。

    在Drupal中为了兼容各种编码,在处理上传文件名时,Drupal会对文件名对相应的处理,如果出现值小于0x20的字符,那么就会将其转化为_

    但如果文件名中,如果出现了\x80\xff的字符时,PHP就会抛出PREG_BAD_UTF8_ERROR,如果发生错误,那么preg_replace就会返回NULL,$basename就会被置为NULL。

    当basename为空时,后面的文件内容会被写入到形似_0的文件内

    在这个基础下,原本会被上传到

    则会被写入

    当服务端开启了评论头像上传,或者是拥有作者账号时

    攻击者可以通过上传一张恶意构造的gif图,然后再上传一张带有恶意字符的同一张图,那么就会将恶意图片的内容写入到相应目录的_0

    但如果我们直接访问这个文件时,该文件可能不会解析,这是因为

    1. 浏览器首先会根据服务端给出的content-type解析页面,而服务端一般不会给空后缀的文件设置content-type,或者设置为application/octet-stream
    2. 其次浏览器会根据文件内容做简单的判断,如果文件的开头为<html>,则部分浏览器会将其解析为html
    3. 部分浏览器还可能会设置默认的content-type,但大部分浏览器会选择不解析该文件。

    这时候我们就需要一个很特殊的小trick了,a标签可以设置打开文件的type(only not for chrome)

    当你访问该页面时,页面会被解析为html并执行相应的代码。

     

     

    当被攻击者访问该页面时,我们就可以执行任意的xss,这为后续的利用带来了很大的便利,我们有了一个同源环境下的任意js执行点,让我们继续看。

    phar反序列化RCE

    2018年BlackHat大会上的Sam Thomas分享的File Operation Induced Unserialization via the “phar://” Stream Wrapper议题,原文https://i.blackhat.com/us-18/Thu-August-9/us-18-Thomas-Its-A-PHP-Unserialization-Vulnerability-Jim-But-Not-As-We-Know-It-wp.pdf 

    在该议题中提到,在PHP中存在一个叫做Stream API,通过注册拓展可以注册相应的伪协议,而phar这个拓展就注册了phar://这个stream wrapper。

    在我们知道创宇404实验室安全研究员seaii曾经的研究(https://paper.seebug.org/680/)中表示,所有的文件函数都支持stream wrapper。

    也就是说,如果我们找到可控的文件操作函数,其参数可控为phar文件,那么我们就可以通过反序列化执行js。

    在Drupal中,存在file system功能,其中就有一个功能,会把传入的地址做一次is_dir的判断,这里就存在这个问题

    直接使用下面的payload生成文件

     

     

    修改后缀为png之后,传图片到服务端,并在file system中设置

    即可触发

    漏洞要求

    这个漏洞在Drual8.6.6的更新中被修复,所以漏洞要求为

    • <= Durpal 8.6.6
    • 服务端开启评论配图或者攻击者拥有author以上权限的账号
    • 被攻击者需要访问攻击者的url

    当上面三点同时成立时,这个攻击链就可以被成立

    漏洞补丁

    无后缀文件写入 SA-CORE-2019-004

    https://www.drupal.org/SA-CORE-2019-004

    如果出现该错误直接抛出,不继续写入

    https://github.com/drupal/drupal/commit/82307e02cf974d48335e723c93dfe343894e1a61#diff-5c54acb01b2253384cfbebdc696a60e7

    phar反序列化 SA-CORE-2019-002

    https://www.drupal.org/SA-CORE-2019-002

    写在最后

    回顾整个漏洞,不难发现其实整个漏洞都是由很多个不起眼的小漏洞构成的,Drupal的反序列化POP链已经被公开许久,phar漏洞也已经爆出一年,在2019年初,Drupal也更新修复了这个点,而preg_replace报错会抛出错误我相信也不是特别的特性,把这三个漏洞配合上一个很特别的a标签设置content-type的trick,就成了一个很漂亮的漏洞链。


    Paper

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

    作者:吴烦恼 | Categories:安全研究技术分享 | Tags:
  • Apache 提权漏洞(CVE-2019-0211)复现

    2019-04-12

    作者:Hcamael@知道创宇404实验室
    时间:2019年4月12日

    本月Apache被公布了一个提权的漏洞,并且前天在GitHub上公布出了利用脚本,这几天我负责漏洞应急这个漏洞。

    本篇文章没有叫:《Apache 提权漏洞分析》是因为我觉得CARPE (DIEM): CVE-2019-0211 Apache Root Privilege Escalation这篇文章的分析写的挺好的,所以我没必要再翻译一遍了,本篇文章主要叙述复现该漏洞的过程中踩过的坑。

    复现环境

    我使用的复现环境是:

    1. apache使用apt安装的版本属于已经修复的版本,所以需要指定一下版本: # apt install apache2=2.4.29-1ubuntu4 apache2-bin=2.4.29-1ubuntu4 apache2-utils=2.4.29-1ubuntu4 apache2-data=2.4.29-1ubuntu4
    2. php直接用apt安装就好了
    3. exp地址: https://github.com/cfreal/exploits/blob/master/CVE-2019-0211-apache/cfreal-carpediem.php
    4. 需要开启ssl模块:a2enmod ssl

    关于需要开始ssl模块说明:

    1. 就算不开ssl模块,漏洞也是存在的
    2. 就算不开启ssl模块,你自己修改apache配置,能开启其他端口,也是能利用的
    3. 如果只开了80端口,则需要另行找一条利用链,github上公布exp在只开启了一个端口的情况下是无效的
    4. @cfreal的文章中已经说了,我这里在多说句,相关代码可以看看12还有SAFE_ACCPET的宏定义:

    简单的来说,只有在apache开启多个端口的情况下,才会生成mutex互斥锁,而在github上公布的exp就是通过apache的mutex对象来进行利用的。

    跑exp中遇到的一些坑

    我试过了很多版本,没有一个版本是能直接使用Github上的exp的,在上述表面的版本中,经过调试研究发现了两个问题导致了利用失败:

    1. $all_buckets = $i - 0x10 计算出问题
    2. $bucket_index = $bucket_index_middle - (int) ($total_nb_buckets / 2); 计算出问题

    第一个计算all_buckets的地址,使用gdb进行调试,你会发现,这个值并没有算错,但是在执行apache2ctl graceful命令以后,all_buckets 生成了一个新的值,不过只和之前的all_buckets地址差0x38000,所以这个问题很好解决:

    第二个计算没必要这么复杂,而且在我测试的版本中还是算的错误的地址,直接改成:

    ubuntu中的一个坑

    我的payload是:curl "http://localhost/cfreal-carpediem.php?cmd=id>/tmp/2323232"

    表面上看是执行成功了,但是却并没有在/tmp目录下发现2323232文件,经过随后的研究发现,systemd重定向了apache的tmp目录,执行下$find /tmp -name "2323232"就找到文件了,不过只有root用户能访问。如果不想让systemd重定向tmp目录也简单:

    这项为false就好了,PrivateTmp=false,改完以后重启一下,再测试一遍就能在tmp目录下写文件了

    关于成功率的说法

    在exp的注释中看到了说该利用没法100%成功,有失败的概率,所以我写了个脚本进行测试:

    我测试的跑了20次的结果:

    并没有遇到失败的情况

    总结

    其他版本的还没有进行测试,但是在这里给一些建议。

    1. check all_buckets地址

      这个挺简单的,执行完exp以后,有输出对应的pid和all_buckets地址,可以使用gdb attach上去检查下该地址是否正确:p all_buckets

      PS:这里要注意下,需要安装dbg包,才有all_buckets符号 :apt install apache2-dbg=2.4.29-1ubuntu4

      如果有问题,就调试检查exp中搜索all_buckets地址的流程

      如果没问题,就使用gdb attach主进程(root权限的那个进程),然后断点下在make_child,然后执行apache2ctl graceful,执行完然后在gdb的流程跳到make_child函数的时候,再输出一次:p all_buckets,和exp获取的值对比一下,如果一样就没问题了

    2. check my_bucket地址

      前面的流程和上面一样,重点关注在make_child函数中的my_bucket赋值的代码:3

      这里注意下,因为上面有一个fork,所以在gdb里还要加一句:set follow-fork-mode child

      my_bucket的值是一个指针,指向堆喷的地址,如果my_bucket的值没问题,exp基本就没问题了,如果不对,就调整$bucket_index

    更新

    debian 9测试成功:

    参考

    1. https://github.com/apache/httpd/blob/23167945c17d5764820fdefdcab69295745a15a1/server/mpm/prefork/prefork.c#L433
    2. https://github.com/apache/httpd/blob/23167945c17d5764820fdefdcab69295745a15a1/server/mpm/prefork/prefork.c#L1223
    3. https://github.com/apache/httpd/blob/23167945c17d5764820fdefdcab69295745a15a1/server/mpm/prefork/prefork.c#L691

    Paper

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

    作者:吴烦恼 | Categories:安全研究 | Tags:
  • Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析

    2019-04-09

    作者:Badcode@知道创宇404实验室
    时间:2019年4月8日

    看到官方发布了预警,于是开始了漏洞应急。漏洞描述中指出Confluence Server与Confluence Data Center中的Widget Connector存在服务端模板注入漏洞,攻击者能利用此漏洞能够实现目录穿越与远程代码执行。

    确认漏洞点是Widget Connector,下载最新版的比对补丁,发现在com\atlassian\confluence\extra\widgetconnector\WidgetMacro.java里面多了一个过滤,这个应该就是这个漏洞最关键的地方。

    可以看到

    TEMPLATE_PARAM的值就是_template,所以这个补丁就是过滤了外部传入的_template参数。

    翻了一下Widget Connector里面的文件,发现TEMPLATE_PARAM就是模板文件的路径。

    加载外部的链接时,会调用相对的模板去渲染,如上,模板的路径一般是写死的,但是也有例外,补丁的作用也说明有人突破了限制,调用了意料之外的模板,从而造成了模板注入。

    在了解了补丁和有了一些大概的猜测之后,开始尝试。

    首先先找到这个功能,翻了一下官方的文档,找到了这个功能,可以在文档中嵌入一些视频,文档之类的。

    看到这个,有点激动了,因为在翻补丁的过程中,发现了几个参数,urlwidthheight正好对应着这里,那_template是不是也从这里传递进去的?

    随便找个Youtube视频插入试试,点击预览,抓包。

    params中尝试插入_template参数,好吧,没啥反应。。

    开始debug模式,因为测试插入的是Youtube视频,所以调用的是com/atlassian/confluence/extra/widgetconnector/video/YoutubeRenderer.class

     

     

     

    getEmbeddedHtml下断点,先会调用getEmbedUrl对用户传入的url进行正则匹配,因为我们传入的是个正常的Youtube视频,所以这里是没有问题的,然后调用setDefaultParam函数对传入的其他参数进行处理。

    取出widthheight来判断是否为空,为空则设置默认值。关键的_template参数来了,如果外部传入的参数没有_template,则设置默认的Youtube模板。如果传入了,就使用传入的,也就是说,aaaa是成功的传进来了。

    大概翻了一下Widget Connector里面的Renderer,大部分是不能设置_template的,是直接写死了,也有一些例外,如Youtube,Viddler,DailyMotion等,是可以从外部传入_template的。

    能传递_template了,接下来看下是如何取模板和渲染模板的。

    跟进this.velocityRenderService.render,也就是com/atlassian/confluence/extra/widgetconnector/services/DefaultVelocityRenderService.class里面的render方法。

    _template取出来赋值给template,其他传递进来的参数取出来经过判断之后放入到contextMap,调用getRenderedTemplate函数,也就是调用VelocityUtils.getRenderedTemplate

    一路调用,调用链如下图,最后来到/com/atlassian/confluence/util/velocity/ConfigurableResourceManager.classloadResource函数,来获取模板。

    这里调用了4个ResourceLoader去取模板。

    这里主要看下Velocity自带的FileResourceLoaderClasspathResourceLoader

    FileResourceLoader会对用户传入的模板路径使用normalizePath函数进行校验

    可以看到,过滤了/../,这样就导致没有办法跳目录了。

    路径过滤后调用findTemplate查找模板,可看到,会拼接一个固定的path,这是Confluence的安装路径。

    也就是说现在可以利用FileResourceLoader来读取Confluence目录下面的文件了。

    尝试读取/WEB-INF/web.xml文件,可以看到,是成功的加载到了该文件。

    但是这个无法跳出Confluence的目录,因为不能用/../

    再来看下ClasspathResourceLoader

    跟进ClassUtils.getResourceAsStream

    会跳到/org/apache/catalina/loader/WebappClassLoaderBase.class

    跟进,发现会拼接/WEB-INF/classes,而且其中也是调用了normalize对传入的路径进行过滤。。

    这里还是可以用../跳一级目录。

    尝试读取一下../web.xml,可以看到,也是可以读取成功的,但是仍然无法跳出目录。

    我这里测试用的版本是6.14.1,而后尝试了file://,http://https://都没有成功。后来我尝试把Cookie删掉,发现还是可以读取文件,确认了这个漏洞不需要权限,但是跳不出目录。应急就在这里卡住了。

    而后的几天,有大佬说用file://协议可以跳出目录限制,我惊了,我确定当时是已经试过了,没有成功的。看了大佬的截图,发现用的是6.9.0的版本,我下载了,尝试了一下,发现真的可以。

    问题还是在ClasspathResourceLoader上面,步骤和之前的是一样的,断到/org/apache/catalina/loader/WebappClassLoaderBase.classgetResourceAsStream方法

    前面拼接/WEB-INF/classes获取失败后,继续往下进行。

    跟进findResource,函数前面仍然获取失败

    关键的地方就在这里,会调用super.findResource(name),这里返回了URL,也就是能获取到对象。

    不仅如此,这里还可以使用其他协议(https,ftp等)获取远程的对象,意味着可以加载远程的对象。

    获取到URL对象之后,继续回到之前的getResourceAsStream,可以看到,当返回的url不为null时,

    会调用url.openStream()获取数据。

    最终获取到数据给Velocity渲染。

    尝试一下

    至于6.14.1为啥不行,赶着应急,后续会跟,如果有新的发现,会同步上来,目前只看到ClassLoader不一样。

    6.14.1

    6.9.0

    这两个loader的关系如下

    现在可以加载本地和远程模板了,可以尝试进行RCE。

    关于Velocity的RCE,基本上payload都来源于15年blackhat的服务端模板注入的议题,但是在Confluence上用不了,因为在调用方法的时候会经过velocity-htmlsafe-1.5.1.jar,里面多了一些过滤和限制。但是仍然可以利用反射来执行命令。

    python -m pyftpdlib -p 2121开启一个简单的ftp服务器,将payload保存成rce.vm,保存在当前目录。

    _template设置成ftp://localhost:2121/rce.vm,发送,成功执行命令。

    对于命令回显,同样可以使用反射构造出payload,执行ipconfig的结果。

    漏洞影响

    根据 ZoomEye 网络空间搜索引擎对关键字 "X-Confluence" 进行搜索,共得到 61,856 条结果,主要分布美国、德国、中国等国家。

    全球分布(非漏洞影响范围)

    中国分布(非漏洞影响范围)

    漏洞检测

    2019年4月4日,404实验室公布了该漏洞的检测PoC,可以利用这个PoC检测Confluence是否受该漏洞影响。

    参考链接


    Paper

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

    作者:吴烦恼 | Categories:安全研究技术分享 | Tags:
  • 重现 TP-Link SR20 本地网络远程代码执行漏洞

    2019-04-03

    作者:xax007@知道创宇404 ScanV 安全服务团队

    简述

    3月26号 Google 安全开发人员 Matthew Garrett在 Twitter 上公布了 TP-Link Smart Home Router (SR20) 的远程代码执行漏洞,公布的原因是他去年 12 月份将相关漏洞报告提交给 TP-Link后没有收到任何回复,于是就公开了,该漏洞截至目前官方修复,在最新固件中漏洞仍然存在,属于 0day 漏洞,当我看到漏洞证明代码(POC)后决定尝试重现此漏洞

    img

    TP-Link SR20 是一款支持 Zigbee 和 Z-Wave 物联网协议可以用来当控制中枢 Hub 的触屏 Wi-Fi 路由器,此远程代码执行漏洞允许用户在设备上以 root 权限执行任意命令,该漏洞存在于 TP-Link 设备调试协议(TP-Link Device Debug Protocol 英文简称 TDDP) 中,TDDP 是 TP-Link 申请了专利的调试协议,基于 UDP 运行在 1040 端口

    TP-Link SR20 设备运行了 V1 版本的 TDDP 协议,V1 版本无需认证,只需往 SR20 设备的 UDP 1040 端口发送数据,且数据的第二字节为 0x31 时,SR20 设备会连接发送该请求设备的 TFTP 服务下载相应的文件并使用 LUA 解释器以 root 权限来执行,这就导致存在远程代码执行漏洞

    img

    漏洞环境搭建

    以下所有操作都在 Ubuntu LTS 18.04 系统下进行

    源码编译 QEMU

    Qemu 是纯软件实现的虚拟化模拟器,几乎可以模拟任何硬件设备,我们最熟悉的就是能够模拟一台能够独立运行操作系统的虚拟机

    APT 仓库有 QEMU,本可以使用 APT apt install qemu 直接安装,但 APT 仓库中的版本通常都不是最新的,担心会有未知的 bug,因此选择从 QEMU 官网下载最新稳定版源码来编译安装

    如果 configure 时没有指定 target-list参数,make 会编译针对所有平台的 QEMU 导致会耗很长很长的时间,因此可以选择只编译 ARM 版的 QEMU 来加快编译速度,至于选择 ARM 版是因为 TP-Link SR20 存在漏洞的固件基于是 ARM 架构,下文中会看到。

    编译完成后安装 checkinstall 来生成 deb 包

    如果不使用 checkinstall,直接sudo make install的会把 qemu 安装在多个位置,如果发生错误不方便删除,所以使用 checkinstall 生成 deb 包方便安装和卸载。

    安装完成后可以看到安装的版本

    img

    安装 Binwalk

    Binwalk 是一款文件的分析工具,旨在协助研究人员对文件进行分析,提取及逆向工程

    更详细的安装方法可以查看 Binwalk 的 GitHub wiki

    PS: 本人在最后一步运行deps.sh安装依赖的时 cramfstools 编译出错导致安装失败,如果你也遇到这个问题,不必理会,因为针对本文讲述的漏洞,这个包并不需要安装

    从固件提取文件系统

    从 TP-Link SR20 设备官网下载固件, 下载下来是一个 zip 压缩包,解压以后进入解压后目录,可以看到一个名字很长的叫 tpra_sr20v1_us-up-ver1-2-1-P522_20180518-rel77140_2018-05-21_08.42.04.bin 的文件,这个就是该 SR20 设备的 firmware (固件)

    使用 binwalk 查看该固件

    img

    使用 binwalk 把 Squashfs filesystem 从固件中提取出来,在固件 bin 文件所在目录执行

    binwalk 会在当前目录的 _+bin文件名 目录下生成提取出来的固件里的所有内容,进入到该目录

    img

    squashfs-root 目录就是我们需要的固件文件系统

    img

    在该文件系统目录下查找存在漏洞的 tddp 文件并查看文件类型可以看到该文件是一个 ARM 架构的小端(Small-Endian)32 位 ELF 文件

    img

    最高有效位 MSB(Most Significant Bit) 对应大端 (Big-endian)
    最低有效位 LSB(Least Significant Bit) 对应小端 (Little-endian)
    详细介绍可阅读:大端小端与MSB和LSB

    这时可以使用 QEMU 来运行该文件

    PS: 不加 -L . 参数运行 qemu-arm 会报错, -L . 参数会把当前目录加入到 PATH 路径中

    img

    经过测试发现通过这种方式运行 TDDP 程序并不能触发该漏洞,因此需要搭建完整的 ARM QEMU 虚拟机环境

    搭建 ARM QEMU 虚拟机环境

    ARM CPU 有两个矢量浮点(软浮点和硬浮点)具体区别可以查看 Stackoverflow,本次选择使用硬浮点 armhf

    从 Debian 官网下载 QEMU 需要的 Debian ARM 系统的三个文件:

    • debian_wheezy_armhf_standard.qcow2 2013-12-17 00:04 229M
    • initrd.img-3.2.0-4-vexpress 2013-12-17 01:57 2.2M
    • vmlinuz-3.2.0-4-vexpress 2013-09-20 18:33 1.9M

    把以上三个文件放在同一个目录执行以下命令

    img

    img

    虚拟机启动成功后会提示登陆

    用户名和密码都为 root

    img

    配置网卡IP

    img

    此时 QEMU 虚拟机可以与宿主机进行网络通信

    现在需要把从固件中提取出的文件系统打包后上传到 QEMU 虚拟机中

    压缩固件文件系统目录下的整个文件

    使用 Python 搭建简易 HTTP Server

    在 QEMU 虚拟机中下载上面打包好的文件

    img

    使用 chroot 切换根目录固件文件系统

    PS: 使用 chroot 后,系统读取的是新根下的目录和文件,也就是固件的目录和文件 chroot 默认不会切换 /dev 和 /proc, 因此切换根目录前需要现挂载这两个目录

    img

    如果你有树莓派,可以直接拿来用,几年前买过一个树莓派2B+,经过我的测试,安装了 Raspbian 的树莓派完全可以拿做做 ARM 的测试环境

    img

    img

    搭建 TFTP Server

    在宿主机安装 atftpd 搭建 TFTP 服务

    • 编辑 /etc/default/atftpd 文件,USE_INETD=true 改为 USE_INETD=false
    • 修改 /srv/tftp 为 /tftpboot

    最终 /etc/default/atftpd 文件内容如下:

    如果执行命令 sudo systemctl status atftpd 查看 atftpd 服务状态时

    提示 atftpd: can't bind port :69/udp 无法绑定端口

    可以执行 sudo systemctl stop inetutils-inetd.service 停用 inetutils-inetd 服务后

    再执行 sudo systemctl restart atftpd 重新启动 atftpd 即可正常运行 atftpd

    img

    此时环境已搭建完毕

    重现漏洞

    在 atftp 的根目录 /tftpboot 下写入 payload 文件

    payload 文件内容为:

    img

    重现步骤为:

    1. QEMU 虚拟机中启动 tddp 程序
    2. 宿主机使用 NC 监听端口
    3. 执行 POC,获取命令执行结果

    漏洞证明代码(Proof of concept):

    最终成功重现此漏洞

    img

    img

    参考链接 4 中说到 TP-Link 的 TL-WA5210g 无线路由器的 TDDP 服务只能通过有线网络访问,连 Wi-Fi 也不能访问,由于手上没有 SR20设备,因此断定该 SR20 设备的 TDDP 端口可能也是这种情况,我想这应该就是官方未修复此漏洞的原因吧

    参考链接 4 中详细介绍 TDDP 协议以及该协议 V1 和 V 2版本的区别等知识点

    最后感谢知道创宇404实验室 @fenix 大佬的指点

    参考链接

    1. Remote code execution as root from the local network on TP-Link SR20 routers
    2. How to set up QEMU 3.0 on Ubuntu 18.04
    3. Vivotek 摄像头远程栈溢出漏洞分析及利用
    4. 一个针对TP-Link调试协议(TDDP)漏洞挖掘的故事

     

    Paper

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

    作者:吴烦恼 | Categories:安全研究技术分享 | Tags: