matio icon indicating copy to clipboard operation
matio copied to clipboard

Heap-based Buffer Overflow in strdup_vprintf

Open sae-as-me opened this issue 9 months ago • 2 comments

Hi, this is an issue found by fuzzing the current master branch.

Affected Projects

matio v1.5.28 (https://github.com/tbeu/matio)

Problem Type

CWE-122: Heap-based Buffer Overflow

Description

Summary

A heap-buffer-overflow vulnerability was discovered in the strdup_vprintf function defined in src/io.c at line 67. This issue occurs when processing certain files, leading to an out-of-bounds read and potential application crash.

PoC

Steps to reproduce: (According to OSS-Fuzz)

  1. Build it using the following commands :
git clone --depth 1 https://github.com/madler/zlib
git clone --depth 1 https://github.com/tbeu/matio.git matio
git clone --depth 1 --branch hdf5_1_14 https://github.com/HDFGroup/hdf5.git hdf5
cd matio/

#some env
export CC='clang'
export CFLAGS='-fsanitize=address,fuzzer-no-link -O1 -g'
export CXXFLAGS='-fsanitize=address,fuzzer -O1 -g'
export CXX='clang++'
export WORK=/fuzz/work
export SRC=/fuzz/project
export OUT=/fuzz/fuzzers

pushd "$SRC/zlib"
./configure --static --prefix="$WORK"
make -j$(nproc) CFLAGS="$CFLAGS -fPIC"
make install
popd

wget http://ftp.gnu.org/gnu/autoconf/autoconf-2.71.tar.gz
tar xvfvz autoconf-2.71.tar.gz
pushd autoconf-2.71
./configure
make
make install
popd

#build hdf5
pushd "$SRC"
cd hdf5
./autogen.sh
./configure --disable-shared --disable-deprecated-symbols --disable-hl --disable-parallel --disable-trace --disable-internal-debug --disable-asserts --disable-tests --disable-tools --with-pic --with-zlib="$WORK" --prefix="$WORK"
make -j$(nproc)
make install
popd

# build matio
./autogen.sh
./configure --prefix="$WORK" --disable-shared --with-hdf5="$WORK" --with-zlib="$WORK"
make -j$(nproc)
make install

MATIO_INCLUDE="$WORK/include"
MATIO_LIBS_NO_FUZZ="$WORK/lib/libmatio.a $WORK/lib/libhdf5.a $WORK/lib/libz.a"
MATIO_LIBS="$LIB_FUZZING_ENGINE $MATIO_LIBS_NO_FUZZ"
  1. Compile the fuzzer:
cd ./ossfuzz
for fuzzers in $(find . -name '*_fuzzer.cpp'); do
  base=$(basename -s .cpp $fuzzers)
  $CXX $CXXFLAGS -std=c++11 -I$MATIO_INCLUDE $fuzzers -o $OUT/$base $MATIO_LIBS
done
  1. Run the fuzzer to trigger the segmentation fault:

src_io.zip

./matio_fuzzer src_io.c_67_12

The invalid read access will cause AddressSanitizer to report a segmentation fault during the execution of the post-processing logic.

Report

=================================================================
==24885==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x611000001288 at pc 0x5ae75248ea7d bp 0x7ffc84447540 sp 0x7ffc84446cc8
READ of size 149 at 0x611000001288 thread T0
    #0 0x5ae75248ea7c in printf_common(void*, char const*, __va_list_tag*) asan_interceptors.cpp.o
    #1 0x5ae75252e555 in strdup_vprintf /fuzz/project/matio/src/io.c:67:12
    #2 0x5ae75252e555 in mat_log /fuzz/project/matio/src/io.c:183:14
    #3 0x5ae75252e555 in Mat_Critical /fuzz/project/matio/src/io.c:381:5
    #4 0x5ae7525f5031 in InflateData /fuzz/project/matio/src/inflate.c:369:9
    #5 0x5ae7525fa5c5 in ReadCompressedDoubleDataDouble /fuzz/project/matio/src/./read_data_impl.h:343:5
    #6 0x5ae7525fa5c5 in ReadCompressedDoubleData /fuzz/project/matio/src/./read_data_impl.h:542:13
    #7 0x5ae752556600 in Mat_VarRead5 /fuzz/project/matio/src/mat5.c:3849:38
    #8 0x5ae7525e1285 in ReadNextStructField /fuzz/project/matio/src/mat5.c:1692:45
    #9 0x5ae7525e0f42 in ReadNextStructField /fuzz/project/matio/src/mat5.c:1686:46
    #10 0x5ae7525dd0d4 in Mat_VarReadNextInfo5 /fuzz/project/matio/src/mat5.c:5413:27
    #11 0x5ae7525326fe in Mat_VarReadNextInfoPredicate /fuzz/project/matio/src/mat.c:2651:22
    #12 0x5ae7525326fe in Mat_VarReadNextInfo /fuzz/project/matio/src/mat.c:2625:12
    #13 0x5ae7525326fe in Mat_GetDir /fuzz/project/matio/src/mat.c:827:26
    #14 0x5ae75252d138 in MatioRead(char const*) /fuzz/project/matio/ossfuzz/./matio_wrap.h:39:24
    #15 0x5ae75252d45d in LLVMFuzzerTestOneInput /fuzz/project/matio/ossfuzz/./matio_fuzzer.cpp:30:12
    #16 0x5ae7524535f3 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/fuzz/cs/matio_fuzzer+0x4665f3) (BuildId: 69d0eac2c142cb2dc762c58d0e01e47ee83df8a8)
    #17 0x5ae75243d36f in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) (/fuzz/cs/matio_fuzzer+0x45036f) (BuildId: 69d0eac2c142cb2dc762c58d0e01e47ee83df8a8)
    #18 0x5ae7524430c6 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/fuzz/cs/matio_fuzzer+0x4560c6) (BuildId: 69d0eac2c142cb2dc762c58d0e01e47ee83df8a8)
    #19 0x5ae75246cee2 in main (/fuzz/cs/matio_fuzzer+0x47fee2) (BuildId: 69d0eac2c142cb2dc762c58d0e01e47ee83df8a8)
    #20 0x77303640bd8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    #21 0x77303640be3f in __libc_start_main csu/../csu/libc-start.c:392:3
    #22 0x5ae752437c34 in _start (/fuzz/cs/matio_fuzzer+0x44ac34) (BuildId: 69d0eac2c142cb2dc762c58d0e01e47ee83df8a8)

0x611000001288 is located 0 bytes to the right of 200-byte region [0x6110000011c0,0x611000001288)
allocated by thread T0 here:
    #0 0x5ae7524efc6e in malloc (/fuzz/cs/matio_fuzzer+0x502c6e) (BuildId: 69d0eac2c142cb2dc762c58d0e01e47ee83df8a8)
    #1 0x5ae752554f16 in Mat_VarRead5 /fuzz/project/matio/src/mat5.c:3778:36
    #2 0x5ae7525e1285 in ReadNextStructField /fuzz/project/matio/src/mat5.c:1692:45
    #3 0x5ae7525e0f42 in ReadNextStructField /fuzz/project/matio/src/mat5.c:1686:46
    #4 0x5ae7525dd0d4 in Mat_VarReadNextInfo5 /fuzz/project/matio/src/mat5.c:5413:27
    #5 0x5ae7525326fe in Mat_VarReadNextInfoPredicate /fuzz/project/matio/src/mat.c:2651:22
    #6 0x5ae7525326fe in Mat_VarReadNextInfo /fuzz/project/matio/src/mat.c:2625:12
    #7 0x5ae7525326fe in Mat_GetDir /fuzz/project/matio/src/mat.c:827:26
    #8 0x5ae75252d138 in MatioRead(char const*) /fuzz/project/matio/ossfuzz/./matio_wrap.h:39:24
    #9 0x5ae75252d45d in LLVMFuzzerTestOneInput /fuzz/project/matio/ossfuzz/./matio_fuzzer.cpp:30:12
    #10 0x5ae7524535f3 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/fuzz/cs/matio_fuzzer+0x4665f3) (BuildId: 69d0eac2c142cb2dc762c58d0e01e47ee83df8a8)
    #11 0x5ae75243d36f in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) (/fuzz/cs/matio_fuzzer+0x45036f) (BuildId: 69d0eac2c142cb2dc762c58d0e01e47ee83df8a8)
    #12 0x5ae7524430c6 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/fuzz/cs/matio_fuzzer+0x4560c6) (BuildId: 69d0eac2c142cb2dc762c58d0e01e47ee83df8a8)
    #13 0x5ae75246cee2 in main (/fuzz/cs/matio_fuzzer+0x47fee2) (BuildId: 69d0eac2c142cb2dc762c58d0e01e47ee83df8a8)
    #14 0x77303640bd8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16

SUMMARY: AddressSanitizer: heap-buffer-overflow asan_interceptors.cpp.o in printf_common(void*, char const*, __va_list_tag*)
Shadow bytes around the buggy address:
  0x0c227fff8200: 00 fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff8210: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c227fff8220: 00 00 00 00 00 00 00 00 00 fa fa fa fa fa fa fa
  0x0c227fff8230: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
  0x0c227fff8240: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c227fff8250: 00[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff8260: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff8270: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff8280: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff8290: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c227fff82a0: 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
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  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
==24885==ABORTING

sae-as-me avatar Feb 27 '25 09:02 sae-as-me

CVE-2025-2338 seems to have been associated with this issue.

carnil avatar Mar 17 '25 20:03 carnil

I do not see what fails. Can you check if the error also occurs if #define HAVE_VSNPRINTF 0 is forced in matioConfig.h? Thanks!

tbeu avatar Apr 27 '25 18:04 tbeu

Resolved by 7b31881ea1da30b075658502961dfcc95353d9ae.

tbeu avatar Nov 08 '25 15:11 tbeu