bbc / audiowaveform

C++ program to generate waveform data and render waveform images from audio files
https://waveform.prototyping.bbc.co.uk
GNU General Public License v3.0
1.94k stars 242 forks source link

Crash when parsing malformed DAT and FLAC files #159

Closed retpoline closed 2 years ago

retpoline commented 2 years ago

Hi team,

Some crashes were found while fuzz testing of the audiowaveform binary which can be triggered via malformed DAT and FLAC files. Although these malformed files only crash the program, they could potentially be crafted further into security issues where these kinds of files would be able compromise the process's memory through memory corruption, so hardening the code to prevent these kinds of bugs would be great to mitigate such issues.

See details below for repro and debug information.

crash.dat

$ echo -ne "\x01\x00\x00\x00\x01\x00\x00\x00\x80\x3e\x00\x00\x00\x00\x00\x00\xff\xf8\xfe\xf8\x00\x00" > crash.dat

debug info

$ audiowaveform -i crash.dat -o test.dat
Input file: crash.dat
Expected 4177459455 points, read 1 min and max points
Rescaling to 256 samples/pixel
Input scale: 0 samples/pixel
Output scale: 256 samples/pixel
Input buffer size: 1
Floating point exception (core dumped)

(gdb) r -i crash.dat -o test.dat
Starting program: audiowaveform -i crash.dat -o test.dat
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Input file: crash.dat
Expected 4177459455 points, read 1 min and max points
Rescaling to 256 samples/pixel
Input scale: 0 samples/pixel
Output scale: 256 samples/pixel
Input buffer size: 1

Program received signal SIGFPE, Arithmetic exception.
0x00005555555aa727 in WaveformRescaler::rescale(WaveformBuffer const&, WaveformBuffer&, int) ()
(gdb) bt
#0  0x00005555555aa727 in WaveformRescaler::rescale(WaveformBuffer const&, WaveformBuffer&, int) ()
#1  0x00005555555a2dda in OptionHandler::resampleWaveformData(boost::filesystem::path const&, boost::filesystem::path const&, Options const&) ()
#2  0x00005555555a4469 in OptionHandler::run(Options const&) ()
#3  0x000055555557e171 in main ()

(gdb) i r
rax            0x0                 0
rbx            0x1                 1
rcx            0x0                 0
rdx            0x0                 0
rsi            0x0                 0
rdi            0x100               256
rbp            0x5555555d5b20      0x5555555d5b20
rsp            0x7fffffffdee0      0x7fffffffdee0
r8             0x0                 0
r9             0x0                 0
r10            0x1                 1
r11            0x246               582
r12            0x5555555d5bb0      93824992762800
r13            0x7fffffffdfb0      140737488347056
r14            0x2                 2
r15            0x0                 0
rip            0x5555555aa727      0x5555555aa727 <WaveformRescaler::rescale(WaveformBuffer const&, WaveformBuffer&, int)+999>
eflags         0x10206             [ PF IF RF ]
cs             0x33                51
ss             0x2b                43
ds             0x0                 0
es             0x0                 0
fs             0x0                 0
gs             0x0                 0

(gdb) exploitable
Description: Floating point exception signal
Short description: FloatingPointException (17/22)
Hash: 797108cc254815d70719fb2c23617fa2.797108cc254815d70719fb2c23617fa2
Exploitability Classification: PROBABLY_NOT_EXPLOITABLE
Explanation: The target crashed on a floating point exception. This may indicate a division by zero or a number of other floating point errors. It is generally difficult to leverage these types of errors to gain control of the processor.

crash.flac

You can download the crashing flac file (~8kb file size) from Ufile to to debug and understand where the code is crashing.

debug info

(requires electric fence memory debugger: apt-get install -y electric-fence)

$ audiowaveform -i crash.flac -o test.dat
Failed to read file: crash.flac
File contains data in an unimplemented format.

$ LD_PRELOAD=/usr/lib/libefence.so audiowaveform -i crash.flac -o test.dat

  Electric Fence 2.2 Copyright (C) 1987-1999 Bruce Perens <bruce@perens.com>

ElectricFence Exiting: mmap() failed: Segmentation fault (core dumped)

