royhills / arp-scan

The ARP Scanner

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Buffer overflow in unmarshal_arp_pkt

mrquincle opened this issue · comments

There's an incoming length parameter n = header->caplen set in the callback from libpcap.

void
callback(u_char *args ATTRIBUTE_UNUSED,
         const struct pcap_pkthdr *header, const u_char *packet_in) {
   arp_ether_ipv4 arpei;
   ether_hdr frame_hdr;
   int n = header->caplen;

In unmarshal_arp_pkt there's the following code.

 if (extra_data != NULL) {
      int length;

      length = buf_len - (cp - buffer);
      if (length > 0) {  /* Extra data after ARP packet */
         memcpy(extra_data, cp, length);
      }
      *extra_data_len = length;
   }

I don't see a check that restricts length. I'm afraid that might mean that someone might craft an arp packet that would be beyond extra_data[MAX_FRAME] with MAX_FRAME = 2048 (used to be 65536 in 2017).

From same Changelog it seems that in marshal_arp_pkt you've anticipated buffer overflow, but somehow unmarshal_arp_pkt seems to be overlooked.

If I have report these things in a different way, feel free to nudge me in that direction.

Thanks for finding this. It certainly looks suspect at first glance. This is exactly the right way to report any findings - I'm always happy to hear any comments, bugs etc.

Looking at the code, unmarshal_arp_pkt is only called once - from the libpcap callback function:

void
callback(u_char *args ATTRIBUTE_UNUSED,
         const struct pcap_pkthdr *header, const u_char *packet_in) {
   arp_ether_ipv4 arpei;
   ether_hdr frame_hdr;
   int n = header->caplen;
   struct in_addr source_ip;
   host_entry *temp_cursor;
   unsigned char extra_data[MAX_FRAME];
   size_t extra_data_len;
   int vlan_id;
   int framing;

[snip]

/*
 *      Unmarshal packet buffer into structures and determine framing type
 */
   framing = unmarshal_arp_pkt(packet_in, n, &frame_hdr, &arpei, extra_data,
                               &extra_data_len, &vlan_id);

So extra_data is defined as unsigned char extra_data[MAX_FRAME] and MAXFRAME is #defined as 2048.

I think I was "sure" that an incoming Ethernet frame could never be long enough to overrun the buffer when I wrote the code. The logic being that the buffer is longer than the maximum allowed Ethernet frame size of 1518 octets.

But now I think I forgot about jumbo packets jumbo packets so I think limiting the amount copied to the buffer size would be a sensible mitigation.

This issue is hopefully fixed by commit cbe828c

I'm going to close this issue now as I beleive it's been fixed.