Network Listening

Fully passive network listening to find vulnerabilities in multicast/broadcast DNS and IPv6 neighbor discovery configuration

All-in-One (TCPDump)

Start Listener

sudo tcpdump -i eth0 -n -vv udp port 546 or udp port 547 or icmp6 or udp port 5355 or udp port 137 or udp port 138 or udp port 5353 -w listener.pcap

Parse PCAP (to CSV)

# Input Listener File
LISTENER_FILE="listener.pcap"

# Local Network Poisoning
NBTNS_RESULTS=$(tshark -r $LISTENER_FILE -Y "nbdgm" -T fields -e ip.src -E separator=, | sort -u | grep -v '^$' | awk -F"," '{print $1",NBT-NS,137-138/udp"}')
MDNS_RESULTS=$(tshark -r $LISTENER_FILE -Y "mdns" -T fields -e ip.src | sort -u | grep -v '^$' | awk '{print $1",mDNS,5353/udp"}')
LLMNR_RESULTS=$(tshark -r $LISTENER_FILE -Y "llmnr" -T fields -e ip.src | sort -u | grep -v '^$' | awk '{print $1",LLMNR,5355/udp"}')

# Combine NBT-NS, mDNS, and LLMNR results
LNP_RESULTS="${NBTNS_RESULTS}\n${MDNS_RESULTS}\n${LLMNR_RESULTS}"

# Combine line by IP
SORTED_LNP_RESULTS=$(echo $LNP_RESULTS | 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]
}' | sort -Vu)

# Remove your own IP form results
CLEAN_SORTED_LNP_RESULTS=$(echo $SORTED_LNP_RESULTS | grep -v $(hostname -I | cut -d' ' -f 1))

# Send the final results to a file
echo "IP(s),Protocol,Port\n$CLEAN_SORTED_LNP_RESULTS" > Network-Poisoning.csv

# IPv6 DHCP/ICMP
tshark -r $LISTENER_FILE -T fields -e ipv6.src -e eth.src -e dhcpv6.client_domain -e dhcpv6.vendorclass.enterprise -Y "dhcpv6" -E separator=, -E quote=d | sort -u | grep '"311"' | awk -F"," 'NR==1 {print "\"IPv6 Address\",\"MAC Address\",\"Hostname\""};{print $1","$2","$3}' > Unmanaged-IPv6.csv

The above command limits IPv6 DHCP traffic to only hosts with the vendorclass of "311" which is windows machines.

Local Network DNS Poisoning (Responder)

Install/Listen w/ Responder

mkdir tools
cd tools
git clone https://github.com/lgandx/Responder.git
cd Responder
sudo python3 ./Responder.py -I eth0 -A

Parse Logs (to CSV)

# Get LLMNR (Both in analyze mode and not)
cat Responder-Session.log | grep -a Analyze | grep -a "LLMNR" | awk -F" " '{print $10",5355/UDP,LLMNR"}' | sort -u >> TempResponderData.csv
cat Responder-Session.log | grep -va Analyze | grep -a "LLMNR" | awk -F" " '{print $11",5355/UDP,LLMNR"}' | sort -u >> TempResponderData.csv

# Get mDNS (Both in analyze mode and not)
cat Responder-Session.log | grep -a Analyze | grep -a "MDNS" | awk -F" " '{print $10",5353/UDP,mDNS"}' | sort -u >> TempResponderData.csv
cat Responder-Session.log | grep -va Analyze | grep -a "MDNS" | awk -F" " '{print $11",5353/UDP,mDNS"}' | sort -u >> TempResponderData.csv

# Get NBT-NS (Both in analyze mode and not)
cat Responder-Session.log | grep -a Analyze | grep -a "NBT-NS" | awk -F" " '{print $10",137/UDP,NBT-NS"}' | sort -u >> TempResponderData.csv
cat Responder-Session.log | grep -va Analyze | grep -a "NBT-NS" | awk -F" " '{print $11",137/UDP,NBT-NS"}' | sort -u >> TempResponderData.csv

# Remove Duplicates
vim -c "sort u" -c ":wq" TempResponderData.csv 

# Define Headers
echo "IP(s),Ports,Services" > Network-Poisoning.csv

# Combine line by IP
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]
}' TempResponderData.csv | grep -av "$(hostname -I | cut -d " " -f 1)" >> Network-Poisoning.csv

# Remove Temp data
rm TempResponderData.csv

# Sort final results
vim -c "sort nr" -c ":wq" Network-Poisoning.csv

There is a possible issue with "ICMP" being found causing bad parsing. The CSV needs to be manually reviewed.

Stale ARP

Stale ARP requests (requests without responses) can also be poisoned to direct the victim to the attack's machine. Since this attack is poisoning stale traffic only, it's much less likely to cause disruption.

I've written a tool to automate this attack called Arponder, but it is still in beta and has some known issues with going outside the guard rails.

Locate Stale ARP

Download and install Eavesarp

git clone https://github.com/arch4ngel/eavesarp.git 
cd eavesarp/
sudo apt install virtualenv -y
virtualenv venv
source venv/bin/activate
pip3 install -r requirements.txt
sudo env "PATH=$PATH" ./eavesarp.py capture -i eth0 -ar -dr 

Removing the -ar -dr will make this fully passive. -ar -dr will resolve ARP to IP addresses and then to DNS hostnames

The top line is a vulnerable host. Notice the high ARP count and the "True" under the SNAC column

Look for "SNAC" connections. This will looks like an abnormally high number of ARP requests on a single host. Eavesarp will also try to locate these and mark them as "SNAC = True"

Locate Stale DNS

If there are stale DNS entries to your local network (A.K.A. DNS records pointing to hosts in your local network that are not online), you can hijack these records with a Stale ARP attack.

This is helpful for times where you need a DNS name to complete an attack (Like WebDAV poisoning and Kerberos Relay attacks)

# Scan local network DNS
LOCAL_SUBNET=$(ip -4 -o addr show | grep eth0 | awk '$3 == "inet" && $2 !~ /^lo/ {print $4}' | awk -F'/' '{print $1"/"$2}')
nmap -sn -Pn -R $LOCAL_SUBNET -oG LocalSubnetDNS.gnmap > /dev/null

# Scan for active hosts with ARP
sudo arp-scan -l > ArpScan.txt

# Find DNS names that do not have an ARP response
awk -F' ' '{print $2","$3}' LocalSubnetDNS.gnmap | grep -vE "Nmap|\(\)" | cut -d "," -f 1 >> DNS-IPs.txt
while read line; do grep -q "$line" ArpScan.txt || echo "  [+] The DNS name $(grep "$line" LocalSubnetDNS.gnmap | awk -F' ' '{print $3}' | tr -d '()"') ($(grep "$line" LocalSubnetDNS.gnmap | awk -F' ' '{print $2}')) is stale"; done < DNS-IPs.txt

Last updated