Heap based Buffer Over-read vulnerability in fast_edit_packet() - tcpreplay 4.3
Loginsoft-2018-17580
September 28, 2018
CVE Number
CVE-2018-17580
CWE
CWE-126: Buffer Over-read
Product Details
Tcpreplay is a suite of free Open Source utilities for editing and replaying previously captured network traffic.
URL:https://tcpreplay.appneta.com/
Vulnerable Versions
4.3 branch
Vulnerability Details
A heap-based buffer over-read exists in the function fast_edit_packet() in the file send_packets.c of Tcpreplay v4.3.0 beta1. This can lead to Denial of Service (DoS) and potentially Information Exposure when the application attempts to process a crafted pcap file.
SYNOPSIS
```
if (ctx->options->unique_ip && ctx->unique_iteration &&
ctx->unique_iteration > ctx->last_unique_iteration) {
/* edit packet to ensure every pass has unique IP addresses */
fast_edit_packet(&pkthdr, &pktdata, ctx->unique_iteration - 1, [1]
preload, datalink);
}
```
```
case ETHERTYPE_IP:
ip_hdr = (ipv4_hdr_t *)(packet + l2_len);
src_ip_orig = src_ip = ntohl(ip_hdr->ip_src.s_addr);
dst_ip_orig = dst_ip = ntohl(ip_hdr->ip_dst.s_addr); [2]
break;
```
The function send_packets(), is responsible for figuring out what to do with each packets. It internally calls the fast_edit_packet() function [1][3] , which is responsible for editing a packet to ensure every pass has unique IP addresses. This helps in increasing the flows per second (fps) as it ensures that the IP addresses are unique for every loop iteration. Unfortunately the same also being responsible for triggering the heap overflow issue while getting the source address via network to host byte order conversion [2].
Alike the issue CVE-2018-17974, where the pktlen was larger than the max limit(65535), here the captured length (pkthdr->caplen) which is 60, is greater than the packet length(pkthdr->len) which is 28. The reason behind being a truncated ipv4 packet at the source address field.
While analyzing the package with wireshark, it prompted displaying the packet is truncated, further the third frame being corrupted as the value of the Total Length field of an IPv4 header was larger than the frame length. The IPv4 packet is the payload of the frame whereas the frame length is the total of packet length including the frame header and trailer.
A similar issue was also noticed in tcpdump – https://github.com/the-tcpdump-group/libpcap/issues/626
Analysis
287 switch (ether_type) {
288 case ETHERTYPE_IP:
289 ip_hdr = (ipv4_hdr_t *)(packet + l2_len);
// ip_hdr=0xbfffeb3c -> [...] -> 0x00000000
-> 290 src_ip_orig = src_ip = ntohl(ip_hdr->ip_src.s_addr); //Overflow triggered
291 dst_ip_orig = dst_ip = ntohl(ip_hdr->ip_dst.s_addr);
292 break;
293
gef> p/d ip_hdr->ip_src.s_addr
$33 = 43200
gef> p/d src_ip
$34 = 727806
gef> p/d src_ip_orig
$35 = 28
ASAN Output
==3984==ERROR: AddressSanitizer: heap-buffer-overflow on address 0xb48002ca at pc 0x0804d6c6 bp 0xbfffeb08 sp 0xbfffeaf8
READ of size 4 at 0xb48002ca thread T0
#0 0x804d6c5 in fast_edit_packet /home/loginsoft/ACE/tcpreplay/src/send_packets.c:290
#1 0x804f9c0 in send_packets /home/loginsoft/ACE/tcpreplay/src/send_packets.c:569
#2 0x8060aa4 in replay_file /home/loginsoft/ACE/tcpreplay/src/replay.c:188
#3 0x805f8c1 in tcpr_replay_index /home/loginsoft/ACE/tcpreplay/src/replay.c:61
#4 0x805e791 in tcpreplay_replay /home/loginsoft/ACE/tcpreplay/src/tcpreplay_api.c:1135
#5 0x8056186 in main /home/loginsoft/ACE/tcpreplay/src/tcpreplay.c:139
#6 0xb784c636 in __libc_start_main (/lib/i386-linux-gnu/libc.so.6+0x18636)
#7 0x804a7a0 (/usr/local/bin/tcpreplay+0x804a7a0)
0xb48002cc is located 0 bytes to the right of 28-byte region [0xb48002b0,0xb48002cc)
allocated by thread T0 here:
#0 0xb7ae7dee in malloc (/usr/lib/i386-linux-gnu/libasan.so.2+0x96dee)
#1 0x8065642 in _our_safe_malloc /home/loginsoft/ACE/tcpreplay/src/common/utils.c:50
#2 0x8052efd in get_next_packet /home/loginsoft/ACE/tcpreplay/src/send_packets.c:1044
#3 0x804e921 in preload_pcap_file /home/loginsoft/ACE/tcpreplay/src/send_packets.c:445
#4 0x805615b in main /home/loginsoft/ACE/tcpreplay/src/tcpreplay.c:126
#5 0xb784c636 in __libc_start_main (/lib/i386-linux-gnu/libc.so.6+0x18636)
SUMMARY: AddressSanitizer: heap-buffer-overflow /home/loginsoft/ACE/tcpreplay/src/send_packets.c:290 fast_edit_packet
Shadow bytes around the buggy address:
0x36900000: fa fa 00 00 00 fa fa fa 00 00 00 fa fa fa 00 00
0x36900010: 00 fa fa fa 00 00 00 fa fa fa 00 00 00 fa fa fa
0x36900020: 00 00 00 fa fa fa 00 00 00 fa fa fa 00 00 00 fa
0x36900030: fa fa 00 00 00 fa fa fa 00 00 00 fa fa fa 00 00
0x36900040: 00 fa fa fa 00 00 00 fa fa fa 00 00 00 fa fa fa
=>0x36900050: 00 00 00 fa fa fa 00 00 00[04]fa fa 00 00 00 fa
0x36900060: fa fa 00 00 00 fa fa fa 00 00 00 fa fa fa fd fd
0x36900070: fd fd fa fa fd fd fd fd fa fa fd fd fd fa fa fa
0x36900080: fd fd fd fa fa fa fd fd fd fa fa fa fd fd fd fa
0x36900090: fa fa fd fd fd fa fa fa fd fd fd fa fa fa fd fd
0x369000a0: fd fa fa fa fd fd fd fd fa fa fd fd fd fd fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Heap right redzone: fb
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack partial redzone: f4
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
==3984==ABORTING
glibc detection
*** Error in `tcpreplay': corrupted size vs. prev_size: 0x0825bd50 ***
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x67377)[0xb7d0c377]
/lib/i386-linux-gnu/libc.so.6(+0x6d2f7)[0xb7d122f7]
/lib/i386-linux-gnu/libc.so.6(+0x6d6fe)[0xb7d126fe]
/lib/i386-linux-gnu/libc.so.6(+0x6e395)[0xb7d13395]
tcpreplay[0x8053cf6]
tcpreplay[0x804f7ea]
tcpreplay[0x804e56b]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf7)[0xb7cbd637]
tcpreplay[0x804a671]
======= Memory map: ========
08048000-0804a000 r--p 00000000 08:01 2641698 /usr/local/bin/tcpreplay
0804a000-08059000 r-xp 00002000 08:01 2641698 /usr/local/bin/tcpreplay
08059000-08060000 r--p 00011000 08:01 2641698 /usr/local/bin/tcpreplay
08060000-08061000 r--p 00017000 08:01 2641698 /usr/local/bin/tcpreplay
08061000-08062000 rw-p 00018000 08:01 2641698 /usr/local/bin/tcpreplay
08062000-08065000 rw-p 00000000 00:00 0
08254000-08275000 rw-p 00000000 00:00 0 [heap]
b7b00000-b7b21000 rw-p 00000000 00:00 0
b7b21000-b7c00000 ---p 00000000 00:00 0
b7ca4000-b7ca5000 rw-p 00000000 00:00 0
b7ca5000-b7e55000 r-xp 00000000 08:01 786798 /lib/i386-linux-gnu/libc-2.23.so
b7e55000-b7e57000 r--p 001af000 08:01 786798 /lib/i386-linux-gnu/libc-2.23.so
b7e57000-b7e58000 rw-p 001b1000 08:01 786798 /lib/i386-linux-gnu/libc-2.23.so
b7e58000-b7e5b000 rw-p 00000000 00:00 0
b7e5b000-b7e7b000 r-xp 00000000 08:01 2241910 /usr/lib/i386-linux-gnu/libopts.so.25.16.1
b7e7b000-b7e7c000 r--p 0001f000 08:01 2241910 /usr/lib/i386-linux-gnu/libopts.so.25.16.1
b7e7c000-b7e7d000 rw-p 00020000 08:01 2241910 /usr/lib/i386-linux-gnu/libopts.so.25.16.1
b7e7d000-b7ebf000 r-xp 00000000 08:01 2230579 /usr/lib/i386-linux-gnu/libpcap.so.1.7.4
b7ebf000-b7ec0000 ---p 00042000 08:01 2230579 /usr/lib/i386-linux-gnu/libpcap.so.1.7.4
b7ec0000-b7ec1000 r--p 00042000 08:01 2230579 /usr/lib/i386-linux-gnu/libpcap.so.1.7.4
b7ec1000-b7ec2000 rw-p 00043000 08:01 2230579 /usr/lib/i386-linux-gnu/libpcap.so.1.7.4
b7ec9000-b7ee5000 r-xp 00000000 08:01 786836 /lib/i386-linux-gnu/libgcc_s.so.1
b7ee5000-b7ee6000 rw-p 0001b000 08:01 786836 /lib/i386-linux-gnu/libgcc_s.so.1
b7ee6000-b7ee8000 rw-p 00000000 00:00 0
b7ee8000-b7eeb000 r--p 00000000 00:00 0 [vvar]
b7eeb000-b7eed000 r-xp 00000000 00:00 0 [vdso]
b7eed000-b7f10000 r-xp 00000000 08:01 786770 /lib/i386-linux-gnu/ld-2.23.so
b7f10000-b7f11000 r--p 00022000 08:01 786770 /lib/i386-linux-gnu/ld-2.23.so
b7f11000-b7f12000 rw-p 00023000 08:01 786770 /lib/i386-linux-gnu/ld-2.23.so
bf8e8000-bf909000 rw-p 00000000 00:00 0 [stack]
Aborted
Proof of Concept
tcpreplay -i en33 -t –K –loop 4 –unique-ip $POC
-t switch is for performance improvement to send the packets as fast as possible.-K enables the caching of packets to internal memory. It loads the pcap file into the RAM for performance improvement.--loop is used to specify the loop number, to loop through the capture file N times.The issue is triggered when supplied a crafted pcap file via the above given command.--unique-ip [3]
Timeline
Vendor Disclosure: 2018-09-26
Public Disclosure: 2018-09-28
Credit
Discovered by ACE Team - Loginsoft