]> The Tcpdump Group git mirrors - tcpdump/commitdiff
CVE-2017-13051/RSVP: fix bounds checks for UNI
authorDenis Ovsienko <[email protected]>
Mon, 7 Aug 2017 21:43:20 +0000 (22:43 +0100)
committerDenis Ovsienko <[email protected]>
Wed, 13 Sep 2017 11:25:44 +0000 (12:25 +0100)
Fixup the part of rsvp_obj_print() that decodes the GENERALIZED_UNI
object from RFC 3476 Section 3.1 to check the sub-objects inside that
object more thoroughly.

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).

print-rsvp.c
tests/TESTLIST
tests/rsvp_uni-oobr-1.out [new file with mode: 0644]
tests/rsvp_uni-oobr-1.pcap [new file with mode: 0644]
tests/rsvp_uni-oobr-2.out [new file with mode: 0644]
tests/rsvp_uni-oobr-2.pcap [new file with mode: 0644]
tests/rsvp_uni-oobr-3.out [new file with mode: 0644]
tests/rsvp_uni-oobr-3.pcap [new file with mode: 0644]

index bc599796a827cc117de78954b2b2e8441fb3a404..b0fb34469401e1eaa353cf7e6845dbb2caba4be2 100644 (file)
@@ -1205,6 +1205,17 @@ rsvp_obj_print(netdissect_options *ndo,
                /* read variable length subobjects */
                total_subobj_len = obj_tlen;
                 while(total_subobj_len > 0) {
+                    /* If RFC 3476 Section 3.1 defined that a sub-object of the
+                     * GENERALIZED_UNI RSVP object must have the Length field as
+                     * a multiple of 4, instead of the check below it would be
+                     * better to test total_subobj_len only once before the loop.
+                     * So long as it does not define it and this while loop does
+                     * not implement such a requirement, let's accept that within
+                     * each iteration subobj_len may happen to be a multiple of 1
+                     * and test it and total_subobj_len respectively.
+                     */
+                    if (total_subobj_len < 4)
+                        goto invalid;
                     subobj_len  = EXTRACT_16BITS(obj_tptr);
                     subobj_type = (EXTRACT_16BITS(obj_tptr+2))>>8;
                     af = (EXTRACT_16BITS(obj_tptr+2))&0x00FF;
@@ -1216,7 +1227,13 @@ rsvp_obj_print(netdissect_options *ndo,
                            tok2str(af_values, "Unknown", af), af,
                            subobj_len));
 
-                    if(subobj_len == 0)
+                    /* In addition to what is explained above, the same spec does not
+                     * explicitly say that the same Length field includes the 4-octet
+                     * sub-object header, but as long as this while loop implements it
+                     * as it does include, let's keep the check below consistent with
+                     * the rest of the code.
+                     */
+                    if(subobj_len < 4 || subobj_len > total_subobj_len)
                         goto invalid;
 
                     switch(subobj_type) {
index 62e705bf387fac4a9c777deb6bc158e5fde6c8c8..1681849a0652b4138a8ce579845997a0a2613d66 100644 (file)
@@ -567,6 +567,9 @@ bgp_pmsi_tunnel-oobr        bgp_pmsi_tunnel-oobr.pcap       bgp_pmsi_tunnel-oobr.out -v -c1
 bgp_mvpn_6_and_7       bgp_mvpn_6_and_7.pcap           bgp_mvpn_6_and_7.out    -v -c1
 rsvp_fast_reroute-oobr rsvp_fast_reroute-oobr.pcap     rsvp_fast_reroute-oobr.out -v -c1
 esis_opt_prot-oobr     esis_opt_prot-oobr.pcap         esis_opt_prot-oobr.out  -v -c1
+rsvp_uni-oobr-1        rsvp_uni-oobr-1.pcap    rsvp_uni-oobr-1.out     -v -c1
+rsvp_uni-oobr-2        rsvp_uni-oobr-2.pcap    rsvp_uni-oobr-2.out     -v -c1
+rsvp_uni-oobr-3        rsvp_uni-oobr-3.pcap    rsvp_uni-oobr-3.out     -v -c3
 
 # bad packets from Katie Holly
 mlppp-oobr             mlppp-oobr.pcap                 mlppp-oobr.out
diff --git a/tests/rsvp_uni-oobr-1.out b/tests/rsvp_uni-oobr-1.out
new file mode 100644 (file)
index 0000000..f5da6e7
--- /dev/null
@@ -0,0 +1,5 @@
+IP (tos 0x2,ECT(0), ttl 248, id 0, offset 0, flags [none], proto RSVP (46), length 54312, bad cksum 3743 (->7e72)!)
+    54.35.0.0 > 58.16.0.0: 
+       RSVPv1 Hello Message (20), Flags: [Refresh reduction capable], length: 65527, ttl: 15, checksum: 0x0902
+         Generalized UNI Object (229) Flags: [ignore and forward if unknown], Class-Type: 1 (1), length: 12
+           Subobject Type: Unknown (127), AF: HDLC (4), length: 2 (invalid)
diff --git a/tests/rsvp_uni-oobr-1.pcap b/tests/rsvp_uni-oobr-1.pcap
new file mode 100644 (file)
index 0000000..16d2024
Binary files /dev/null and b/tests/rsvp_uni-oobr-1.pcap differ
diff --git a/tests/rsvp_uni-oobr-2.out b/tests/rsvp_uni-oobr-2.out
new file mode 100644 (file)
index 0000000..cc41acd
--- /dev/null
@@ -0,0 +1,5 @@
+IP (tos 0x2,ECT(0), ttl 248, id 0, offset 0, flags [none], proto RSVP (46), length 54312, bad cksum 3743 (->3051)!)
+    54.35.78.33 > 58.16.0.0: 
+       RSVPv1 Hello Message (20), Flags: [Refresh reduction capable], length: 65527, ttl: 15, checksum: 0x0902
+         Generalized UNI Object (229) Flags: [ignore and forward if unknown], Class-Type: 1 (1), length: 12
+           Subobject Type: Unknown (0), AF: HDLC (4), length: 2 (invalid)
diff --git a/tests/rsvp_uni-oobr-2.pcap b/tests/rsvp_uni-oobr-2.pcap
new file mode 100644 (file)
index 0000000..c9265ce
Binary files /dev/null and b/tests/rsvp_uni-oobr-2.pcap differ
diff --git a/tests/rsvp_uni-oobr-3.out b/tests/rsvp_uni-oobr-3.out
new file mode 100644 (file)
index 0000000..3afa86e
--- /dev/null
@@ -0,0 +1,12 @@
+IP (tos 0x0, ttl 48, id 25615, offset 0, flags [+, DF, rsvd], proto UDP (17), length 61735, bad cksum 8ef1 (->10e1)!)
+    1.2.3.3.1812 > 64.112.0.96.4567:  wb-29!
+IP (tos 0x2,ECT(0), ttl 248, id 0, offset 0, flags [none], proto RSVP (46), length 54312, bad cksum 3701 (->8972)!)
+    54.35.0.0 > 47.16.0.0: 
+       RSVPv1 Hello Message (20), Flags: [Refresh reduction capable], length: 65527, ttl: 15, checksum: 0x0902
+         Generalized UNI Object (229) Flags: [ignore and forward if unknown], Class-Type: 1 (1), length: 12
+           Subobject Type: Unknown (0), AF: HDLC (4), length: 1 (invalid)
+IP (tos 0x2,ECT(0), ttl 248, id 0, offset 0, flags [none], proto RSVP (46), length 54312, bad cksum 3701 (->7e72)!)
+    54.35.0.0 > 58.16.0.0: 
+       RSVPv1 Hello Message (20), Flags: [Refresh reduction capable], length: 65527, ttl: 15, checksum: 0x0902
+         Generalized UNI Object (229) Flags: [ignore and forward if unknown], Class-Type: 1 (1), length: 12
+           Subobject Type: Unknown (225), AF: HDLC (4), length: 1 (invalid)
diff --git a/tests/rsvp_uni-oobr-3.pcap b/tests/rsvp_uni-oobr-3.pcap
new file mode 100644 (file)
index 0000000..0006a4f
Binary files /dev/null and b/tests/rsvp_uni-oobr-3.pcap differ