Again is an easy machine from HackMyVM by SML. Here, the author has marked the machine as hard but this is quite easy if we understand the code. This machine is similar to his previous machine Texte. You can use it on VirtualBox. “Again – Writeup – HackMyVM – Walkthrough”
Link to the machine: https://hackmyvm.eu/machines/machine.php?vm=Again
Identify the target
As usual, we have to start the exploitation by identifying the IP address of the target. The machines by SML have the IP address on the login prompt but I will do it using a binary.
sudo netdiscover -r 10.0.0.0/24
Scan open ports
Next, we can scan the open ports so that we get the knowledge services that are running on the target.
nmap -v -T4 -p- -sC -sV -oN nmap.log 10.0.0.45
Only ports 22 and 80 are open on the target. Thus, we can start enumerating the webserver.
Enumerate the webserver
As usual, I checked the homepage and it is quite similar to the previous machine. It is an index.html file that has a file upload option.
However, upon checking the source, we have a hint to check “.bck” files.
Also, we see the script used for uploading i.e. upload.php. Hence, we can try hitting upload.bck. Luckily, we have this file on the target. Therefore, I saved it on my local machine.
Understand the upload.bck file
Understanding the upload.bck script is a tricky part of the machine. Let’s see this line by line.
From lines 1 to 4, we have an error handling if a user doesn’t upload a file. If we avoid this line, then, it will throw an exception and the script dies prematurely. That’s where we use isset() function. Similarly, on line 6, we get the temporary path of the uploaded file. In PHP, ‘tmp_name’ contains the temporary name of the file that is stored somewhere inside /tmp directory in Linux. Likewise, on line 7, we get the size of the file. In a similar manner, we get the mime type of the file from lines 8 and 9. This means that it is using the content of the file rather than the Content-Type header to determine the file type.
Let’s elaborate on the last line. Every file has some sort of headers included. So, when we do “file filename.ext” in Linux, it returns the type of the file based on the headers. On contrary, Windows uses extensions to determine the file type.
As we see above, the upload.bck is also a PHP script as identified by the file command. A similar thing is happening in the upload.bck script. It will check the headers of the file.
On line 11, this is checking for an empty file. Likewise, we have an array that maps two mime types to their extensions. Here, we can see the support for jpg and txt extensions only.
Now, on line 20, it is exiting the script if we don’t send the proper file. Next, there is a rabbit hole on lines 25 and 26. We don’t see those variables anywhere. Then, on line 27, this is copying the file to the current directory. Here, we can see that the uploaded file is already copied on the current directory and there isn’t a check for extensions. This means we can upload anything as long as we can spoof the content to make it look like a plain text file. However, if the author had verified the extension after line 26 with allowed types, then, we couldn’t have done so.
Then, on lines 32-35, we have a major diversion. There are some characters that will terminate the script if matched with the filename. Now, if your mind is like mine, you will think, we might have to bypass this. However, we must match this to exploit the machine. I will explain this in the next section.
There is a conditional if-else block of which we can simply ignore the “if” block for now. Because this is quite similar to the else block, we can simply go for understanding the else part. On line 50, it opens a local file “outputtext.txt” in write mode. Then, on lines 51 and 52, it will execute the “cat” command for the name of the file. On line 53, it is going to delete the file. Lastly, the output is written on the outputtext.txt file. Here, if we use a valid filename, then, the file will be deleted. In this way, we will never be able to put our shell code on the target. Thus, this is necessary to exit before reaching this code block. That is, we have to use an invalid filename that will terminate the script prematurely while keeping the file undeleted.
Upload a shell
Up to now, you understood how we can exploit the logic. So, let’s do it. In this case, we don’t even need the burp suite. I will be using pentestmonkey’s reverse shell. However, we have to add some random text before the “<?php” tag so that the script deems it as plain text rather than a PHP script. Then, we can name the file with any of the blacklisted characters, e.g. a semicolon.
Listen on port 9001.
nc -nlvp 9001
Now, we have to update the shellcode with our IP address and port. Also, we have to add a random text at the top.
cp shell.php \;shell.php vim \;shell.php head \;shell.php
Now, let’s upload the file and upon visiting /;shell.php, we will have a shell.
Lastly, we can make it better. Check the link below.
Root privilege escalation
We can directly escalate to the root user in this machine. Firstly, we have to check the binaries with capabilities.
getcap -r / 2>/dev/null
Here, the binary php7.4 has the cap_fowner capability set. This allows changing the permissions of the files of the directories where he has access to traverse.
So, we can change the permissions of /etc/passwd file programmatically using PHP.
php7.4 -r 'chmod("/etc/passwd", 0666);'
Then, we can generate an MD5 hash of a password and use it as follows.
openssl passwd -1 nepcodex
Next, we can switch to the root user.
In this way, we can get the root shell.