Enumerating Hosts and Identifying the Domain Controllers
Fingerprinting Domain Controllers
PORT STATE SERVICE
53/tcp open domain
88/tcp open kerberos-sec
135/tcp open msrpc
139/tcp open netbios-ssn
389/tcp open ldap
445/tcp open microsoft-ds
464/tcp open kpasswd5
593/tcp open http-rpc-epmap
636/tcp open ldapssl
3268/tcp open globalcatLDAP
3269/tcp open globalcatLDAPssl
Typical port signature of a domain controller (e.g. DNS, Kerberos, LDAP)
Host Discovery
Internal
ARP-Scan
Since this is an internal assessment, Kali is on the same LAN segment as the target(s) and ICMP is not needed to enumerate. ARP does not flow over VPN connections, as ARP is a layer 2 protocol and most VPNs operate at layer 3.
sudo arp-scan -d 10.10.10.0/24
Broadcast ARP discover requests on 10.10.10.0/24
nmap -n -sn 10.10.10.0/24
Functionally doing the same thing as arp-scan above
NetExec
You can spray some unauthenticated SMB requests around a network to discover hosts. This will reveal the hosts' NetBIOS names, from which you may able to identify domain controllers and servers.
This will only work on hosts where SMB is enabled.
nxc smb 10.10.10.0/24
Send unauthenticated SMB requests to 10.10.10.0/24
External
Ping Sweep on Target
Not the most reliable, as ICMP is disabled by default on Windows hosts.
Linux
ip="10.80.80.0"; cidr=24; IFS=. read -r i1 i2 i3 i4 <<< "$ip"; raw=$(( (1 << (32 - cidr)) - 2 )); base_ip=$(( (i1<<24) + (i2<<16) + (i3<<8) + i4 )); network=$(( base_ip & (0xFFFFFFFF << (32 - cidr)) )); for i in $(seq 1 $raw); do ip_calc=$((network + i)); printf "%d.%d.%d.%d\n" $(( (ip_calc >> 24) & 255 )) $(( (ip_calc >> 16) & 255 )) $(( (ip_calc >> 8) & 255 )) $(( ip_calc & 255 )); done | awk '{ system("ping -c 1 -w 1 " $1 " | grep \"bytes from\" &"); }' > ping_sweep.txt
Awk ICMP sweep (as documented here), output to ping_sweep.txt
PowerShell
1..254 | % { try { (ping -n 1 -w 1 10.10.10.$_ | select-string 'reply from').ToString().Split(' ')[2] -replace ':' } catch {} }
PowerShell ICMP sweep
NetExec
Again, only effective as long as SMB is enabled on the target.
# Via proxy host
proxychains -q nxc smb 10.10.10.0/24
fping
fping -ag 10.10.10.0/24
If pivoting through ligolo-ng, then ICMP is supported, would not work on SOCKS -- e.g. chisel or ssh
Nmap
SOCKS
sudo proxychains -q nmap -Pn -sT -T4 --top-ports 100 -oN discovered_hosts.txt 10.10.10.0/24
Scan via SOCKS proxy for top 100 ports on 10.10.10.0/24 as a means of finding live hosts
Tunnel
sudo nmap -sn -oN discovered-hosts.txt 10.10.10.0/24
Using a tunnel such as ligolo-ng supports ICMP host discovery
Transferred Tools
Could transfer tools internally to further enumerate hosts
Port Scans
Now that you've enumerated live hosts, save any hostnames or IP addresses that you've found to a file -- for example, targets.txt -- and feed this file into tooling for convenience.
In both scenarios below -- internal and external -- the scan output should include the SMB signing requirements for the target(s). Make a note of this for SMB relaying where SMB signing is not required.
Internal
Nmap on the Target
sudo nmap -Pn -p- -T4 -sC -sV -oN nmap-scan.txt -iL targets.txt
Scan all ports on targets.txt list and save output in nmap-scan.txt
Linux Binaries
seq 1 65535 | awk '{ target="10.80.80.2"; port = $1; if (system("nc -nz " target " " port) == 0) { print "Port " port " is open"} ; }' > awk_scan.txt &
Awk port scan (as documented here), output to awk_scan.txt
PowerShell
https://github.com/0xBEN/PSToolbox/blob/master/Public/ps1/Test-TcpPort.ps1
External
You also have the option of transferring a statically compiled nmap binary to a target internally and running from there; in which case, see the "Internal" port scan notes just above.
SOCKS
sudo proxychains -q nmap -Pn -sT -sC -sV -T4 --top-ports 1000 -oN nmap-scan.txt -iL targets.txt
If pivoting through chisel or ssh SOCKS proxies, must use -sT and recommend using --top-ports, as TCP connect scans are notoriously slow
Tunnel
sudo nmap -Pn -p- -T4 -sC -sV -oN nmap-scan.txt -iL targets.txt
If pivoting through a layer 3 tunnel like ligolo-ng will typically perform better, but may still have some overhead as opposed to running internally
Identify the Root Domain
Now that you've run your port scan on the targets.txt list, refer to your nmap-scan.txt output and compare that with the information above on fingerprinting the Domain Controller.
Once you've identified the Domain Controller, it's time to establish the root domain of the environment.
LDAP DSE
The root DSE is the entry at the top of the LDAP server directory information tree. All the namingcontexts (suffixes) in the LDAP server are directly below the root DSE. The root DSE contains information about the LDAP server, including the namingcontexts that are configured and the capabilities of the server.
-- https://www.ibm.com/docs/en/zos/2.1.0?topic=considerations-root-dse
Internal
sudo nmap -Pn -T4 -p 389,636 --script ldap-rootdse 10.10.10.2 | grep dnsHostName | sort -u
Assumes 10.10.10.2 is the DC based on port enumeration
External
SOCKS
sudo proxychains -q nmap -Pn -T4 -sT -p 389,636 --script ldap-rootdse 10.10.10.2 | grep dnsHostName | sort -u
Assumes 10.10.10.2 is the DC based on port enumeration. Scan via SOCKS proxy -- e.g. chisel or ssh
Tunnel
sudo nmap -Pn -T4 -p 389,636 --script ldap-rootdse 10.10.10.2 | grep dnsHostName | sort -u
Functionally the same as above, but assumes you're pivoting via tunnel -- e.g. ligolo-ng
Add DC to Hosts File
echo -e '10.10.10.2\t\tdc01.ad.lab ad.lab' | sudo tee -a /etc/hosts