>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 r...@syspatch-72-arm64.openbsd.org:/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.