Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] tcpreplay-edit ——heap-use-after-free in get_ipv6_next() at get.c:454 #578

Closed
14isnot40 opened this issue May 19, 2020 · 2 comments
Assignees
Labels
Milestone

Comments

@14isnot40
Copy link

14isnot40 commented May 19, 2020

Describe the bug
A heap-use-after-free bug was discovered in tcpreplay-edit binary, during the structure 'exthdr' points to the memory address released after use. The issue is being triggered in the function get_ipv6_next() at common/get.c:454.

To Reproduce
Steps to reproduce the behavior:

  1. Compile tcpreplay according to the default configuration
./configure CFLAGS="-g -O0 -fsanitize=address"
  1. execute command
tcpreplay-edit -r 80:84 -s 20 -b -C -m 1500 -P --oneatatime -i lo $poc

poc can be found here.

Expected behavior
An attacker can exploit this vulnerability by submitting a malicious pcap that exploits this issue. This will result in a Denial of Service (DoS), potentially Information Exposure and even Code Execution when the application attempts to process the file.

Screenshots
ASAN Reports

==64632==ERROR: AddressSanitizer: heap-use-after-free on address 0x611000009c87 at pc 0x0000004412bc bp 0x7fffffffd500 sp 0x7fffffffd4f0
READ of size 4 at 0x611000009c87 thread T0
    #0 0x4412bb in get_ipv6_next /home/test/Desktop/evaulation/tcpreplay/src/common/get.c:454
    #1 0x44112b in get_layer4_v6 /home/test/Desktop/evaulation/tcpreplay/src/common/get.c:409
    #2 0x428410 in do_checksum /home/test/Desktop/evaulation/tcpreplay/src/tcpedit/checksum.c:66
    #3 0x42033a in fix_ipv4_checksums /home/test/Desktop/evaulation/tcpreplay/src/tcpedit/edit_packet.c:82
    #4 0x41c8f9 in tcpedit_packet /home/test/Desktop/evaulation/tcpreplay/src/tcpedit/tcpedit.c:354
    #5 0x40963b in send_packets /home/test/Desktop/evaulation/tcpreplay/src/send_packets.c:552
    #6 0x418e9a in replay_file /home/test/Desktop/evaulation/tcpreplay/src/replay.c:182
    #7 0x417e73 in tcpr_replay_index /home/test/Desktop/evaulation/tcpreplay/src/replay.c:59
    #8 0x416de4 in tcpreplay_replay /home/test/Desktop/evaulation/tcpreplay/src/tcpreplay_api.c:1136
    #9 0x40fb4f in main /home/test/Desktop/evaulation/tcpreplay/src/tcpreplay.c:139
    #10 0x7ffff687f82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #11 0x403508 in _start (/usr/local/bin/tcpreplay-edit+0x403508)

0x611000009c87 is located 7 bytes inside of 196-byte region [0x611000009c80,0x611000009d44)
freed by thread T0 here:
    #0 0x7ffff6f022ca in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x982ca)
    #1 0x7ffff6c37b91 (/usr/lib/x86_64-linux-gnu/libpcap.so.0.8+0xeb91)

previously allocated by thread T0 here:
    #0 0x7ffff6f02602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)
    #1 0x7ffff6c36c38 (/usr/lib/x86_64-linux-gnu/libpcap.so.0.8+0xdc38)

SUMMARY: AddressSanitizer: heap-use-after-free /home/test/Desktop/evaulation/tcpreplay/src/common/get.c:454 get_ipv6_next
Shadow bytes around the buggy address:
  0x0c227fff9340: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff9350: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff9360: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
  0x0c227fff9370: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c227fff9380: 00 00 00 00 00 00 00 07 fa fa fa fa fa fa fa fa
=>0x0c227fff9390:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c227fff93a0: fd fd fd fd fd fd fd fd fd fa fa fa fa fa fa fa
  0x0c227fff93b0: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd
  0x0c227fff93c0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c227fff93d0: fd fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff93e0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
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
==64632==ABORTING
[Inferior 1 (process 64632) exited with code 01]

Debug

Starting program: /usr/local/bin/tcpreplay-edit -r 80:84 -s 20 -b -C -m 1500 -P --oneatatime -i lo huaf_get_ipv6_next 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Hardware watchpoint 1: *(int*) 0x611000009c87

