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
Vulnerability: resource exhaustion attack when built with asan; denial of service when built with msan #1013
Comments
For C++, you can limit the size as follows: |
We're using the C version of the library. Size limit is an option (if implemented in the C version), but it's a bit crude, because when you're actually reading large data, you may want to be able to read all of that. The problem here is that small data (5 bytes of input) can cause really large allocations (96 GB) in the parser. This makes a resource exhaustion or DoS attack very cheap. Size limits additionally restrict how much data a benign client can send. For the most part, it's reasonable to pass a 96GB input to the parser and expect it to cause a 96GB allocation. Passing such data is something the client code can easily control and decide not to process if the size is not reasonable for the application. The problem here is that the client cannot easily verify whether there's possibly going to be some problem with large allocations in the parser. So, possible fixes:
|
I'm not sure about C version. But if limit size is good enough, MSGPACK_XXX_LIMIT macro is acceptable. But as you mentioned it's a bit crude. C++ is using limit and it is good enough, so far. For C version pull request is welcome but you need to preserve the current behavior. Behavior selecting preprosessor macro (by default disabled is acceptable).
I think that the C++ current implementation do that using zone and unpacking buffer. |
The c++ version allocates the whole array at once, as well. The code to pointed at is the parse buffer (which is indeed managed with exponential growth), not the resulting object. |
Ah, I understand. Thank you for clarifying.
I think that C++ version (since v2 API) has it. C++ version has parser and object_create_visitor. It used to be mixed as unpacker but now separated. For C, there is no such mechanism, so far. I think that adding the functionality is reasonable way. https://github.com/msgpack/msgpack-c/blob/c_master/include/msgpack/unpack.h
If the current implementation is preserved as the default behavior, and the new increasingly allocating way is provided optionally, it is good. Am I understanding about your two options correctly ? I think that separating parse and creating object is better. But I guess that it requires many code changes. |
When sending a message like
ddff000000
, msgpack-c and msgpack-cpp allocate about 96GB of memory:msgpack-c/include/msgpack/unpack_template.h
Line 364 in a9a48ce
msgpack-c/include/msgpack/unpack_template.h
Line 145 in a9a48ce
0xff000000 * 24
):msgpack-c/src/unpack.c
Line 205 in a9a48ce
msgpack-c/src/unpack.c
Line 215 in a9a48ce
In most situations, this is not a problem, because that memory isn't written to, so it's never mapped. However, if someone runs a networked program (e.g. a chat client using msgpack) under MemorySanitizer or AddressSanitizer, one of two things will happen:
ERROR: MemorySanitizer: requested allocation size 0x2000000008 exceeds maximum supported size of 0x200000000
and the program will abort.__interceptor_malloc -> asan_malloc
. If the user has swap enabled, this will soon cause thrashing, rendering the computer unusable. If not, the Linux OOM killer will come along and kill processes until more memory is available (hopefully it kills the chat client).As an alternative, the code could allocate a smaller array at first and then exponentially grow it until it reaches the given size (similar to
std::vector::push_back
). If performance is a concern, you could limit this behaviour to arrays larger than some number (e.g. only for array_32s).The text was updated successfully, but these errors were encountered: