In xlsxioread_sheetlist_open(), result is a pointer to struct xlsxio_read_sheetlist_struct object to be initialized. If XML_Char_openzip() fails (returns NULL), result->xmlparser remains uninitialized and then xlsxioread_sheetlist_open() returns result to user directly.
When user calls xlsxioread_sheetlist_close() to destroy struct xlsxio_read_sheetlist_struct object, this uninitialized pointer xmlparser will be passed to XML_ParserFree(), leading to freeing arbitrary pointers.
// xlsxio_read.c:1426, xlsxioread_sheetlist_close()
if (sheetlisthandle->xmlparser)
XML_ParserFree(sheetlisthandle->xmlparser);
System information
Ubuntu 20.04.6 LTS
GNU C Library (Ubuntu GLIBC 2.31-0ubuntu9.9) stable release version 2.31.
gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.1)
Ubuntu clang version 11.1.0-++20211011094159+1fdec59bffc1-1~exp1~20211011214622.5
cmake 3.16.3-1ubuntu1.20.04.1
libexpat1 2.2.9-1ubuntu0.6
libminizip1 1.1-8build1
Reproduction
Script to build test program
```
#!/bin/sh
PREFIX=/tmp/build
wget https://github.com/brechtsanders/xlsxio/releases/download/0.2.34/xlsxio-0.2.34.tar.xz
tar -xvf xlsxio-0.2.34.tar.xz
cd xlsxio-0.2.34
# patch may complain different line endings, I don't know why :(
patch -p1 < /path/to/attachment_fuzz/fuzz.patch
mkdir _build && cd _build/
export LLVM_CONFIG="llvm-config-11"
cmake -G"Unix Makefiles" \
-DCMAKE_C_COMPILER="clang-11" \
-DCMAKE_CXX_COMPILER="clang++-11" \
-DCMAKE_INSTALL_PREFIX="${PREFIX}" \
-DCMAKE_C_FLAGS="-fsanitize=address -fno-omit-frame-pointer" \
-DCMAKE_CXX_FLAGS="-fsanitize=address -fno-omit-frame-pointer" \
-DBUILD_STATIC=ON \
-DBUILD_SHARED=OFF \
-DWITH_WIDE=OFF \
-DBUILD_EXAMPLES=OFF \
-DBUILD_TOOLS=OFF \
-DBUILD_DOCUMENTATION=OFF \
..
make install
```
$ ./fuzz malformed.xlsx
Available sheets:
AddressSanitizer:DEADLYSIGNAL
=================================================================
==13887==ERROR: AddressSanitizer: SEGV on unknown address (pc 0x7f7248790798 bp 0x7fff4fe90410 sp 0x7fff4fe903b0 T0)
==13887==The signal is caused by a READ memory access.
==13887==Hint: this fault was caused by a dereference of a high value address (see register values below). Dissassemble the provided pc to learn which register was used.
#0 0x7f7248790798 in XML_ParserFree lib/../../src/lib/xmlparse.c:1327:11
#1 0x4d163b in xlsxioread_sheetlist_close (/tmp/xlsxio-0.2.34/_build/fuzz+0x4d163b)
#2 0x4c7027 in fuzz (/tmp/xlsxio-0.2.34/_build/fuzz+0x4c7027)
#3 0x4c7570 in fuzz_from_file (/tmp/xlsxio-0.2.34/_build/fuzz+0x4c7570)
#4 0x4c7631 in main (/tmp/xlsxio-0.2.34/_build/fuzz+0x4c7631)
#5 0x7f7248416082 in __libc_start_main /build/glibc-SzIz7B/glibc-2.31/csu/../csu/libc-start.c:308:16
#6 0x41d46d in _start (/tmp/xlsxio-0.2.34/_build/fuzz+0x41d46d)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV lib/../../src/lib/xmlparse.c:1327:11 in XML_ParserFree
==13887==ABORTING
malformed.xlsx can be found in attachment_poc.zip.
PoC
The following PoC could perform a RCE attack by corrupting a freed XML_Parser object, making target program try to execute on an attacker-specified address (e.g. 0x4141414141414141).
Script to build PoC program
```bash
#!/bin/sh
wget https://github.com/brechtsanders/xlsxio/releases/download/0.2.34/xlsxio-0.2.34.tar.xz
tar -xvf xlsxio-0.2.34.tar.xz
cd xlsxio-0.2.34
make
cp /path/to/attachment_poc/poc.c /path/to/attachment_poc/*.xlsx .
gcc -c -o poc.static.o poc.c -DBUILD_XLSXIO_STATIC -g -Iinclude -Ilib -DUSE_MINIZIP
gcc -o poc poc.static.o libxlsxio_read.a -lminizip -lexpat
```
Hi. I found a free of uninitialized pointer vulnerability while fuzzing libxlsxio_read 0.2.34 with AFL++ and AddressSanitizer. This bug could be triggered by a malformed XLSX file, and cause a Denial of Service (DoS) by crashing program or potentially a Remote Code Execution (RCE) by hijacking some function pointers via Use-After-Free (UAF).
Description
In
xlsxioread_sheetlist_open()
,result
is a pointer tostruct xlsxio_read_sheetlist_struct
object to be initialized. IfXML_Char_openzip()
fails (returnsNULL
),result->xmlparser
remains uninitialized and thenxlsxioread_sheetlist_open()
returnsresult
to user directly.When user calls
xlsxioread_sheetlist_close()
to destroystruct xlsxio_read_sheetlist_struct
object, this uninitialized pointerxmlparser
will be passed toXML_ParserFree()
, leading to freeing arbitrary pointers.System information
Reproduction
Script to build test program
``` #!/bin/sh PREFIX=/tmp/build wget https://github.com/brechtsanders/xlsxio/releases/download/0.2.34/xlsxio-0.2.34.tar.xz tar -xvf xlsxio-0.2.34.tar.xz cd xlsxio-0.2.34 # patch may complain different line endings, I don't know why :( patch -p1 < /path/to/attachment_fuzz/fuzz.patch mkdir _build && cd _build/ export LLVM_CONFIG="llvm-config-11" cmake -G"Unix Makefiles" \ -DCMAKE_C_COMPILER="clang-11" \ -DCMAKE_CXX_COMPILER="clang++-11" \ -DCMAKE_INSTALL_PREFIX="${PREFIX}" \ -DCMAKE_C_FLAGS="-fsanitize=address -fno-omit-frame-pointer" \ -DCMAKE_CXX_FLAGS="-fsanitize=address -fno-omit-frame-pointer" \ -DBUILD_STATIC=ON \ -DBUILD_SHARED=OFF \ -DWITH_WIDE=OFF \ -DBUILD_EXAMPLES=OFF \ -DBUILD_TOOLS=OFF \ -DBUILD_DOCUMENTATION=OFF \ .. make install ```attachment_fuzz.zip
malformed.xlsx can be found in attachment_poc.zip.
PoC
The following PoC could perform a RCE attack by corrupting a freed
XML_Parser
object, making target program try to execute on an attacker-specified address (e.g.0x4141414141414141
).Script to build PoC program
```bash #!/bin/sh wget https://github.com/brechtsanders/xlsxio/releases/download/0.2.34/xlsxio-0.2.34.tar.xz tar -xvf xlsxio-0.2.34.tar.xz cd xlsxio-0.2.34 make cp /path/to/attachment_poc/poc.c /path/to/attachment_poc/*.xlsx . gcc -c -o poc.static.o poc.c -DBUILD_XLSXIO_STATIC -g -Iinclude -Ilib -DUSE_MINIZIP gcc -o poc poc.static.o libxlsxio_read.a -lminizip -lexpat ```attachment_poc.zip
Suggested fix
This simple patch should fix it: