From: Victor Julien Date: Wed, 17 Sep 2014 12:26:27 +0000 (+0200) Subject: ipv6: RH extension header parsing issue X-Git-Tag: suricata-2.1beta2~102 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5f4a23deb93b68a97b37ec44810932d52ac6cfad;p=thirdparty%2Fsuricata.git ipv6: RH extension header parsing issue A logic error in the IPv6 Routing header parsing caused accidental updating of the original packet buffer. The calculated extension header lenght was set to the length field of the routing header, causing it to be wrong. This has 2 consequences: 1. defrag failure. As the now modified payload was used in defrag, the decoding of the reassembled packet now contained a broken length field for the routing header. This would lead to decoding failure. The potential here is evasion, although it would trigger: [1:2200014:1] SURICATA IPv6 truncated extension header 2. in IPS mode, especially the AF_PACKET mode, the modified and now broken packet would be transmitted on the wire. It's likely that end hosts and/or routers would reject this packet. NFQ based IPS mode would be less affected, as it 'verdicts' based on the packet handle. In case of replacing the packet (replace keyword or stream normalization) it could broadcast the bad packet. Additionally, the RH Type 0 address parsing was also broken. It too would modify the original packet. As the result of this code was not used anywhere else in the engine, this code is now disabled. Reported-By: Rafael Schaefer --- diff --git a/src/decode-ipv6.c b/src/decode-ipv6.c index aad3099b1f..111810bd97 100644 --- a/src/decode-ipv6.c +++ b/src/decode-ipv6.c @@ -181,13 +181,13 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt } IPV6_EXTHDR_SET_RH(p, pkt); - IPV6_EXTHDR_RH(p)->ip6rh_len = hdrextlen; + /** \todo move into own function and load on demand */ if (IPV6_EXTHDR_RH(p)->ip6rh_type == 0) { +#if 0 // XXX usused and broken, original packet is modified in the memcpy uint8_t i; - uint8_t n = IPV6_EXTHDR_RH(p)->ip6rh_len / 2; - + uint8_t n = hdrextlen / 2; /* because we devide the header len by 2 (as rfc 2460 tells us to) * we devide the result by 8 and not 16 as the header fields are * sized */ @@ -197,7 +197,7 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt memcpy(&IPV6_EXTHDR_RH(p)->ip6rh0_addr[i], pkt+(i*16)+8, sizeof(IPV6_EXTHDR_RH(p)->ip6rh0_addr[i])); } IPV6_EXTHDR_RH(p)->ip6rh0_num_addrs = i; - +#endif ENGINE_SET_EVENT(p, IPV6_EXTHDR_RH_TYPE_0); } diff --git a/src/decode-ipv6.h b/src/decode-ipv6.h index 24dffb8fad..23824269e1 100644 --- a/src/decode-ipv6.h +++ b/src/decode-ipv6.h @@ -164,10 +164,12 @@ typedef struct IPV6RouteHdr_ including first 8 bytes. */ uint8_t ip6rh_type; /* routing type */ uint8_t ip6rh_segsleft; /* segments left */ +#if 0 struct in6_addr ip6rh0_addr[23]; /* type 0 addresses */ uint8_t ip6rh0_num_addrs; /* number of actual addresses in the array/packet. The array is guarranteed to be filled up to this number. */ +#endif } __attribute__((__packed__)) IPV6RouteHdr; #define IPV6_EXTHDR_GET_RAW_RH_NH(p) ((p)->ip6eh.ip6rh->ip6rh_nxt)