Sunday, September 8, 2019

HackTheBox Walkthrough - BASTION

Overview

HackTheBox is a great online platform for practicing penetration testing - users submit vulnerable machines and challenges and invite users (both free and premium subscriptions) to poke at them. It's a great way to learn - the only downside I've come across so far as a free user is that you're hitting the machine at the same time as other users. Occasionally machines get overwhelmed, or someone breaks something or changes some files, or someone leaves too many breadcrumbs behind and spoils things for others. You can always reset a machine back to its initial starting state, but that can get annoying if you have to redo exploit after exploit (at least it's good practice!).

Aside from the slight inconveniences from sharing, it's a great platform and place to learn - I highly recommend it for anyone who's looking for penetrating testing resources.  Note - you may have to "hack" your way into the website to get your invite code ;)

As a general rule, users can't submit their solutions and walkthroughs for machines and challenges until after they're retired. Luckily, Bastion was retired just recently, and I'm excited to post my first HackTheBox walkthrough on my blog.  Bastion is the first Windows machine I attempted on HackTheBox, and it was certainly a fun learning experience.




Enumeration & Recon

The first step involves researching the target machine - enumerating open ports and services to try to find vulnerabilities to exploit, and also looking for information that shouldn't be publicly available.

A quick nmap scan over TCP shows that ports 22 (SSH), 135 (MS RPC), 139 (NetBIOS), and 445 (SMB) are open.

nmap -A --script=banner -oN bastion_tcp.nmap.out 10.10.10.134

nmap -d -A -p445 10.10.10.134

We now have some more information on the machine, like the NetBIOS name and Workgroup name.  Port 445 definitely looks like the topic of interest here. As a sanity check, let's check for EternalBlue vulnerabilities since port 445 is open.

nmap -p 445 -d --script=smb-vuln-ms17-010 10.10.10.134

Unfortunately, we don't get that easy win.  Looks like we'll need to keep digging. Let's see what shares are open and what we can do with them.

nmap -d2 --script=smb-enum-shares -p445 10.10.10.134 -oN bastion_smb_enum_shares_d2.nmap.out

Running smbmap also confirms the results from the nmap scan.

smbmap -H 10.10.10.134 -d BASTION -u guest

Let's dig into the shares some more. That "Backups" share looks very interesting.

smbmap -H 10.10.10.134 -d BASTION -u guest -r

smbmap -H 10.10.10.134 -d BASTION -u guest -R Backups

The "WindowsImageBackup" directory in the Backups share deserves a closer look, especially if it actually contains Windows backups.


We see some VHDfiles (virtual hard drives) that most likely contain the Windows image backups.  Let's mount them on our local machine to explore them.  To do this on my standard Kali install, I had to install a couple packages to use guestmount:
apt-get install libguestfs-tools
apt-get install cifs-utils
Afterwards, I used mount on the Backups share, and then guestmount on the VHD files.

mount -t cifs //10.10.10.134/Backups -o rw,user=guest,password= /mnt/bastion

Making sure the mount succeeded.

Finding the VHD files.

We see the VHD backup files after mounting Backups. Time to mount those using guestmount (you may get an error when mounting the smaller VHD file, which is fine. The larger VHD file is the one we want anyway).

guestmount --add /mnt/bastion/WindowsImageBackup/L4mpje-PC/Backup\ 2019-02-22\ 124351/9b9cfbc4-369e-11e9-a17c-806e6f6e6963.vhd --inspector --ro /mnt/bastion_vhd2


Making sure our VHD mount succeeded.

The larger VHD file contains all the Windows image backup files we need.  Since our goal is to grab an initial foothold into the system, let's see if we can find registry hive files and obtain user account hashes.  We'll want to get the registry files from C:\Windows\System32\Config - let's copy them to our local directory.  The SYSTEM and SAM files are what we'll need at a minimum.


Next, let's run samdump2 to extract password hashes.


We have all the information we need to try to get a foothold into Bastion!


Getting User

Time to crack the hash for the user "L4mpje". I used hashcat for this, though I imagine John the Ripper would work just fine, as well.  I set hashcat to run the rockyou.txt wordlist, and the hash mode we're looking at is NTLM (hence, the "-m 1000" option).

hashcat --force -m 1000 -a 0 l4mpjehash.txt /usr/share/wordlists/rockyou.txt

Success! Let's see what the resulting password is:


L4mpje's password is "bureaulampje".  Since port 22 is open with SSH running, let's SSH into Bastion using our newly found credentials.


SSHing in as L4mpje.



Let's get the user flag and submit it!



Privilege Escalation

Now things get interesting - we have a user shell, and our goal is to get Administrator privileges.  Playing around with some Windows commands quickly shows that our privileges as L4mpje are pretty limited. We can't run systeminfo or tasklist, for starters.  However, what we can do is look for installed programs and see if there are any vulnerable ones to exploit.

Looking at 32-bit executables.

