제출 #752790: ChaiScript develop branch Use After Free정보

제목ChaiScript develop branch Use After Free
설명### Description We discovered a Heap-use-after-free vulnerability in ChaiScript triggered by a race condition between the main thread (engine destruction) and a worker thread (exception handling). The crash occurs when an asynchronous thread throws an exception (e.g., eval_error) and attempts to format the error message by looking up type names (get_type_name), while the main thread is simultaneously destroying the Dispatch_Engine and its internal type maps. ### Environment - OS: Linux x86_64 - Complier: Clang - Build Configuration: Release mode with ASan enabled. ### Vulnerability Details - Target: ChaiScript - Vulnerability Type: Heap-use-after-free (Race Condition) - Function: chaiscript::Type_Info::bare_equal - Location: include/chaiscript/dispatchkit/type_info.hpp:58 called from dispatchkit.hpp:586 - Root Cause Analysis: 1. The PoC launches an async task that executes a loop with a potential logic error or type mismatch (!+i), which triggers a chaiscript::exception::eval_error. 2. The main thread reaches the end of the script (or encounters the syntax error at the end of the PoC) and begins destroying the ChaiScript instance. 3. Thread T0 (Main) frees the memory associated with the internal type map (std::_Rb_tree::_M_erase). 4. Thread T1 (Worker), while constructing the eval_error message, calls Dispatch_Engine::get_type_name -> Type_Info::bare_equal to describe the objects involved in the error. 5. T1 accesses the memory of a type node that T0 has just freed, causing the UAF. ### Reproduce 1. Build ChaiScript with Release optimization and ASAN enabled. 2. Run with the crashing file: <details> <summary>poc</summary> ``` var func = fun(){ var ret = 0; for (var i = 0; i < 50000; !+i) { ret += i; } return ret; } var fut1 = async(func); var fut2 = async(func); ?print(" ${fut1.get()} ${fut2.get()} ") ``` </details> ``` ./chai crash.chai ``` <details> <summary>ASAN report</summary> ``` AddressSanitizer:DEADLYSIGNAL ================================================================= ==30557==ERROR: AddressSanitizer: heap-use-after-free on address 0x508000001ee8 at pc 0x55d4f13f3f91 bp 0x7f33c65fdde0 sp 0x7f33c65fddd8 READ of size 8 at 0x508000001ee8 thread T1 #0 0x55d4f13f3f90 in chaiscript::Type_Info::bare_equal(chaiscript::Type_Info const&) const /src/ChaiScript/include/chaiscript/dispatchkit/type_info.hpp:58:37 #1 0x55d4f13f3f90 in chaiscript::detail::Dispatch_Engine::get_type_name[abi:cxx11](chaiscript::Type_Info const&) const /src/ChaiScript/include/chaiscript/dispatchkit/dispatchkit.hpp:586:27 #2 0x55d4f18959f7 in chaiscript::detail::Dispatch_Engine::type_name[abi:cxx11](chaiscript::Boxed_Value const&) const /src/ChaiScript/static_libs/../include/chaiscript/language/../dispatchkit/dispatchkit.hpp:965:68 #3 0x55d4f18959f7 in chaiscript::exception::eval_error::format_parameters[abi:cxx11](std::vector<chaiscript::Boxed_Value, std::allocator<chaiscript::Boxed_Value>> const&, bool, chaiscript::detail::Dispatch_Engine const&) /src/ChaiScript/static_libs/../include/chaiscript/language/chaiscript_common.hpp:491:30 #4 0x55d4f189377e in chaiscript::exception::eval_error::format(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, std::vector<chaiscript::Boxed_Value, std::allocator<chaiscript::Boxed_Value>> const&, bool, chaiscript::detail::Dispatch_Engine const&) /src/ChaiScript/static_libs/../include/chaiscript/language/chaiscript_common.hpp:559:38 #5 0x55d4f188e502 in chaiscript::exception::eval_error::eval_error(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, std::vector<chaiscript::Boxed_Value, std::allocator<chaiscript::Boxed_Value>> const&, std::vector<std::shared_ptr<chaiscript::dispatch::Proxy_Function_Base const>, std::allocator<std::shared_ptr<chaiscript::dispatch::Proxy_Function_Base const>>> const&, bool, chaiscript::detail::Dispatch_Engine const&) /src/ChaiScript/static_libs/../include/chaiscript/language/chaiscript_common.hpp:327:32 #6 0x55d4f1946f54 in chaiscript::eval::Prefix_AST_Node<chaiscript::eval::Tracer<chaiscript::eval::Noop_Tracer_Detail>>::eval_internal(chaiscript::detail::Dispatch_State const&) const /src/ChaiScript/static_libs/../include/chaiscript/language/chaiscript_eval.hpp:1175:17 #7 0x55d4f185f1e8 in chaiscript::eval::AST_Node_Impl<chaiscript::eval::Tracer<chaiscript::eval::Noop_Tracer_Detail>>::eval(chaiscript::detail::Dispatch_State const&) const /src/ChaiScript/static_libs/../include/chaiscript/language/chaiscript_eval.hpp:141:18 #8 0x55d4f1990693 in chaiscript::eval::For_AST_Node<chaiscript::eval::Tracer<chaiscript::eval::Noop_Tracer_Detail>>::eval_internal(chaiscript::detail::Dispatch_State const&) const /src/ChaiScript/static_libs/../include/chaiscript/language/chaiscript_eval.hpp:950:125 #9 0x55d4f185f1e8 in chaiscript::eval::AST_Node_Impl<chaiscript::eval::Tracer<chaiscript::eval::Noop_Tracer_Detail>>::eval(chaiscript::detail::Dispatch_State const&) const /src/ChaiScript/static_libs/../include/chaiscript/language/chaiscript_eval.hpp:141:18 #10 0x55d4f18b191c in chaiscript::eval::Block_AST_Node<chaiscript::eval::Tracer<chaiscript::eval::Noop_Tracer_Detail>>::eval_internal(chaiscript::detail::Dispatch_State const&) const /src/ChaiScript/static_libs/../include/chaiscript/language/chaiscript_eval.hpp:703:30 #11 0x55d4f185f1e8 in chaiscript::eval::AST_Node_Impl<chaiscript::eval::Tracer<chaiscript::eval::Noop_Tracer_Detail>>::eval(chaiscript::detail::Dispatch_State const&) const /src/ChaiScript/static_libs/../include/chaiscript/language/chaiscript_eval.hpp:141:18 #12 0x55d4f1906a68 in chaiscript::Boxed_Value chaiscript::eval::detail::eval_function<chaiscript::eval::Tracer<chaiscript::eval::Noop_Tracer_Detail>>(chaiscript::detail::Dispatch_Engine&, chaiscript::eval::AST_Node_Impl<chaiscript::eval::Tracer<chaiscript::eval::Noop_Tracer_Detail>> const&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>> const&, chaiscript::Function_Params const&, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, chaiscript::Boxed_Value, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const, chaiscript::Boxed_Value>>> const*, bool) /src/ChaiScript/static_libs/../include/chaiscript/language/chaiscript_eval.hpp:88:25 #13 0x55d4f190500c in chaiscript::eval::Lambda_AST_Node<chaiscript::eval::Tracer<chaiscript::eval::Noop_Tracer_Detail>>::eval_internal(chaiscript::detail::Dispatch_State const&) const::'lambda'(chaiscript::Function_Params const&)::operator()(chaiscript::Function_Params const&) const /src/ChaiScript/static_libs/../include/chaiscript/language/chaiscript_eval.hpp:660:22 #14 0x55d4f190500c in chaiscript::dispatch::Dynamic_Proxy_Function_Impl<chaiscript::eval::Lambda_AST_Node<chaiscript::eval::Tracer<chaiscript::eval::Noop_Tracer_Detail>>::eval_internal(chaiscript::detail::Dispatch_State const&) const::'lambda'(chaiscript::Function_Params const&)>::do_call(chaiscript::Function_Params const&, chaiscript::Type_Conversions_State const&) const /src/ChaiScript/static_libs/../include/chaiscript/language/../dispatchkit/proxy_functions.hpp:413:20 #15 0x55d4f14303b3 in chaiscript::dispatch::Proxy_Function_Base::operator()(chaiscript::Function_Params const&, chaiscript::Type_Conversions_State const&) const /src/ChaiScript/include/chaiscript/dispatchkit/proxy_functions.hpp:181:18 #16 0x55d4f14303b3 in chaiscript::Boxed_Value chaiscript::dispatch::dispatch<std::vector<std::shared_ptr<chaiscript::dispatch::Proxy_Function_Base const>, std::allocator<std::shared_ptr<chaiscript::dispatch::Proxy_Function_Base const>>>>(std::vector<std::shared_ptr<chaiscript::dispatch::Proxy_Function_Base const>, std::allocator<std::shared_ptr<chaiscript::dispatch::Proxy_Function_Base const>>> const&, chaiscript::Function_Params const&, chaiscript::Type_Conversions_State const&) /src/ChaiScript/include/chaiscript/dispatchkit/proxy_functions.hpp:803:22 #17 0x55d4f1801ef1 in chaiscript::dispatch::detail::Build_Function_Caller_Helper<chaiscript::Boxed_Value>::call(chaiscript::Function_Params const&, chaiscript::Type_Conversions_State const&) /src/ChaiScript/static_libs/../include/chaiscript/dispatchkit/function_call_detail.hpp:40:32 #18 0x55d4f1801ade in chaiscript::Boxed_Value chaiscript::dispatch::detail::Build_Function_Caller_Helper<chaiscript::Boxed_Value>::operator()<>() /src/ChaiScript/static_libs/../include/chaiscript/dispatchkit/function_call_detail.hpp:50:16 #19 0x55d4f1801767 in chaiscript::Boxed_Value std::__invoke_impl<chaiscript::Boxed_Value, chaiscript::dispatch::detail::Build_Function_Caller_Helper<chaiscript::Boxed_Value>&>(std::__invoke_other, chaiscript::dispatch::detail::Build_Function_Caller_Helper<chaiscript::Boxed_Value>&) /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/invoke.h:61:14 #20 0x55d4f1801767 in std::enable_if<is_invocable_r_v<chaiscript::Boxed_Value, chaiscript::dispatch::detail::Build_Function_Caller_Helper<chaiscript::Boxed_Value>&>, chaiscript::Boxed_Value>::type std::__invoke_r<chaiscript::Boxed_Value, chaiscript::dispatch::detail::Build_Function_Caller_Helper<chaiscript::Boxed_Value>&>(chaiscript::dispatch::detail::Build_Function_Caller_Helper<chaiscript::Boxed_Value>&) /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/invoke.h:114:9 #21 0x55d4f1801767 in std::_Function_handler<chaiscript::Boxed_Value (), chaiscript::dispatch::detail::Build_Function_Caller_Helper<chaiscript::Boxed_Value>>::_M_invoke(std::_Any_data const&) /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/s
원천⚠️ https://github.com/ChaiScript/ChaiScript/issues/636
사용자 Oneafter (UID 92781)
제출2026. 02. 05. AM 11:12 (4 개월 ago)
모더레이션2026. 02. 18. AM 07:43 (13 days later)
상태수락
VulDB 항목346454 [ChaiScript 까지 6.1.0 type_info.hpp bare_equal 메모리 손상]
포인트들20

Interested in the pricing of exploits?

See the underground prices here!