Skip to content

Commit

Permalink
CVE-2017-12992/RIPng: Clean up bounds checking.
Browse files Browse the repository at this point in the history
Do bounds checking as we access items.

Scan the list of netinfo6 entries based on the supplied packet length,
without taking the captured length into account; let the aforementioned
bounds checking handle that.

This fixes a buffer over-read discovered by Kamil Frankowicz.

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 db24063 commit e942fb8
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 31 deletions.
71 changes: 40 additions & 31 deletions print-ripng.c
Expand Up @@ -110,65 +110,74 @@ ripng_print(netdissect_options *ndo, const u_char *dat, unsigned int length)
{
register const struct rip6 *rp = (const struct rip6 *)dat;
register const struct netinfo6 *ni;
register u_int amt;
register u_int i;
int j;
int trunc;

if (ndo->ndo_snapend < dat)
return;
amt = ndo->ndo_snapend - dat;
i = min(length, amt);
if (i < (sizeof(struct rip6) - sizeof(struct netinfo6)))
return;
i -= (sizeof(struct rip6) - sizeof(struct netinfo6));
unsigned int length_left;
u_int j;

ND_TCHECK(rp->rip6_cmd);
switch (rp->rip6_cmd) {

case RIP6_REQUEST:
j = length / sizeof(*ni);
if (j == 1
&& rp->rip6_nets->rip6_metric == HOPCNT_INFINITY6
&& IN6_IS_ADDR_UNSPECIFIED(&rp->rip6_nets->rip6_dest)) {
ND_PRINT((ndo, " ripng-req dump"));
break;
length_left = length;
if (length_left < (sizeof(struct rip6) - sizeof(struct netinfo6)))
goto trunc;
length_left -= (sizeof(struct rip6) - sizeof(struct netinfo6));
j = length_left / sizeof(*ni);
if (j == 1) {
ND_TCHECK(rp->rip6_nets);
if (rp->rip6_nets->rip6_metric == HOPCNT_INFINITY6
&& IN6_IS_ADDR_UNSPECIFIED(&rp->rip6_nets->rip6_dest)) {
ND_PRINT((ndo, " ripng-req dump"));
break;
}
}
if (j * sizeof(*ni) != length - 4)
ND_PRINT((ndo, " ripng-req %d[%u]:", j, length));
if (j * sizeof(*ni) != length_left)
ND_PRINT((ndo, " ripng-req %u[%u]:", j, length));
else
ND_PRINT((ndo, " ripng-req %d:", j));
trunc = ((i / sizeof(*ni)) * sizeof(*ni) != i);
for (ni = rp->rip6_nets; i >= sizeof(*ni);
i -= sizeof(*ni), ++ni) {
ND_PRINT((ndo, " ripng-req %u:", j));
for (ni = rp->rip6_nets; length_left >= sizeof(*ni);
length_left -= sizeof(*ni), ++ni) {
ND_TCHECK(*ni);
if (ndo->ndo_vflag > 1)
ND_PRINT((ndo, "\n\t"));
else
ND_PRINT((ndo, " "));
rip6_entry_print(ndo, ni, 0);
}
if (length_left != 0)
goto trunc;
break;
case RIP6_RESPONSE:
j = length / sizeof(*ni);
if (j * sizeof(*ni) != length - 4)
length_left = length;
if (length_left < (sizeof(struct rip6) - sizeof(struct netinfo6)))
goto trunc;
length_left -= (sizeof(struct rip6) - sizeof(struct netinfo6));
j = length_left / sizeof(*ni);
if (j * sizeof(*ni) != length_left)
ND_PRINT((ndo, " ripng-resp %d[%u]:", j, length));
else
ND_PRINT((ndo, " ripng-resp %d:", j));
trunc = ((i / sizeof(*ni)) * sizeof(*ni) != i);
for (ni = rp->rip6_nets; i >= sizeof(*ni);
i -= sizeof(*ni), ++ni) {
for (ni = rp->rip6_nets; length_left >= sizeof(*ni);
length_left -= sizeof(*ni), ++ni) {
ND_TCHECK(*ni);
if (ndo->ndo_vflag > 1)
ND_PRINT((ndo, "\n\t"));
else
ND_PRINT((ndo, " "));
rip6_entry_print(ndo, ni, ni->rip6_metric);
}
if (trunc)
ND_PRINT((ndo, "[|ripng]"));
if (length_left != 0)
goto trunc;
break;
default:
ND_PRINT((ndo, " ripng-%d ?? %u", rp->rip6_cmd, length));
break;
}
ND_TCHECK(rp->rip6_vers);
if (rp->rip6_vers != RIP6_VERSION)
ND_PRINT((ndo, " [vers %d]", rp->rip6_vers));
return;

trunc:
ND_PRINT((ndo, "[|ripng]"));
return;
}
1 change: 1 addition & 0 deletions tests/TESTLIST
Expand Up @@ -450,6 +450,7 @@ isoclns-oobr isoclns-oobr.pcap isoclns-oobr.out
nfs-attr-oobr nfs-attr-oobr.pcap nfs-attr-oobr.out
decnet-oobr decnet-oobr.pcap decnet-oobr.out
oobr_parse_elements oobr_parse_elements.pcap oobr_parse_elements.out
hoobr_ripng_print hoobr_ripng_print.pcap hoobr_ripng_print.out

# bad packets from Wilfried Kirsch
slip-bad-direction slip-bad-direction.pcap slip-bad-direction.out -ve
Expand Down
1 change: 1 addition & 0 deletions tests/hoobr_ripng_print.out
@@ -0,0 +1 @@
IP 48.48.48.48.521 > 48.48.48.48.12336: [|ripng]
Binary file added tests/hoobr_ripng_print.pcap
Binary file not shown.

0 comments on commit e942fb8

Please sign in to comment.