In the 32-bit executables section, we see a program called mRemoteNG, which handles and manages remote connections.  The interesting thing about this non-standard Windows program is that it has a history of poor password storage, at least in older versions.  Essentially, mRemoteNG could encrypt passwords using a known default passphrase "mR3m".   Encrypting passwords is generally not a good way to safely store passwords, even without a default passphrase (but that's a post for another time).

If mRemoteNG's connection configuration XML file were readable, one could take the encrypted passwords and trivially decrypt it if the default passphrase were used. Let's see what we can do.

Looking for the confCons.xml file.

The confCons.xml file, if readable in plaintext format, will provide encrypted passwords and indicate how they were encrypted.

Seeing if we can read the file.

Excellent - we can read the file.  For convenience, I went ahead and copied it locally.



Let's look at the configuration file.

Looking at confCons.xml

We see several things - the encrypted Administrator password, information on the key derivation technique for the password encryption key, and information on the symmetric encryption algorithm for the Administrator password encryption.

Password encryption information.

It looks like the encryption key is generated by taking a passphrase and running a key derivation function with 1000 iterations to generate the encryption key.  mRemoteNG then uses AES in Galois/Counter (GCM) mode to encrypt passwords with the encryption key.  GCM is an interesting block cipher mode in that it provides both data confidentiality and integrity.  The expected block size is 16 bytes, and the output will contain the initialization vector used, the actual ciphertext, and the authentication tag.

Encrypted Administrator password.

We have the encrypted Administrator password from the file:
aEWNFV5uGcjUHF0uS17QTdT9kVqtKCPeoC0Nw5dmaPFjNQ2kt/zO5xDqE4HdVmHAowVRdC7emf7lWWA10dQKiw==
The encrypted password is stored in base64 format for us to play with.  Several decryption tools I found online only handled AES-CBC mode for mRemoteNG (for older versions), which wouldn't apply to AES-GCM mode. Let's dig through the mRemoteNG source code to see how they encrypt and decrypt the passwords.  If we find enough information, we can decrypt the password ourselves, assuming the default passphrase was used in Bastion to encrypt user passwords.  I went ahead and cloned their git repository and started digging through their files.

Since mRemoteNG has a history of using "mR3m" as the default passphrase to generate the encryption key, we can see if the more recent version in the git repository also uses such a default passphrase.

mRemoteV1/Tree/Root/RootNodeInfo.cs

Indeed, we have the same default passphrase as usual. Let's see if we can find information on the encryption and decryption functions.

mRemoteV1/Security/SymmetricEncryption/AeadCryptographyProvider.cs

The mRemoteNG source code provides the following information in mRemoteV1/Security/SymmetricEncryption/AeadCryptographyProvider.cs:

  • Symmetric encryption key is set for 256 bits (32 bytes)
  • The GCM tag (MAC) is set for 128 bits (16 bytes)
  • The nonce, or Initialization Vector (IV) for AES-GCM is set for 128 bits (16 bytes)
  • The salt for key derivation is set for 128 bits (16 bytes)
  • 1000 iterations for key derivation (which matches up with what we saw in the configuration file).

Looking at the encryption functions in the same file and the key derivation functions in mRemoteV1/Security/KeyDerivation/Pkcs5S2KeyGenerator.cs, we find the following high-level algorithm:

  1. Take in the message to encrypt (a user's password), and a passphrase for deriving the encryption key.
  2. Generate a 16-byte salt.
  3. Use the PBKDF2 key derivation function with SHA-1 HMAC, the salt, and passphrase for 1000 iterations to generate the 32-byte symmetric key for encryption.
  4. Generate a 16-byte IV.
  5. Using the IV, 32-byte key, and using the 16-byte salt as associated data for GCM mode, encrypt the user password using AES-256-GCM and also generate the 16-byte MAC, or GCM authentication tag.
  6. Base64-encode and return the ciphertext, which is of the following format: [16-byte salt / GCM associated data + 16-byte IV + encrypted password + 16-byte MAC / GCM auth tag]
So it looks like the GCM functionality makes use of associated data.  GCM handles authenticated encryption (confidentiality + integrity), and it can come in an AEAD variant (authenticated encryption with associated data). The associated data is bound to the appropriate ciphertext, so that an attacker can't just copy-paste valid ciphertexts. The associated data doesn't need to be encrypted, but we'll definitely need it if we want to properly decrypt a ciphertext.

Looking at the decryption functions in the same files, we find the following high-level algorithm:

  1. Grab the base64-encoded ciphertext and convert it to bytes. Recall that the ciphertext format is [16-byte salt / GCM associated data + 16-byte IV + encrypted password + 16-byte MAC / GCM auth tag]
  2. Take the first 16 bytes of the ciphertext and use that as the salt for the key derivation function.
  3. The next 16 bytes of the ciphertext are the IV for AES-GCM.
  4. The remaining bytes of the ciphertext contain the encrypted password and the GCM tag / MAC.
  5. Use the PBKDF2 key derivation function with using SHA-1 HMAC, 1000 iterations, the salt, and the provided passphrase to generate the same 32-byte symmetric key that was used to encrypt the password.
  6. Use the salt as associated data for GCM mode.
  7. Use the IV, associated data, and 32-byte key to decrypt the ciphertext.
So we can write up our own decryption script to repeat those decryption steps, using "mR3m" as the default passphrase.

Let's run the Python script and decrypt the password!


Looks like we got successful decryption. Let's see if we can SSH as Administrator using this password, "thXLHM96BeKL0ER2"!



Success! Let's find and submit the root flag.



No comments:

Post a Comment