$ gdb -q audiowaveform
Reading symbols from audiowaveform...
(No debugging symbols found in audiowaveform)
(gdb) set environment LD_PRELOAD=/usr/lib/libefence.so
(gdb) r -i crash-2.flac -o test.dat
Starting program: audiowaveform -i crash.flac -o test.dat

  Electric Fence 2.2 Copyright (C) 1987-1999 Bruce Perens <bruce@perens.com>

ElectricFence Exiting: mmap() failed: 
Program received signal SIGSEGV, Segmentation fault.
__strlen_avx2 () at ../sysdeps/x86_64/multiarch/strlen-avx2.S:65

(gdb) bt
#0  __strlen_avx2 () at ../sysdeps/x86_64/multiarch/strlen-avx2.S:65
#1  0x00007ffff7dc462f in EF_Printv () from /usr/lib/libefence.so
#2  0x00007ffff7dc4845 in EF_Exitv () from /usr/lib/libefence.so
#3  0x00007ffff7dc48f9 in EF_Exit () from /usr/lib/libefence.so
#4  0x00007ffff7dc4226 in Page_Create () from /usr/lib/libefence.so
#5  0x00007ffff7dc380c in ?? () from /usr/lib/libefence.so
#6  0x00007ffff7dc3e7e in memalign () from /usr/lib/libefence.so
#7  0x00007ffff7695d11 in ?? () from /lib/x86_64-linux-gnu/libFLAC.so.8
#8  0x00007ffff7697160 in FLAC__stream_decoder_process_until_end_of_metadata () from /lib/x86_64-linux-gnu/libFLAC.so.8
#9  0x00007ffff7d301d3 in ?? () from /lib/x86_64-linux-gnu/libsndfile.so.1
#10 0x00007ffff7d268c8 in ?? () from /lib/x86_64-linux-gnu/libsndfile.so.1
#11 0x00005555555a5a73 in SndFileAudioFileReader::open(char const*, bool) ()
#12 0x00005555555a33b6 in OptionHandler::generateWaveformData(boost::filesystem::path const&, FileFormat::FileFormat, boost::filesystem::path const&, FileFormat::FileFormat, Options const&) ()
#13 0x00005555555a472b in OptionHandler::run(Options const&) ()
#14 0x000055555557e171 in main ()

(gdb) i r
rax            0x7fffffffdb68      140737488345960
rbx            0x0                 0
rcx            0x0                 0
rdx            0x0                 0
rsi            0x73                115
rdi            0x0                 0
rbp            0x7fffffffdad6      0x7fffffffdad6
rsp            0x7fffffffdac8      0x7fffffffdac8
r8             0x7ffff78c1660      140737346541152
r9             0x0                 0
r10            0x7ffff7dc2a50      140737351789136
r11            0x7ffff785f660      140737346139744
r12            0x7fffffffdad7      140737488345815
r13            0x7ffff7dc4c60      140737351797856
r14            0x7fffffffdb40      140737488345920
r15            0x7ffff7dc4bc0      140737351797696
rip            0x7ffff785f675      0x7ffff785f675 <__strlen_avx2+21>
eflags         0x10283             [ CF SF IF RF ]
cs             0x33                51
ss             0x2b                43
ds             0x0                 0
es             0x0                 0
fs             0x0                 0
gs             0x0                 0

(gdb) x/i $rip
=> 0x7ffff785f675 <__strlen_avx2+21>:   vpcmpeqb (%rdi),%ymm0,%ymm1

(gdb) exploitable
Description: Access violation
Short description: AccessViolation (21/22)
Hash: c462e0259d99ca6f6f03acfb38e184b9.c07ac7fda1cb9418c6081bdbfb00c52a
Exploitability Classification: UNKNOWN
Explanation: The target crashed due to an access violation but there is not enough additional information available to determine exploitability.
wincentbalin commented 2 years ago

Does the second crash happen in audiowaveform or rather in the library libsndfile?

chrisn commented 2 years ago

Thank you for testing this! I have just pushed a fix for the first crash. The second one does indeed comes from libsndfile.

retpoline commented 2 years ago

Great, thanks for the quick fix!

And yes, a bug has been filed for libsndfile to look into the flac file crash.

chrisn commented 2 years ago

Thanks again. I'll close this as there's nothing more I can do in audiowaveform.