Support Web Challenge — TryHackMe
TL;DR
The Support web application contained several vulnerabilities that could be chained to gain administrator access and achieve remote command execution.
The exposed support email address was used in a password brute-force attack, revealing the password
snoopy. After authentication, an insecure isITUser cookie could be changed
from the MD5 hash of false to the MD5 hash of true, exposing an internal
administration panel.
The internal API was vulnerable to Insecure Direct Object Reference, allowing the administrator
email address to be disclosed. A Local File Inclusion vulnerability in the skin
parameter exposed the contents of config.php, revealing the administrator password.
Finally, the sys parameter was passed directly to shell_exec() after an
insufficient prefix check, allowing authenticated operating system command injection and retrieval
of the final flag.
Challenge Overview
The main page presented a support portal login form. The application disclosed a support email address that could be used as a valid username.
Directory and File Discovery
I started by enumerating directories and files using Gobuster with several common web file extensions.
gobuster dir \ -u http://10.66.150.48 -w ~/SecLists/Discovery/Web-Content/raft-medium-directories.txt -x .php,.txt,.js,.html,.xml,.json -t 200 --delay 10ms
=============================================================== # Starting gobuster in directory enumeration mode /js (Status: 301) [Size: 309] [--> http://10.66.150.48/js/] /logout.php (Status: 302) [Size: 0] [--> index.php] /api.php (Status: 302) [Size: 0] [--> index.php] /config.php (Status: 200) [Size: 0] /info.php (Status: 200) [Size: 73286] /skins (Status: 301) [Size: 312] [--> http://10.66.150.48/skins/] /index.php (Status: 200) [Size: 2591] /includes (Status: 301) [Size: 315] [--> http://10.66.150.48/includes/] /layout (Status: 301) [Size: 313] [--> http://10.66.150.48/layout/] /footer.php (Status: 200) [Size: 1253] /dashboard.php (Status: 302) [Size: 0] [--> index.php] /server-status (Status: 403) [Size: 277] Progress: 209993 / 210000 (100.00%)
Several interesting resources were discovered:
/api.php— authenticated internal API./config.php— application configuration file./info.php— exposed PHP information page./skins/— directory containing application themes./dashboard.php— authenticated dashboard./footer.php— reusable application component.
Exposed Skin Directory
Directory listing was enabled on /skins/, revealing the PHP files used to define the
available visual themes of the application.
Files such as green.php indicated that the selected theme was likely loaded dynamically
through a user-controlled parameter.
Exposed PHP Information Page
The /info.php endpoint exposed the output of phpinfo(), revealing detailed
information about the server, PHP configuration, loaded modules and filesystem paths.
Although this did not immediately provide a flag, such information can help an attacker understand the server environment and identify relevant configuration weaknesses.
Network Reconnaissance
I also performed Nmap scans against the target to identify exposed ports and services.
nmap --top-ports 1000 -T4 10.66.150.48
nmap -sC -sV -p 22,80 10.66.150.48
The scan identified SSH on port 22 and the web application on port 80.
No additional network services immediately relevant to the challenge were discovered.
Credential Brute Force
The login page exposed the email address help@support.thm. Since the application did not
appear to implement effective rate limiting or account lockout protections, I used FFUF to
brute-force the password.
ffuf \ -w ~/SecLists/Passwords/Common-Credentials/xato-net-10-million-passwords-1000.txt:PASS -u http://10.66.150.48/ -X POST -H "Content-Type: application/x-www-form-urlencoded" -H "Cookie: PHPSESSID=a003n6bt3pivdc144cmgvfh254" -d "email=help%40support.thm&password=PASS" -mc all -fc 200
snoopy [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 114ms]
Most unsuccessful login attempts returned HTTP status code 200. The password
snoopy generated a 302 redirect, indicating a successful login.
Initial Account Access
Using the exposed email address and the password identified through brute force, I authenticated to the application.
Email: help@support.thm Password: snoopy
Cookie Analysis and Privilege Escalation
After authentication, the application issued two cookies:
PHPSESSID— the PHP session identifier.isITUser— an MD5 hash representing whether the current user was an IT user.
The value of isITUser corresponded to the MD5 hash of the string
false. This suggested that the application trusted a client-controlled cookie to
determine user privileges.
I generated the MD5 hash of true:
echo -n "true" | md5sum
b326b5062b2f0e69046810717534cb09
After replacing the original isITUser value with
b326b5062b2f0e69046810717534cb09, the application treated the account as an IT user
and displayed the administration panel.
Internal User API
The newly exposed administration panel provided access to an internal user API.
The API returned user information based on a numeric identifier supplied in the request.
Insecure Direct Object Reference
By intercepting the API request in Burp Suite and modifying the user identifier, I was able to retrieve information belonging to other users.
The endpoint did not verify whether the authenticated user was authorised to access the requested record. Enumerating the identifier exposed the administrator email address:
specialadmin@support.thm
At this point, the administrator username was known, but the corresponding password was still required.
Local File Inclusion Through the Skin Parameter
The application allowed users to change its visual theme using the skin parameter.
Since the discovered /skins/ directory contained PHP theme files, I tested whether the
parameter was used directly in a server-side file inclusion operation.
Supplying directory traversal sequences and requesting ../config caused the contents of
the configuration file to appear in the HTML source of the response.
/dashboard.php?skin=../config
The disclosed configuration file contained the administrator password:
support110
This confirmed that the skin parameter was vulnerable to Local File Inclusion or
directory traversal within a server-side include.
Administrator Login and First Flag
Using the email address obtained through the IDOR vulnerability and the password exposed through the Local File Inclusion vulnerability, I authenticated as the administrator.
Email: specialadmin@support.thm Password: support110
Successful administrator authentication revealed the first challenge flag.
Date and Time Functionality
While exploring the administrator dashboard, I observed that the application allowed the user to display either the current date or the current time.
Since both options represented operating system commands, I inspected the associated HTTP request and application source code.
Source Code Disclosure
The previously identified Local File Inclusion vulnerability could also be used to include
footer.php through the following request:
/dashboard.php?skin=../footer
The disclosed code showed that the selected command was submitted through the POST parameter
sys and assigned directly to the $sys variable:
$sys = $_POST['sys'];
Insufficient Command Validation
The application attempted to restrict the submitted command by checking whether the supplied value
began with the string date:
if (strpos($sys, 'date') === 0) {
$output = shell_exec($sys);
}
This validation was insufficient because it only verified the beginning of the supplied string. It did not ensure that the complete value matched one of the intended commands.
As a result, any command beginning with date passed the check and was then sent
directly to shell_exec().
Operating System Command Injection
Shell metacharacters could be appended to the permitted date command to execute
additional operating system commands.
I used a semicolon to terminate the valid command and appended a command to read the user flag:
sys=date; cat /home/ubuntu/user.txt
The shell interpreted the value as two separate commands:
- Execute the legitimate
datecommand. - Execute
cat /home/ubuntu/user.txt.
Because the application passed the complete string directly to shell_exec(), the
appended command was executed with the privileges of the web server process.
The response contained the contents of /home/ubuntu/user.txt, revealing the second and
final flag.
Attack Chain
- Enumerated directories and discovered
api.php,info.php,config.phpand the/skins/directory. - Used the email address exposed on the login page as a valid username.
- Brute-forced the login password using FFUF and identified
snoopy. - Authenticated as
help@support.thm. - Analysed the
isITUsercookie and changed its value to the MD5 hash oftrue. - Accessed the internal administration panel and user API.
- Exploited an IDOR vulnerability to obtain the administrator email address.
- Exploited Local File Inclusion in the
skinparameter to readconfig.php. - Recovered the administrator password and authenticated as
specialadmin@support.thm. - Obtained the first flag from the administrator panel.
- Reviewed disclosed source code and identified the unsafe use of the
sysparameter. - Bypassed the command prefix validation and injected an additional shell command.
- Read
/home/ubuntu/user.txtand obtained the final flag.
Outcome & Lessons Learned
- Exposing valid usernames or email addresses can make password brute-force attacks significantly easier.
- Authentication endpoints should implement effective rate limiting, account lockout and monitoring.
- Client-controlled cookies must never be trusted to make authorisation decisions.
- Hashing a Boolean value does not make it secure when the possible values are predictable.
- An IDOR vulnerability can expose sensitive information belonging to other users, including privileged account details.
- User-controlled file inclusion parameters can expose configuration files, credentials and application source code.
- Source code disclosure can reveal additional vulnerabilities that would otherwise be difficult to identify remotely.
- Prefix-based validation is not sufficient when untrusted input is passed to a shell.
-
Functions such as
shell_exec()should never receive raw user-controlled data. - Multiple low-complexity vulnerabilities can be chained to progress from an unauthenticated user to administrator access and remote command execution.