There is a Use-After-Free vulnerability triggered by supplying a malformed AIFF file to SoX, using the command
./sox -D -V -V %file% /dev/null
The hexdump of the crash-case is:
0000000 4f46 4d52 0200 1168 4941 4646 4f43 544d
0000010 0000 1200 0100 8000 0000 0000 0000 0201
0000020 1268 4941 4646 4f43 544d 0000 1201 0000
0000030 0100 0000 6a00 2e65 7338 7876 0000 0100
0000040 0000 0000 4e41 4f4e 0000 1d00 7541 6964
0000050 6974 6e6f 3420 0000 8000 0000 6974 6e6f
0000060 3420 0000 8000 0000 0000 0000 4f42 5944
0000070 00fe b072 ffff 0001 0000 0000 0000 0000
0000080 0000 0000 0000 0000 0000 4100 4e4e 004f
0000090 0000 411d 6f69 206e 0034 0000 0080 0000
00000a0 0000 4200 444f fe59 7200 ffb0 01ff 0000
00000b0 4e00 4d41 0045 0000 6d14 6e65 6173 656a
00000c0 382e 7673 0078 0000 0001 0000 4100 4e4e
00000d0 004f 0000 411d 6475 7469 6f69 206e 0022
00000e0 0000 0080 0000 0000 4200 444f fe59 7200
00000f0 ffb0 01ff 0000 0000 0000 0000 0000 0000
0000100 0000 0000 0000 0000 4e41 4f4e 0000 1d00
0000110 6941 6e6f 3420 0000 8000 0000 0000 0000
0000120 4f42 5944 00fe b072 ffff 0001 0000 0000
0000130 0000 0000 0000 0000 4f42 5944 00fe b072
0000140 ffff 0001 0000 0000 0000 0000 0000 0000
0000150 0000 0000 0000 4100 4e4e 004f 0000 411d
0000160 6f69 206e 0034 0000 0080 0000 0000 4200
0000170 444f fe59 7200 ffb0 01ff 0000 4e00 4d41
0000180 0045 0000 6d14 6e65 6173 656a 382e 7673
0000190 0078 0000 0001 0000 4100 4e4e 004f 0000
00001a0 0002 6475 7469 6f69 206e 0022 0000 0080
00001b0 0000 0000 4200 444f fe59 7200 ffb0 01ff
00001c0 0000 0000 0000 0000 0000 0000 0000 0000
00001d0 0000 0000 4e41 4f4e 0000 1d00 6941 6e6f
00001e0 3420 0000 8000 0000 0000 0000 4f42 5944
00001f0 00fe b072 ffff 0001 0000 0000 0000 0000
0000200 0000 0000 0000 0000 0000 0000 820b 3f0c
0000210
The relevant Memcheck output after feeding in the malformed file is:
./sox -D crashes/sox00\:000009 /dev/null
==7433== Memcheck, a memory error detector
==7433== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==7433== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==7433== Command: ./sox -D crash00 /dev/null
==7433==
==7433== Invalid read of size 1
==7433== at 0x5688CD0: __strchr_sse2 (strchr.S:24)
==7433== by 0x4154F4: sox_append_comments (formats.c:236)
==7433== by 0x4AA082: lsx_aiffstartread (aiff.c:279)
==7433== by 0x416A9D: open_read (formats.c:545)
==7433== by 0x415E22: sox_open_read (formats.c:585)
==7433== by 0x404822: main (sox.c:2945)
==7433== Address 0x59c40b0 is 0 bytes inside a block of size 1 free'd
==7433== at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7433== by 0x4AA0AD: lsx_aiffstartread (aiff.c:280)
==7433== by 0x416A9D: open_read (formats.c:545)
==7433== by 0x415E22: sox_open_read (formats.c:585)
==7433== by 0x404822: main (sox.c:2945)
==7433== Block was alloc'd at
==7433== at 0x4C2FA3F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7433== by 0x4C31D84: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7433== by 0x4224A2: lsx_realloc (xmalloc.c:37)
==7433== by 0x4A9B4F: commentChunk (aiff.c:526)
==7433== by 0x4A9B4F: lsx_aiffstartread (aiff.c:273)
==7433== by 0x416A9D: open_read (formats.c:545)
==7433== by 0x415E22: sox_open_read (formats.c:585)
==7433== by 0x404822: main (sox.c:2945)
==7433==
==7433== Invalid read of size 1
==7433== at 0x4155CD: sox_append_comments (formats.c:245)
==7433== by 0x4AA082: lsx_aiffstartread (aiff.c:279)
==7433== by 0x416A9D: open_read (formats.c:545)
==7433== by 0x415E22: sox_open_read (formats.c:585)
==7433== by 0x404822: main (sox.c:2945)
==7433== Address 0x59c40b0 is 0 bytes inside a block of size 1 free'd
==7433== at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7433== by 0x4AA0AD: lsx_aiffstartread (aiff.c:280)
==7433== by 0x416A9D: open_read (formats.c:545)
==7433== by 0x415E22: sox_open_read (formats.c:585)
==7433== by 0x404822: main (sox.c:2945)
==7433== Block was alloc'd at
==7433== at 0x4C2FA3F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7433== by 0x4C31D84: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7433== by 0x4224A2: lsx_realloc (xmalloc.c:37)
==7433== by 0x4A9B4F: commentChunk (aiff.c:526)
==7433== by 0x4A9B4F: lsx_aiffstartread (aiff.c:273)
==7433== by 0x416A9D: open_read (formats.c:545)
==7433== by 0x415E22: sox_open_read (formats.c:585)
==7433== by 0x404822: main (sox.c:2945)
==7433==
==7433== Invalid free() / delete / delete[] / realloc()
==7433== at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7433== by 0x4AA0AD: lsx_aiffstartread (aiff.c:280)
==7433== by 0x416A9D: open_read (formats.c:545)
==7433== by 0x415E22: sox_open_read (formats.c:585)
==7433== by 0x404822: main (sox.c:2945)
==7433== Address 0x59c40b0 is 0 bytes inside a block of size 1 free'd
==7433== at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7433== by 0x4AA0AD: lsx_aiffstartread (aiff.c:280)
==7433== by 0x416A9D: open_read (formats.c:545)
==7433== by 0x415E22: sox_open_read (formats.c:585)
==7433== by 0x404822: main (sox.c:2945)
==7433== Block was alloc'd at
==7433== at 0x4C2FA3F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7433== by 0x4C31D84: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7433== by 0x4224A2: lsx_realloc (xmalloc.c:37)
==7433== by 0x4A9B4F: commentChunk (aiff.c:526)
==7433== by 0x4A9B4F: lsx_aiffstartread (aiff.c:273)
==7433== by 0x416A9D: open_read (formats.c:545)
==7433== by 0x415E22: sox_open_read (formats.c:585)
==7433== by 0x404822: main (sox.c:2945)
==7433==
./sox FAIL formats: can't open input file `crash00': AIFF: no sound data on input file
==7433==
==7433== HEAP SUMMARY:
==7433== in use at exit: 4,429 bytes in 7 blocks
==7433== total heap usage: 31 allocs, 25 frees, 10,730 bytes allocated
==7433==
==7433== LEAK SUMMARY:
==7433== definitely lost: 16 bytes in 1 blocks
==7433== indirectly lost: 7 bytes in 1 blocks
==7433== possibly lost: 0 bytes in 0 blocks
==7433== still reachable: 4,406 bytes in 5 blocks
previously allocated by thread T0 here:
~~~
#0 0x4cc9f5 in realloc (/home/ksg/testbench/sox-14.4.2/src/sox+0x4cc9f5)
#1 0x5369b0 in lsx_realloc /home/ksg/testbench/sox-14.4.2/src/xmalloc.c:37:14
#2 0x523459 in open_read /home/ksg/testbench/sox-14.4.2/src/formats.c:545:32
#3 0x506dcd in main /home/ksg/testbench/sox-14.4.2/src/sox.c:2945:20
#4 0x7f1d2296d1c0 in __libc_start_main /build/glibc-CxtIbX/glibc-2.26/csu/../csu/libc-start.c:308
freed by thread T0 here:
~~~
#0 0x4cc418 in __interceptor_free.localalias.0 (/home/ksg/testbench/sox-14.4.2/src/sox+0x4cc418)
#1 0x636fb4 in lsx_aiffstartread /home/ksg/testbench/sox-14.4.2/src/aiff.c:280:7
#2 0x523459 in open_read /home/ksg/testbench/sox-14.4.2/src/formats.c:545:32
#3 0x506dcd in main /home/ksg/testbench/sox-14.4.2/src/sox.c:2945:20
#4 0x7f1d2296d1c0 in __libc_start_main /build/glibc-CxtIbX/glibc-2.26/csu/../csu/libc-start.c:308
READ of size 2 at 0x60200000ee90 thread T0
#0 0x469adf in printf_common(void*, char const*, __va_list_tag*) (/home/ksg/testbench/sox-14.4.2/src/sox+0x469adf)
#1 0x469921 in printf_common(void*, char const*, __va_list_tag*) (/home/ksg/testbench/sox-14.4.2/src/sox+0x469921)
#2 0x46a6eb in __interceptor_vfprintf (/home/ksg/testbench/sox-14.4.2/src/sox+0x46a6eb)
#3 0x50fd56 in output_message /home/ksg/testbench/sox-14.4.2/src/sox.c:2841:5
#4 0x53c036 in lsx_debug_impl /home/ksg/testbench/sox-14.4.2/src/libsox.c:209:1
#5 0x636dcc in commentChunk /home/ksg/testbench/sox-14.4.2/src/aiff.c:545:3
#6 0x636dcc in lsx_aiffstartread /home/ksg/testbench/sox-14.4.2/src/aiff.c:273
#7 0x523459 in open_read /home/ksg/testbench/sox-14.4.2/src/formats.c:545:32
#8 0x506dcd in main /home/ksg/testbench/sox-14.4.2/src/sox.c:2945:20
#9 0x7f1d2296d1c0 in __libc_start_main /build/glibc-CxtIbX/glibc-2.26/csu/../csu/libc-start.c:308
#10 0x41d009 in _start (/home/ksg/testbench/sox-14.4.2/src/sox+0x41d009)
heap-use-after-free (/home/ksg/testbench/sox-14.4.2/src/sox+0x469adf) in printf_common(void, char const, __va_list_tag*)
Shadow bytes around the buggy address:
0x0c047fff9d80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff9d90: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff9da0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff9db0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff9dc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c047fff9dd0: fa fa[fd]fa fa fa 05 fa fa fa fd fa fa fa 00 00
0x0c047fff9de0: fa fa 00 02 fa fa fd fd fa fa fd fd fa fa fd fa
0x0c047fff9df0: fa fa fd fd fa fa fd fa fa fa fd fd fa fa fd fd
0x0c047fff9e00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff9e10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff9e20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Prior to Segfaulting, the program gives the following output in Verbose mode:
./sox: SoX v
time: Oct 17 2017 09:39:41
uname: Linux ksg 4.13.0-16-generic #19-Ubuntu SMP Wed Oct 11 18:35:14 UTC 2017 x86_64
compiler: gcc 4.2.1 Compatible Clang 3.9.1 (tags/RELEASE_391/rc2)
arch: 1288 48 88 L
./sox INFO formats: detected file format type `aiff'
./sox DBUG aiff: Comment: ""
./sox DBUG aiff: =================================================================
comment is not initialized when an empty comment loop is encountered. attached patch fixes it.