Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

heap-buffer-overflow in ANSSymbolReader::DecodeHistograms #14

Closed
gy741 opened this issue Jul 28, 2017 · 1 comment
Closed

heap-buffer-overflow in ANSSymbolReader::DecodeHistograms #14

gy741 opened this issue Jul 28, 2017 · 1 comment

Comments

@gy741
Copy link

gy741 commented Jul 28, 2017

Hi.

I found a heap-buffer-overflow bug in pik.

Please confirm.

Thanks.

Summary: heap-buffer-overflow
Browser/OS: Ubuntu 17.04 64bit
Steps to reproduce:
1.Download the .POC files.
2.Execute the following command
: ./dpik $PoC /dev/null
PoC download : PoC

--------------------------------------------
gdb log
--------------------------------------------
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:58
#1 0x00007ffff6ae537a in __GI_abort () at abort.c:89
#2 0x00007ffff6b27090 in __libc_message (do_abort=do_abort@entry=2, fmt=fmt@entry=0x7ffff6c3d000 "*** Error in `%s': %s: 0x%s ***\n")
at ../sysdeps/posix/libc_fatal.c:175
#3 0x00007ffff6b30c3a in malloc_printerr (ar_ptr=<optimized out>, ptr=<optimized out>, str=0x7ffff6c39bb0 "free(): invalid size", action=3)
at malloc.c:5048
#4 _int_free (av=<optimized out>, p=<optimized out>, have_lock=<optimized out>) at malloc.c:3904
#5 0x00007ffff6b34d2c in __GI___libc_free (mem=<optimized out>) at malloc.c:2984
#6 0x00005555555987b4 in __gnu_cxx::new_allocator<int>::deallocate (this=0x7fffffffdb60, __p=<optimized out>) at /usr/include/c++/6/ext/new_allocator.h:110
#7 std::allocator_traits<std::allocator<int> >::deallocate (__a=..., __n=<optimized out>, __p=<optimized out>)
at /usr/include/c++/6/bits/alloc_traits.h:462
#8 std::_Vector_base<int, std::allocator<int> >::_M_deallocate (__n=<optimized out>, __p=<optimized out>, this=0x7fffffffdb60)
at /usr/include/c++/6/bits/stl_vector.h:178
#9 std::_Vector_base<int, std::allocator<int> >::~_Vector_base (this=0x7fffffffdb60, __in_chrg=<optimized out>) at /usr/include/c++/6/bits/stl_vector.h:160
#10 std::vector<int, std::allocator<int> >::~vector (this=0x7fffffffdb60, __in_chrg=<optimized out>) at /usr/include/c++/6/bits/stl_vector.h:427
#11 pik::ANSSymbolReader::DecodeHistograms (in=0x7fffffffdb80, symbol_lut_size=0, symbol_lut=0x0, num_histograms=8, this=0x7fffffffdc30)
at opsin_codec.cc:671
#12 pik::DecodeHistograms (data=data@entry=0x5555557ce454 "\265b", len=len@entry=1000, num_contexts=num_contexts@entry=3, symbol_lut=symbol_lut@entry=0x0,
symbol_lut_size=symbol_lut_size@entry=0, decoder=decoder@entry=0x7fffffffdc30, context_map=0x7fffffffdc10) at opsin_codec.cc:733
#13 0x0000555555598c35 in pik::DecodeImage (data=data@entry=0x5555557ce454 "\265b", len=len@entry=1000, stride=stride@entry=64,
coeffs=coeffs@entry=0x7fffffffe160) at opsin_codec.cc:882
#14 0x0000555555568cea in pik::CompressedImage::Decode (xsize=<optimized out>, ysize=<optimized out>,
data="\201\061\000\000\000@\000\b\340&;\032\030\004S\253>0\327еb\000\000\224KҺ\361\212\352\000\001\000\000\000\f\000\346\317\354\253pn\213\254\t9^\035\224\331!\213\366w\255 \227#%傆\230o\347\067k\362T\260uu\207\004\223>\223\325}\016\000\000\347\344\306\030r\203\231\375?Q4<(\247k\235\241\333۴\256\335\367s\241IK/v,\024)\246'Y\006\241\221\064c±S2\265\346h\243\251⫣\363\240\016k\274\270F4V\v\337\277\360Ob\301\202\226â\206\277 $ۘ\371|\256\346\253\326Yj\342#\275\332\357\345\374\336{\365\275\347\367\356\356\275w\274\367\356\275w\357\356\275\367\364\336", <incomplete sequence \357>...,
info=info@entry=0x7fffffffe3c0) at compressed_image.cc:394
#15 0x00005555555726d1 in pik::PikToPixels (params=..., compressed=..., planes=0x7fffffffe360, aux_out=0x7fffffffe3c0) at pik.cc:544
#16 0x000055555555689e in pik::(anonymous namespace)::Decompress (pathname_in=<optimized out>, pathname_out=0x7fffffffe81d "/dev/null") at dpik.cc:58
#17 0x00007ffff6ace3f1 in __libc_start_main (main=0x555555556470 <main(int, char**)>, argc=3, argv=0x7fffffffe588, init=<optimized out>,
fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffe578) at ../csu/libc-start.c:291
#18 0x00005555555564da in _start ()
=================================================================
==11691==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x62500000c100 at pc 0x00000067171d bp 0x7ffcdf67b9f0 sp 0x7ffcd f67b9e8
WRITE of size 1 at 0x62500000c100 thread T0
#0 0x67171c in pik::ANSSymbolReader::DecodeHistograms(unsigned long, unsigned char const*, unsigned long, pik::BitReader*) /ro ot/karas/pik/opsin_codec.cc:684:47
#1 0x65c26f in pik::DecodeHistograms(unsigned char const*, unsigned long, unsigned long, unsigned char const*, unsigned long, pik::ANSSymbolReader*, std::vector<unsigned char, std::allocator<unsigned char> >*) /root/karas/pik/opsin_codec.cc:733:12
#2 0x65c26f in pik::DecodeImage(unsigned char const*, unsigned long, int, pik::Image3<short>*) /root/karas/pik/opsin_codec .cc:882
#3 0x581268 in pik::CompressedImage::Decode(int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator< char> > const&, pik::PikInfo*) /root/karas/pik/compressed_image.cc:394:10
#4 0x5afa67 in pik::PikToPixels(pik::DecompressParams const&, std::vector<unsigned char, std::allocator<unsigned char> > const &, pik::Image3<unsigned char>*, pik::PikInfo*) /root/karas/pik/pik.cc:543:29
#5 0x50f124 in pik::(anonymous namespace)::Decompress(char const*, char const*) /root/karas/pik/dpik.cc:58:7
#6 0x50f124 in main /root/karas/pik/dpik.cc:80
#7 0x7f8bdd1f13f0 in __libc_start_main /build/glibc-mXZSwJ/glibc-2.24/csu/../csu/libc-start.c:291
#8 0x41b759 in _start (/root/karas/pik/bin/dpik+0x41b759)

