]> The Tcpdump Group git mirrors - tcpdump/commitdiff
CVE-2017-5204/IPv6: fix header printing
authorDenis Ovsienko <[email protected]>
Mon, 9 Jan 2017 01:01:46 +0000 (01:01 +0000)
committerFrancois-Xavier Le Bail <[email protected]>
Wed, 18 Jan 2017 08:16:41 +0000 (09:16 +0100)
Add a few checks to ip6_print() to make it stop decoding the IPv6
headers immediately when the header-specific functions signal an error
condition. Without this it tried to fetch the next header selector for
the next round regardless and could run outside of the allocated packet
space on a specially crafted IPv6 packet.

Brian Carpenter has demonstrated this for the Hop-by-Hop Options header.
Fix that specific case and also the Destination Options and Fragment
header processing as those use the same logic.

print-ip6.c
tests/TESTLIST
tests/ipv6hdr-heapoverflow-v.out [new file with mode: 0644]
tests/ipv6hdr-heapoverflow.out [new file with mode: 0644]
tests/ipv6hdr-heapoverflow.pcap [new file with mode: 0644]

index 2e1803f05d5155cf0ce6d1d1825f92ab40a26480..9f590f2af4e1a8763a31b64e2330f7d57868d801 100644 (file)
@@ -293,15 +293,19 @@ ip6_print(netdissect_options *ndo, const u_char *bp, u_int length)
                switch (nh) {
                case IPPROTO_HOPOPTS:
                        advance = hbhopt_print(ndo, cp);
+                       if (advance < 0)
+                               return;
                        nh = *cp;
                        break;
                case IPPROTO_DSTOPTS:
                        advance = dstopt_print(ndo, cp);
+                       if (advance < 0)
+                               return;
                        nh = *cp;
                        break;
                case IPPROTO_FRAGMENT:
                        advance = frag6_print(ndo, cp, (const u_char *)ip6);
-                       if (ndo->ndo_snapend <= cp + advance)
+                       if (advance < 0 || ndo->ndo_snapend <= cp + advance)
                                return;
                        nh = *cp;
                        fragmented = 1;
index 9d6dfa3697a3e9c414d329df4deeab2891b838ed..266e093f269a92d01c32ed028f6775fd15cb8603 100644 (file)
@@ -419,6 +419,10 @@ juniper_header-heapoverflow        juniper_header-heapoverflow.pcap        juniper_header-heap
 tftp-heapoverflow      tftp-heapoverflow.pcap  tftp-heapoverflow.out   -t -v -n
 relts-0x80000000       relts-0x80000000.pcap   relts-0x80000000.out    -t -v -n
 
+# bad packets from Brian Carpenter
+ipv6hdr-heapoverflow   ipv6hdr-heapoverflow.pcap       ipv6hdr-heapoverflow.out        -t
+ipv6hdr-heapoverflow-v ipv6hdr-heapoverflow.pcap       ipv6hdr-heapoverflow-v.out      -t -v
+
 # RTP tests
 # fuzzed pcap
 rtp-seg-fault-1  rtp-seg-fault-1.pcap  rtp-seg-fault-1.out  -t -v -T rtp
diff --git a/tests/ipv6hdr-heapoverflow-v.out b/tests/ipv6hdr-heapoverflow-v.out
new file mode 100644 (file)
index 0000000..4e3730a
--- /dev/null
@@ -0,0 +1 @@
+IP6 (class 0x33, flowlabel 0x03030, hlim 48, next-header Options (0) payload length: 12336) 3030:3030:3030:3030:3030:3030:3030:3030 > 3030:3030:3030:3030:3030:3030:3030:3030: HBH [trunc] [|HBH]
diff --git a/tests/ipv6hdr-heapoverflow.out b/tests/ipv6hdr-heapoverflow.out
new file mode 100644 (file)
index 0000000..f9bc97e
--- /dev/null
@@ -0,0 +1 @@
+IP6 3030:3030:3030:3030:3030:3030:3030:3030 > 3030:3030:3030:3030:3030:3030:3030:3030: HBH [|HBH]
diff --git a/tests/ipv6hdr-heapoverflow.pcap b/tests/ipv6hdr-heapoverflow.pcap
new file mode 100644 (file)
index 0000000..19d28d6
Binary files /dev/null and b/tests/ipv6hdr-heapoverflow.pcap differ