Skip to content

Commit

Permalink
CVE-2017-12901/EIGRP: Do more length checks.
Browse files Browse the repository at this point in the history
This fixes a buffer over-read discovered by Forcepoint's security
researchers Otto Airamo & Antti Levomäki.

Add a test using the capture file supplied by the reporter(s).
  • Loading branch information
guyharris authored and infrastation committed Sep 13, 2017
1 parent 7ac73d6 commit de981e6
Show file tree
Hide file tree
Showing 4 changed files with 4,184 additions and 0 deletions.
47 changes: 47 additions & 0 deletions print-eigrp.c
Expand Up @@ -31,6 +31,7 @@
/*
* packet format documented at
* http://www.rhyshaden.com/eigrp.htm
* RFC 7868
*/

struct eigrp_common_header {
Expand Down Expand Up @@ -246,6 +247,12 @@ eigrp_print(netdissect_options *ndo, register const u_char *pptr, register u_int

/* ok they seem to want to know everything - lets fully decode it */

if (len < sizeof(struct eigrp_common_header)) {
ND_PRINT((ndo, "EIGRP %s, length: %u (too short, < %u)",
tok2str(eigrp_opcode_values, "unknown (%u)",eigrp_com_header->opcode),
len, (u_int) sizeof(struct eigrp_common_header)));
return;
}
tlen=len-sizeof(struct eigrp_common_header);

/* FIXME print other header info */
Expand Down Expand Up @@ -286,6 +293,11 @@ eigrp_print(netdissect_options *ndo, register const u_char *pptr, register u_int
eigrp_tlv_type,
eigrp_tlv_len));

if (eigrp_tlv_len < sizeof(struct eigrp_tlv_header)) {
ND_PRINT((ndo, " (too short, < %u)",
(u_int) sizeof(struct eigrp_tlv_header)));
break;
}
tlv_tptr=tptr+sizeof(struct eigrp_tlv_header);
tlv_tlen=eigrp_tlv_len-sizeof(struct eigrp_tlv_header);

Expand All @@ -296,6 +308,11 @@ eigrp_print(netdissect_options *ndo, register const u_char *pptr, register u_int

case EIGRP_TLV_GENERAL_PARM:
tlv_ptr.eigrp_tlv_general_parm = (const struct eigrp_tlv_general_parm_t *)tlv_tptr;
if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_general_parm)) {
ND_PRINT((ndo, " (too short, < %u)",
(u_int) (sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_general_parm))));
break;
}

ND_PRINT((ndo, "\n\t holdtime: %us, k1 %u, k2 %u, k3 %u, k4 %u, k5 %u",
EXTRACT_16BITS(tlv_ptr.eigrp_tlv_general_parm->holdtime),
Expand All @@ -308,6 +325,11 @@ eigrp_print(netdissect_options *ndo, register const u_char *pptr, register u_int

case EIGRP_TLV_SW_VERSION:
tlv_ptr.eigrp_tlv_sw_version = (const struct eigrp_tlv_sw_version_t *)tlv_tptr;
if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_sw_version)) {
ND_PRINT((ndo, " (too short, < %u)",
(u_int) (sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_sw_version))));
break;
}

ND_PRINT((ndo, "\n\t IOS version: %u.%u, EIGRP version %u.%u",
tlv_ptr.eigrp_tlv_sw_version->ios_major,
Expand All @@ -318,6 +340,11 @@ eigrp_print(netdissect_options *ndo, register const u_char *pptr, register u_int

case EIGRP_TLV_IP_INT:
tlv_ptr.eigrp_tlv_ip_int = (const struct eigrp_tlv_ip_int_t *)tlv_tptr;
if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_ip_int)) {
ND_PRINT((ndo, " (too short, < %u)",
(u_int) (sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_ip_int))));
break;
}

bit_length = tlv_ptr.eigrp_tlv_ip_int->plen;
if (bit_length > 32) {
Expand Down Expand Up @@ -347,6 +374,11 @@ eigrp_print(netdissect_options *ndo, register const u_char *pptr, register u_int

case EIGRP_TLV_IP_EXT:
tlv_ptr.eigrp_tlv_ip_ext = (const struct eigrp_tlv_ip_ext_t *)tlv_tptr;
if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_ip_ext)) {
ND_PRINT((ndo, " (too short, < %u)",
(u_int) (sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_ip_ext))));
break;
}

bit_length = tlv_ptr.eigrp_tlv_ip_ext->plen;
if (bit_length > 32) {
Expand Down Expand Up @@ -384,6 +416,11 @@ eigrp_print(netdissect_options *ndo, register const u_char *pptr, register u_int

case EIGRP_TLV_AT_CABLE_SETUP:
tlv_ptr.eigrp_tlv_at_cable_setup = (const struct eigrp_tlv_at_cable_setup_t *)tlv_tptr;
if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_at_cable_setup)) {
ND_PRINT((ndo, " (too short, < %u)",
(u_int) (sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_at_cable_setup))));
break;
}

ND_PRINT((ndo, "\n\t Cable-range: %u-%u, Router-ID %u",
EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_cable_setup->cable_start),
Expand All @@ -393,6 +430,11 @@ eigrp_print(netdissect_options *ndo, register const u_char *pptr, register u_int

case EIGRP_TLV_AT_INT:
tlv_ptr.eigrp_tlv_at_int = (const struct eigrp_tlv_at_int_t *)tlv_tptr;
if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_at_int)) {
ND_PRINT((ndo, " (too short, < %u)",
(u_int) (sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_at_int))));
break;
}

ND_PRINT((ndo, "\n\t Cable-Range: %u-%u, nexthop: ",
EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->cable_start),
Expand All @@ -416,6 +458,11 @@ eigrp_print(netdissect_options *ndo, register const u_char *pptr, register u_int

case EIGRP_TLV_AT_EXT:
tlv_ptr.eigrp_tlv_at_ext = (const struct eigrp_tlv_at_ext_t *)tlv_tptr;
if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_at_ext)) {
ND_PRINT((ndo, " (too short, < %u)",
(u_int) (sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_at_ext))));
break;
}

ND_PRINT((ndo, "\n\t Cable-Range: %u-%u, nexthop: ",
EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->cable_start),
Expand Down
1 change: 1 addition & 0 deletions tests/TESTLIST
Expand Up @@ -461,6 +461,7 @@ icmp-cksum-oobr-3 icmp-cksum-oobr-3.pcap icmp-cksum-oobr-3.out -vvv -e
icmp-cksum-oobr-4 icmp-cksum-oobr-4.pcap icmp-cksum-oobr-4.out -vvv -e
tok2str-oobr-1 tok2str-oobr-1.pcap tok2str-oobr-1.out -vvv -e
tok2str-oobr-2 tok2str-oobr-2.pcap tok2str-oobr-2.out -vvv -e
eigrp-tlv-oobr eigrp-tlv-oobr.pcap eigrp-tlv-oobr.out -vvv -e

# RTP tests
# fuzzed pcap
Expand Down

0 comments on commit de981e6

Please sign in to comment.