-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
Remote code execution vulnerability #3351
Comments
Nice find! Could you please send a PR to fix it? |
Given this works only without authentication, although not good, I don't think it's catastrophic either, fortunately. Public endpoint should always use CURVE/GSSAPI. |
Fixed by #3353 |
@guidovranken have you requested a CVE for this issue? |
I've just requested one, will post the ID as soon as I get it. |
thanks |
MohammadAlTurany
pushed a commit
to FairRootGroup/libzmq
that referenced
this issue
Jan 28, 2019
… remote code execution (issue zeromq#3351) Solution: refactor bounds check arithmetic such that no overflow shall occur Signed-off-by: Guido Vranken <guidovranken@gmail.com>
netbsd-srcmastr
pushed a commit
to NetBSD/pkgsrc
that referenced
this issue
Feb 14, 2019
0MQ version 4.3.1 stable: * CVE-2019-6250: A vulnerability has been found that would allow attackers to direct a peer to jump to and execute from an address indicated by the attacker. This issue has been present since v4.2.0. Older releases are not affected. NOTE: The attacker needs to know in advance valid addresses in the peer's memory to jump to, so measures like ASLR are effective mitigations. NOTE: this attack can only take place after authentication, so peers behind CURVE/GSSAPI are not vulnerable to unauthenticated attackers. See zeromq/libzmq#3351 for more details. Thanks to Guido Vranken for uncovering the issue and providing the fix! * Note for packagers: as pkg-config's Requires.private is now used to properly propagate dependencies for static builds, the libzmq*-dev or zeromq-devel or equivalent package should now depend on the libfoo-dev or foo-devel packages of all the libraries that zmq is linked against, or pkg-config --libs libzmq will fail due to missing dependencies on end users machines. 0MQ version 4.3.0 stable: * The following DRAFT APIs have been marked as STABLE and will not change anymore: - ZMQ_MSG_T_SIZE context option (see doc/zmq_ctx_get.txt) - ZMQ_THREAD_AFFINITY_CPU_ADD and ZMQ_THREAD_AFFINITY_CPU_REMOVE (Posix only) context options, to add/remove CPUs to the affinity set of the I/O threads. See doc/zmq_ctx_set.txt and doc/zmq_ctx_get.txt for details. - ZMQ_THREAD_NAME_PREFIX (Posix only) context option, to add a specific integer prefix to the background threads names, to easily identify them. See doc/zmq_ctx_set.txt and doc/zmq_ctx_get.txt for details. - ZMQ_GSSAPI_PRINCIPAL_NAMETYPE and ZMQ_GSSAPI_SERVICE_PRINCIPAL_NAMETYPE socket options, for the corresponding GSSAPI features. Additional definitions for principal name types: - ZMQ_GSSAPI_NT_HOSTBASED - ZMQ_GSSAPI_NT_USER_NAME - ZMQ_GSSAPI_NT_KRB5_PRINCIPAL See doc/zmq_gssapi.txt for details. - ZMQ_BINDTODEVICE socket option (Linux only), which will bind the socket(s) to the specified interface. Allows to use Linux VRF, see: https://www.kernel.org/doc/Documentation/networking/vrf.txt NOTE: requires the program to be ran as root OR with CAP_NET_RAW - zmq_timers_* APIs. These functions can be used for cross-platforms timed callbacks. See doc/zmq_timers.txt for details. - The following socket monitor events: - ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL: unknown errors during handshake. - ZMQ_EVENT_HANDSHAKE_SUCCEEDED: Handshake completed with authentication. - ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL: Protocol errors with peers or ZAP. - ZMQ_EVENT_HANDSHAKE_FAILED_AUTH: Failed authentication requests. See doc/zmq_socket_monitor.txt for more details and error codes. - zmq_stopwatch_intermediate which returns the time elapsed without stopping the stopwatch. - zmq_proxy_steerable command 'STATISTICS' to retrieve stats about the amount of messages and bytes sent and received by the proxy. See doc/zmq_proxy_steerable.txt for more information. * The build-time configuration option to select the poller has been split, and new API_POLLER (CMake) and --with-api-poller (autoconf) options will now determine what system call is used to implement the zmq_poll/zmq_poller APIs. The previous POLLER and --with-poller options now only affects the internal I/O thread. In case API_POLLER is not specified, the behaviour keeps backward compatibility intact and will be the same as with previous releases. * The non-default "poll" poller for the internal I/O thread (note: NOT for the zmq_poll/zmq_poller user APIs!) has been disabled on Windows as WSAPoll does not report connection failures. For more information see: - https://daniel.haxx.se/blog/2012/10/10/wsapoll-is-broken/ - https://curl.haxx.se/mail/lib-2012-10/0038.html - https://bugs.python.org/issue16507 * New epoll implementation for Windows, using the following implementation: https://github.com/piscisaureus/wepoll/tree/v1.5.4 To use this, select "epoll" as the poller option in the build system. Note for distributors: the wepoll source code is embedded and distributed. It is licensed under the BSD-2-Clause and thus it is compatible with LGPL-3.0. Note that, if selected at build time, the license text must be distributed with the binary in accordance to the license terms. A copy can be found at: external/wepoll/license.txt * The pre-made Visual Studio solutions file are deprecated, and users are encouraged to use the CMake solution generation feature instead. * New DRAFT (see NEWS for 4.2.0) socket options: - ZMQ_ROUTER_NOTIFY to deliver a notification when a peer connects and/or disconnects in the form of a routing id plus a zero-length frame. - ZMQ_MULTICAST_LOOP to control whether the data sent should be looped back on local listening sockets for UDP multicast sockets (ZMQ_RADIO). See doc/zmq_setsockopt.txt and doc/zmq_getsockopt.txt for details. * New perf tool, perf/benchmark_radix_tree, to measure the performance of the different internal implementations of the trie algorithm used to track subscriptions. Requires a compiler that supports C++11. * New autoconf flag "--enable-force-CXX98-compat" which will force -std=gnu++98 and, if the compiler supports them (clang++ at the moment), it will also add -Wc++98-compat -Wc++98-compat-pedantic so that compatibility with C++98 can be tested. * Many, many coding style, duplication and static analysis improvements. * Many, many improvements to the CMake build system, especially on Windows. * Many, many improvements to unit tests.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Bug details
In
src/v2_decoder.cpp zmq::v2_decoder_t::eight_byte_size_ready()
, the attacker can provide anuint64_t
of his choosing:Then, in
src/v2_decoder.cpp zmq::v2_decoder_t::size_ready()
, a comparison is performed to check if this peer-suppliedmsg_size_
is within the bounds of the currently allocated block of memory:This is inadequate because a very large
msg_size_
will overflow the pointer (read_pos_
).In other words, the comparison will compute as 'false' even though
msg_size_
bytes don't fit in the currently allocated block.Exploit details
Now that
msg_size_
has been set to a very high value, the attacker is allowed to send this amount of bytes, and libzmq will copy it to its internal buffer without any further checks.This means that it's possible to write beyond the bounds of the allocated space.
However, for the exploit this is not necessary to corrupt memory beyond the buffer proper.
As it turns out, the space the attacker is writing to is immediately followed by a
struct content_t
block:So the memory layout is such that the receive buffer is immediately followed by
data
, thensize
, thenffn
, thenhint
, thenrefcnt
.Note that the receive buffer + the
struct content_t
is a single, solid block of memory; by overwriting beyond the designated receive buffer's bounds, no dlmalloc state variables in memory (likebk
,fd
) are corrupted (or, in other words, it wouldn't trigger AddressSanitizer).This means that the attacker can overwrite all these members with arbitrary values.
ffn
is a function pointer, that upon connection closure, is called with two parameters,data
andhint
.This means the attacker can call an arbitrary function/address with two arbitrary parameters.
In my exploit, I set
ffn
to the address ofstrcpy
, set the first parameter to somewhere in the executable's .data section, and the second parameter to the address of the character I want to write followed by a NULL character.So for instance, if i want to write a 'g' character, I search the binary for an occurrence of 'g\x00', and use this address as the second value to my
strcpy
call.For each character of the command I want to execute on the remote machine, I make a separate request to write that character to the .data section.
So if I want to execute 'gnome-calculator', I first write a 'g', then a 'n', then an 'o', and so on, until the full 'gnome-calculator' string is written to .data.
In the next request, I overwrite the 'data' member of
struct content_t
with the address of the .data section (where nowgnome-calculator
resides), set theffn
member to thesystem
libc function, andhint
to NULL.In effect, this calls
system("gnome-calculator")
, by which this command is executed on the remote machine.Exploit
The following is a self-exploit, that demonstrates the exploit flow as explained above.
Notes
Crucial to this exploit is knowing certain addresses, like
strcpy
andsystem
, though the address ofstrcpy
could be replaced with any executable location that containsstosw / ret
or anything else that moves[rsi]
to[rdi]
, andsystem
might be replaced with code that executes the string atrsi
.I did not find any other vulnerabilities in libzmq, but if there is any information leaking vulnerability in libzmq, or the application that uses it, that would allow the attacker to calculate proper code offsets, this would defeat ASLR.
Resolution
Resolution of this vulnerability must consist of preventing pointer arithmetic overflow in
src/v2_decoder.cpp zmq::v2_decoder_t::size_ready()
.The text was updated successfully, but these errors were encountered: