Skip to content

Commit 6fca58f

Browse files
guyharrisinfrastation
authored andcommitted
CVE-2017-12996/PIMv2: Make sure PIM TLVs have the right length.
We do bounds checks based on the TLV length, so if the TLV's length is too short, and we don't check for that, we could end up fetching data past the end of the TLV - including past the length of the captured data in the packet. This fixes a buffer over-read discovered by Forcepoint's security researchers Otto Airamo & Antti Levomäki. Add tests using the capture files supplied by the reporter(s).
1 parent 34cec72 commit 6fca58f

10 files changed

+51570
-9
lines changed

Diff for: print-pim.c

+21-9
Original file line numberDiff line numberDiff line change
@@ -730,7 +730,11 @@ pimv2_print(netdissect_options *ndo,
730730

731731
switch (otype) {
732732
case PIMV2_HELLO_OPTION_HOLDTIME:
733-
unsigned_relts_print(ndo, EXTRACT_16BITS(bp));
733+
if (olen != 2) {
734+
ND_PRINT((ndo, "ERROR: Option Length != 2 Bytes (%u)", olen));
735+
} else {
736+
unsigned_relts_print(ndo, EXTRACT_16BITS(bp));
737+
}
734738
break;
735739

736740
case PIMV2_HELLO_OPTION_LANPRUNEDELAY:
@@ -764,17 +768,25 @@ pimv2_print(netdissect_options *ndo,
764768
break;
765769

766770
case PIMV2_HELLO_OPTION_GENID:
767-
ND_PRINT((ndo, "0x%08x", EXTRACT_32BITS(bp)));
771+
if (olen != 4) {
772+
ND_PRINT((ndo, "ERROR: Option Length != 4 Bytes (%u)", olen));
773+
} else {
774+
ND_PRINT((ndo, "0x%08x", EXTRACT_32BITS(bp)));
775+
}
768776
break;
769777

770778
case PIMV2_HELLO_OPTION_REFRESH_CAP:
771-
ND_PRINT((ndo, "v%d", *bp));
772-
if (*(bp+1) != 0) {
773-
ND_PRINT((ndo, ", interval "));
774-
unsigned_relts_print(ndo, *(bp+1));
775-
}
776-
if (EXTRACT_16BITS(bp+2) != 0) {
777-
ND_PRINT((ndo, " ?0x%04x?", EXTRACT_16BITS(bp+2)));
779+
if (olen != 4) {
780+
ND_PRINT((ndo, "ERROR: Option Length != 4 Bytes (%u)", olen));
781+
} else {
782+
ND_PRINT((ndo, "v%d", *bp));
783+
if (*(bp+1) != 0) {
784+
ND_PRINT((ndo, ", interval "));
785+
unsigned_relts_print(ndo, *(bp+1));
786+
}
787+
if (EXTRACT_16BITS(bp+2) != 0) {
788+
ND_PRINT((ndo, " ?0x%04x?", EXTRACT_16BITS(bp+2)));
789+
}
778790
}
779791
break;
780792

Diff for: tests/TESTLIST

+4
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,10 @@ isis-areaaddr-oobr-2 isis-areaaddr-oobr-2.pcap isis-areaaddr-oobr-2.out -vvv -e
481481
isis-extd-ipreach-oobr isis-extd-ipreach-oobr.pcap isis-extd-ipreach-oobr.out -vvv -e
482482
lldp-infinite-loop-1 lldp-infinite-loop-1.pcap lldp-infinite-loop-1.out -vvv -e
483483
lldp-infinite-loop-2 lldp-infinite-loop-2.pcap lldp-infinite-loop-2.out -vvv -e
484+
pimv2-oobr-1 pimv2-oobr-1.pcap pimv2-oobr-1.out -vvv -e
485+
pimv2-oobr-2 pimv2-oobr-2.pcap pimv2-oobr-2.out -vvv -e
486+
pimv2-oobr-3 pimv2-oobr-3.pcap pimv2-oobr-3.out -vvv -e
487+
pimv2-oobr-4 pimv2-oobr-4.pcap pimv2-oobr-4.out -vvv -e
484488

485489
# RTP tests
486490
# fuzzed pcap

Diff for: tests/pimv2-oobr-1.out

+16,377
Large diffs are not rendered by default.

Diff for: tests/pimv2-oobr-1.pcap

64 KB
Binary file not shown.

Diff for: tests/pimv2-oobr-2.out

+21,581
Large diffs are not rendered by default.

Diff for: tests/pimv2-oobr-2.pcap

64 KB
Binary file not shown.

Diff for: tests/pimv2-oobr-3.out

+7,674
Large diffs are not rendered by default.

Diff for: tests/pimv2-oobr-3.pcap

64 KB
Binary file not shown.

Diff for: tests/pimv2-oobr-4.out

+5,913
Large diffs are not rendered by default.

Diff for: tests/pimv2-oobr-4.pcap

64 KB
Binary file not shown.

0 commit comments

Comments
 (0)