Skip to content

Disguising A Network Scan With ARP Requests

When an attacker has gained access to a private network the next goal is to look around the network to see what is on it. There is always a possibility of an intrusion detection system monitoring the network so obfuscating the network scan could be the factor in not getting detected or leaving obvious digital forensics. In this scenario I will show you how an adversary can get a network scan of the IP address range without even sending one SYN packet like with normal port scanners.

To perform this scan, we will leverage the Address Resolution Protocol (ARP). ARP is the common protocol that allows nodes on the network to map the internet layer with the link layer to be able to communicate. ARP is what ties your network card’s MAC address with your IP address on the network. Without it, software and hardware cannot communicate over the network.

ARP is a series of requests and responses. A computer sends a broadcast message. A message every device on the network automatically receives. It asks who is on a specific IP address and who to send a response with the MAC address to. If a host is up, it will send a ARP response responding to that request. Most modern day operating systems host a local ARP file with the mappings it has discovered on the network to maintain these records.

The attack

We need to be able to craft our own network packets so we can trick every user on the network to offer up their IP address by thinking an ARP request is coming from the router asking for a MAC address. If monitored, this will look like regular network traffic. If it looks a bit suspicious, the router is to blame.

We can accomplish this by using the Python module, Scapy. Scapy is a package that allows us to create our own network packets from scratch in Python and inject them into the network.

In the first method of the following Python script, we initially send one ARP request to the router to get it’s MAC address. This is the only unusual packet we need to worry about because we request a response with an unknown source MAC address.

We are assuming the router is at the traditional X.X.X.1 address. Once we have the router’s MAC address, we can masquerade the network acting as the router.

import scapy.all as scapy

def get_router_mac():
    arp = scapy.ARP(pdst="10.0.0.1")
    broadcast = scapy.Ether(dst="ff:ff:ff:ff:ff:ff")
    packet = broadcast/arp
    answered_list = scapy.srp(packet, timeout=1, verbose=0)[0]
    return answered_list[0][1].hwsrc

Once router details are obtained, we can perform the next method. This method is passed the router MAC and spoofs each target packet in the range with it’s MAC and IP Address. We iterate over all 254 hosts on the rest of subnet.

def send_arp_flood(router_mac):
    for i in range(1,255):
        arp = scapy.ARP(pdst="10.0.0.{0}".format(i))
        arp.hwscr = router_mac
        arp.psrc = "10.0.0.1"
        broadcast = scapy.Ether(dst="ff:ff:ff:ff:ff:ff")
        packet = broadcast/arp
        ans, unans = scapy.srp(packet, timeout=.9, verbose=0)
        for snt, recv in ans:
            if recv:
                print(recv[scapy.ARP].psrc)
    
router_mac = get_router_mac()
send_arp_flood(router_mac)

Run the script and confirm the packets are being delivered with tcpdump.

tcpdump arp

Note that each ARP request to each IP address is requesting to tell the gateway. That means spoofed packets are now being injected into the network disguised as being sourced from the gateway router.

Using Wireshark to capture all network traffic, you hardly even notice the attack if there is enough activity going on over the wire. We see here that a single ARP packet is lost in between DNS and TLS traffic.

Within minutes you will have received back all potential requests from the 254 host addresses. With this attack you have just mapped out every active node on the network without the need for a noisy port scan, and disguised as normal ARP protocol traffic.

How to stop this or at least detect this?

If you suspect you are or have been a victim of this attack, then packet analysis is the first thing to look at. If your attacker does not have full control over his or her network card, they may not be able to spoof the source MAC address at the link layer when they send out the disguised packet. In this case, there will be two devices or MAC addresses tying to the gateway router IP address. This is easy to spot. Wireshark will notify you in the packet listing when capturing traffic of duplicate use.

If the attacker is able to spoof at the link layer, then it means that there is no other way to look for this other than watching for ARP packets requesting in an incremental fashion. In this case, the attack can just be randomized through the 254 host range though.

At this time Suricata IDS does not have any logic in their system to monitor for this or ARP spoofing in general. Snort does have a preprocessor to detect ARP spoofing attacks but it does need to be configured in the configuration file.

preprocessor arpspoof
preprocessor arpspoof_detect_host: 192.168.1.9 xx:xx:xx:xx:xx:xx
preprocessor arpspoof_detect_host: 192.168.1.6 xx:xx:xx:xx:xx:xx

Unfortunately, this preprocesser is not going to detect malicious packets that look like they are legitimately coming from the router. There is no ARP incremental IP request signature to stop this attack. The beauty is although the nodes will eventually ask for the default router via ARP request, the attack ignores these requests. The benefit of this is there is no ARP cache poisoning which means it will not affect the network or disrupt communications.

Being an attack that cannot be fully captured or detected without human analysis, it is something to think about on how to have a better mitigation for this attack.

Leave a Reply

Your email address will not be published. Required fields are marked *