>Synopsis: wrap of length into the high 4 billion in print-etherip.c
>Category: system
>Environment:
System : OpenBSD 7.2
Details : OpenBSD 7.2 (GENERIC.MP) #2: Thu Nov 24 23:53:03 MST 2022
[email protected]:/usr/src/sys/arch/arm64/compile/GENERIC.MP
Architecture: OpenBSD.arm64
Machine : arm64
>Description:
This is a good bug, good because it can't be exploited via the Internet.
But it was able to be exploited at 7.2 time with NSH to bring tcpdump to seg-
fault on a local LAN. Luckily NSH is now fixed so I can't demonstrate that
avenue. The spoofed frame has an illegal IP len that routers would not carry
along for the hop but tcpdump doesn't care so much about this.
In print-etherip.c much care is taken to check plen from becoming too small but
len is passed to sub-printers after an underflow (wrap).
>How-To-Repeat:
I changed computers and had to use vether because the old workstation
that I was using is sleeping. Here is a tcpdump of vether and the spoofery
into it. Notice the second packet indicates length -20 (it would be in
print-llc.c). That's the underflow / wrap of the unsigned integer.
tcpdump -v -n -i vether0 -X -s 1500
tcpdump: listening on vether0, link-type EN10MB
13:03:50.302274 192.168.177.13 > 255.255.255.255: etherip 3 len 0:
192.168.177.13 > 255.255.255.255: [|udp] (ttl 255, id 0, len 20) (ttl 255, id
0, len 20)
0000: 4500 0014 0000 0000 ff61 49d3 c0a8 b10d E........aI.....
0010: ffff ffff 3000 ffff ffff ffff 0101 0101 ....0...........
0020: 0101 0800 4500 0014 0000 0000 ff11 4a23 ....E.........J#
0030: c0a8 b10d ffff ffff ........
13:08:50.234684 192.168.177.13 > 255.255.255.255: etherip 3 len 0:
01:01:01:01:01:01 > ff:ff:ff:ff:ff:ff sap 00 I (s=0,r=0,C) len=-20 (ttl 255, id
0, len 20)
0000: 4500 0014 0000 0000 ff61 49d3 c0a8 b10d E........aI.....
0010: ffff ffff 3000 ffff ffff ffff 0101 0101 ....0...........
0020: 0101 05dc 0000 0000 0000 ..........
>Fix:
The fix is rather simple. instead of passing len to llc_print() (line
116) and ether_encap_print() (line 126 of print-etherip.c) pass snapend - pbuf.
Before that it must be tested whether pbuf is less than snapend.
(excerpt of cat -n of print-etherip.c):
115 if (etype <= ETHERMTU) {
116 if (llc_print(pbuf, len, plen, ESRC(eh), EDST(eh)) ==
0) {
126 } else if (ether_encap_print(etype, pbuf, len, plen) == 0) {
dmesg:
none.