tfussell / xlnt

:bar_chart: Cross-platform user-friendly xlsx library for C++11+
Other
1.45k stars 406 forks source link

Heap-buffer-overflow in xlnt::detail::izstream::read_central_header() #662

Open bladchan opened 1 year ago

bladchan commented 1 year ago

Hi,

I am running some experiments for AFLAPI and it has found a heap-buffer-overflow in xlnt::detail::izstream::read_central_header. It seems to be hard to be exploited, but this bug also allows attackers to lead to Dos, so I report it here.

Environment: Ubuntu 20.04 + g++ 6.0

Harness code:

#include <stdio.h>
#include <xlnt/xlnt.hpp>

int main(int argc, char** argv){
    if(argc < 2) return 0;
    xlnt::workbook wb;
    wb.load((char*)argv[1]);
}

Poc here: buf_overflow_testcase.zip

To reproduce: • Complie the hole project with ASAN • Complie the harness with ASAN: g++-6 -fsanitize=address -o harness harness.cc -lxlnt • Run harness: ./harness ./buf_overflow_testcase

ASAN says:

================================================================= ==2167==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000eff1 at pc 0x7f0d5da13f5d bp 0x7ffe488d2b80 sp 0x7ffe488d2b70 READ of size 1 at 0x60200000eff1 thread T0

0 0x7f0d5da13f5c in xlnt::detail::izstream::read_central_header() (/usr/local/lib/libxlnt.so.1.5.0+0x54cf5c)

#1 0x7f0d5da13a10 in xlnt::detail::izstream::izstream(std::istream&) (/usr/local/lib/libxlnt.so.1.5.0+0x54ca10)
#2 0x7f0d5d96069e in xlnt::detail::xlsx_consumer::read(std::istream&) (/usr/local/lib/libxlnt.so.1.5.0+0x49969e)
#3 0x7f0d5d845e2e in xlnt::workbook::load(std::istream&) (/usr/local/lib/libxlnt.so.1.5.0+0x37ee2e)
#4 0x7f0d5d846719 in xlnt::workbook::load(xlnt::path const&) (/usr/local/lib/libxlnt.so.1.5.0+0x37f719)
#5 0x7f0d5d8464fe in xlnt::workbook::load(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (/usr/local/lib/libxlnt.so.1.5.0+0x37f4fe)
#6 0x55864e4f23d7 in main (/home/ubuntu/xlnt/Fuzz/harness+0x23d7)
#7 0x7f0d5d0fc082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082)
#8 0x55864e4f219d in _start (/home/ubuntu/xlnt/Fuzz/harness+0x219d)

0x60200000eff1 is located 0 bytes to the right of 1-byte region [0x60200000eff0,0x60200000eff1) allocated by thread T0 here:

0 0x7f0d5dc85ec0 in operator new(unsigned long) (/lib/x86_64-linux-gnu/libasan.so.3+0xc7ec0)

#1 0x7f0d5d89d9e6 in __gnu_cxx::new_allocator<unsigned char>::allocate(unsigned long, void const*) (/usr/local/lib/libxlnt.so.1.5.0+0x3d69e6)
#2 0x7f0d5d895c3d in std::allocator_traits<std::allocator<unsigned char> >::allocate(std::allocator<unsigned char>&, unsigned long) (/usr/local/lib/libxlnt.so.1.5.0+0x3cec3d)
#3 0x7f0d5d88a4d9 in std::_Vector_base<unsigned char, std::allocator<unsigned char> >::_M_allocate(unsigned long) (/usr/local/lib/libxlnt.so.1.5.0+0x3c34d9)
#4 0x7f0d5d8ed440 in std::_Vector_base<unsigned char, std::allocator<unsigned char> >::_M_create_storage(unsigned long) (/usr/local/lib/libxlnt.so.1.5.0+0x426440)
#5 0x7f0d5d8ed294 in std::_Vector_base<unsigned char, std::allocator<unsigned char> >::_Vector_base(unsigned long, std::allocator<unsigned char> const&) (/usr/local/lib/libxlnt.so.1.5.0+0x426294)
#6 0x7f0d5d901149 in std::vector<unsigned char, std::allocator<unsigned char> >::vector(unsigned long, unsigned char const&, std::allocator<unsigned char> const&) (/usr/local/lib/libxlnt.so.1.5.0+0x43a149)
#7 0x7f0d5da13dbd in xlnt::detail::izstream::read_central_header() (/usr/local/lib/libxlnt.so.1.5.0+0x54cdbd)
#8 0x7f0d5da13a10 in xlnt::detail::izstream::izstream(std::istream&) (/usr/local/lib/libxlnt.so.1.5.0+0x54ca10)
#9 0x7f0d5d96069e in xlnt::detail::xlsx_consumer::read(std::istream&) (/usr/local/lib/libxlnt.so.1.5.0+0x49969e)
#10 0x7f0d5d845e2e in xlnt::workbook::load(std::istream&) (/usr/local/lib/libxlnt.so.1.5.0+0x37ee2e)
#11 0x7f0d5d846719 in xlnt::workbook::load(xlnt::path const&) (/usr/local/lib/libxlnt.so.1.5.0+0x37f719)
#12 0x7f0d5d8464fe in xlnt::workbook::load(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (/usr/local/lib/libxlnt.so.1.5.0+0x37f4fe)
#13 0x55864e4f23d7 in main (/home/ubuntu/xlnt/Fuzz/harness+0x23d7)
#14 0x7f0d5d0fc082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082)

SUMMARY: AddressSanitizer: heap-buffer-overflow (/usr/local/lib/libxlnt.so.1.5.0+0x54cf5c) in xlnt::detail::izstream::read_central_header() Shadow bytes around the buggy address: 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 fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff9de0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa =>0x0c047fff9df0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa[01]fa 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 0x0c047fff9e30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff9e40: 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 Heap right redzone: fb Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack partial redzone: f4 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 ==2167==ABORTING

Impact: An attacker can exploit this vulnerability by submitting a malicious xlsx file that exploits this bug which will result in a DoS even buffer overflow.