RSS Feed
更好更安全的互联网
  • Redis 基于主从复制的 RCE 利用方式

    2019-07-15

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

    在2019年7月7日结束的WCTF2019 Final上,LC/BC的成员Pavel Toporkov在分享会上介绍了一种关于redis新版本的RCE利用方式,比起以前的利用方式来说,这种利用方式更为通用,危害也更大,下面就让我们从以前的redis RCE利用方式出发,一起聊聊关于redis的利用问题。

    https://2018.zeronights.ru/wp-content/uploads/materials/15-redis-post-exploitation.pdf

    通过写入文件 GetShell

    未授权的redis会导致GetShell,可以说已经是众所周知的了。

    而这种方式是通过写文件来完成GetShell的,这种方式的主要问题在于,redis保存的数据并不是简单的json或者是csv,所以写入的文件都会有大量的无用数据,形似

    这种主要利用了crontab、ssh key、webshell这样的文件都有一定容错性,再加上crontab和ssh服务可以说是服务器的标准的服务,所以在以前,这种通过写入文件的getshell方式基本就可以说是很通杀了。

    但随着现代的服务部署方式的不断发展,组件化成了不可逃避的大趋势,docker就是这股风潮下的产物之一,而在这种部署模式下,一个单一的容器中不会有除redis以外的任何服务存在,包括ssh和crontab,再加上权限的严格控制,只靠写文件就很难再getshell了,在这种情况下,我们就需要其他的利用手段了。

    通过主从复制 GetShell

    在介绍这种利用方式之前,首先我们需要介绍一下什么是主从复制和redis的模块。

    Redis主从复制

    Redis是一个使用ANSI C编写的开源、支持网络、基于内存、可选持久性的键值对存储数据库。但如果当把数据存储在单个Redis的实例中,当读写体量比较大的时候,服务端就很难承受。为了应对这种情况,Redis就提供了主从模式,主从模式就是指使用一个redis实例作为主机,其他实例都作为备份机,其中主机和从机数据相同,而从机只负责读,主机只负责写,通过读写分离可以大幅度减轻流量的压力,算是一种通过牺牲空间来换取效率的缓解方式。

    这里我们开两台docker来做测试

    然后通过slaveof可以设置主从状态

    这样一来数据就会自动同步了

    Redis模块

    在了解了主从同步之后,我们还需要对redis的模块有所了解。

    在Reids 4.x之后,Redis新增了模块功能,通过外部拓展,可以实现在redis中实现一个新的Redis命令,通过写c语言并编译出.so文件。

    编写恶意so文件的代码

    https://github.com/RicterZ/RedisModules-ExecuteCommand

    利用原理

    Pavel Toporkov在2018年的zeronights会议上,分享了关于这个漏洞的详细原理。

    https://2018.zeronights.ru/wp-content/uploads/materials/15-redis-post-exploitation.pdf

    在ppt中提到,在两个Redis实例设置主从模式的时候,Redis的主机实例可以通过FULLRESYNC同步文件到从机上。

    然后在从机上加载so文件,我们就可以执行拓展的新命令了。

    复现过程

    这里我们选择使用模拟的恶意服务端来作为主机,并模拟fullresync请求。

    https://github.com/LoRexxar/redis-rogue-server

    然后启用redis 5.0的docker

    为了能够更清晰的看到效果,这里我们把从服务端执行完成后删除的部分暂时注释掉。

    然后直接通过脚本来攻击服务端

    然后我们链接上去就可以执行命令

     

    Paper

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

    作者:吴烦恼 | Categories:安全研究技术分享 | Tags:
  • 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:
  • 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:
  • 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去取模板。