JayXon / Leanify

lightweight lossless file minifier/optimizer
MIT License
831 stars 75 forks source link

[Bug Report]heap-buffer-overflow in function LeanifyFile():leanify.cpp:140 #80

Closed Asteriska001 closed 2 years ago

Asteriska001 commented 2 years ago

Description

A heap-buffer-overflow was discovered in function LeanifyFile():leanify.cpp:140 The issue is being triggered in function Swf::Leanify(unsigned long) formats/swf.cpp:124

Version

Version b5f2efc (Lastest commit)

Environment

Ubuntu 18.04, 64bit

Reproduce

Command

git clone the Lastest Version firstly.
make && make install
./leanify poc

image

POC file at the bottom of this report.

With ASAN

Note: You can use ASAN for more direct verification. Compile program with address sanitizer with this command:

LEANIFY_SRC     := leanify.cpp main.cpp utils.cpp $(wildcard formats/*.cpp)
LZMA_OBJ        := lib/LZMA/Alloc.o lib/LZMA/LzFind.o lib/LZMA/LzFindMt.o lib/LZMA/LzFindOpt.o lib/LZMA/LzmaDec.o lib/LZMA/LzmaEnc.o lib/LZMA/Threads.o
MOZJPEG_OBJ     := lib/mozjpeg/jaricom.o lib/mozjpeg/jcapimin.o lib/mozjpeg/jcarith.o lib/mozjpeg/jcext.o lib/mozjpeg/jchuff.o lib/mozjpeg/jcmarker.o lib/mozjpeg/jcmaster.o lib/mozjpeg/jcomapi.o lib/mozjpeg/jcparam.o lib/mozjpeg/jcphuff.o lib/mozjpeg/jctrans.o lib/mozjpeg/jdapimin.o lib/mozjpeg/jdarith.o lib/mozjpeg/jdatadst.o lib/mozjpeg/jdatasrc.o lib/mozjpeg/jdcoefct.o lib/mozjpeg/jdhuff.o lib/mozjpeg/jdinput.o lib/mozjpeg/jdmarker.o lib/mozjpeg/jdphuff.o lib/mozjpeg/jdtrans.o lib/mozjpeg/jerror.o lib/mozjpeg/jmemmgr.o lib/mozjpeg/jmemnobs.o lib/mozjpeg/jsimd_none.o lib/mozjpeg/jutils.o
PUGIXML_OBJ     := lib/pugixml/pugixml.o
ZOPFLI_OBJ      := lib/zopfli/hash.o lib/zopfli/squeeze.o lib/zopfli/gzip_container.o lib/zopfli/katajainen.o lib/zopfli/zopfli_lib.o lib/zopfli/cache.o lib/zopfli/zlib_container.o lib/zopfli/util.o lib/zopfli/tree.o lib/zopfli/deflate.o lib/zopfli/blocksplitter.o lib/zopfli/lz77.o
ZOPFLIPNG_OBJ   := lib/zopflipng/lodepng/lodepng.o lib/zopflipng/lodepng/lodepng_util.o lib/zopflipng/zopflipng_lib.o

CFLAGS      += -g -fsanitize=address -Wall -Wextra -Wno-unused-parameter -Werror -O3 -msse2 -mfpmath=sse -flto
CPPFLAGS    += -g -fsanitize=address -I./lib
CXXFLAGS    += -g -fsanitize=address $(CFLAGS) -std=c++17 -fno-rtti
LDFLAGS     += -g -fsanitize=address -flto -lpthread

ifeq ($(OS), Windows_NT)
    SYSTEM  := Windows
    LDLIBS  += -lshlwapi
else
    SYSTEM  := $(shell uname -s)
endif

# Gold linker only supports Linux
ifeq ($(SYSTEM), Linux)
    LDFLAGS += -fuse-ld=gold
endif

ifeq ($(SYSTEM), Darwin)
    LDLIBS  += -liconv
else
    # -s is "obsolete" on mac

endif

ifeq ($(SYSTEM), Windows)
    LEANIFY_SRC += fileio_win.cpp
else
    LEANIFY_SRC += fileio_linux.cpp
endif

.PHONY:     leanify clean

leanify:    $(LEANIFY_SRC) $(LZMA_OBJ) $(MOZJPEG_OBJ) $(PUGIXML_OBJ) $(ZOPFLI_OBJ) $(ZOPFLIPNG_OBJ)
    $(CXX) $(CPPFLAGS) $(CXXFLAGS) $^ $(LDFLAGS) $(LDLIBS) -o $@

$(LZMA_OBJ):    CFLAGS := $(filter-out -Wextra,$(CFLAGS))

$(MOZJPEG_OBJ): CFLAGS := $(filter-out -Wextra,$(CFLAGS))

$(ZOPFLI_OBJ):  CFLAGS += -Wno-unused-function

clean:
    rm -f $(LZMA_OBJ) $(MOZJPEG_OBJ) $(PUGIXML_OBJ) $(ZOPFLI_OBJ) $(ZOPFLIPNG_OBJ) leanify

ASAN Report

Processing: /home/nisl1/nisl8121/Asteriska/fuzz/projects/Leanify/input/crashes/id:000096,sig:11,src:003629,time:487086765,op:havoc,rep:2
=================================================================
==5061==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000001021 at pc 0x5555555c1c3b bp 0x7ffff30fbe20 sp 0x7ffff30fbe10
READ of size 2 at 0x602000001021 thread T1
#0 0x5555555c1c3a in Swf::Leanify(unsigned long) formats/swf.cpp:124
#1 0x55555559c176 in LeanifyFile(void*, unsigned long, unsigned long, std::__cxx11::basic_string, std::allocator > const&) /home/nisl1/nisl8121/Asteriska/fuzz/projects/Leanify/asan_bin/Leanify/leanify.cpp:140
#2 0x5555555a3b97 in ProcessFile(std::__cxx11::basic_string, std::allocator > const&) /home/nisl1/nisl8121/Asteriska/fuzz/projects/Leanify/asan_bin/Leanify/main.cpp:65
#3 0x5555555b4610 in operator() /home/nisl1/nisl8121/Asteriska/fuzz/projects/Leanify/asan_bin/Leanify/main.cpp:139
#4 0x5555555b4610 in std::_Function_handler::_M_invoke(std::_Any_data const&) [clone .lto_priv.536] /usr/include/c++/7/bits/std_function.h:316
#5 0x55555559a1e8 in std::function::operator()() const /usr/include/c++/7/bits/std_function.h:706
#6 0x55555559a1e8 in _invoke_static_task lib/taskflow/core/executor.hpp:823
#7 0x55555559a1e8 in tf::Executor::_invoke(tf::Worker&, tf::Node*) lib/taskflow/core/executor.hpp:671
#8 0x5555555b063a in tf::Executor::_exploit_task(tf::Worker&, tf::Node*&) lib/taskflow/core/executor.hpp:467
#9 0x5555555b063a in operator() lib/taskflow/core/executor.hpp:397
#10 0x5555555b063a in void std::__invoke_impl >(std::__invoke_other, tf::Executor::_spawn(unsigned long)::{lambda(tf::Worker&)#1}&&, std::reference_wrapper&&) /usr/include/c++/7/bits/invoke.h:60
#11 0x5555555b063a in std::__invoke_result >::type std::__invoke >(std::__invoke_result&&, (tf::Executor::_spawn(unsigned long)::{lambda(tf::Worker&)#1}&&)...) /usr/include/c++/7/bits/invoke.h:95
#12 0x5555555b063a in decltype (__invoke((_S_declval<0ul>)(), (_S_declval<1ul>)())) std::thread::_Invoker > >::_M_invoke<0ul, 1ul>(std::_Index_tuple<0ul, 1ul>) /usr/include/c++/7/thread:234
#13 0x5555555b063a in std::thread::_Invoker > >::operator()() /usr/include/c++/7/thread:243
#14 0x5555555b063a in _M_run /usr/include/c++/7/thread:186
#15 0x7ffff7f23066 in execute_native_thread_routine /home/conda/feedstock_root/build_artifacts/ctng-compilers_1618239181388/work/.build/x86_64-conda-linux-gnu/src/gcc/libstdc++-v3/src/c++11/thread.cc:80
#16 0x7ffff6c006da in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x76da)
#17 0x7ffff637371e in __clone (/lib/x86_64-linux-gnu/libc.so.6+0x12171e)

0x602000001021 is located 16 bytes to the right of 1-byte region [0x602000001010,0x602000001011)
allocated by thread T1 here:
#0 0x7ffff6ef8608 in operator new[](unsigned long) (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xe0608)
#1 0x5555555bc333 in Swf::Leanify(unsigned long) formats/swf.cpp:106

Thread T1 created by T0 here:
#0 0x7ffff6e4fd2f in __interceptor_pthread_create (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x37d2f)
#1 0x7ffff7f231f8 in __gthread_create /home/conda/feedstock_root/build_artifacts/ctng-compilers_1618239181388/work/.build/x86_64-conda-linux-gnu/build/build-cc-gcc-final/x86_64-conda-linux-gnu/libstdc++-v3/include/x86_64-conda-linux-gnu/bits/gthr-default.h:676
#2 0x7ffff7f231f8 in std::thread::_M_start_thread(std::unique_ptr >, void (*)()) /home/conda/feedstock_root/build_artifacts/ctng-compilers_1618239181388/work/.build/x86_64-conda-linux-gnu/src/gcc/libstdc++-v3/src/c++11/thread.cc:135

SUMMARY: AddressSanitizer: heap-buffer-overflow formats/swf.cpp:124 in Swf::Leanify(unsigned long)
Shadow bytes around the buggy address:
0x0c047fff81b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff81c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff81d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff81e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff81f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c047fff8200: fa fa 01 fa[fa]fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8210: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8220: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8230: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8240: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8250: 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
==5061==ABORTING

POC

POC

Any issue plz contact with me: asteriska001@gmail.com OR: twitter: @Asteriska8

JayXon commented 2 years ago

Thanks for the report, it should be fixed now.

JayXon commented 2 years ago

I went through the entire file and fixed all potential out of boundary issue, hopefully I didn't miss any.

Asteriska001 commented 2 years ago

Nice work! I re-checked and validated it.