Old value = <unreadable>
New value = 0xbebebebe
0x00007ffff69d19a4 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
[ Legend: Modified register | Code | Heap | Stack | String ]
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$rax   : 0x0000611000009c80  →  0xbebebebebebebebe
$rbx   : 0x108             
$rcx   : 0x0               
$rdx   : 0xc4              
$rsp   : 0x00007fffffffcfb8  →  0x00007ffff6e8d046  →   mov r10, QWORD PTR [rsp+0x8]
$rbp   : 0x00000c22000013a8  →  0x0000000000000000
$rsi   : 0x0000611000009d44  →  0x0000000000000000
$rdi   : 0x0000611000009c80  →  0xbebebebebebebebe
$rip   : 0x00007ffff69d19a4  →   vmovdqu XMMWORD PTR [rdi+0x10], xmm0
$r8    : 0x0               
$r9    : 0x1b8eb           
$r10   : 0x0000611000009c80  →  0xbebebebebebebebe
$r11   : 0x00007ffff7fa3408  →  0x0000000000000000
$r12   : 0x00007ffff7381760  →  0x0000001010000000  →  0x0000000000000000
$r13   : 0x00007fffffffd080  →  0x00007fffffffd090  →  0x00007ffff6f02603  →  <malloc+227> mov edi, DWORD PTR [r13+0x0]
$r14   : 0x0000611000009c70  →  0x12ffffff00000000
$r15   : 0xc4              
$eflags: [carry PARITY adjust zero sign trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x0033 $ss: 0x002b $ds: 0x0000 $es: 0x0000 $fs: 0x0000 $gs: 0x0000 
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0x00007fffffffcfb8│+0x0000: 0x00007ffff6e8d046  →   mov r10, QWORD PTR [rsp+0x8]	 ← $rsp
0x00007fffffffcfc0│+0x0008: 0x0000000000000008
0x00007fffffffcfc8│+0x0010: 0x0000611000009c80  →  0xbebebebebebebebe
0x00007fffffffcfd0│+0x0018: 0x0000000000000001
0x00007fffffffcfd8│+0x0020: 0x0000000000000001
0x00007fffffffcfe0│+0x0028: 0xfffffffffffffff8
0x00007fffffffcfe8│+0x0030: 0x0000000000000007
0x00007fffffffcff0│+0x0038: 0x0000000000000040 ("@"?)
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:64 ────
   0x7ffff69d1998                  add    BYTE PTR [rax], al
   0x7ffff69d199a                  add    BYTE PTR [rax+0x507280fa], al
   0x7ffff69d19a0                  vmovdqu XMMWORD PTR [rdi], xmm0
 → 0x7ffff69d19a4                  vmovdqu XMMWORD PTR [rdi+0x10], xmm0
   0x7ffff69d19a9                  vmovdqu XMMWORD PTR [rdi+0x20], xmm0
   0x7ffff69d19ae                  vmovdqu XMMWORD PTR [rdi+0x30], xmm0
   0x7ffff69d19b3                  vmovdqu XMMWORD PTR [rdi+0x40], xmm0
   0x7ffff69d19b8                  vmovdqu XMMWORD PTR [rdi+0x50], xmm0
   0x7ffff69d19bd                  vmovdqu XMMWORD PTR [rdi+0x60], xmm0
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "tcpreplay-edit", stopped, reason: BREAKPOINT
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x7ffff69d19a4 → vmovdqu XMMWORD PTR [rdi+0x10], xmm0
[#1] 0x7ffff6e8d046 → mov r10, QWORD PTR [rsp+0x8]
[#2] 0x7ffff6f025d3 → malloc()
[#3] 0x7ffff6c36c39 → test rax, rax
[#4] 0x7ffff6c388f0 → pcap_activate()
[#5] 0x7ffff6c39508 → mov rdx, QWORD PTR [rsp+0x8]
[#6] 0x7ffff6c39acd → mov rdx, QWORD PTR [rsp+0x8]
[#7] 0x7ffff6c37745 → sar eax, 0x1f
[#8] 0x7ffff6c37d34 → pcap_findalldevs()
[#9] 0x4481ef → get_interface_list()
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
gef➤  bt
#0  0x00007ffff69d19a4 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#1  0x00007ffff6e8d046 in ?? () from /usr/lib/x86_64-linux-gnu/libasan.so.2
#2  0x00007ffff6f025d3 in malloc () from /usr/lib/x86_64-linux-gnu/libasan.so.2
#3  0x00007ffff6c36c39 in ?? () from /usr/lib/x86_64-linux-gnu/libpcap.so.0.8
#4  0x00007ffff6c388f0 in pcap_activate () from /usr/lib/x86_64-linux-gnu/libpcap.so.0.8
#5  0x00007ffff6c39508 in ?? () from /usr/lib/x86_64-linux-gnu/libpcap.so.0.8
#6  0x00007ffff6c39acd in ?? () from /usr/lib/x86_64-linux-gnu/libpcap.so.0.8
#7  0x00007ffff6c37745 in ?? () from /usr/lib/x86_64-linux-gnu/libpcap.so.0.8
#8  0x00007ffff6c37d34 in pcap_findalldevs () from /usr/lib/x86_64-linux-gnu/libpcap.so.0.8
#9  0x00000000004481ef in get_interface_list () at interface.c:100
#10 0x0000000000410998 in tcpreplay_init () at tcpreplay_api.c:119
#11 0x000000000040f316 in main (argc=0xe, argv=0x7fffffffe458) at tcpreplay.c:67
gef➤  c
Continuing.
PID: 64914
Warning: Unsupported physical layer type 0x0304 on lo.  Maybe it works, maybe it won't.  See tickets #123/318
Warning: huaf_get_ipv6_next was captured using a snaplen of 255 bytes.  This may mean you have truncated packets.

Breakpoint 3, get_ipv6_next (exthdr=0x611000009b76, len=0xc1) at get.c:454
454	    maxlen = *((int*)((u_char *)exthdr + len));
[ Legend: Modified register | Code | Heap | Stack | String ]
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$rax   : 0x0000611000009b76  →  0xbe1b000000003301
$rbx   : 0x00007fffffffd830  →  0x00007fffffffdbb0  →  0x00000ffffffffb80  →  0x0000000000000000
$rcx   : 0x0               
$rdx   : 0xc1              
$rsp   : 0x00007fffffffd540  →  0x000000c10041f99a  →  0x0000000000000000
$rbp   : 0x00007fffffffd560  →  0x00007fffffffd5a0  →  0x00007fffffffd610  →  0x00007fffffffd650  →  0x00007fffffffd850  →  0x00007fffffffdbd0  →  0x00007fffffffdd90  →  0x00007fffffffddc0
$rsi   : 0xc1              
$rdi   : 0x0000611000009b76  →  0xbe1b000000003301
$rip   : 0x0000000000441277  →  <get_ipv6_next+59> mov eax, DWORD PTR [rbp-0x1c]
$r8    : 0x2f              
$r9    : 0x00001000322fe900  →  0x0000000000000000
$r10   : 0x84              
$r11   : 0x00007ffff6978390  →  <ntohl+0> mov eax, edi
$r12   : 0x00000ffffffffada  →  0x0000000000000000
$r13   : 0x00007fffffffd6d0  →  0x0000000041b58ab3
$r14   : 0x00007fffffffd6d0  →  0x0000000041b58ab3
$r15   : 0x00007fffffffdc00  →  0x0000000041b58ab3
$eflags: [carry parity adjust zero sign trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x0033 $ss: 0x002b $ds: 0x0000 $es: 0x0000 $fs: 0x0000 $gs: 0x0000 
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0x00007fffffffd540│+0x0000: 0x000000c10041f99a  →  0x0000000000000000	 ← $rsp
0x00007fffffffd548│+0x0008: 0x0000611000009b76  →  0xbe1b000000003301
0x00007fffffffd550│+0x0010: 0x00007fff00000000
0x00007fffffffd558│+0x0018: 0x000000000041fea6  →  <csum_replace4+127> mov ecx, eax
0x00007fffffffd560│+0x0020: 0x00007fffffffd5a0  →  0x00007fffffffd610  →  0x00007fffffffd650  →  0x00007fffffffd850  →  0x00007fffffffdbd0  →  0x00007fffffffdd90  →  0x00007fffffffddc0	 ← $rbp
0x00007fffffffd568│+0x0028: 0x0000000000441515  →  <get_ipv6_l4proto+228> mov QWORD PTR [rbp-0x8], rax
0x00007fffffffd570│+0x0030: 0x000000c1ffffd5c0  →  0x0000000000000000
0x00007fffffffd578│+0x0038: 0x0000611000009b4e  →  0x1000322fe9000060 ("`"?)
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:64 ────
     0x441267 <get_ipv6_next+43> add    BYTE PTR [rsi+0x48e7a0], bh
     0x44126d <get_ipv6_next+49> mov    edi, 0x48eb20
     0x441272 <get_ipv6_next+54> call   0x402ee0 <__assert_fail@plt>
 →   0x441277 <get_ipv6_next+59> mov    eax, DWORD PTR [rbp-0x1c]
     0x44127a <get_ipv6_next+62> movsxd rdx, eax
     0x44127d <get_ipv6_next+65> mov    rax, QWORD PTR [rbp-0x18]
     0x441281 <get_ipv6_next+69> lea    rcx, [rdx+rax*1]
     0x441285 <get_ipv6_next+73> mov    rax, rcx
     0x441288 <get_ipv6_next+76> mov    rdx, rax
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── source:get.c+454 ────
    449	     int extlen = 0;
    450	     int maxlen;
    451	     void *ptr;
    452	     assert(exthdr);
    453	 
             // exthdr=0x00007fffffffd548  →  [...]  →  0xbe1b000000003301, len=0xc1, maxlen=0x7fff
 →  454	     maxlen = *((int*)((u_char *)exthdr + len));
    455	 
    456	     dbgx(3, "Jumping to next IPv6 header.  Processing 0x%02x", exthdr->ip_nh);
    457	     switch (exthdr->ip_nh) {
    458	     /* no further processing */
    459	     case TCPR_IPV6_NH_NO_NEXT:
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "tcpreplay-edit", stopped, reason: BREAKPOINT
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x441277 → get_ipv6_next(exthdr=0x611000009b76, len=0xc1)
[#1] 0x441515 → get_ipv6_l4proto(ip6_hdr=0x611000009b4e, len=0xc1)
[#2] 0x4283fa → do_checksum(tcpedit=0x61d00001ea80, data=0x611000009b4e "`", proto=0x0, len=0xe9)
[#3] 0x42033b → fix_ipv4_checksums(tcpedit=0x61d00001ea80, pkthdr=0x7fffffffdaf0, ip_hdr=0x611000009b4e)
[#4] 0x41c8fa → tcpedit_packet(tcpedit=0x61d00001ea80, pkthdr=0x7fffffffd970, pktdata=0x7fffffffd8f0, direction=TCPR_DIR_C2S)
[#5] 0x40963c → send_packets(ctx=0x61e00000f080, pcap=0x61600000f380, idx=0x0)
[#6] 0x418e9b → replay_file(ctx=0x61e00000f080, idx=0x0)
[#7] 0x417e74 → tcpr_replay_index(ctx=0x61e00000f080)
[#8] 0x416de5 → tcpreplay_replay(ctx=0x61e00000f080)
[#9] 0x40fb50 → main(argc=0x1, argv=0x7fffffffe4c0)
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
gef➤  c
Continuing.

Breakpoint 3, get_ipv6_next (exthdr=0x611000009b76, len=0x111) at get.c:454
454	    maxlen = *((int*)((u_char *)exthdr + len));
[ Legend: Modified register | Code | Heap | Stack | String ]
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$rax   : 0x0000611000009b76  →  0xbe1b000000003301
$rbx   : 0x00007fffffffd830  →  0x00007fffffffdbb0  →  0x00000ffffffffb80  →  0x0000000000000000
$rcx   : 0x0000611000009c00  →  0xbebebebebebebebe
$rdx   : 0x111             
$rsp   : 0x00007fffffffd540  →  0x000001110041f99a  →  0x0000000000000000
$rbp   : 0x00007fffffffd560  →  0x00007fffffffd5a0  →  0x00007fffffffd610  →  0x00007fffffffd650  →  0x00007fffffffd850  →  0x00007fffffffdbd0  →  0x00007fffffffdd90  →  0x00007fffffffddc0
$rsi   : 0x111             
$rdi   : 0x0000611000009b76  →  0xbe1b000000003301
$rip   : 0x0000000000441277  →  <get_ipv6_next+59> mov eax, DWORD PTR [rbp-0x1c]
$r8    : 0x2f              
$r9    : 0x00001000322fe900  →  0x0000000000000000
$r10   : 0x84              
$r11   : 0x00007ffff6978390  →  <ntohl+0> mov eax, edi
$r12   : 0x00000ffffffffada  →  0x0000000000000000
$r13   : 0x00007fffffffd6d0  →  0x0000000041b58ab3
$r14   : 0x00007fffffffd6d0  →  0x0000000041b58ab3
$r15   : 0x00007fffffffdc00  →  0x0000000041b58ab3
$eflags: [carry parity adjust zero sign trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x0033 $ss: 0x002b $ds: 0x0000 $es: 0x0000 $fs: 0x0000 $gs: 0x0000 
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0x00007fffffffd540│+0x0000: 0x000001110041f99a  →  0x0000000000000000	 ← $rsp
0x00007fffffffd548│+0x0008: 0x0000611000009b76  →  0xbe1b000000003301
0x00007fffffffd550│+0x0010: 0xbebebebe00000000
0x00007fffffffd558│+0x0018: 0x000000000041fea6  →  <csum_replace4+127> mov ecx, eax
0x00007fffffffd560│+0x0020: 0x00007fffffffd5a0  →  0x00007fffffffd610  →  0x00007fffffffd650  →  0x00007fffffffd850  →  0x00007fffffffdbd0  →  0x00007fffffffdd90  →  0x00007fffffffddc0	 ← $rbp
0x00007fffffffd568│+0x0028: 0x000000000044112c  →  <get_layer4_v6+249> mov QWORD PTR [rbp-0x8], rax
0x00007fffffffd570│+0x0030: 0x000000e9ffffd5c0  →  0x0000000000000000
0x00007fffffffd578│+0x0038: 0x0000611000009b4e  →  0x1000322fe9000060 ("`"?)
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:64 ────
     0x441267 <get_ipv6_next+43> add    BYTE PTR [rsi+0x48e7a0], bh
     0x44126d <get_ipv6_next+49> mov    edi, 0x48eb20
     0x441272 <get_ipv6_next+54> call   0x402ee0 <__assert_fail@plt>
 →   0x441277 <get_ipv6_next+59> mov    eax, DWORD PTR [rbp-0x1c]
     0x44127a <get_ipv6_next+62> movsxd rdx, eax
     0x44127d <get_ipv6_next+65> mov    rax, QWORD PTR [rbp-0x18]
     0x441281 <get_ipv6_next+69> lea    rcx, [rdx+rax*1]
     0x441285 <get_ipv6_next+73> mov    rax, rcx
     0x441288 <get_ipv6_next+76> mov    rdx, rax
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── source:get.c+454 ────
    449	     int extlen = 0;
    450	     int maxlen;
    451	     void *ptr;
    452	     assert(exthdr);
    453	 
             // exthdr=0x00007fffffffd548  →  [...]  →  0xbe1b000000003301, len=0x111, maxlen=-0x41414142
 →  454	     maxlen = *((int*)((u_char *)exthdr + len));
    455	 
    456	     dbgx(3, "Jumping to next IPv6 header.  Processing 0x%02x", exthdr->ip_nh);
    457	     switch (exthdr->ip_nh) {
    458	     /* no further processing */
    459	     case TCPR_IPV6_NH_NO_NEXT:
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "tcpreplay-edit", stopped, reason: BREAKPOINT
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x441277 → get_ipv6_next(exthdr=0x611000009b76, len=0x111)
[#1] 0x44112c → get_layer4_v6(ip6_hdr=0x611000009b4e, len=0xe9)
[#2] 0x428411 → do_checksum(tcpedit=0x61d00001ea80, data=0x611000009b4e "`", proto=0x1, len=0xe9)
[#3] 0x42033b → fix_ipv4_checksums(tcpedit=0x61d00001ea80, pkthdr=0x7fffffffdaf0, ip_hdr=0x611000009b4e)
[#4] 0x41c8fa → tcpedit_packet(tcpedit=0x61d00001ea80, pkthdr=0x7fffffffd970, pktdata=0x7fffffffd8f0, direction=TCPR_DIR_C2S)
[#5] 0x40963c → send_packets(ctx=0x61e00000f080, pcap=0x61600000f380, idx=0x0)
[#6] 0x418e9b → replay_file(ctx=0x61e00000f080, idx=0x0)
[#7] 0x417e74 → tcpr_replay_index(ctx=0x61e00000f080)
[#8] 0x416de5 → tcpreplay_replay(ctx=0x61e00000f080)
[#9] 0x40fb50 → main(argc=0x1, argv=0x7fffffffe4c0)

Possible cause of vulnerability
Firstly, the address 0x611000009c87 is malloced in pcap_findalldevs() at interface.c:100

    if (pcap_findalldevs(&pcap_if, ebuf) < 0)
        errx(-1, "Error: %s", ebuf);

Then the target address is freed in function pcap_freealldevs() at interface.c:196

pcap_freealldevs(pcap_if);

The get_ipv6_next() lacks the check for exthdr + len, resulting in a reference to the memory that has been released.

gefp len
$7 = 0x111
gefp exthdr
$8 = (struct tcpr_ipv6_ext_hdr_base *) 0x611000009b76

System (please complete the following information):

  • OS version : Ubuntu 16.04
  • Tcpreplay Version : 4.3.2/master branch
@fklassen fklassen self-assigned this May 20, 2020
@fklassen fklassen added the bug label May 20, 2020
@fklassen fklassen added this to the 4.3.3 milestone May 20, 2020
@fklassen
Copy link
Member

fklassen commented Jun 1, 2020

Thanks for the detailed bug report.

I am getting a different report, possibly due to #584 fix.

==88578==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x61100000a047 at pc 0x55eae6a18417 bp 0x7fff83b5ee60 sp 0x7fff83b5ee58
READ of size 4 at 0x61100000a047 thread T0
    #0 0x55eae6a18416 in get_ipv6_next /home/fklassen/git/tcpreplay/src/common/get.c:474
    #1 0x55eae6a180d5 in get_layer4_v6 /home/fklassen/git/tcpreplay/src/common/get.c:429
    #2 0x55eae69fae39 in do_checksum /home/fklassen/git/tcpreplay/src/tcpedit/checksum.c:66
    #3 0x55eae69f1a5f in fix_ipv4_checksums /home/fklassen/git/tcpreplay/src/tcpedit/edit_packet.c:82
    #4 0x55eae69edbf0 in tcpedit_packet /home/fklassen/git/tcpreplay/src/tcpedit/tcpedit.c:354
    #5 0x55eae69d86e1 in send_packets /home/fklassen/git/tcpreplay/src/send_packets.c:552
    #6 0x55eae69e9a2a in replay_file /home/fklassen/git/tcpreplay/src/replay.c:182
    #7 0x55eae69e89c4 in tcpr_replay_index /home/fklassen/git/tcpreplay/src/replay.c:59
    #8 0x55eae69e78c5 in tcpreplay_replay /home/fklassen/git/tcpreplay/src/tcpreplay_api.c:1136
    #9 0x55eae69e004c in main /home/fklassen/git/tcpreplay/src/tcpreplay.c:139
    #10 0x7f76fc0b82e0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202e0)
    #11 0x55eae69d06f9 in _start (/home/fklassen/git/tcpreplay/src/tcpreplay-edit+0x2a6f9)

AddressSanitizer can not describe address in more detail (wild memory access suspected).
SUMMARY: AddressSanitizer: heap-buffer-overflow /home/fklassen/git/tcpreplay/src/common/get.c:474 in get_ipv6_next
Shadow bytes around the buggy address:
  0x0c227fff93b0: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
  0x0c227fff93c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c227fff93d0: 00 00 00 00 00 00 00 07 fa fa fa fa fa fa fa fa
  0x0c227fff93e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c227fff93f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 07
=>0x0c227fff9400: fa fa fa fa fa fa fa fa[fa]fa fa fa fa fa fa fa
  0x0c227fff9410: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff9420: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff9430: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff9440: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff9450: fa fa fa fa fa fa fa fa fa fa fa fa fa fa 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
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==88578==ABORTING

Note that I added a --enable-asan configure option to make this type of debugging a little easier.

fklassen added a commit that referenced this issue Jun 1, 2020
fklassen added a commit that referenced this issue Jun 1, 2020
@fklassen
Copy link
Member

fklassen commented Jun 1, 2020

Fixed in PR #587.

Warning in sendpacket.c:sendpacket_open_pf() line 943:
Unsupported physical layer type 0x0304 on lo.  Maybe it works, maybe it won't.  See tickets #123/318
Warning in replay.c:replay_file() line 138:
../tcpreplay-pcaps/huaf_get_ipv6_next was captured using a snaplen of 255 bytes.  This may mean you have truncated packets.

Fatal Error in send_packets.c:send_packets() line 553:
 Error editing packet #1: From edit_packet.c:fix_ipv4_checksums() line 73:
Invalid packet: Expected IPv4 packet: got 6

@fklassen fklassen closed this as completed Jun 1, 2020
fklassen added a commit that referenced this issue Jun 1, 2020
…ndomize_iparp

Bug #578 guard HBO in randomize_xxx functions
fklassen added a commit that referenced this issue Jun 2, 2020
…_checksum

Bug #578 guard HBO in randomize_xxx functions
fklassen added a commit that referenced this issue Jun 2, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants