Vulnerabilities > CVE-2017-2922 - Use After Free vulnerability in Cesanta Mongoose 6.8
Attack vector
NETWORK Attack complexity
LOW Privileges required
NONE Confidentiality impact
HIGH Integrity impact
HIGH Availability impact
HIGH Summary
An exploitable memory corruption vulnerability exists in the Websocket protocol implementation of Cesanta Mongoose 6.8. A specially crafted websocket packet can cause a buffer to be allocated while leaving stale pointers which leads to a use-after-free vulnerability which can be exploited to achieve remote code execution. An attacker needs to send a specially crafted websocket packet over the network to trigger this vulnerability.
Vulnerable Configurations
Part | Description | Count |
---|---|---|
Application | 1 |
Common Weakness Enumeration (CWE)
Seebug
bulletinFamily | exploit |
description | ### Summary An exploitable memory corruption vulnerability exists in the Websocket protocol implementation of Cesanta Mongoose 6.8. A specially crafted websocket packet can cause a buffer to be allocated while leaving stale pointers which leads to a use-after-free vulnerability which can be exploited to achieve remote code execution. An attacker needs to send a specially crafted websocket packet over network to trigger this vulnerability. ### Tested Versions Cesanta Mongoose 6.8 ### Product URLs https://cesanta.com/ ### CVSSv3 Score 9.8 - CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H ### CWE CWE-416: Use After Free ### Details Mongoose is a monolithic library implementing a number of networking protocols, including HTTP, MQTT, MDNS and others. It’s HTTP implementation includes upgrade support required for websocket applications. It is designed with embedded devices in mind and as such is used in many IoT devices and runs on virtually all platforms. A websocket frame can be fragmented over multiple packets. Flags in the websocket header specify if the packet is fragmented and it’s order. When encountering a first frame fragment, a buffer reallocation causes several pointers to become invalid, but the code doesn’t invalidate or update them leading to potential use after free condition which can lead to further memory corruption. In function `mg_deliver_websocket_data` responsible for parsing the websocket packet we observe the following code: ``` if (reass) { [1] /* On first fragmented frame, nullify size */ if (mg_is_ws_first_fragment(wsm.flags)) { [2] mbuf_resize(&nc->recv_mbuf, nc->recv_mbuf.size + sizeof(*sizep)); [3] p[0] &= ~0x0f; /* Next frames will be treated as continuation */ [4] buf = p + 1 + sizeof(*sizep); [5] *sizep = 0; /* TODO(lsm): fix. this can stomp over frame data */ [6] } /* Append this frame to the reassembled buffer */ memmove(buf, wsm.data, e - wsm.data); [7] ``` In the above code, if the packet is marked for reassembly (checked at [1]) and is first fragment (checked at [2]), receive buffer is resized at [3]. Function `mbuf_resize` actually calls `realloc` to resize the buffer. Calling `realloc` on a buffer to resize it doesn’t guarantee that the same memory would be used, a different heap chunk can be chosen and original data would be copied there. This effectively makes old pointers - pointing to original buffer - invalid. In the above code, stale pointers are reused at [4],[5],[6] and [7] to do memory reads, writes and a memory copy. Pointers `p`, `buf`,`e`,sizep and wsm.dataare all initialized based on `originalnc->recv_mbuf` buffer at the beginning of the function: ``` static int mg_deliver_websocket_data(struct mg_connection *nc) { /* Using unsigned char *, cause of integer arithmetic below */ uint64_t i, data_len = 0, frame_len = 0, buf_len = nc->recv_mbuf.len, len, mask_len = 0, header_len = 0; unsigned char *p = (unsigned char *) nc->recv_mbuf.buf, *buf = p, *e = p + buf_len; ``` Calling `realloc` won’t invalidate a pointer always but, in this case steps can be taken make that probability higher, like multiple simultaneous network connections. Not invalidating and updating pointers after `realloc` leads to a use after free condition which can be abused to cause denial of service and ultimately remote code execution. ### Crash Information ``` Address sanitizer output: ==88299==ERROR: AddressSanitizer: heap-use-after-free on address 0x619000005f80 at pc 0x00000051b1ee bp 0x7fffffffb490 sp 0x7fffffffb488 READ of size 1 at 0x619000005f80 thread T0 #0 0x51b1ed in mg_deliver_websocket_data /home/user/mongoose/examples/websocket_chat/../../mongoose.c:8874 #1 0x51b1ed in ?? ??:0 #2 0x5128d4 in mg_ws_handler /home/user/mongoose/examples/websocket_chat/../../mongoose.c:9045 (discriminator 1) #3 0x5128d4 in ?? ??:0 #4 0x4f9de6 in mg_call /home/user/mongoose/examples/websocket_chat/../../mongoose.c:2051 #5 0x4f9de6 in ?? ??:0 #6 0x4fdcf9 in mg_recv_common /home/user/mongoose/examples/websocket_chat/../../mongoose.c:2502 #7 0x4fdcf9 in ?? ??:0 #8 0x506603 in mg_if_recv_tcp_cb /home/user/mongoose/examples/websocket_chat/../../mongoose.c:2506 #9 0x506603 in mg_handle_tcp_read /home/user/mongoose/examples/websocket_chat/../../mongoose.c:3372 #10 0x506603 in mg_mgr_handle_conn /home/user/mongoose/examples/websocket_chat/../../mongoose.c:3497 #11 0x506603 in ?? ??:0 #12 0x509dd8 in mg_socket_if_poll /home/user/mongoose/examples/websocket_chat/../../mongoose.c:3690 #13 0x509dd8 in ?? ??:0 #14 0x4fb695 in mg_mgr_poll /home/user/mongoose/examples/websocket_chat/../../mongoose.c:2232 #15 0x4fb695 in ?? ??:0 #16 0x4ea65a in main /home/user/mongoose/examples/websocket_chat/websocket_chat.c:78 #17 0x4ea65a in ?? ??:0 #18 0x7ffff6ee582f in __libc_start_main /build/glibc-bfm8X4/glibc-2.23/csu/../csu/libc-start.c:291 #19 0x7ffff6ee582f in ?? ??:0 #20 0x418e58 in _start ??:? #21 0x418e58 in ?? ??:0 0x619000005f80 is located 0 bytes inside of 1024-byte region [0x619000005f80,0x619000006380) freed by thread T0 here: #0 0x4b9308 in realloc ??:? #1 0x4b9308 in ?? ??:0 #2 0x4f0275 in mbuf_resize /home/user/mongoose/examples/websocket_chat/../../mongoose.c:1044 (discriminator 1) #3 0x4f0275 in ?? ??:0 previously allocated by thread T0 here: #0 0x4b8f88 in __interceptor_malloc ??:? #1 0x4b8f88 in ?? ??:0 #2 0x506453 in mg_handle_tcp_read /home/user/mongoose/examples/websocket_chat/../../mongoose.c:3336 (discriminator 1) #3 0x506453 in mg_mgr_handle_conn /home/user/mongoose/examples/websocket_chat/../../mongoose.c:3497 (discriminator 1) #4 0x506453 in ?? ??:0 #5 0x509dd8 in mg_socket_if_poll /home/user/mongoose/examples/websocket_chat/../../mongoose.c:3690 #6 0x509dd8 in ?? ??:0 #7 0x4fb695 in mg_mgr_poll /home/user/mongoose/examples/websocket_chat/../../mongoose.c:2232 #8 0x4fb695 in ?? ??:0 #4 0x60200000efef (<unknown module>) SUMMARY: AddressSanitizer: heap-use-after-free (/home/user/mongoose/examples/websocket_chat/websocket_chat+0x51b1ed) Shadow bytes around the buggy address: 0x0c327fff8ba0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c327fff8bb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c327fff8bc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c327fff8bd0: 04 fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c327fff8be0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa =>0x0c327fff8bf0:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x0c327fff8c00: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x0c327fff8c10: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x0c327fff8c20: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x0c327fff8c30: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x0c327fff8c40: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Heap right redzone: fb Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack partial redzone: f4 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb ==88299==ABORTING ``` ### Timeline * 2017-08-30 - Vendor Disclosure * 2017-10-31 - Public Release |
id | SSV:96811 |
last seen | 2017-11-19 |
modified | 2017-11-08 |
published | 2017-11-08 |
reporter | Root |
source | https://www.seebug.org/vuldb/ssvid-96811 |
title | Cesanta Mongoose Websocket Protocol Fragmented Packet Code Execution Vulnerability(CVE-2017-2922) |
Talos
id | TALOS-2017-0429 |
last seen | 2019-05-29 |
published | 2017-10-31 |
reporter | Talos Intelligence |
source | http://www.talosintelligence.com/vulnerability_reports/TALOS-2017-0429 |
title | Cesanta Mongoose Websocket Protocol Fragmented Packet Code Execution Vulnerability |