Skip to content

Another Heap-based Buffer Overflow in Mat_VarPrint #268

Closed
@sae-as-me

Description

@sae-as-me

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 Mat_VarPrint function. This issue occurs when processing certain files, leading to an out-of-bounds read and potential application crash.

Details

The vulnerability arises in the Mat_VarPrint function defined in src/mat.c at line 2462. The function fails to properly check the buffer boundaries, resulting in a read operation beyond the allocated memory.

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_mat.zip

./matio_fuzzer src_mat.c_2462_69

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

Report

=================================================================
==24879==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60b00002bb24 at pc 0x5e76dec3cb3d bp 0x7ffc380a9790 sp 0x7ffc380a9788
READ of size 4 at 0x60b00002bb24 thread T0
    #0 0x5e76dec3cb3c in Mat_VarPrint /fuzz/project/matio/src/mat.c:2462:69
    #1 0x5e76dec3a9ae in Mat_VarPrint /fuzz/project/matio/src/mat.c:2252:25
    #2 0x5e76dec3a9ae in Mat_VarPrint /fuzz/project/matio/src/mat.c:2252:25
    #3 0x5e76dec2e199 in MatioRead(char const*) /fuzz/project/matio/ossfuzz/./matio_wrap.h:48:9
    #4 0x5e76dec2e45d in LLVMFuzzerTestOneInput /fuzz/project/matio/ossfuzz/./matio_fuzzer.cpp:30:12
    #5 0x5e76deb545f3 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/fuzz/cs/matio_fuzzer+0x4665f3) (BuildId: 69d0eac2c142cb2dc762c58d0e01e47ee83df8a8)
    #6 0x5e76deb3e36f in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) (/fuzz/cs/matio_fuzzer+0x45036f) (BuildId: 69d0eac2c142cb2dc762c58d0e01e47ee83df8a8)
    #7 0x5e76deb440c6 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/fuzz/cs/matio_fuzzer+0x4560c6) (BuildId: 69d0eac2c142cb2dc762c58d0e01e47ee83df8a8)
    #8 0x5e76deb6dee2 in main (/fuzz/cs/matio_fuzzer+0x47fee2) (BuildId: 69d0eac2c142cb2dc762c58d0e01e47ee83df8a8)
    #9 0x78476f80fd8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    #10 0x78476f80fe3f in __libc_start_main csu/../csu/libc-start.c:392:3
    #11 0x5e76deb38c34 in _start (/fuzz/cs/matio_fuzzer+0x44ac34) (BuildId: 69d0eac2c142cb2dc762c58d0e01e47ee83df8a8)

0x60b00002bb24 is located 0 bytes to the right of 100-byte region [0x60b00002bac0,0x60b00002bb24)
allocated by thread T0 here:
    #0 0x5e76debf0e58 in __interceptor_calloc (/fuzz/cs/matio_fuzzer+0x502e58) (BuildId: 69d0eac2c142cb2dc762c58d0e01e47ee83df8a8)
    #1 0x5e76dec5a297 in ReadSparse /fuzz/project/matio/src/mat5.c:528:26
    #2 0x5e76dec54a60 in Mat_VarRead5 /fuzz/project/matio/src/mat5.c:3391:26
    #3 0x5e76dece2285 in ReadNextStructField /fuzz/project/matio/src/mat5.c:1692:45
    #4 0x5e76dece1f42 in ReadNextStructField /fuzz/project/matio/src/mat5.c:1686:46
    #5 0x5e76decde0d4 in Mat_VarReadNextInfo5 /fuzz/project/matio/src/mat5.c:5413:27
    #6 0x5e76dec33b8f in Mat_VarReadNextInfoPredicate /fuzz/project/matio/src/mat.c:2651:22
    #7 0x5e76dec33b8f in Mat_VarReadNextInfo /fuzz/project/matio/src/mat.c:2625:12
    #8 0x5e76dec2e1de in MatioRead(char const*) /fuzz/project/matio/ossfuzz/./matio_wrap.h:42:23
    #9 0x5e76dec2e45d in LLVMFuzzerTestOneInput /fuzz/project/matio/ossfuzz/./matio_fuzzer.cpp:30:12
    #10 0x5e76deb545f3 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/fuzz/cs/matio_fuzzer+0x4665f3) (BuildId: 69d0eac2c142cb2dc762c58d0e01e47ee83df8a8)
    #11 0x5e76deb3e36f in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) (/fuzz/cs/matio_fuzzer+0x45036f) (BuildId: 69d0eac2c142cb2dc762c58d0e01e47ee83df8a8)
    #12 0x5e76deb440c6 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/fuzz/cs/matio_fuzzer+0x4560c6) (BuildId: 69d0eac2c142cb2dc762c58d0e01e47ee83df8a8)
    #13 0x5e76deb6dee2 in main (/fuzz/cs/matio_fuzzer+0x47fee2) (BuildId: 69d0eac2c142cb2dc762c58d0e01e47ee83df8a8)
    #14 0x78476f80fd8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16

SUMMARY: AddressSanitizer: heap-buffer-overflow /fuzz/project/matio/src/mat.c:2462:69 in Mat_VarPrint
Shadow bytes around the buggy address:
  0x0c167fffd710: fa fa fa fa fa fa fd fd fd fd fd fd fd fd fd fd
  0x0c167fffd720: fd fd fd fd fa fa fa fa fa fa fa fa fd fd fd fd
  0x0c167fffd730: fd fd fd fd fd fd fd fd fd fd fa fa fa fa fa fa
  0x0c167fffd740: fa fa fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c167fffd750: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
=>0x0c167fffd760: 00 00 00 00[04]fa fa fa fa fa fa fa fa fa fd fd
  0x0c167fffd770: fd fd fd fd fd fd fd fd fd fd fd fd fa fa fa fa
  0x0c167fffd780: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c167fffd790: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c167fffd7a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c167fffd7b0: 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
==24879==ABORTING

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions