Skip to content

Commit bd4e697

Browse files
committed
CVE-2017-13053/BGP: fix VPN route target bounds checks
decode_rt_routing_info() didn't check bounds before fetching 4 octets of the origin AS field and could over-read the input buffer, put it right. It also fetched the varying number of octets of the route target field from 4 octets lower than the correct offset, put it right. It also used the same temporary buffer explicitly through as_printf() and implicitly through bgp_vpn_rd_print() so the end result of snprintf() was not what was originally intended. 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).
1 parent e6511cc commit bd4e697

File tree

4 files changed

+63
-3
lines changed

4 files changed

+63
-3
lines changed

Diff for: print-bgp.c

+19-3
Original file line numberDiff line numberDiff line change
@@ -761,32 +761,48 @@ decode_rt_routing_info(netdissect_options *ndo,
761761
{
762762
uint8_t route_target[8];
763763
u_int plen;
764+
char asbuf[sizeof(astostr)]; /* bgp_vpn_rd_print() overwrites astostr */
764765

766+
/* NLRI "prefix length" from RFC 2858 Section 4. */
765767
ND_TCHECK(pptr[0]);
766768
plen = pptr[0]; /* get prefix length */
767769

770+
/* NLRI "prefix" (ibid), valid lengths are { 0, 32, 33, ..., 96 } bits.
771+
* RFC 4684 Section 4 defines the layout of "origin AS" and "route
772+
* target" fields inside the "prefix" depending on its length.
773+
*/
768774
if (0 == plen) {
775+
/* Without "origin AS", without "route target". */
769776
snprintf(buf, buflen, "default route target");
770777
return 1;
771778
}
772779

773780
if (32 > plen)
774781
return -1;
775782

783+
/* With at least "origin AS", possibly with "route target". */
784+
ND_TCHECK_32BITS(pptr + 1);
785+
as_printf(ndo, asbuf, sizeof(asbuf), EXTRACT_32BITS(pptr + 1));
786+
776787
plen-=32; /* adjust prefix length */
777788

778789
if (64 < plen)
779790
return -1;
780791

792+
/* From now on (plen + 7) / 8 evaluates to { 0, 1, 2, ..., 8 }
793+
* and gives the number of octets in the variable-length "route
794+
* target" field inside this NLRI "prefix". Look for it.
795+
*/
781796
memset(&route_target, 0, sizeof(route_target));
782-
ND_TCHECK2(pptr[1], (plen + 7) / 8);
783-
memcpy(&route_target, &pptr[1], (plen + 7) / 8);
797+
ND_TCHECK2(pptr[5], (plen + 7) / 8);
798+
memcpy(&route_target, &pptr[5], (plen + 7) / 8);
799+
/* Which specification says to do this? */
784800
if (plen % 8) {
785801
((u_char *)&route_target)[(plen + 7) / 8 - 1] &=
786802
((0xff00 >> (plen % 8)) & 0xff);
787803
}
788804
snprintf(buf, buflen, "origin AS: %s, route target %s",
789-
as_printf(ndo, astostr, sizeof(astostr), EXTRACT_32BITS(pptr+1)),
805+
asbuf,
790806
bgp_vpn_rd_print(ndo, (u_char *)&route_target));
791807

792808
return 5 + (plen + 7) / 8;

Diff for: tests/TESTLIST

+1
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,7 @@ rsvp_uni-oobr-2 rsvp_uni-oobr-2.pcap rsvp_uni-oobr-2.out -v -c1
572572
rsvp_uni-oobr-3 rsvp_uni-oobr-3.pcap rsvp_uni-oobr-3.out -v -c3
573573
rpki-rtr-oob rpki-rtr-oob.pcap rpki-rtr-oob.out -v -c1
574574
lldp_8023_mtu-oobr lldp_8023_mtu-oobr.pcap lldp_8023_mtu-oobr.out -v -c1
575+
bgp_vpn_rt-oobr bgp_vpn_rt-oobr.pcap bgp_vpn_rt-oobr.out -v -c1
575576

576577
# bad packets from Katie Holly
577578
mlppp-oobr mlppp-oobr.pcap mlppp-oobr.out

Diff for: tests/bgp_vpn_rt-oobr.out

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
IP (tos 0xc, ttl 254, id 21263, offset 0, flags [rsvd], proto TCP (6), length 60165, bad cksum 8e15 (->9eb8)!)
2+
241.0.128.19.179 > 239.8.0.1.0: Flags [none], seq 2146695561:2146755682, win 56026, options [unknown-161,eol], length 60121: BGP
3+
Update Message (2), length: 45
4+
Withdrawn routes: 3 bytes
5+
Attribute Set (128), length: 7, Flags [OTPE+f]:
6+
Origin AS: 0
7+
Multi-Protocol Unreach NLRI (15), length: 227, Flags [T+6]:
8+
AFI: IPv6 (2), SAFI: Multicast VPN (5)
9+
Route-Type: Source-Active (5), length: 5, RD: unknown RD format, Group bogus address length 127
10+
Route-Type: Unknown (142), length: 142
11+
Route-Type: Unknown (0), length: 0
12+
Route-Type: Unknown (33), length: 0
13+
Route-Type: Unknown (0), length: 0[|BGP] [|BGP]
14+
Update Message (2), length: 45[|BGP] [|BGP]
15+
Update Message (2), length: 45
16+
Withdrawn routes: 3 bytes
17+
Attribute Set (128), length: 7, Flags [OTPE+f]:
18+
Origin AS: 0
19+
Multi-Protocol Reach NLRI (14), length: 227, Flags [T+6]:
20+
AFI: IPv4 (1), vendor specific SAFI: Route Target Routing Information (132)
21+
nexthop: invalid len, nh-length: 1, no SNPA
22+
origin AS: 0, route target 0:0 (= 0.0.0.0)
23+
default route target
24+
default route target
25+
default route target
26+
default route target
27+
default route target
28+
default route target
29+
default route target
30+
default route target
31+
default route target
32+
default route target
33+
default route target
34+
default route target
35+
default route target
36+
default route target
37+
default route target
38+
default route target
39+
default route target
40+
default route target
41+
default route target
42+
default route target
43+
default route target[|BGP]

Diff for: tests/bgp_vpn_rt-oobr.pcap

4.97 KB
Binary file not shown.

0 commit comments

Comments
 (0)