Debug - THM Walkthrough
Walkthrough of the machine Debug on TryHackMe - https://tryhackme.com/room/debug
IP: 10.10.51.225
Enumeration
We can scan the host using rustscan (like nmap; but faster!) for open ports:
rustscan -a 10.10.51.225 --timeout 5000 --tries 2 --ulimit 5000 -- -sC -sV-aspecifies the Host IP address--timeoutspecifies the timeout before saying the port is closed--trieshow many times to try and connect to the port--ulimitspecifies how many sockets to open at a time--for passing arguments for nmap-sC -sVnmap arguments telling rustscan to run default scripts and version fingerprinting
Scan results:

Alright, so, we’ve found 2 open ports. 22 and 80.
SSH (Port 22)
Let’s go with the waterfall mechanism and first enumerate port 22. We can try credentials bruteforcing using BruteX and check the version for any vulnerabilities which are public and exploitable.
From googling the exact banner/version, we can see that the specific version is vulnerable to username enumeration

–
Let’s try and do it using metasploit’s module.
We can search for the module using search with an filter of port:22 for only searching for everything written for SSH/Port22 with enum

–
Let’s run it.

–
We can see that it enumerated the user root and can probably guess the password will be something really long. Let’s goto port 80 for now and we’ll come back to SSH if we need something.
HTTP (Port 80)
Let’s browse the application to get an idea in which programming language it was written, what’s it’s using as it’s backend server, etc.

So, we get met with Apache2’s default installation page. Let’s try and see if /robots.txt has something in it.

Sadly, it doesn’t exist either.
–
We can now utilize gobuster or dirsearch to enumerate the hidden directories hosted on the web application.
I’ll use dirsearch to save some time downloading and setting up gobuster.

–
Alright, we can see /backup/ directory and /readme.md which also seems kinda interesting. Let’s visit these and see what’s hosted in them.
Let’s cURL it.
We can see that it returns README.md source of some repository, maybe we can explore it later?
For now, let’s move to the /backup/ folder

The /backup/ directory contains interesting .bak files, let’s cURL those one by one and see their source code.
We can see that the page also points to default Apache installation page. Let’s try .php.bak file now.
I’ll be downloading and analysing it in Sublime text (text editor).
–
In the heading, we can see that it too points to the same framework Base which was discussed above in the README.md file, let’s try searching this framework.

So, the guy has deleted this repository (base) from his github account. Maybe shifted somewhere else? Let’s try searching it on google rather than using the link from readme.md file.

Seeing the readme.md contents again, we can probably deduce that this framework (if used) is only going to be used for styling. Since, it doesn’t mention anywhere in the README.md file that there is any PHP code in it.
–
We can continue reading the source code of the index.php.bak file for now.
–
We can see on line 216 – 220. We can just input a $_GET['debug'] debug parameter with serialize input and the source code will unserialize it.

We know that the code is vulnerable to PHP Deserialization but how to exploi this? We only have the .bak file and this won’t execute/render as PHP on the server.
Were there any hidden directories we missed while the enumeration?

Yes! we didn’t discuss /index.php file, let’s try accessing it.
The page looks something like this:

