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

  1. Coercion Attacks

    1. Local Network Poising

    2. IPv6 MITM

    3. Stale Half-Duplex ARP

    4. WPAD

    5. WebDAV

    6. LNK file drop

  2. 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'

If you define the above variables, you can just copy and paste the below command into the terminal

Sync Clock to Domain Controller

sudo apt install ntpdate -y
sudo ntpdate $ADCONTROLLER

Syncing the clock to the domain controller is VERY important for Kerberos and tools that utilize Kerberos

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

If you are getting the error:Kerberos SessionError: KRB_AP_ERR_SKEW(Clock skew too great), you need to sync your local lock to the DC. You can do this with sudo ntpdate $ADCONTROLLER


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

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

Run the following commands against the unzipped Bloodhound.py output

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.

Searching for affected accounts can also be done easily using Bloodhound

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=""

Note that $(read -sp "PWD: " PWD;echo $PWD) is used to prompt for a password instead of putting it into the terminal. However, this leaves a cleartext password in the $PWD variable in the current shell sessions, so it is overwritten using PWD="" at the end of the command.


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=""

See Searching SMB Shares for info on how to search these results


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

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=""

Look for the following vulnerabilities

  • Missing Signing/Channel Binding = Encryption: not enforced

  • Coercible = Privileges: ['xp_dirtree', 'xp_fileexist'] (Either one)

  • Command Execution: Privileges: ['xp_cmdshell'] (I'm not sure if mssqlrelay checks for this)

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

Exploit Information can be found at ADCS Exploitation


Check SCCM Configuration

A new tool called SCCHound was recently released and could make this process easier. Once I test it I will add notes here.

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

If you know the SCCM server IP, you can use: pxethief.py 2 <SCCM SERVER IP>

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" 

It's not uncommon to see a lot of these ports open even when SCCM is not enabled. Check the output carefully

Last updated