[arp] possible DoS, fixes and improvements
rozhuk.im at gmail.com
rozhuk.im at gmail.com
Thu Dec 9 21:18:44 UTC 2010
Hi!
> I wonder which version of netinet/if_ether.c you are working from?
uname -a
FreeBSD firewall 9.0-CURRENT FreeBSD 9.0-CURRENT #2: Wed Dec 8 02:53:50
IRKT 2010 root at firewall:/usr/obj/usr/src/sys/RIMx64 amd64
--
Rozhuk Ivan
> -----Original Message-----
> From: Chuck Swiger [mailto:cswiger at mac.com]
> Sent: Wednesday, December 08, 2010 4:54 AM
> To: Rozhuk.IM at gmail.com
> Cc: freebsd-net at freebsd.org
> Subject: Re: [arp] possible DoS, fixes and improvements
>
> Hi, Rozhuk--
>
> On Dec 7, 2010, at 11:19 AM, rozhuk.im at gmail.com wrote:
> > Hi!
> >
> > 1. ah->ar_hln - is depend from ar_hrd?
> > Yes, and for ARPHRD_ETHER is 6 (ETHER_ADDR_LEN)
> > For ARPHRD_IEEE1394 - sizeof(struct fw_hwaddr)
> > ah->ar_hln ignored in ether_output: bcopy(ar_tha(ah), edst,
> ETHER_ADDR_LEN);
>
> If you know that ar_hrd is ARPHRD_ETHER, then you can either assume the
> length is ETHER_ADDR_LEN, or optionally check it, per RFC 826:
>
> "When an address resolution packet is received, the receiving
> Ethernet module gives the packet to the Address Resolution module
> which goes through an algorithm similar to the following.
> Negative conditionals indicate an end of processing and a
> discarding of the packet.
>
> ?Do I have the hardware type in ar$hrd?
> Yes: (almost definitely)
> [optionally check the hardware length ar$hln]
> ?Do I speak the protocol in ar$pro?
> Yes:
> [optionally check the protocol length ar$pln]"
>
> > check in in_arpinput:
> > if (ifp->if_addrlen != ah->ar_hln) {
> > LLE_WUNLOCK(la);
> > log(LOG_WARNING,
> > "arp from %*D: addr len: new %d, i/f %d
> (ignored)",
> > ifp->if_addrlen, (u_char *) ar_sha(ah), ":",
> > ah->ar_hln, ifp->if_addrlen);
> > goto reply;
> > }
> > NO DROP!!!!
>
> I wonder which version of netinet/if_ether.c you are working from?
> In 7-STABLE sources, it breaks rather than going to generate a reply:
>
> if (ifp->if_addrlen != ah->ar_hln) {
> log(LOG_WARNING,
> "arp from %*D: addr len: "
> "new %d, i/f %d (ignored)",
> ifp->if_addrlen, (u_char *)
> ar_sha(ah),
> ":", ah->ar_hln, ifp->if_addrlen);
> RT_UNLOCK(rt);
> break;
> }
>
> > In reply we get:
> > (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln);
> > (void)memcpy(ar_sha(ah), enaddr, ah->ar_hln);
> > Or
> > (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln);
> > (void)memcpy(ar_sha(ah), &lle->ll_addr, ah->ar_hln);
> >
> > How to use it see below.
> >
> >
> > 2. ah->ar_pln - does not checked!
> > We can make big arp request (512 nulls after struct arphdr + 2*6 +
> 2*4) ,
> > valid for host, set ar_plt = 255
> > And in reply will receive part of stack or core panic:
> > in_arpinput:
> > (void)memcpy(ar_spa(ah), &itaddr, ah->ar_pln);
> > ...
> > m->m_len = sizeof(*ah) + (2 * ah->ar_pln) + (2 * ah->ar_hln);
> > ( eq arphdr_len(ah) )
>
> I think I agree that this is not being checked for properly....
>
> Regards,
> --
> -Chuck
More information about the freebsd-net
mailing list