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

Heap overflow in get_next_packet() #484

Closed
SegfaultMasters opened this issue Sep 24, 2018 · 4 comments
Closed

Heap overflow in get_next_packet() #484

SegfaultMasters opened this issue Sep 24, 2018 · 4 comments
Assignees
Labels

Comments

@SegfaultMasters
Copy link

tcpreplay contains a heap-based buffer overflow vulnerability. The get_next_packet() function in the send_packets.c file uses the memcpy() function to copy sequences from the source buffer pktdata to the destination (*prev_packet)->pktdata. However, there are no checks in place to ensure that dst is a non-zero value. An attacker can exploit this vulnerability by submitting a malicious file that exploits this issue. This will result in a Denial of Service (DoS) and potentially Information Exposure when the application attempts to process the file.

Affected version:

4.3 branch

Command:

sudo tcpreplay -i eno1 -t -K --loop 4 --unique-ip $POC

Debugging

  1044                      (*prev_packet)->pktdata = safe_malloc(pktlen);
                // prev_packet=0xbfffef60 -> [...] -> 0x00000000, pktdata=0xbfffef24 -> [...] -> 0x07290c00
->1045                       memcpy((*prev_packet)->pktdata, pktdata, pktlen);   //Buffer overflow
   1046                      memcpy(&((*prev_packet)->pkthdr), pkthdr, sizeof(struct pcap_pkthdr));
   1047                  }
   1048              }
   1049          }

[#0] 0x8052f3a->Name: get_next_packet(ctx=0xb6403280, pcap=0xb4203280, pkthdr=0xbffff000, idx=0x0, prev_packet=0xbfffefc0)
[#1] 0x804e922->Name: preload_pcap_file(ctx=0xb6403280, idx=0x0)
[#2] 0x805615c->Name: main(argc=0x1, argv=0xbffff724)
gef> info locals
options = 0xb6200200
pktdata = 0xb3514800 ""
pktlen = 0x80003e
__PRETTY_FUNCTION__ = "get_next_packet"
__FUNCTION__ = "get_next_packet"

gef> ptype (*prev_packet)->pktdata
type = unsigned char *
gef> p pktdata
$30 = (u_char *) 0xb3514800 ""


gef> p (*prev_packet)->pktdata
$27 = (u_char *) 0xb2afe800 ""
gef> x (*prev_packet)->pktdata
0xb2afe800:     0

gef> ptype pktlen
type = unsigned int
gef> p/d pktlen
$25 = 8388670
gef> i r
eax            0xb4800320          0xb4800320
ecx            0x3                 0x3
edx            0x0                 0x0
ebx            0xb4800310          0xb4800310
esp            0xbfffef00          0xbfffef00
ebp            0xbfffef48          0xbfffef48
esi            0x0                 0x0
edi            0xb2afe800          0xb2afe800
eip            0x8052f3a           0x8052f3a <get_next_packet+1725>
eflags         0x246               [ PF ZF IF ]
cs             0x73                0x73
ss             0x7b                0x7b
ds             0x7b                0x7b
es             0x7b                0x7b
fs             0x0                 0x0
gs             0x33                0x33

ASAN output

=================================================================
==22604==ERROR: AddressSanitizer: heap-buffer-overflow on address 0xb35247ff at pc 0xb7adba75 bp 0xbfffeec8 sp 0xbfffea9c
READ of size 8388670 at 0xb35247ff thread T0
    #0 0xb7adba74 in __asan_memcpy (/usr/lib/i386-linux-gnu/libasan.so.2+0x8aa74)
    #1 0xb7adbc2f in memcpy (/usr/lib/i386-linux-gnu/libasan.so.2+0x8ac2f)
    #2 0x8052fb6 in get_next_packet /home/loginsoft/ACE/tcpreplay/src/send_packets.c:1045
    #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)
    #6 0x804a7a0  (/usr/local/bin/tcpreplay+0x804a7a0)

0xb35247ff is located 0 bytes to the right of 65535-byte region [0xb3514800,0xb35247ff)
allocated by thread T0 here:
    #0 0xb7ae7dee in malloc (/usr/lib/i386-linux-gnu/libasan.so.2+0x96dee)
    #1 0xb7a28e7c  (/usr/lib/i386-linux-gnu/libpcap.so.0.8+0x1ce7c)

SUMMARY: AddressSanitizer: heap-buffer-overflow ??:0 __asan_memcpy
Shadow bytes around the buggy address:
  0x366a48a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x366a48b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x366a48c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x366a48d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x366a48e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x366a48f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00[07]
  0x366a4900: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x366a4910: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x366a4920: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x366a4930: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x366a4940: 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
==22604==ABORTING
[Inferior 1 (process 22604) exited with code 01]

Valgrind report

==13353== Source and destination overlap in memcpy(0x467d028, 0x4648c50, 8388670)
==13353==    at 0x4030D39: memcpy (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==13353==    by 0x804D24B: ??? (in /usr/local/bin/tcpreplay)
==13353==    by 0x804BCC0: ??? (in /usr/local/bin/tcpreplay)
==13353==    by 0x804E3FA: ??? (in /usr/local/bin/tcpreplay)
==13353==    by 0x40DD636: (below main) (libc-start.c:291)
==13353==
==13353== Invalid read of size 4
==13353==    at 0x4030DD0: memcpy (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==13353==    by 0x804D24B: ??? (in /usr/local/bin/tcpreplay)
==13353==    by 0x804BCC0: ??? (in /usr/local/bin/tcpreplay)
==13353==    by 0x804E3FA: ??? (in /usr/local/bin/tcpreplay)
==13353==    by 0x40DD636: (below main) (libc-start.c:291)
==13353==  Address 0x467d024 is 4 bytes before a block of size 8,388,670 alloc'd
==13353==    at 0x402C17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==13353==    by 0x8053B5B: ??? (in /usr/local/bin/tcpreplay)
==13353==    by 0x804D22E: ??? (in /usr/local/bin/tcpreplay)
==13353==    by 0x804BCC0: ??? (in /usr/local/bin/tcpreplay)
==13353==    by 0x804E3FA: ??? (in /usr/local/bin/tcpreplay)
==13353==    by 0x40DD636: (below main) (libc-start.c:291)
==13353==
==13353== Invalid read of size 4
==13353==    at 0x4030DDE: memcpy (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==13353==    by 0x804D24B: ??? (in /usr/local/bin/tcpreplay)
==13353==    by 0x804BCC0: ??? (in /usr/local/bin/tcpreplay)
==13353==    by 0x804E3FA: ??? (in /usr/local/bin/tcpreplay)
==13353==    by 0x40DD636: (below main) (libc-start.c:291)
==13353==  Address 0x467d020 is 8 bytes before a block of size 8,388,670 alloc'd
==13353==    at 0x402C17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==13353==    by 0x8053B5B: ??? (in /usr/local/bin/tcpreplay)
==13353==    by 0x804D22E: ??? (in /usr/local/bin/tcpreplay)
==13353==    by 0x804BCC0: ??? (in /usr/local/bin/tcpreplay)
==13353==    by 0x804E3FA: ??? (in /usr/local/bin/tcpreplay)
==13353==    by 0x40DD636: (below main) (libc-start.c:291)
==13353==

Please check if you are able to reproduce the issue via the Reproducer file

@fklassen fklassen self-assigned this Sep 24, 2018
@fklassen fklassen added the bug label Sep 24, 2018
@carnil
Copy link

carnil commented Sep 29, 2018

https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-17582 was assigned for this issue

@mkubecek
Copy link

mkubecek commented Oct 3, 2018

I don't think the analysis is correct. This has nothing to do with null destination pointer (safe_malloc() checks return value of malloc() and exits on allocation failure) and most likely not with the destination at all.

IMHO the actual problem here is a buffer overflow on read because of unrealistic value of pktlen (taken from pkthdr->len) which is 8388670 while the data actually present is much shorter (65535). The same problem could probably happen with real life pcap files taken with tcpdump -s option. We should probably check if pkthdr->caplen is shorter than pkthdr->len and either drop the packet with a warning or bail out completely.

After all, it does not make much sense to replay packets if we only have leading parts of them. We might perhaps fill the missing part with zeros or random content but that would mostly result in incorrect checksums.

@fklassen
Copy link
Member

I agree with @mkubecek in that the original analysis is incorrect. There is a check for the condition where dst is non-zero.

That said, there can be additional checks for cases where libpcap returns invalid data. Specifically, need to add checks for packets greater than maximum packet size (65535) and for capture lengths greater than packet length.

By adding checks to all calls to pcap_next(), can fix several potential heap overflows such as #477.

fklassen added a commit that referenced this issue Oct 18, 2018
* Check for packets that are larger than 262144 bytes
* Check for capture lengths that are greater than packet length

Example of a corrupt PCAP file ...

sudo src/tcpreplay -i ens33 --unique-ip -t --loop 4 get_next_paket_01
safe_pcap_next ERROR: Invalid packet length in send_packets.c:get_next_packet() line 1054: 8388670 is greater than maximum 262144
fklassen added a commit that referenced this issue Oct 18, 2018
@fklassen
Copy link
Member

fixed in PR #491

fklassen added a commit that referenced this issue Oct 18, 2018
Also added check for packet size > cap len, although this may
be never be hit since #484
fklassen added a commit that referenced this issue Oct 19, 2018
* Enhancement_#493_codacy_fixes: (26 commits)
  Enhancement #493 - fixes for Codacy identified issues
  Bug #486 Enforce max snaplen rather than doing realloc
  Bug #486 CVE-2018-17974 realloc memory if packet size increases
  Bug #484 CVE-2018-17582 Check for corrupt PCAP files
  4.3 - revert travis updates from merge
  Remove dead code
  resolve possible null pointer dereference
  travis-ci: add autogen package
  Bug #461 build warnings (#462)
  #412 fix gcc 6.3 compiler warning
  #421 fix ms to ns conversion
  Bug #423 remove commented code
  Bug #423 Remove limit for tcpprep -S
  Bug #398 Rewrite of tcpdump.c (#457)
  Bug #402 memset dlt radiotap get 80211 (#454)
  #404 fix check_list return values (#453)
  #406 fix zero-length IP headers
  #416 apply STDIN restore to all programs
  #416 fix compile issue introduced by downstream PR
  #416 update CHANGELOG [ci skip]
  ...
fklassen added a commit that referenced this issue Oct 19, 2018
* Bug #486 CVE-2018-17974 realloc memory if packet size increases

Also added check for packet size > cap len, although this may
be never be hit since #484

* Bug #486 Enforce max snaplen rather than doing realloc

* increase MAX_SNAPLEN from 65535 to 262144
* increase MAXPACKET from 65549 to 262158
* exit on buffer overflow for adding VLAN tag (as opposed to realloc)
fklassen added a commit that referenced this issue Oct 20, 2018
Getting the following error message when attempting to reproduce bug:

tcpreplay -i ens33 --unique-ip -t --loop 4 fast_edit_package_02
safe_pcap_next ERROR: Invalid packet length in send_packets.c:get_next_packet() line 1054: packet length 28 is less than capture length 60
fklassen added a commit that referenced this issue Oct 20, 2018
fklassen added a commit that referenced this issue Oct 23, 2018
* 4.3: (22 commits)
  Bug #418 don't ignore 2nd packet timing
  Bug #411 allow TAP on all platforms
  Bug #174 ensure --with-testnic does not affect replay
  Bug #406 change packet length to network order
  Bug #413 fix manpage typos
  Bug #485 Heap overflow fixed in #484
  Enhancement_#482 update CHANGELOG/CREDITS
  Enhancement_#482 test Makefile merge error fixup
  Enhancement_#482 test Makefile cleanup
  Bug #489 free after memcpy
  Bug #488 heap overflow csum replace4 (#496)
  Bug #486 CVE-2018-17974 realloc memory if packet size increases (#492)
  Enhancement #493 - fixes for Codacy identified issues
  Bug #486 Enforce max snaplen rather than doing realloc
  Bug #486 CVE-2018-17974 realloc memory if packet size increases
  Bug #484 CVE-2018-17582 Check for corrupt PCAP files
  4.3 - revert travis updates from merge
  Simplify plugin Makefiles
  allow out-of-tree build
  Remove dead code
  ...
fklassen added a commit that referenced this issue Oct 23, 2018
…ging

* 4.3: (36 commits)
  Enhancement #506 disable C99 and fix warnings (#507)
  Bug #418 don't ignore 2nd packet timing
  Bug #411 allow TAP on all platforms
  Bug #174 ensure --with-testnic does not affect replay
  Bug #406 change packet length to network order
  Bug #413 fix manpage typos
  Bug #485 Heap overflow fixed in #484
  Enhancement_#482 update CHANGELOG/CREDITS
  Enhancement_#482 test Makefile merge error fixup
  Enhancement_#482 test Makefile cleanup
  Bug #489 free after memcpy
  Bug #488 heap overflow csum replace4 (#496)
  Bug #486 CVE-2018-17974 realloc memory if packet size increases (#492)
  Enhancement #493 - fixes for Codacy identified issues
  Bug #486 Enforce max snaplen rather than doing realloc
  Bug #486 CVE-2018-17974 realloc memory if packet size increases
  Bug #484 CVE-2018-17582 Check for corrupt PCAP files
  4.3 - revert travis updates from merge
  Simplify plugin Makefiles
  allow out-of-tree build
  ...
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

4 participants