AD Testing Checklist (Linux)
Below are the things you should check on every Active Directory assessment from a Linux machine
Shortlist
Short bullet point to jog your memory. If this is not enough, click on the check to get full notes.
Extra Attacks
Coercion Attacks
Local Network Poising
IPv6 MITM
Stale Half-Duplex ARP
WPAD
WebDAV
LNK file drop
ADIDNS Wildcard Attack (Dangerous and not well understood)
Confirm AD Access (Linux)
Define Shell Variables
command -v vared >/dev/null && vared -p 'Username of Active Directory account: ' -c ADUSER || read -p "Username of Active Directory account: " ADUSER
command -v vared >/dev/null && vared -p 'Domain of Active Directory account: ' -c ADDOMAIN || read -p "Domain of Active Directory account: " ADDOMAIN
command -v vared >/dev/null && vared -p 'Primary domain controller IP of target domain: ' -c ADCONTROLLER || read -p "Primary domain controller IP of target domain: " ADCONTROLLER
command -v vared >/dev/null && vared -p 'Target IP/CIDR list file path: ' -c TARGETS || read -p "Target IP/CIDR list file path: " TARGETS
alias PSWPRMPT='command -v vared >/dev/null && vared -p "Password: " -c PSW || { read -sp "Password: " PSW; echo; }; echo $PSW'
Sync Clock to Domain Controller
sudo apt install ntpdate -y
sudo ntpdate $ADCONTROLLER
Check access (NTLM)
impacket-GetADUsers $ADDOMAIN/$ADUSER -dc-ip $ADCONTROLLER
Check access (Kerberos)
# Get Kerberos TGT
impacket-getTGT $ADDOMAIN/$ADUSER -dc-ip $ADCONTROLLER
export KRB5CCNAME=$(realpath $ADUSER.ccache)
# Make call using TGT
impacket-GetADUsers $ADDOMAIN/$ADUSER -dc-ip $ADCONTROLLER -k -no-pass
Search for abusable ACLs (Bloodhound CE)
To search for abuseable ACLs, Bloodhound is the tool of choice. For further informational about how to analyze the information once you collect it, see Analyzing Data with Bloodhound.
Install Bloodhound.py
pipx install git+https://github.com/dirkjanm/BloodHound.py.git@bloodhound-ce
Collect Data (NTLM)
bloodhound-ce-python -u $ADUSER -d $ADDOMAIN -c All --zip
Collect Data (Kerberos)
bloodhound-ce-python -u $ADUSER -d $ADDOMAIN -p "" -k --auth-method kerberos -no-pass -c All --zip
The above has given me some issues during testing and sometimes reverted to NTLM instead of Kerberos. If you have issues, try using the NTLM version which will often attempt to use Kerberos regardless.
Collect Data (w/ Channel Binding)
The current Bloodhound.py does not support connection to LDAPS that has channel binding. In my experience, it will throw a vague issue related to a failed connection or invalid address (ldap3.core.exceptions.LDAPSocketOpenError: invalid server address
). There is a pull request out there that fixes this issue but it has not been merged so far (it has been waiting about half a year). Therefore, you will have to manually install a forked version from deadjakk that supports channel binding. You will also need a forked version of LDAP3 to run the forked version of bloodhound.py.
sudo apt remove bloodhound.py -y
mkdir bloodhound-new
cd bloodhound-new
virtualenv venv
source ./venv/bin/activate
git clone https://github.com/deadjakk/BloodHound.py.git
cd BloodHound.py
pip3 install .
pip3 install git+https://github.com/ly4k/ldap3 # Fork of ldap3 needed
bloodhound-python -u $ADUSER -d $ADDOMAIN -c All --zip --ldap-channel-binding
Search for passwords in user descriptions
Install JQ
sudo apt install jq -y
Search for quick hits
cat *users.json | jq . | grep -E '"description":|"name":|"AllowedToDelegate":' | sed 's/"AllowedToDelegate": \[\],//g' | tr -d '",' | grep -B 1 -iE "password|pw"
List sorted user descriptions (Full Review)
cat *users.json | jq . | grep -E '"description":' | sed 's/"description": //g' | tr -d '",' | sort -u
Search for Kerberoastable accounts
Search for all SPNs in the domain that are vulnerable to Kerberoasting. For exploit information, see Kerberoasting.
Check for affected accounts (NTLM)
impacket-GetUserSPNs $ADDOMAIN/$ADUSER -dc-ip $ADCONTROLLER
Check for affected accounts (Kerberos)
impacket-GetUserSPNs $ADDOMAIN/$ADUSER -no-pass -k -dc-ip $ADCONTROLLER
Search for As-Rep Roastable accounts
Search for all user accounts that do not require pre-authentication. For exploit information, see As-Rep Roasting.
Check for affected accounts (NTLM)
impacket-GetNPUsers $ADDOMAIN/$ADUSER -dc-ip $ADCONTROLLER
Check for affected accounts (Kerberos)
impacket-GetNPUsers $ADDOMAIN/$ADUSER -no-pass -k -dc-ip $ADCONTROLLER
Perform Timeroasting attack
Timeroast via RID Bruit Force
# Using NXC version >= 1.4
nxc smb $ADCONTROLLER -M timeroast --log nxc-timeroast.txt
Check for default Machine Account Quota
Get Machine Account Quota (NTLM)
nxc ldap $ADCONTROLLER -M maq -u $ADUSER -d $ADDOMAIN -p $(PSWPRMPT) --log MAQ.log;PSW=""
Get Machine Account Quota (Kerberos)
nxc ldap $ADCONTROLLER -M maq -k --use-kcache --log MAQ.log
Get Machine Account Quota (NTLM) - Alternate
ldapsearch -x -H ldap://$ADCONTROLLER -b 'DC=<DOMAIN NAME>,DC=<DOMAIN TLD>' -D "$ADUSER@$ADDOMAIN" -W -s sub "(objectclass=domain)" | grep ms-DS-MachineAccountQuota
Check password policy
Get Password Policy (NTLM)
nxc smb $ADCONTROLLER -u $ADUSER -d $ADDOMAIN -p $(PSWPRMPT) --pass-pol --log PassPol.log;PSW=""
Check for active WebDAV clients
Method 1 (WebClientScanner) - Faster
Install
pipx install git+https://github.com/Hackndo/WebclientServiceScanner
NTLM
webclientservicescanner $ADDOMAIN/$ADUSER@$TARGETS -dc-ip $ADCONTROLLER | tee WebDAV-Scan.txt
Kerberos
webclientservicescanner $ADDOMAIN/$ADUSER@$TARGETS -no-pass -k -dc-ip $ADCONTROLLER | tee WebDAV-Scan.txt
Method 2 (NetExec) - CSV Output
Scan hosts
nxc smb $TARGETS -M webdav -u "$ADUSER" -d "$ADDOMAIN" -p $(PSWPRMPT) --log WebDAV.log;PSW=""
Create affected host CSV
cat WebDAV.log | grep -a WEBDAV | grep -vE 'STATUS_ACCESS_DENIED|STATUS_OBJECT_PATH_NOT_FOUND' | awk -F' ' 'NR==1{print "IP(s),Hostname,Port"};{print $9","$11","$10"/tcp"}' > WebDAV-Service-Enabled.csv
Check for missing SMB signing
nxc smb $TARGETS --log Missing-SMB-Signing.log
grep "signing:False" Missing-SMB-Signing.log | sed -E 's/\(name:[^)]*\)//g;s/\(domain:[^)]*\)//g;s/\(SMBv1:[^)]*\)//g;s/[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2} \| smb\.py:[0-9]+ - INFO - SMB\s+//' | grep --color=always -e "^" -e "signing:False"
Check for SMBv1 Support
nxc smb $TARGETS --log SMBv1-Support.log
grep "SMBv1:True" SMBv1-Support.log | sed -E 's/\(name:[^)]*\)//g;s/\(domain:[^)]*\)//g;s/\(signing:[^)]*\)//g;s/[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2} \| smb\.py:[0-9]+ - INFO - SMB\s+//' | grep --color=always -e "^" -e "SMBv1:True"
Check for writable shares
NTLM
nxc smb $TARGETS -u $ADUSER -d $ADDOMAIN -p $(PSWPRMPT) --shares --log SMB-Shares.log;PSW=""
grep "WRITE" SMB-Shares.log
Check for sensitive data in shares
Collect Info (NTLM)
nxc smb $TARGETS -u $ADUSER -d $ADDOMAIN -p $(PSWPRMPT) -M spider_plus;PSW=""
Check for anonymous access
nxc smb $TARGETS -u " " -p " " --local-auth --shares --log Anonymous-SMB.log
grep "[+]" Anonymous-SMB.log
Check for Unconstrained Delegation (Non-DCs)
Bloodhound CE Query
MATCH (dc)-[:MemberOf*0..]->(dg:Group)
WHERE dg.objectid ENDS WITH '-516'
WITH COLLECT(dc) AS domainControllers
MATCH (m)
WHERE m.unconstraineddelegation = true AND NOT m IN domainControllers
RETURN m
This query will also list disabled objects. Make sure to investigate the context of the Unconstrained Delegation object before reporting!
Get list of affected objects from JSON Bloodhound query export
jq -r '.data.nodes[] | .label' bh-graph.json | tr '[:upper:]' '[:lower:]' | sort -u
Check LDAP Configuration
NTLM
nxc ldap $TARGETS -M ldap-checker -u $ADUSER -d $ADDOMAIN -p $(PSWPRMPT) --log LDAP-Signing_Binding.log;PSW=""
Create CSV Output
CHANNEL_BINDING=$(grep -E 'LDAPS Channel Binding is set to "NEVER"' LDAP-Signing_Binding.log | awk -F' ' '{print $9",636/tcp,"$11",LDAP Channel Binding not Enforced"}' | sort -uV)
LDAP_SIGNING=$(grep 'LDAP Signing NOT Enforced!' LDAP-Signing_Binding.log | awk -F' ' '{print $9","$10"/tcp,"$11",LDAP Signing not Enforced"}' | sort -uV)
echo "IP(s),Port,Hostname,Issue$COMBINED_RESULTS" > Insecure-LDAP-Authentication.csv
echo -e "$LDAP_SIGNING\n$CHANNEL_BINDING" | awk 'BEGIN{FS=OFS=","} NR==1{next} {for(i=2;i<=NF;i++) if(!seen[$1,$i,i]++) grp[$1,i]=(grp[$1,i]==""?"":grp[$1,i] ($i!=""?", ":"")) $i; else grp[$1,i]=grp[$1,i]} END{for(x in grp){split(x,tmp,SUBSEP); join[tmp[1]]=(join[tmp[1]]==""?"":join[tmp[1]] OFS) "\""grp[x]"\""} for(x in join) print x, join[x]}' >> Insecure-LDAP-Authentication.csv
Check MsSQL Configuration
Install MsSQLRelay
pipx install git+https://github.com/CompassSecurity/mssqlrelay
Run all checks (Coercion, Command Execution, Signing)
command -v vared >/dev/null && vared -p 'Path to Nmap TCP Scan (gnmap file): ' -c NMAP_TCP || read -p "Path to Nmap TCP Scan (gnmap file): " NMAP_TCP
grep '1433/open/tcp' $NMAP_TCP| cut -d ' ' -f 2 | sort -uV > mssql.hosts
PSW=$(PSWPRMPT);echo;while read MSSQL_SERVER; do mssqlrelay check -target $MSSQL_SERVER -ns $ADCONTROLLER -u $ADUSER@$ADDOMAIN -p $PSW 2> /dev/null | tee -a MsSQL_Search.txt; done < mssql.hosts;PSW=""
Create CSV of Missing EPA
grep "Encryption: not enforced" -B 2 MsSQL_Search.txt | grep -E "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" | sort -u | awk -F' ' 'NR==1{print "IP,Port"};{print $3"/tcp"}' | tr -d '()' | tr ':' ',' > MsSQL-Missing-EPA.csv
Check ADCS Configuration
Install Certipy
pipx install git+https://github.com/ly4k/Certipy.git
Run all checks
certipy find -u "$ADUSER@$ADDOMAIN" -dc-ip $ADCONTROLLER -stdout -vulnerable | tee ADCS-Vuln.txt
Check for CA when Certipy does not find CA
nxc smb $TARGETS -u $ADUSER -d $ADDOMAIN -p $(PSWPRMPT) --shares --log ADCS.log;PSW=""
grep -i "cert" ADCS.log
Check SCCM Configuration
Install Tools
# Install SCCMHuneter
git clone https://github.com/garrettfoster13/sccmhunter.git
cd sccmhunter
chmod +x *.py
virtualenv venv
source ./venv/bin/activate
pip install -r requirements.txt
cd ../
# Install PXETheif
git clone https://github.com/MWR-CyberSec/PXEThief
cd PXEThief
sed -i '/pywin32>=303/d' requirements.txt # This module is not supported on linux
pip install -r requirements.txt
cd ../
Find SCCM Server (w/ SCCMHunter)
python3 sccmhunter/sccmhunter.py find -u $ADUSER -d $ADDOMAIN -dc-ip $ADCONTROLLER
Search for SCCM user accounts (Bloodhound data)
cat *users.json | jq -r .data[].Properties.name | grep -Ei 'naa|sccm|client.push'
Send PXE Boot Request via DHCP (PXEThief)
sudo python3 PXEThief/pxethief.py 1
This will not only send the request, but also auto exploit by downloading the encrypted media file and attempting to steal data if there is no password.
Check for Open SCCM Ports
sudo nmap -sS -iL $TARGETS -T4 --open -oA Nmap_SCCM_TCP_Scan_$(date +"%b-%d-%Y") -p 8530-8531,49152-49159,10123
sudo nmap -sU -iL $TARGETS -T4 --open -oA Nmap_SCCM_UDP_Scan_$(date +"%b-%d-%Y") -p 4011
# Search for hits
cat Nmap_SCCM_*_Scan_*.gnmap | grep open | grep -vE "filtered|scan initiated"
Last updated