WavPack 5.1.0 CVE-2018-10540 – DOS-Code Execution

Authors:thuanpv             Risk:High

CVE:CVE-2018-10540         0day:Code Execution

0day -id:0DAY-176122        Date:2018-04-30

Description

An issue was discovered in WavPack 5.1.0 and earlier for W64 input. Out-of-bounds writes can occur because ParseWave64HeaderConfig in wave64.c does not validate the sizes of unknown chunks before attempting memory allocation, related to a lack of integer-overflow protection within a bytes_to_copy calculation and subsequent malloc call, leading to insufficient memory allocation.

Analysis

This bug was found with AFLSmart, an extension of AFL. Thanks also to Marcel Böhme, Andrew Santosa and Alexandru Razvan Caciulescu. This could lead to denial of service and potentially code execution.

This bug was found on Ubuntu 16.04 64-bit & WavPack revision 0a7295 (HEAD)

To reproduce:
Download & extract the attached file – wavpack_crash5.wav
wavpack -y wavpack_crash5.wav

Error message:

WAVPACK Hybrid Lossless Audio Compressor Linux Version 5.1.0
 Copyright (c) 1998 - 2017 David Bryant. All Rights Reserved.

creating wavpack_crash5.wv,Segmentation fault
Valgrind says
creating wavpack_crash5.wv,==169803== Argument 'size' of function malloc has a fishy (possibly negative) value: -359324770
==169803==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==169803==    by 0x44AC47: ParseRiffHeaderConfig (riff.c:289)
==169803==    by 0x430762: pack_file (wavpack.c:1776)
==169803==    by 0x407442: main (wavpack.c:1272)
==169803== 
==169803== Invalid write of size 1
==169803==    at 0x4C3507C: __GI_mempcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==169803==    by 0x51BC03D: _IO_file_xsgetn (fileops.c:1392)
==169803==    by 0x51B1235: fread (iofread.c:38)
==169803==    by 0x462496: fread (stdio2.h:295)
==169803==    by 0x462496: DoReadFile (utils.c:618)
==169803==    by 0x44ACE2: ParseRiffHeaderConfig (riff.c:296)
==169803==    by 0x430762: pack_file (wavpack.c:1776)
==169803==    by 0x407442: main (wavpack.c:1272)
==169803==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==169803== 
==169803== 
==169803== Process terminating with default action of signal 11 (SIGSEGV)
==169803==  Access not within mapped region at address 0x0
==169803==    at 0x4C3507C: __GI_mempcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==169803==    by 0x51BC03D: _IO_file_xsgetn (fileops.c:1392)
==169803==    by 0x51B1235: fread (iofread.c:38)
==169803==    by 0x462496: fread (stdio2.h:295)
==169803==    by 0x462496: DoReadFile (utils.c:618)
==169803==    by 0x44ACE2: ParseRiffHeaderConfig (riff.c:296)
==169803==    by 0x430762: pack_file (wavpack.c:1776)
==169803==    by 0x407442: main (wavpack.c:1272)
==169803==  If you believe this happened as a result of a stack
==169803==  overflow in your program's main thread (unlikely but
==169803==  possible), you can try to increase the size of the
==169803==  main thread stack using the --main-stacksize= flag.
==169803==  The main thread stack size used in this run was 8388608.
ASAN says
creating wavpack_crash5.wv,common_utils.c:626:104: runtime error: left shift of 234 by 24 places cannot be represented in type 'int'
==169891==WARNING: AddressSanitizer failed to allocate 0xffffffffea95239e bytes
==169891==AddressSanitizer's allocator is terminating the process instead of returning 0
==169891==If you don't like this behavior set allocator_may_return_null=1
==169891==AddressSanitizer CHECK failed: ../../../../src/libsanitizer/sanitizer_common/sanitizer_allocator.cc:145 "((0)) != (0)" (0x0, 0x0)
    #0 0x7f64437698ba  (/usr/lib/x86_64-linux-gnu/libasan.so.3+0xd08ba)
    #1 0x7f6443770283 in __sanitizer::CheckFailed(char const*, int, char const*, unsigned long long, unsigned long long) (/usr/lib/x86_64-linux-gnu/libasan.so.3+0xd7283)
    #2 0x7f644376e446  (/usr/lib/x86_64-linux-gnu/libasan.so.3+0xd5446)
    #3 0x7f64436be3b4  (/usr/lib/x86_64-linux-gnu/libasan.so.3+0x253b4)
    #4 0x7f644375ff34 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.3+0xc6f34)
    #5 0x41dcd8 in ParseRiffHeaderConfig /home/thuan/subjects/WavPack-asan/cli/riff.c:289
    #6 0x40cf26 in pack_file /home/thuan/subjects/WavPack-asan/cli/wavpack.c:1776
    #7 0x40a80b in main /home/thuan/subjects/WavPack-asan/cli/wavpack.c:1272
    #8 0x7f64422c782f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #9 0x402528 in _start (/home/thuan/subjects/WavPack-asan/cli/wavpack+0x402528)

patch

diff --git a/cli/riff.c b/cli/riff.c
index de98c1e..27ec298 100644
--- a/cli/riff.c
+++ b/cli/riff.c
@@ -286,6 +286,10 @@ int ParseRiffHeaderConfig (FILE *infile, char *infilename, char *fourcc, Wavpack
         else {          // just copy unknown chunks to output file
 
             int bytes_to_copy = (chunk_header.ckSize + 1) & ~1L;
+            if (bytes_to_copy < 0) {
+                error_line("%s has an unknown chunk that is too large for WavPack!", infilename);
+                return WAVPACK_SOFT_ERROR;
+            }
             char *buff = malloc (bytes_to_copy);
 
             if (debug_logging_mode)

Leave a Reply