You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
During fuzzing I found this vulnerability inside wabt::BinaryReader.
Based on quick analysis using GDB, valgrind and ASAN, it seems to be a uncontrolled memory allocation vulnerability (CWE-789) which generates a std::bad_alloc exception and finally allows an attacker to cause a denial of service.
In details, this bug is triggered using a crafted wasm module file with br_table size value out of bound. Asan determined that 7365283840 bytes (~58 GB) are trying to be allocated.
Bug seems to happen during resizing line 661:
$ ./wasm2wat abort_wabt_reader_bad_alloc.wasm
terminate called after throwing an instance of 'std::bad_alloc'what(): std::bad_alloc
[1] 28040 abort ./wasm2wat abort_wabt_reader_bad_alloc.wasm
ASAN
==30756==ERROR: AddressSanitizer failed to allocate 0x1b7015000 (7365283840) bytes of LargeMmapAllocator (error code: 12)
==30756==Process memory map follows:
[...]
==30756==End of process memory map.
==30756==AddressSanitizer CHECK failed: ../../../../src/libsanitizer/sanitizer_common/sanitizer_common.cc:118 "((0 && "unable to mmap")) != (0)" (0x0, 0x0)
#0 0x7f3f77112bf2 (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xe9bf2)#1 0x7f3f77131575 in __sanitizer::CheckFailed(char const*, int, char const*, unsigned long long, unsigned long long) (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x108575)#2 0x7f3f7711c482 (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xf3482)#3 0x7f3f77128895 (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xff895)#4 0x7f3f77052a51 (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x29a51)#5 0x7f3f7710940e in operator new(unsigned long) (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xe040e)#6 0x5617ed052c54 in __gnu_cxx::new_allocator<unsigned int>::allocate(unsigned long, void const*) /usr/include/c++/7/ext/new_allocator.h:111#7 0x5617ed0528f3 in std::allocator_traits<std::allocator<unsigned int> >::allocate(std::allocator<unsigned int>&, unsigned long) /usr/include/c++/7/bits/alloc_traits.h:436#8 0x5617ed05276b in std::_Vector_base<unsigned int, std::allocator<unsigned int> >::_M_allocate(unsigned long) /usr/include/c++/7/bits/stl_vector.h:172#9 0x5617ed0518ad in std::vector<unsigned int, std::allocator<unsigned int> >::_M_default_append(unsigned long) /usr/include/c++/7/bits/vector.tcc:571#10 0x5617ed0512e8 in std::vector<unsigned int, std::allocator<unsigned int> >::resize(unsigned long) (/tmp/wabt/bin/wasm2wat+0x2cf2e8)#11 0x5617ed025da0 in ReadFunctionBody /tmp/wabt/src/binary-reader.cc:661#12 0x5617ed04af0b in ReadCodeSection /tmp/wabt/src/binary-reader.cc:2272#13 0x5617ed04e2be in ReadSections /tmp/wabt/src/binary-reader.cc:2412#14 0x5617ed04f0f5 in ReadModule /tmp/wabt/src/binary-reader.cc:2474#15 0x5617ed04f5d1 in wabt::ReadBinary(void const*, unsigned long, wabt::BinaryReaderDelegate*, wabt::ReadBinaryOptions const&) /tmp/wabt/src/binary-reader.cc:2491#16 0x5617ecf42927 in wabt::ReadBinaryIr(char const*, void const*, unsigned long, wabt::ReadBinaryOptions const&, std::vector<wabt::Error, std::allocator<wabt::Error> >*, wabt::Module*) /tmp/wabt/src/binary-reader-ir.cc:1340#17 0x5617ecf0fa00 in ProgramMain(int, char**) /tmp/wabt/src/tools/wasm2wat.cc:115#18 0x5617ecf0ff58 in main /tmp/wabt/src/tools/wasm2wat.cc:147#19 0x7f3f768d0b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)#20 0x5617ecf0e8d9 in _start (/tmp/wabt/bin/wasm2wat+0x18c8d9)
GDB
$ gdb --args ./wasm2wat abort_wabt_reader_bad_alloc.wasm
GNU gdb (Ubuntu 8.1-0ubuntu3.2) 8.1.0.20180409-git
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty"for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration"for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type"help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./wasm2wat...done.
(gdb) r
Starting program: /tmp/wabt/build/wasm2wat abort_wabt_reader_bad_alloc.wasm
terminate called after throwing an instance of 'std::bad_alloc'what(): std::bad_alloc
Program received signal SIGABRT, Aborted.
__GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
51 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51#1 0x00007ffff769b801 in __GI_abort () at abort.c:79#2 0x00007ffff7ad8957 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6#3 0x00007ffff7adeae6 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6#4 0x00007ffff7adeb21 in std::terminate() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6#5 0x00007ffff7aded54 in __cxa_throw () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6#6 0x00007ffff7adf2dc in operator new(unsigned long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6#7 0x000055555572825e in __gnu_cxx::new_allocator<unsigned int>::allocate (this=0x7fffffffd6e8,
__n=1841318002) at /usr/include/c++/7/ext/new_allocator.h:111
#8 0x00005555557280a6 in std::allocator_traits<std::allocator<unsigned int> >::allocate (__a=...,
__n=1841318002) at /usr/include/c++/7/bits/alloc_traits.h:436
#9 0x0000555555727f1e in std::_Vector_base<unsigned int, std::allocator<unsigned int> >::_M_allocate (
this=0x7fffffffd6e8, __n=1841318002) at /usr/include/c++/7/bits/stl_vector.h:172
#10 0x0000555555727795 in std::vector<unsigned int, std::allocator<unsigned int> >::_M_default_append (
this=0x7fffffffd6e8, __n=1841318002) at /usr/include/c++/7/bits/vector.tcc:571
#11 0x0000555555727415 in std::vector<unsigned int, std::allocator<unsigned int> >::resize (
this=0x7fffffffd6e8, __new_size=1841318002) at /usr/include/c++/7/bits/stl_vector.h:692
#12 0x000055555571b7cc in wabt::(anonymous namespace)::BinaryReader::ReadFunctionBody (
this=0x7fffffffd650, end_offset=73) at /tmp/wabt/src/binary-reader.cc:661
#13 0x000055555572583e in wabt::(anonymous namespace)::BinaryReader::ReadCodeSection (
this=0x7fffffffd650, section_size=42) at /tmp/wabt/src/binary-reader.cc:2272
#14 0x00005555557265fc in wabt::(anonymous namespace)::BinaryReader::ReadSections (this=0x7fffffffd650)
at /tmp/wabt/src/binary-reader.cc:2412
#15 0x00005555557269e2 in wabt::(anonymous namespace)::BinaryReader::ReadModule (this=0x7fffffffd650)
at /tmp/wabt/src/binary-reader.cc:2474
#16 0x0000555555726ba7 in wabt::ReadBinary (data=0x555555a35a20, size=122, delegate=0x7fffffffd790,
options=...) at /tmp/wabt/src/binary-reader.cc:2491
#17 0x00005555556abb08 in wabt::ReadBinaryIr (
filename=0x555555a35ee0 "abort_wabt_reader_bad_alloc.wasm", data=0x555555a35a20, size=122,
options=..., errors=0x7fffffffd860, out_module=0x7fffffffd900)
at /tmp/wabt/src/binary-reader-ir.cc:1340
#18 0x0000555555699103 in ProgramMain (argc=2, argv=0x7fffffffdd98)
at /tmp/wabt/src/tools/wasm2wat.cc:115
#19 0x0000555555699364 in main (argc=2, argv=0x7fffffffdd98) at /tmp/wabt/src/tools/wasm2wat.cc:147
Valgrind
$ valgrind ./wasm2wat abort_wabt_reader_bad_alloc.wasm
==28191== Memcheck, a memory error detector
==28191== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.==28191== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info==28191== Command: ./wasm2wat abort_wabt_reader_bad_alloc.wasm==28191== **28191** new/new[] failed and should throw an exception, but Valgrind**28191** cannot throw exceptions and so is aborting instead. Sorry.==28191== at 0x4C2F81C: ??? (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)==28191== by 0x4C301F5: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)==28191== by 0x2DC25D: __gnu_cxx::new_allocator<unsigned int>::allocate(unsigned long, void const*) (new_allocator.h:111)==28191== by 0x2DC0A5: std::allocator_traits<std::allocator<unsigned int> >::allocate(std::allocator<unsigned int>&, unsigned long) (alloc_traits.h:436)==28191== by 0x2DBF1D: std::_Vector_base<unsigned int, std::allocator<unsigned int> >::_M_allocate(unsigned long) (stl_vector.h:172)==28191== by 0x2DB794: std::vector<unsigned int, std::allocator<unsigned int> >::_M_default_append(unsigned long) (vector.tcc:571)==28191== by 0x2DB414: std::vector<unsigned int, std::allocator<unsigned int> >::resize(unsigned long) (stl_vector.h:692)==28191== by 0x2CF7CB: wabt::(anonymous namespace)::BinaryReader::ReadFunctionBody(unsigned long) (binary-reader.cc:661)==28191== by 0x2D983D: wabt::(anonymous namespace)::BinaryReader::ReadCodeSection(unsigned long) (binary-reader.cc:2272)==28191== by 0x2DA5FB: wabt::(anonymous namespace)::BinaryReader::ReadSections() (binary-reader.cc:2412)==28191== by 0x2DA9E1: wabt::(anonymous namespace)::BinaryReader::ReadModule() (binary-reader.cc:2474)==28191== by 0x2DABA6: wabt::ReadBinary(void const*, unsigned long, wabt::BinaryReaderDelegate*, wabt::ReadBinaryOptions const&) (binary-reader.cc:2491)==28191== ==28191== HEAP SUMMARY:==28191== in use at exit: 2,863 bytes in 34 blocks==28191== total heap usage: 218 allocs, 184 frees, 94,966 bytes allocated==28191== ==28191== LEAK SUMMARY:==28191== definitely lost: 0 bytes in 0 blocks==28191== indirectly lost: 0 bytes in 0 blocks==28191== possibly lost: 0 bytes in 0 blocks==28191== still reachable: 2,863 bytes in 34 blocks==28191== suppressed: 0 bytes in 0 blocks==28191== Rerun with --leak-check=full to see details of leaked memory==28191== ==28191== For counts of detected and suppressed errors, rerun with: -v==28191== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
The text was updated successfully, but these errors were encountered:
The binary reader tries to allocate a vector for all of the branch
targets, but wasn't checking whether the length was excessively long.
There's already a function to do this: `ReadCount`, which errors out if
the count is longer than the section (this assumes each element requires
at least one byte).
Fixes issue #1386.
The binary reader tries to allocate a vector for all of the branch
targets, but wasn't checking whether the length was excessively long.
There's already a function to do this: `ReadCount`, which errors out if
the count is longer than the section (this assumes each element requires
at least one byte).
Fixes issue #1386.
Hi,
During fuzzing I found this vulnerability inside
wabt::BinaryReader
.Based on quick analysis using GDB, valgrind and ASAN, it seems to be a uncontrolled memory allocation vulnerability (CWE-789) which generates a
std::bad_alloc
exception and finally allows an attacker to cause a denial of service.In details, this bug is triggered using a crafted wasm module file with
br_table
size value out of bound. Asan determined that 7365283840 bytes (~58 GB) are trying to be allocated.Bug seems to happen during resizing
line 661
:wabt/src/binary-reader.cc
Lines 658 to 662 in 343d24b
Reproducer
WABT commit: 343d24b
Download:
abort_wabt_reader_bad_alloc.zip
ASAN
GDB
Valgrind
The text was updated successfully, but these errors were encountered: