A heap-based buffer over-read was found in WEBP_Support.cpp
Hello, I found a heap-based buffer over-read bug in function VP8XChunk::VP8XChunk at WEBP_Support.cpp:125 & 126. Actually, it looks like CVE-2018-7731(https://bugs.freedesktop.org/show_bug.cgi?id=105247) and it might be an issue caused by the incomplete consideration of the former issue. The ASAN report is as below:
processing file /home/liwc/crashes/case1
dump_xmp for file /home/liwc/crashes/case1
=================================================================
==58159==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000ef77 at pc 0x0000005ce0b3 bp 0x7ffc7d9b8580 sp 0x7ffc7d9b8570
READ of size 1 at 0x60200000ef77 thread T0
#0 0x5ce0b2 in WEBP::VP8XChunk::VP8XChunk(WEBP::Container*) /home/liwc/exempi-master/XMPFiles/source/FormatSupport/WEBP_Support.cpp:125
#1 0x5ce81c in WEBP::Container::Container(WEBP_MetaHandler*) /home/liwc/exempi-master/XMPFiles/source/FormatSupport/WEBP_Support.cpp:203
#2 0x5c9661 in WEBP_MetaHandler::CacheFileData() /home/liwc/exempi-master/XMPFiles/source/FileHandlers/WEBP_Handler.cpp:89
#3 0x48874f in DoOpenFile /home/liwc/exempi-master/XMPFiles/source/XMPFiles.cpp:1076
#4 0x488f8a in XMPFiles::OpenFile(char const*, unsigned int, unsigned int) /home/liwc/exempi-master/XMPFiles/source/XMPFiles.cpp:1179
#5 0x47e415 in WXMPFiles_OpenFile_1 /home/liwc/exempi-master/XMPFiles/source/WXMPFiles.cpp:233
#6 0x41dab4 in TXMPFiles<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::OpenFile(char const*, unsigned int, unsigned int) (/home/liwc/exempi-master/exempi/exempi+0x41dab4)
#7 0x40bd79 in xmp_files_open_new /home/liwc/exempi-master/exempi/exempi.cpp:294
#8 0x408ccb in get_xmp_from_file /home/liwc/exempi-master/exempi/main.cpp:242
#9 0x408ece in dump_xmp /home/liwc/exempi-master/exempi/main.cpp:257
#10 0x409b54 in process_file /home/liwc/exempi-master/exempi/main.cpp:348
#11 0x408728 in main /home/liwc/exempi-master/exempi/main.cpp:194
#12 0x7fd3f681d82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
#13 0x407a58 in _start (/home/liwc/exempi-master/exempi/exempi+0x407a58)
0x60200000ef77 is located 1 bytes to the right of 6-byte region [0x60200000ef70,0x60200000ef76)
allocated by thread T0 here:
#0 0x7fd3f7b54592 in operator new(unsigned long) (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x99592)
#1 0x4fedc6 in __gnu_cxx::new_allocator<unsigned char>::allocate(unsigned long, void const*) /usr/include/c++/5/ext/new_allocator.h:104
#2 0x4fe8f0 in std::allocator_traits<std::allocator<unsigned char> >::allocate(std::allocator<unsigned char>&, unsigned long) /usr/include/c++/5/bits/alloc_traits.h:491
#3 0x4fe50f in std::_Vector_base<unsigned char, std::allocator<unsigned char> >::_M_allocate(unsigned long) /usr/include/c++/5/bits/stl_vector.h:170
#4 0x58ec6d in unsigned char* std::vector<unsigned char, std::allocator<unsigned char> >::_M_allocate_and_copy<std::move_iterator<unsigned char*> >(unsigned long, std::move_iterator<unsigned char*>, std::move_iterator<unsigned char*>) (/home/liwc/exempi-master/exempi/exempi+0x58ec6d)
#5 0x58e6c9 in std::vector<unsigned char, std::allocator<unsigned char> >::reserve(unsigned long) /usr/include/c++/5/bits/vector.tcc:75
#6 0x5cd019 in WEBP::Chunk::Chunk(WEBP::Container*, WEBP_MetaHandler*) /home/liwc/exempi-master/XMPFiles/source/FormatSupport/WEBP_Support.cpp:38
#7 0x5ce72c in WEBP::Container::Container(WEBP_MetaHandler*) /home/liwc/exempi-master/XMPFiles/source/FormatSupport/WEBP_Support.cpp:190
#8 0x5c9661 in WEBP_MetaHandler::CacheFileData() /home/liwc/exempi-master/XMPFiles/source/FileHandlers/WEBP_Handler.cpp:89
#9 0x48874f in DoOpenFile /home/liwc/exempi-master/XMPFiles/source/XMPFiles.cpp:1076
#10 0x488f8a in XMPFiles::OpenFile(char const*, unsigned int, unsigned int) /home/liwc/exempi-master/XMPFiles/source/XMPFiles.cpp:1179
#11 0x47e415 in WXMPFiles_OpenFile_1 /home/liwc/exempi-master/XMPFiles/source/WXMPFiles.cpp:233
#12 0x41dab4 in TXMPFiles<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::OpenFile(char const*, unsigned int, unsigned int) (/home/liwc/exempi-master/exempi/exempi+0x41dab4)
#13 0x40bd79 in xmp_files_open_new /home/liwc/exempi-master/exempi/exempi.cpp:294
#14 0x408ccb in get_xmp_from_file /home/liwc/exempi-master/exempi/main.cpp:242
#15 0x408ece in dump_xmp /home/liwc/exempi-master/exempi/main.cpp:257
#16 0x409b54 in process_file /home/liwc/exempi-master/exempi/main.cpp:348
#17 0x408728 in main /home/liwc/exempi-master/exempi/main.cpp:194
#18 0x7fd3f681d82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
SUMMARY: AddressSanitizer: heap-buffer-overflow /home/liwc/exempi-master/XMPFiles/source/FormatSupport/WEBP_Support.cpp:125 WEBP::VP8XChunk::VP8XChunk(WEBP::Container*)
Shadow bytes around the buggy address:
0x0c047fff9d90: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
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 00 02 fa fa 00 04 fa fa 00 06
=>0x0c047fff9de0: fa fa fd fd fa fa 06 fa fa fa 00 fa fa fa[06]fa
0x0c047fff9df0: fa fa fd fa fa fa fd fd fa fa fd fa fa fa 00 00
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
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
==58159==ABORTING
The size of VP8XChunk was assigned to 10, but in this case there was no valid VP8XChunk, and the buffer pointed by bitstream was malloced with only 6 bytes. In this way the heap-based buffer over-read happened. A crafted webp can trigger this issue, which allows a DoS attack.
114 VP8XChunk::VP8XChunk(Container* parent_)
115 : Chunk(parent_, kChunk_VP8X)
116 {
117 this->needsRewrite = true;
118 this->size = 10;
119 this->data.resize(this->size);
120 this->data.assign(this->size, 0);
121 XMP_Uns8* bitstream =
122 (XMP_Uns8*)parent->chunks[WEBP_CHUNK_IMAGE][0]->data.data();
123 // See bug https://bugs.freedesktop.org/show_bug.cgi?id=105247
124 // bitstream could be NULL.
125 XMP_Uns32 width = bitstream ? ((bitstream[7] << 8) | bitstream[6]) & 0x3fff : 0; <= buffer over-read
126 XMP_Uns32 height = bitstream ? ((bitstream[9] << 8) | bitstream[8]) & 0x3fff : 0; <= buffer over-read
127 this->width(width);
128 this->height(height);
129 parent_->vp8x = this;
}
You can reproduce it as below.
OS:Ubuntu 16.04 x86_64
export CFLAGS="-fsanitize=address -ggdb"
export CXXFLAGS="-fsanitize=address -ggdb"
export LDFLAGS="-fsanitize=address -ggdb"
sudo apt install libboost-dev
sudo apt install libboost-test-dev
./autogen.sh
./configure --disable-shared
make
./exampi/exempi -x POC -o out
WenChao Li of VARAS@IIE