]> The Tcpdump Group git mirrors - tcpdump/commitdiff
CVE-2017-13037/IP: Add bounds checks when printing time stamp options.
authorGuy Harris <[email protected]>
Sat, 25 Mar 2017 01:42:09 +0000 (18:42 -0700)
committerDenis Ovsienko <[email protected]>
Wed, 13 Sep 2017 11:25:44 +0000 (12:25 +0100)
This fixes a buffer over-read discovered by Bhargava Shastry,
SecT/TU Berlin.

Add a test using the capture file supplied by the reporter(s), modified
so the capture file won't be rejected as an invalid capture.

print-ip.c
tests/TESTLIST
tests/ip_ts_opts_asan.out [new file with mode: 0644]
tests/ip_ts_opts_asan.pcap [new file with mode: 0644]

index 6831b7aa2d28acbb9c85519009c5017c6f1da400..f8e02c1e79c85c92e70b058a6422dc2e912060a5 100644 (file)
@@ -168,7 +168,7 @@ nextproto4_cksum(netdissect_options *ndo,
        return (in_cksum(vec, 2));
 }
 
-static void
+static int
 ip_printts(netdissect_options *ndo,
            register const u_char *cp, u_int length)
 {
@@ -179,16 +179,18 @@ ip_printts(netdissect_options *ndo,
 
        if (length < 4) {
                ND_PRINT((ndo, "[bad length %u]", length));
-               return;
+               return (0);
        }
        ND_PRINT((ndo, " TS{"));
        hoplen = ((cp[3]&0xF) != IPOPT_TS_TSONLY) ? 8 : 4;
        if ((length - 4) & (hoplen-1))
                ND_PRINT((ndo, "[bad length %u]", length));
+       ND_TCHECK(cp[2]);
        ptr = cp[2] - 1;
        len = 0;
        if (ptr < 4 || ((ptr - 4) & (hoplen-1)) || ptr > length + 1)
                ND_PRINT((ndo, "[bad ptr %u]", cp[2]));
+       ND_TCHECK(cp[3]);
        switch (cp[3]&0xF) {
        case IPOPT_TS_TSONLY:
                ND_PRINT((ndo, "TSONLY"));
@@ -217,6 +219,7 @@ ip_printts(netdissect_options *ndo,
        for (len = 4; len < length; len += hoplen) {
                if (ptr == len)
                        type = " ^ ";
+               ND_TCHECK2(cp[len], hoplen);
                ND_PRINT((ndo, "%s%d@%s", type, EXTRACT_32BITS(&cp[len+hoplen-4]),
                       hoplen!=8 ? "" : ipaddr_string(ndo, &cp[len])));
                type = " ";
@@ -229,6 +232,10 @@ done:
                ND_PRINT((ndo, " [%d hops not recorded]} ", cp[3]>>4));
        else
                ND_PRINT((ndo, "}"));
+       return (0);
+
+trunc:
+       return (-1);
 }
 
 /*
@@ -278,7 +285,8 @@ ip_optprint(netdissect_options *ndo,
                        return;
 
                case IPOPT_TS:
-                       ip_printts(ndo, cp, option_len);
+                       if (ip_printts(ndo, cp, option_len) == -1)
+                               goto trunc;
                        break;
 
                case IPOPT_RR:       /* fall through */
index 27c38b9c313b41bdbf3f2d86afb24d31cff1adf8..5732f8ff5093bafcfba4d100ca6a3d4a11ef5191 100644 (file)
@@ -552,6 +552,7 @@ pim_header_asan-4   pim_header_asan-4.pcap          pim_header_asan-4.out   -v
 ip6_frag_asan          ip6_frag_asan.pcap              ip6_frag_asan.out       -v
 radius_attr_asan       radius_attr_asan.pcap           radius_attr_asan.out    -v
 ospf6_decode_v3_asan   ospf6_decode_v3_asan.pcap       ospf6_decode_v3_asan.out -v
+ip_ts_opts_asan                ip_ts_opts_asan.pcap            ip_ts_opts_asan.out     -v
 
 # RTP tests
 # fuzzed pcap
diff --git a/tests/ip_ts_opts_asan.out b/tests/ip_ts_opts_asan.out
new file mode 100644 (file)
index 0000000..ce890b1
--- /dev/null
@@ -0,0 +1,2 @@
+IP (tos 0xe2,ECT(0), id 32, offset 0, flags [+, DF, rsvd], proto ICMP (1), length 65319, options (timestamp TS{[bad length 14]TS+ADDR ^ [email protected][|ip]), bad cksum a09b (->90a7)!)
+    149.8.33.81 > 95.18.83.227: [|icmp]
diff --git a/tests/ip_ts_opts_asan.pcap b/tests/ip_ts_opts_asan.pcap
new file mode 100644 (file)
index 0000000..c9bb6b4
Binary files /dev/null and b/tests/ip_ts_opts_asan.pcap differ