]> The Tcpdump Group git mirrors - tcpdump/commitdiff
CVE-2017-13045/VQP: add some bounds checks
authorDenis Ovsienko <[email protected]>
Sat, 29 Jul 2017 22:21:00 +0000 (23:21 +0100)
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).

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

index 44a21935232bb86e14888677a901cbe25bb87296..90cf8ddfef9bf785395447184afafb7054dc9834 100644 (file)
@@ -26,6 +26,7 @@
 #include "netdissect.h"
 #include "extract.h"
 #include "addrtoname.h"
+#include "ether.h"
 
 #define VQP_VERSION                            1
 #define VQP_EXTRACT_VERSION(x) ((x)&0xFF)
@@ -105,13 +106,15 @@ vqp_print(netdissect_options *ndo, register const u_char *pptr, register u_int l
     const u_char *tptr;
     uint16_t vqp_obj_len;
     uint32_t vqp_obj_type;
-    int tlen;
+    u_int tlen;
     uint8_t nitems;
 
     tptr=pptr;
     tlen = len;
     vqp_common_header = (const struct vqp_common_header_t *)pptr;
     ND_TCHECK(*vqp_common_header);
+    if (sizeof(struct vqp_common_header_t) > tlen)
+        goto trunc;
 
     /*
      * Sanity checking of the header.
@@ -151,6 +154,9 @@ vqp_print(netdissect_options *ndo, register const u_char *pptr, register u_int l
     while (nitems > 0 && tlen > 0) {
 
         vqp_obj_tlv = (const struct vqp_obj_tlv_t *)tptr;
+        ND_TCHECK(*vqp_obj_tlv);
+        if (sizeof(struct vqp_obj_tlv_t) > tlen)
+            goto trunc;
         vqp_obj_type = EXTRACT_32BITS(vqp_obj_tlv->obj_type);
         vqp_obj_len = EXTRACT_16BITS(vqp_obj_tlv->obj_length);
         tptr+=sizeof(struct vqp_obj_tlv_t);
@@ -167,9 +173,13 @@ vqp_print(netdissect_options *ndo, register const u_char *pptr, register u_int l
 
         /* did we capture enough for fully decoding the object ? */
         ND_TCHECK2(*tptr, vqp_obj_len);
+        if (vqp_obj_len > tlen)
+            goto trunc;
 
         switch(vqp_obj_type) {
        case VQP_OBJ_IP_ADDRESS:
+            if (vqp_obj_len != 4)
+                goto trunc;
             ND_PRINT((ndo, "%s (0x%08x)", ipaddr_string(ndo, tptr), EXTRACT_32BITS(tptr)));
             break;
             /* those objects have similar semantics - fall through */
@@ -182,6 +192,8 @@ vqp_print(netdissect_options *ndo, register const u_char *pptr, register u_int l
             /* those objects have similar semantics - fall through */
        case VQP_OBJ_MAC_ADDRESS:
        case VQP_OBJ_MAC_NULL:
+            if (vqp_obj_len != ETHER_ADDR_LEN)
+                goto trunc;
              ND_PRINT((ndo, "%s", etheraddr_string(ndo, tptr)));
               break;
         default:
index b42ba5b1490d9a98e531c44cdbf2afa67b8a65d7..687e92f37874ae713461fe50cc431e75d5884ead 100644 (file)
@@ -562,6 +562,7 @@ isakmpv1-attr-oobr  isakmpv1-attr-oobr.pcap         isakmpv1-attr-oobr.out  -v
 hncp_dhcpv6data-oobr   hncp_dhcpv6data-oobr.pcap       hncp_dhcpv6data-oobr.out -v -c1
 # Same comments apply to the case below.
 hncp_dhcpv4data-oobr   hncp_dhcpv4data-oobr.pcap       hncp_dhcpv4data-oobr.out -v -c1
+vqp-oobr               vqp-oobr.pcap                   vqp-oobr.out            -v -c1
 
 # bad packets from Katie Holly
 mlppp-oobr             mlppp-oobr.pcap                 mlppp-oobr.out
diff --git a/tests/vqp-oobr.out b/tests/vqp-oobr.out
new file mode 100644 (file)
index 0000000..3b1f71e
--- /dev/null
@@ -0,0 +1,4 @@
+IP (tos 0x0, ttl 17, id 40207, offset 0, flags [+, DF, rsvd], proto UDP (17), length 46, bad cksum 8f04 (->f897)!)
+    0.0.128.20.1589 > 12.251.167.8.62720: 
+       VQPv1, unknown (127) Message, error-code unknown (31) (31), seq 0x80f90000, items 27, length 18
+       [|VQP]
diff --git a/tests/vqp-oobr.pcap b/tests/vqp-oobr.pcap
new file mode 100644 (file)
index 0000000..50be013
Binary files /dev/null and b/tests/vqp-oobr.pcap differ