–
Exploitation
Alright, now time for the exploitation. Before that, we need to learn what PHP deserialization is and before that, what is serialization?
We use serialization when we want a piece of code or some object to be stored in a database or when we’re expecting some piece of code through an API call or something and then we want to execute it/load it.
If you’re a programmer, you might have come across this hurdle, to solve this, you always need to create a new file, write the source code in it and execute the file manually.
To not do the above^, we use serialization, it takes your piece of code/object, serializes it and stores in the database and while retreiving it, it unserializes the piece of code and executes it.
For the API call, it just receieves serialized code already and executes it while unserializing it.
Note: It is always recommended to never take any input either through database or through APIs or any files on the system and mostly don’t even use deserialization if not really required. If it’s required, never let the user control the parameters!
P.S ~ The above information about serialization is generic and not only based on PHP de(serialization)!
You can find more details in this youtube video created by a friend of mine; Mukarram Khalid.
So, now that we’ve a base understanding of what serialization is, let’s move to the source code and see what we can exploit here.
We can see that the PHP code is using a magic function (i.e. __destruct())
–
What is __destruct?
__destruct magic method is used to always run or do a task at the end of the execution. Let’s say we want to do something everytime (maybe update a local log file?), it’ll do that in the end of the execution.
What is it doing in the above application?
It’s creating a file in our
__DIR__(orpwd) in the directory and with the message whatever is specified (using the two properties being used from the class)It then echo’s a string: ‘Your submission has been successfully saved’
–
Now, we can write our own code matching the above^ but just change the contents and the file name, let’s try it.
Remember, we need to use the same class name and same properties names!
Let’s run add this PHP code in a local file and run it.

Alright, we get the serialized string:
Let me try and walk you through the whole serialized string.
Omeans objectO:10means object name’s length (i.e. -> 10)2:{means there are two properties/attributess:9means that our property/attribute is a string and is of length of 9 charss:9:"form_file";Length of 9 and property name
Probably, that explained the serialized string. You can always google for more details!
Now, we need to URL encode our string and pass it into the debug parameter in the application.
For URL encoding, I’ll use cyberchef.

URL Encoded string looks like:
Let’s pass this in the URL and see if our new file gets created.

Yay! It did, the string printed in the bottom indicates that.
Here’s the cURL request, if you’ve problems reproducing the above:
Now, let’s access the .php file with our RCE code in it and get reverse shell!

We can generate RCE payloads to fallback if something isn’t present utilizing reverse-shell.sh and call it with cURL.

I’ll let you figure out what’s happening below, just remember that I wrote the above shell script generated in a file named shell.sh in my local directory since the machine doesn’t have access to the internet.
Reverse Shell:
Now that we’ve reverse shell, let’s try and get tty shell and make it interactive!
–
First, we’ll get the tty shell using python’s onliner:
–
Now that we’ve tty shell, let’s make it interactive (i.e. Ctrl + C or other things don’t exit the shell!)
Note: We need bash shell to make it interactive!
Type: ‘Ctrl + Z’ and background the process.
Now we’ll use:
And then type fg to foreground the process (get it back)

Now that we’ve interactive shell, let’s add the rows/cols (generic) and add some colors UwU!


–
Alright, we got the initial shell and it’s fully interactive! Time to get the initial flag and privesc our way to root!
–
We can find a .htpasswd (usually used for HTTP authentication) file right in /var/www/html/ containing the following credentials:
Let’s run john and try to crack these.

–
We get a password: jamaica
Where can we use it? Let’s see /etc/passwd file if it contains any other users except for www-data and root
Alright, we can try the credentials against the user: james

–
Flag (user.txt)

–
Time for privesc!
Privileges Escalation
Before running LinEnum, LSE or LinPeas, let’s try and do some manual enumeration first!
Let’s try and get the list of binaries we can run with sudo!
Nothing we can run with sudo! :(
Let’s try and list the crontabs (if any)
Nothing there as well!
–
We can see that .bash_history is present in the directory, let’s check it out.
–
We’ve a note file in the local directory:
–
We’ve seen .bash_history containing a directory /etc/update-motd.d/, let’s check it out!
We can see that we’ve read/write/execute permissions on the files. But what can we do with these?
Alright, seems like simple bash commands, let’s just copy bash to tmp and set root’s SUID bit on it and see if that works.
Added the instructions in 3-4 lines.
But how does this execute? Is there a cron? don’t think so.
Since, the .bash_history shows we need to ssh for the instructions to execute, let’s try and SSH as james.

Root!
Cool, we’ve got SUID bit of root user on the bash file, let’s get root! :)
The flag is of the characters what we need!
Thanks for reading the walkthrough, hopefully you enjoyed it. I think maybe I was too verbose while writing it :P
Last updated
Was this helpful?