0x62500000c100 is located 0 bytes to the right of 8192-byte region [0x62500000a100,0x62500000c100)
allocated by thread T0 here:
#0 0x50a1b0 in operator new(unsigned long) (/root/karas/pik/bin/dpik+0x50a1b0)
#1 0x5551e7 in __gnu_cxx::new_allocator<unsigned char>::allocate(unsigned long, void const*) /usr/bin/../lib/gcc/x86_64-linux- gnu/6.3.0/../../../../include/c++/6.3.0/ext/new_allocator.h:104:27
#2 0x5551e7 in std::allocator_traits<std::allocator<unsigned char> >::allocate(std::allocator<unsigned char>&, unsigned long) /usr/bin/../lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/bits/alloc_traits.h:436
#3 0x5551e7 in std::_Vector_base<unsigned char, std::allocator<unsigned char> >::_M_allocate(unsigned long) /usr/bin/../lib/gc c/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/bits/stl_vector.h:170
#4 0x5551e7 in std::vector<unsigned char, std::allocator<unsigned char> >::_M_default_append(unsigned long) /usr/bin/../lib/gc c/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/bits/vector.tcc:557

SUMMARY: AddressSanitizer: heap-buffer-overflow /root/karas/pik/opsin_codec.cc:684:47 in pik::ANSSymbolReader::DecodeHistogram s(unsigned long, unsigned char const*, unsigned long, pik::BitReader*)
Shadow bytes around the buggy address:
0x0c4a7fff97d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c4a7fff97e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c4a7fff97f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c4a7fff9800: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c4a7fff9810: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c4a7fff9820:[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c4a7fff9830: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c4a7fff9840: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c4a7fff9850: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c4a7fff9860: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c4a7fff9870: 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
==11691==ABORTING
----------------------------------------------------
EXPLOITABLE plugin log
----------------------------------------------------
Classification: EXPLOITABLE
Faulting Frame:
__gnu_cxx::new_allocator<int>::deallocate @ 0x00005555555987b4: in /root/karas/pik/bin/dpik
Disassembly:
Stack Head (17 entries):
__GI_raise @ 0x00007ffff6ae377f: in /lib/x86_64-linux-gnu/libc-2.24.so (BL)
__GI_abort @ 0x00007ffff6ae537a: in /lib/x86_64-linux-gnu/libc-2.24.so (BL)
__libc_message @ 0x00007ffff6b27090: in /lib/x86_64-linux-gnu/libc-2.24.so (BL)
malloc_printerr @ 0x00007ffff6b30c3a: in /lib/x86_64-linux-gnu/libc-2.24.so (BL)
_int_free @ 0x00007ffff6b30c3a: in /lib/x86_64-linux-gnu/libc-2.24.so (BL)
__GI___libc_free @ 0x00007ffff6b34d2c: in /lib/x86_64-linux-gnu/libc-2.24.so (BL)
__gnu_cxx::new_allocator< @ 0x00005555555987b4: in /root/karas/pik/bin/dpik
std::allocator_traits<std @ 0x00005555555987b4: in in /root/karas/pik/bin/dpik
std::_Vector_base<int, @ 0x00005555555987b4: in 0x5555555987b4 in /root/karas/pik/bin/dpik
std::_Vector_base<int, @ 0x00005555555987b4: in 0x5555555987b4 in /root/karas/pik/bin/dpik
std::vector<int, @ 0x00005555555987b4: in 0x5555555987b4 in /root/karas/pik/bin/dpik
pik::ANSSymbolReader::Dec @ 0x00005555555987b4: in /root/karas/pik/bin/dpik
pik::DecodeHistograms @ 0x00005555555987b4: in /root/karas/pik/bin/dpik
pik::DecodeImage @ 0x0000555555598c35: in /root/karas/pik/bin/dpik
pik::CompressedImage::Dec @ 0x0000555555568cea: in /root/karas/pik/bin/dpik
pik::PikToPixels @ 0x00005555555726d1: in /root/karas/pik/bin/dpik
Registers:
rax=0x0000000000000000 rbx=0x0000000000000058 rcx=0x00007ffff6ae377f rdx=0x0000000000000000
rsi=0x00007fffffffd510 rdi=0x0000000000000002 rbp=0x00007fffffffd9b0 rsp=0x00007fffffffd588
r8=0x0000000000000000 r9=0x00007fffffffd510 r10=0x0000000000000008 r11=0x0000000000000246
r12=0x0000000000000058 r13=0x00007fffffffd7c0 r14=0x00007fffffffd7c0 r15=0x00007ffff7ff4000
rip=0x00007ffff6ae377f efl=0x0000000000000246 cs=0x0000000000000033 ss=0x000000000000002b
ds=0x0000000000000000 es=0x0000000000000000 fs=0x0000000000000000 gs=0x0000000000000000
Extra Data:
Description: Heap error
Short description: HeapError (10/22)
Explanation: The target's backtrace indicates that libc has detected a heap error or that the target was executing a heap function when it stopped. This could be due to heap corruption, passing a bad pointer to a heap function such as free(), etc. Since heap errors might include buffer overflows, use-after-free situations, etc. they are generally considered exploitable.
---END SUMMARY---
@jan-wassenberg
Copy link
Member

jan-wassenberg commented Jul 28, 2017

Thank you very much for the report and test case! Confirmed, segfault without asan and otherwise the 1-byte write past end.
We will look at this next Wednesday.

For repro: I added -fsanitize=address and -lasan to Makefile cxxflags/ldflags.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants