]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
ipv6: more robust ipv6 exthdr handling
authorVictor Julien <victor@inliniac.net>
Mon, 28 Jul 2014 11:59:44 +0000 (13:59 +0200)
committerVictor Julien <victor@inliniac.net>
Wed, 6 Aug 2014 08:56:05 +0000 (10:56 +0200)
Skip past Shim6, HIP and Mobility header.

Detect data after 'none' header.
    decode-event:ipv6.data_after_none_header;

rules/decoder-events.rules
src/decode-events.h
src/decode-ipv6.c
src/decode.h
src/detect-engine-event.h

index 0e7d2c68f64a157e4df8658c36775d51eaba73a7..779d6ed30e96d591983709947388857852c75860 100644 (file)
@@ -41,6 +41,8 @@ alert ipv6 any any -> any any (msg:"SURICATA RH Type 0"; decode-event:ipv6.rh_ty
 alert ipv6 any any -> any any (msg:"SURICATA zero length padN option"; decode-event:ipv6.zero_len_padn; sid:2200094; rev:1;)
 # Frag Header 'length' field is reserved and should be 0
 alert ipv6 any any -> any any (msg:"SURICATA reserved field in Frag Header not zero"; decode-event:ipv6.fh_non_zero_reserved_field; sid:2200095; rev:1;)
+# Data after the 'none' header (59) is suspicious.
+alert ipv6 any any -> any any (msg:"SURICATA data after none (59) header"; decode-event:ipv6.data_after_none_header; sid:2200096; rev:1;)
 alert ipv6 any any -> any any (msg:"SURICATA IPv6 with ICMPv4 header"; decode-event:ipv6.icmpv4; sid:2200090; rev:1;)
 alert pkthdr any any -> any any (msg:"SURICATA ICMPv4 packet too small"; decode-event:icmpv4.pkt_too_small; sid:2200023; rev:1;)
 alert pkthdr any any -> any any (msg:"SURICATA ICMPv4 unknown type"; decode-event:icmpv4.unknown_type; sid:2200024; rev:1;)
@@ -112,5 +114,5 @@ alert pkthdr any any -> any any (msg:"SURICATA IPv4-in-IPv6 invalid protocol"; d
 alert pkthdr any any -> any any (msg:"SURICATA IPv6-in-IPv6 packet too short"; decode-event:ipv6.ipv6_in_ipv6_too_small; sid:2200084; rev:1;)
 alert pkthdr any any -> any any (msg:"SURICATA IPv6-in-IPv6 invalid protocol"; decode-event:ipv6.ipv6_in_ipv6_wrong_version; sid:2200085; rev:1;)
 
-# next sid is 2200096
+# next sid is 2200097
 
index 8c47af1799fd540ac9f2093f94fed063d3727c09..1eceb8af7a7a6c97bd91da6f23f8a6597162a36b 100644 (file)
@@ -82,6 +82,7 @@ enum {
     IPV6_EXTHDR_RH_TYPE_0,          /**< RH 0 is deprecated as per rfc5095 */
     IPV6_EXTHDR_ZERO_LEN_PADN,      /**< padN w/o data (0 len) */
     IPV6_FH_NON_ZERO_RES_FIELD,     /**< reserved field not zero */
+    IPV6_DATA_AFTER_NONE_HEADER,    /**< data after 'none' (59) header */
 
     IPV6_WITH_ICMPV4,               /**< IPv6 packet with ICMPv4 header */
 
index 099a7bfbc9717be5ebd3119128a6c742501d1cef..5424765f837c95702220204dcf55fa994f801ba2 100644 (file)
@@ -107,7 +107,7 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
     SCEnter();
 
     uint8_t *orig_pkt = pkt;
-    uint8_t nh;
+    uint8_t nh = 0; /* careful, 0 is actually a real type */
     uint16_t hdrextlen;
     uint16_t plen;
     char dstopts = 0;
@@ -118,6 +118,12 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
 
     while(1)
     {
+        /* No upper layer, but we do have data. Suspicious. */
+        if (nh == IPPROTO_NONE && plen > 0) {
+            ENGINE_SET_EVENT(p, IPV6_DATA_AFTER_NONE_HEADER);
+            SCReturn;
+        }
+
         if (plen < 2) { /* minimal needed in a hdr */
             SCReturn;
         }
@@ -535,12 +541,26 @@ DecodeIPV6ExtHdrs(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
                 IPV6_SET_L4PROTO(p,nh);
                 DecodeIPv4inIPv6(tv, dtv, p, pkt, plen, pq);
                 SCReturn;
+            /* none, last header */
             case IPPROTO_NONE:
                 IPV6_SET_L4PROTO(p,nh);
                 SCReturn;
             case IPPROTO_ICMP:
                 ENGINE_SET_EVENT(p,IPV6_WITH_ICMPV4);
                 SCReturn;
+            /* no parsing yet, just skip it */
+            case IPPROTO_MH:
+            case IPPROTO_HIP:
+            case IPPROTO_SHIM6:
+                hdrextlen = 8 + (*(pkt+1) * 8);  /* 8 bytes + length in 8 octet units */
+                if (hdrextlen > plen) {
+                    ENGINE_SET_EVENT(p, IPV6_TRUNC_EXTHDR);
+                    SCReturn;
+                }
+                nh = *pkt;
+                pkt += hdrextlen;
+                plen -= hdrextlen;
+                break;
             default:
                 IPV6_SET_L4PROTO(p,nh);
                 SCReturn;
@@ -633,6 +653,9 @@ int DecodeIPV6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, u
         case IPPROTO_DSTOPTS:
         case IPPROTO_AH:
         case IPPROTO_ESP:
+        case IPPROTO_MH:
+        case IPPROTO_HIP:
+        case IPPROTO_SHIM6:
             DecodeIPV6ExtHdrs(tv, dtv, p, pkt + IPV6_HEADER_LEN, IPV6_GET_PLEN(p), pq);
             break;
         case IPPROTO_ICMP:
index b5fa6cbb98c3129e61fdd6d289e8e65a15319e39..d99d3d4bea472d28137b803e424ce174a3f77749 100644 (file)
@@ -903,6 +903,19 @@ void AddressDebugPrint(Address *);
 #define IPPROTO_SCTP 132
 #endif
 
+#ifndef IPPROTO_MH
+#define IPPROTO_MH 135
+#endif
+
+/* Host Identity Protocol (rfc 5201) */
+#ifndef IPPROTO_HIP
+#define IPPROTO_HIP 139
+#endif
+
+#ifndef IPPROTO_SHIM6
+#define IPPROTO_SHIM6 140
+#endif
+
 /* pcap provides this, but we don't want to depend on libpcap */
 #ifndef DLT_EN10MB
 #define DLT_EN10MB 1
index 8c550922532b98c617fb3b91471f937c03a44a67..288956ddf327cc1f638cfd2d64ade6bd73bcb1ae 100644 (file)
@@ -92,6 +92,7 @@ struct DetectEngineEvents_ {
     { "ipv6.rh_type_0", IPV6_EXTHDR_RH_TYPE_0, },
     { "ipv6.zero_len_padn", IPV6_EXTHDR_ZERO_LEN_PADN, },
     { "ipv6.fh_non_zero_reserved_field", IPV6_FH_NON_ZERO_RES_FIELD, },
+    { "ipv6.data_after_none_header", IPV6_DATA_AFTER_NONE_HEADER, },
     { "ipv6.icmpv4", IPV6_WITH_ICMPV4, },
 
     /* TCP EVENTS */