-
Notifications
You must be signed in to change notification settings - Fork 764
Open
Description
Hi, I also found a stack-buffer-overflow vulnerability using my fuzzer.
Environment
- OS: Ubuntu 22.04
- Compiler: clang 13.0.1
- C++ Standard: C++17
- Sanitizers: AddressSanitizer (ASan) + UndefinedBehaviorSanitizer (UBSan)
Build Instructions
export CXXFLAGS="${CXXFLAGS} -std=c++17 -stdlib=libstdc++ -fsanitize=address -O1 -g"
export CFLAGS="${CFLAGS} -fsanitize=address -O1 -g"
export LDFLAGS="${LDFLAGS} -fsanitize=address"
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DENABLE_FUZZING=ON -DFORCE_STATIC_LINKING=ON -DBUILD_TESTING=OFF
cmake --build . --parallel
Reproduction
Run the fuzzer with a crafted input file:
./bt_fuzzer poc
Observed Behavior
Program crashes with ASan/UBSan report:
==27299==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffdeab4a080 at pc 0x00000080bef3 bp 0x7ffdeab47c70 sp 0x7ffdeab47c68
...
#24 0x75e930 in BT::ParseScript(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /root/behavior/behavior_fix/src/script_parser.cpp:20:7
#25 0x5d3ff8 in auto BT::BehaviorTreeFactory::instantiateTreeNode(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, BT::NodeConfig const&) const::$_3::operator()<std::map<BT::PreCond, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<BT::PreCond>, std::allocator<std::pair<BT::PreCond const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > const, std::array<std::function<BT::Any (BT::Ast::Environment&)>, 4ul> >(std::map<BT::PreCond, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<BT::PreCond>, std::allocator<std::pair<BT::PreCond const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > const&, std::array<std::function<BT::Any (BT::Ast::Environment&)>, 4ul>&) const /root/behavior/behavior_fix/src/bt_factory.cpp:303:26
#26 0x5d3ff8 in BT::BehaviorTreeFactory::instantiateTreeNode(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, BT::NodeConfig const&) const /root/behavior/behavior_fix/src/bt_factory.cpp:313:3
...
Root Cause Analysis
When parsing scripts, the function ParseScript allocates a fixed-size buffer on the stack:
BehaviorTree.CPP/src/script_parser.cpp
Lines 14 to 20 in 8d47d39
Expected<ScriptFunction> ParseScript(const std::string& script) | |
{ | |
char error_msgs_buffer[2048]; | |
auto input = lexy::string_input<lexy::utf8_encoding>(script); | |
auto result = | |
lexy::parse<BT::Grammar::stmt>(input, ErrorReport().to(error_msgs_buffer)); |
However, ErrorReport can produce arbitrarily long diagnostic messages. If the error output exceeds 2048 bytes, it will overflow the stack buffer, causing a stack-buffer-overflow (as detected by AddressSanitizer).
The attached file contains a proof-of-concept.
Metadata
Metadata
Assignees
Labels
No labels