Skip to main content
Background Image

Archangel - TryHackMe

·1602 words·8 mins
Brady McLaughlin
Author
Brady McLaughlin

This is a write-up for the “Archangel” lab, an easy room on TryHackMe. This is a free room located at https://tryhackme.com/room/archangel. I am documenting the process I used to find all information in this writeup WITHOUT including any flags, in the spirit of the game. However, following this process exactly should result in a full compromise of the target system.


Recon, Scanning, and Enumeration
#

My first step was to ping the box to ensure that it was alive and ready for enumeration:

Next, I ran a quick nmap scan to enumerate the service versions and run some basic nmap scripts against found ports:

We see that we have SSH, which will help us if we find some credentials to use, and an Apache web server running on port 80.

First, let’s check out the website:

We have a potential email address, which contains a domain name. Let’s add this to our notes, and add the domain name to our /etc/hosts file, where our local machine looks for name resolution:

Now, if we navigate to this hostname (we’ll need to add “http://” to the front so our browser knows what to do with it), we’ll go to a new page, with flag 1:

Now we’ll need to expand our search by fuzzing for other items on the site. A standard directory fuzz won’t get us anywhere, so I’ll add the -x flag to gobuster to add file extensions to the wordlist in order to find more results. Because we’re looking at an Apache web server (nmap told us this), we know to look for PHP extensions:

If we navigate to this page, we see a “Test Page” with a button on it.

If we press the button, we get the following text. This is interesting, however, because we can see that this page is making a call to a local file in the GET parameter in the address bar:

This is indicative of a potential local file inclusion (LFI) vulnerability. To see how this works, we can add a PHP wrapper to base64 encode the content - this will convert the contents of this page from PHP code that the web server can interpret and execute into something the server doesn’t understand, so it will just output the results to the screen:

Now we can decode the base64 and see the source code for the “mrrobot.php” page:

So the button literally just outputs the string that we saw earlier. This isn’t very interesting, but let’s see if we can use this technique to find out what the “test.php” page that we are abusing is doing under the hood:

Taking a look at the code, there are a few things we can notice. First, for the quick and easy, the source code contains flag 2!

Second (and more importantly), we can see that the test.php page is checking for two things - the “view” parameter is looking for the string “/var/www/html/development_testing” AND checking to ensure that the string “../..” is NOT present:

The checks for ../.. are an attempt to prevent path traversal. If we tried to use the ../../../../ method to go back to the root and read the “/etc/passwd” file, we’d get something like this:

However, this check is NOT very robust, and we can bypass it with a couple of tricks. Because it is only checking for exactly those characters (../..), we can use other combinations of characters to achieve the same effect but not be caught by the check.

For instance, we can do either of these options (as well as likely others, but for the sake of brevity, we’ll just hit two):

  1. We can use ..//.. instead of ../.., which will still be interpreted the same way by the Linux filesystem, but not be caught by the check because it is only looking for a single forward slash.

  2. We can use .././.., which breaks up the block of characters that the check is looking for using a ./, which just indicates the current directory.

Now that we know how to bypass this check, we can move on to more actionable exploitation of this LFI and gain some shell access!

Initial Access
#

Let’s attempt a classic initial access method - Apache log poisoning with LFI. We can use our LFI to call /var/log/apache2/access.log, a system file that logs requests to the web server:

Note here that it is logging the User-Agent string for each request. If we can modify this header, we can inject some code that will be called each time we access this page. Remembering that our LFI will execute code if it comes across PHP that it understands, we can try to insert some PHP code into a User-Agent string and call it.

You can use something as simple as curl to make this request, but for visual aid, I am going to use Burp Suite:

Now that we’ve confirmed that we can inject, let’s weaponize this with a payload we can use to get code execution. We can just use the PHP string <?php system($_GET['cmd']); ?>, which essentially runs a system command with the contents of the GET request that we make with the “cmd” parameter:

Here, we used a command with visible output (I like which python3 because it gives us information we can use to get our reverse shell later) to confirm our injection has granted us code execution.

Since we’ve confirmed both that we have code execution and that the system can run python3, let’s use that information to get a reverse shell. We can use revshells.com to craft a reverse shell payload and get a more interactive shell on the host:

I personally like the “Python3 #2” payload, but this is not the only one that will work. We just need to make sure that we target our tun0 IP address, since that is the one the machine can access over the TryHackMe VPN.

We will need to start a listener using nc to catch our reverse shell, then we can run our payload and see the shell run in our listener:

Now that we have an (unstable) reverse shell, we can stabilize using python3, which we already know that we have on this machine:

python3 -c 'import pty;pty.spawn("/bin/bash")'

Ctrl + Z #(to background the shell, taking us back to our host machine's shell)

stty raw -echo;fg #(on the host shell - gives us a raw terminal with no input or output processing, then foregrounds the reverse shell from the victim machine)

export TERM=xterm #(sets the TERM variable so that we can use commands like clear in the reverse shell)

Lateral Movement
#

Now that we have a more stable foothold on the machine, it’s time to start looking around for ways to move laterally and vertically. A good place to start is the /home directory:

Rather than starting our checks manually, we can get help from LinPEAS. Because TryHackMe machines are not connected to the Internet, we will need to source our own version of the file on our attacking machine and transfer it to the host with a method of our choosing. We can use the FTP server from earlier, but I am going to host the file on a local HTTP service with python3 -m http.server 80 and then download the file on the victim machine with wget:

In the “Check for vulnerable cron jobs” section of our LinPEAS output, we can see an interesting cron job that runs as the “archangel” user:

Let’s see if we can write to this file, and check out what it is doing:

Perfect, so we do have the ability to write to this file. Currently, it just echoes to a text file. We can weaponize this cron job (since it runs as the “archangel” user) to move laterally. We’ll just need to start another listener; we can re-use our reverse shell command from before, since we already know that it works:

Poking around in the user’s home directory, we can see a “secret” directory, which contains a SUID binary and the user2 flag:

Privilege Escalation
#

Checking out the SUID binary, we can see that this is an Executable and Linking Format (ELF) file, so we can’t just read the file and find out what it’s doing in the same way that we did the script. However, we can run strings on the binary to see if any human-readable strings are stored in the compiled executable:

It looks like the SUID binary is running the cp binary here with arguments that will be arbitrary to our current purposes. Since cp is being called without an absolute can manipulate our PATH variable in order to make cp do something malicious of our choosing.

The first thing we’ll want to do is find out what we currently have in our PATH:

The way that PATH works is that running a binary will attempt locations from left to right. So if we run cp right now, it will look for it in /usr/local/sbin, since that’s the first location seen. If the file is there, it will execute; otherwise, it will move on to the next location (/usr/local/bin, in this case), and so on.

This means that if we can change our PATH to put a location we have control over before it finds the binary that we’re calling, it will run our malicious file instead of the legitimate copy:

Now that we see that calling cp will run our file instead, we can run the SUID binary, which will result in our malicious invocation:

Thanks to Archangel for the creation of this challenge!