VAR-201704-1519
Vulnerability from variot - Updated: 2025-04-20 23:23Use-after-free vulnerability in the mg_http_multipart_wait_for_boundary function in mongoose.c in Cesanta Mongoose Embedded Web Server Library 6.7 and earlier and Mongoose OS 1.2 and earlier allows remote attackers to cause a denial of service (crash) via a multipart/form-data POST request without a MIME boundary string. Cesanta Mongoose Embedded Web Server Library and Mongoose OS are both products of Cesanta, USA. The former is a network library for embedded Web servers; the latter is an open source operating system for the Internet of Things. Mongoose OS is prone to a denial-of-service vulnerability. An attacker can exploit this issue to crash the server, resulting in a denial-of-service condition. #############################################################
COMPASS SECURITY ADVISORY
https://www.compass-security.com/en/research/advisories/
Product: Mongoose OS
Vendor: Cesanta
CVE ID: CVE-2017-7185
CSNC ID: CSNC-2017-003
Subject: Use-after-free / Denial of Service
Risk: Medium
Effect: Remotely exploitable
Authors:
Philipp Promeuschel philipp.promeuschel@compass-security.com
Carel van Rooyen carel.vanrooyen@compass-security.com
Stephan Sekula stephan.sekula@compass-security.com
Date: 2017-04-03
Introduction:
Cesanta's Mongoose OS [1] - an open source operating system for the Internet of Things. Supported micro controllers: * ESP32 * ESP8266 * STM32 * TI CC3200
Additionally, Amazon AWS IoT is integrated for Cloud connectivity. Developers can write applications in C or JavaScript (the latter by using the v7 component of Mongoose OS).
Affected versions:
Vulnerable: * <= Release 1.2 Not vulnerable: * Patched in current dev / master branch Not tested: * N/A
Technical Description
The handling of HTTP-Multipart boundary [3] headers does not properly close connections when malformed requests are sent to the Mongoose server. This leads to a use-after-free/null-pointer-de-reference vulnerability, causing the Mongoose HTTP server to crash. As a result, the entire system is rendered unusable.
The mg_parse_multipart [2] function performs proper checks for empty boundaries, but, since the flag "MG_F_CLOSE_IMMEDIATELY" does not have any effect, mg_http_multipart_continue() is called: --------------->8--------------- void mg_http_handler(struct mg_connection *nc, int ev, void *ev_data) { [CUT BY COMPASS] #if MG_ENABLE_HTTP_STREAMING_MULTIPART if (req_len > 0 && (s = mg_get_http_header(hm, "Content-Type")) != NULL && s->len >= 9 && strncmp(s->p, "multipart", 9) == 0) { mg_http_multipart_begin(nc, hm, req_len); // properly checks for empty boundary // however, the socket is not closed, and mg_http_multipart_continue() is executed mg_http_multipart_continue(nc); return; } ---------------8<--------------- In the mg_http_multipart_begin function, the boundary is correctly verified: --------------->8--------------- boundary_len = mg_http_parse_header(ct, "boundary", boundary, sizeof(boundary));
if (boundary_len == 0) { /* * Content type is multipart, but there is no boundary, * probably malformed request */ nc->flags = MG_F_CLOSE_IMMEDIATELY; DBG(("invalid request")); goto exit_mp; } ---------------8<--------------- However, the socket is not closed (even though the flag "MG_F_CLOSE_IMMEDIATELY" has been set), and mg_http_multipart_continue is executed. In mg_http_multipart_continue(), the method mg_http_multipart_wait_for_boundary() is executed: ---------------8<--------------- static void mg_http_multipart_continue(struct mg_connection *c) { struct mg_http_proto_data *pd = mg_http_get_proto_data(c); while (1) { switch (pd->mp_stream.state) { case MPS_BEGIN: { pd->mp_stream.state = MPS_WAITING_FOR_BOUNDARY; break; } case MPS_WAITING_FOR_BOUNDARY: { if (mg_http_multipart_wait_for_boundary(c) == 0) { return; } break; } --------------->8--------------- Then, mg_http_multipart_wait_for_boundary() tries to identify the boundary-string. However, this string has never been initialized, which causes c_strnstr to crash. ---------------8<--------------- static int mg_http_multipart_wait_for_boundary(struct mg_connection *c) { const char *boundary; struct mbuf *io = &c->recv_mbuf; struct mg_http_proto_data *pd = mg_http_get_proto_data(c);
if ((int) io->len < pd->mp_stream.boundary_len + 2) { return 0; }
boundary = c_strnstr(io->buf, pd->mp_stream.boundary, io->len); if (boundary != NULL) { [CUT BY COMPASS] --------------->8---------------
Steps to reproduce
Request to HTTP server (code running on hardware device): ---------------8<--------------- POST / HTTP/1.1 Connection: keep-alive Content-Type: multipart/form-data; Content-Length: 1 1 --------------->8--------------- The above request results in a stack trace on the mongoose console: ---------------8<--------------- Guru Meditation Error of type LoadProhibited occurred on core 0. Exception was unhandled. Register dump: PC : 0x400014fd PS : 0x00060330 A0 : 0x801114b4 A1 : 0x3ffbfcf0 A2 : 0x00000000 A3 : 0xfffffffc A4 : 0x000000ff A5 : 0x0000ff00 A6 : 0x00ff0000 A7 : 0xff000000 A8 : 0x00000000 A9 : 0x00000085 A10 : 0xcccccccc A11 : 0x0ccccccc A12 : 0x00000001 A13 : 0x00000000 A14 : 0x00000037 A15 : 0x3ffbb3cc SAR : 0x0000000f EXCCAUSE: 0x0000001c EXCVADDR: 0x00000000 LBEG : 0x400014fd LEND : 0x4000150d LCOUNT : 0xffffffff
Backtrace: 0x400014fd:0x3ffbfcf0 0x401114b4:0x3ffbfd00 0x401136cc:0x3ffbfd30 0x401149ac:0x3ffbfe30 0x40114b71:0x3ffbff00 0x40112b80:0x3ffc00a0 0x40112dc6:0x3ffc00d0 0x40113295:0x3ffc0100 0x4011361a:0x3ffc0170 0x40111716:0x3ffc01d0 0x40103b8f:0x3ffc01f0 0x40105099:0x3ffc0210 --------------->8---------------
Further debugging shows that an uninitialized string has indeed been passed to c_strnstr:
---------------8<---------------
(gdb) info symbol 0x401114b4
c_strnstr + 12 in section .flash.text
(gdb) list 0x401114b4
0x401114b4 is in c_strnstr (/mongoose-os/mongoose/mongoose.c:1720).
warning: Source file is more recent than executable.
1715 }
1716 #endif / _WIN32 /
1717
1718 / The simplest O(mn) algorithm. Better implementation are GPLed */
1719 const char *c_strnstr(const char *s, const char *find, size_t slen) WEAK;
1720 const char *c_strnstr(const char *s, const char *find, size_t slen) {
1721 size_t find_length = strlen(find);
1722 size_t i;
1723
1724 for (i = 0; i < slen; i++) {
(gdb) list *0x401136cc
0x401136cc is in mg_http_multipart_continue (/mongoose-os/mongoose/mongoose.c:5893).
5888 mg_http_free_proto_data_mp_stream(&pd->mp_stream);
5889 pd->mp_stream.state = MPS_FINISHED;
5890
5891 return 1;
5892 }
5893
5894 static int mg_http_multipart_wait_for_boundary(struct mg_connection *c) {
5895 const char *boundary;
5896 struct mbuf *io = &c->recv_mbuf;
5897 struct mg_http_proto_data *pd = mg_http_get_proto_data(c);
(gdb)
--------------->8---------------
Workaround / Fix:
Apply the following (tested and confirmed) patch: ---------------8<--------------- $ diff --git a/mongoose/mongoose.c b/mongoose/mongoose.c index 91dc8b9..063f8c6 100644 --- a/mongoose/mongoose.c +++ b/mongoose/mongoose.c @@ -5889,6 +5889,12 @@ static int mg_http_multipart_wait_for_boundary(struct mg_connection *c) { return 0; }
- if(pd->mp_stream.boundary == NULL){
- pd->mp_stream.state = MPS_FINALIZE;
- LOG(LL_INFO, ("invalid request: boundary not initialized"));
- return 0;
- } + boundary = c_strnstr(io->buf, pd->mp_stream.boundary, io->len); if (boundary != NULL) { const char *boundary_end = (boundary + pd->mp_stream.boundary_len); --------------->8--------------- The patch has been merged into Mongoose OS on github.com on 2017-04-03 [4]
Timeline:
2017-04-03: Coordinated public disclosure date 2017-04-03: Release of patch 2017-03-20: Initial vendor response, code usage sign-off 2017-03-19: Initial vendor notification 2017-03-19: Assigned CVE-2017-7185 2017-03-11: Confirmation and patching Philipp Promeuschel, Carel van Rooyen 2017-03-08: Initial inspection Philipp Promeuschel, Carel van Rooyen 2017-03-08: Discovery by Philipp Promeuschel
References:
[1] https://www.cesanta.com/ [2] https://github.com/cesanta/mongoose/blob/66a96410d4336c312de32b1cf5db954aab9ee2ec/mongoose.c#L7760 [3] http://www.ietf.org/rfc/rfc2046.txt [4] https://github.com/cesanta/mongoose-os/commit/042eb437973a202d00589b13d628181c6de5cf5b
Show details on source website{
"@context": {
"@vocab": "https://www.variotdbs.pl/ref/VARIoTentry#",
"affected_products": {
"@id": "https://www.variotdbs.pl/ref/affected_products"
},
"configurations": {
"@id": "https://www.variotdbs.pl/ref/configurations"
},
"credits": {
"@id": "https://www.variotdbs.pl/ref/credits"
},
"cvss": {
"@id": "https://www.variotdbs.pl/ref/cvss/"
},
"description": {
"@id": "https://www.variotdbs.pl/ref/description/"
},
"exploit_availability": {
"@id": "https://www.variotdbs.pl/ref/exploit_availability/"
},
"external_ids": {
"@id": "https://www.variotdbs.pl/ref/external_ids/"
},
"iot": {
"@id": "https://www.variotdbs.pl/ref/iot/"
},
"iot_taxonomy": {
"@id": "https://www.variotdbs.pl/ref/iot_taxonomy/"
},
"patch": {
"@id": "https://www.variotdbs.pl/ref/patch/"
},
"problemtype_data": {
"@id": "https://www.variotdbs.pl/ref/problemtype_data/"
},
"references": {
"@id": "https://www.variotdbs.pl/ref/references/"
},
"sources": {
"@id": "https://www.variotdbs.pl/ref/sources/"
},
"sources_release_date": {
"@id": "https://www.variotdbs.pl/ref/sources_release_date/"
},
"sources_update_date": {
"@id": "https://www.variotdbs.pl/ref/sources_update_date/"
},
"threat_type": {
"@id": "https://www.variotdbs.pl/ref/threat_type/"
},
"title": {
"@id": "https://www.variotdbs.pl/ref/title/"
},
"type": {
"@id": "https://www.variotdbs.pl/ref/type/"
}
},
"@id": "https://www.variotdbs.pl/vuln/VAR-201704-1519",
"affected_products": {
"@context": {
"@vocab": "https://www.variotdbs.pl/ref/affected_products#",
"data": {
"@container": "@list"
},
"sources": {
"@container": "@list",
"@context": {
"@vocab": "https://www.variotdbs.pl/ref/sources#"
},
"@id": "https://www.variotdbs.pl/ref/sources"
}
},
"data": [
{
"model": "mongoose os",
"scope": "lte",
"trust": 1.8,
"vendor": "cesanta",
"version": "1.2"
},
{
"model": "mongoose embedded web server library",
"scope": "lte",
"trust": 1.0,
"vendor": "cesanta",
"version": "6.7"
},
{
"model": "mongoose embedded web server and networking library",
"scope": "lte",
"trust": 0.8,
"vendor": "cesanta",
"version": "6.7"
},
{
"model": "mongoose embedded web server library",
"scope": "lte",
"trust": 0.6,
"vendor": "cesanta",
"version": "\u003c=6.7"
},
{
"model": "mongoose os",
"scope": "lte",
"trust": 0.6,
"vendor": "cesanta",
"version": "\u003c=1.2"
},
{
"model": "mongoose os",
"scope": "eq",
"trust": 0.6,
"vendor": "cesanta",
"version": "1.2"
},
{
"model": "mongoose embedded web server library",
"scope": "eq",
"trust": 0.6,
"vendor": "cesanta",
"version": "6.7"
},
{
"model": "mongoose",
"scope": "eq",
"trust": 0.3,
"vendor": "cesanta",
"version": "1.2"
}
],
"sources": [
{
"db": "CNVD",
"id": "CNVD-2017-05422"
},
{
"db": "BID",
"id": "97370"
},
{
"db": "JVNDB",
"id": "JVNDB-2017-003079"
},
{
"db": "CNNVD",
"id": "CNNVD-201703-811"
},
{
"db": "NVD",
"id": "CVE-2017-7185"
}
]
},
"configurations": {
"@context": {
"@vocab": "https://www.variotdbs.pl/ref/configurations#",
"children": {
"@container": "@list"
},
"cpe_match": {
"@container": "@list"
},
"data": {
"@container": "@list"
},
"nodes": {
"@container": "@list"
}
},
"data": [
{
"CVE_data_version": "4.0",
"nodes": [
{
"cpe_match": [
{
"cpe22Uri": "cpe:/a:cesanta:mongoose_embedded_web_server_library",
"vulnerable": true
},
{
"cpe22Uri": "cpe:/o:cesanta:mongoose_os",
"vulnerable": true
}
],
"operator": "OR"
}
]
}
],
"sources": [
{
"db": "JVNDB",
"id": "JVNDB-2017-003079"
}
]
},
"credits": {
"@context": {
"@vocab": "https://www.variotdbs.pl/ref/credits#",
"sources": {
"@container": "@list",
"@context": {
"@vocab": "https://www.variotdbs.pl/ref/sources#"
}
}
},
"data": "COMPASS SECURITY.",
"sources": [
{
"db": "BID",
"id": "97370"
}
],
"trust": 0.3
},
"cve": "CVE-2017-7185",
"cvss": {
"@context": {
"cvssV2": {
"@container": "@list",
"@context": {
"@vocab": "https://www.variotdbs.pl/ref/cvss/cvssV2#"
},
"@id": "https://www.variotdbs.pl/ref/cvss/cvssV2"
},
"cvssV3": {
"@container": "@list",
"@context": {
"@vocab": "https://www.variotdbs.pl/ref/cvss/cvssV3#"
},
"@id": "https://www.variotdbs.pl/ref/cvss/cvssV3/"
},
"severity": {
"@container": "@list",
"@context": {
"@vocab": "https://www.variotdbs.pl/cvss/severity#"
},
"@id": "https://www.variotdbs.pl/ref/cvss/severity"
},
"sources": {
"@container": "@list",
"@context": {
"@vocab": "https://www.variotdbs.pl/ref/sources#"
},
"@id": "https://www.variotdbs.pl/ref/sources"
}
},
"data": [
{
"cvssV2": [
{
"accessComplexity": "LOW",
"accessVector": "NETWORK",
"authentication": "NONE",
"author": "nvd@nist.gov",
"availabilityImpact": "PARTIAL",
"baseScore": 5.0,
"confidentialityImpact": "NONE",
"exploitabilityScore": 10.0,
"id": "CVE-2017-7185",
"impactScore": 2.9,
"integrityImpact": "NONE",
"severity": "MEDIUM",
"trust": 1.8,
"vectorString": "AV:N/AC:L/Au:N/C:N/I:N/A:P",
"version": "2.0"
},
{
"accessComplexity": "LOW",
"accessVector": "NETWORK",
"authentication": "NONE",
"author": "CNVD",
"availabilityImpact": "PARTIAL",
"baseScore": 5.0,
"confidentialityImpact": "NONE",
"exploitabilityScore": 10.0,
"id": "CNVD-2017-05422",
"impactScore": 2.9,
"integrityImpact": "NONE",
"severity": "MEDIUM",
"trust": 0.6,
"vectorString": "AV:N/AC:L/Au:N/C:N/I:N/A:P",
"version": "2.0"
}
],
"cvssV3": [
{
"attackComplexity": "LOW",
"attackVector": "NETWORK",
"author": "nvd@nist.gov",
"availabilityImpact": "HIGH",
"baseScore": 7.5,
"baseSeverity": "HIGH",
"confidentialityImpact": "NONE",
"exploitabilityScore": 3.9,
"id": "CVE-2017-7185",
"impactScore": 3.6,
"integrityImpact": "NONE",
"privilegesRequired": "NONE",
"scope": "UNCHANGED",
"trust": 1.8,
"userInteraction": "NONE",
"vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
"version": "3.0"
}
],
"severity": [
{
"author": "nvd@nist.gov",
"id": "CVE-2017-7185",
"trust": 1.0,
"value": "HIGH"
},
{
"author": "NVD",
"id": "CVE-2017-7185",
"trust": 0.8,
"value": "High"
},
{
"author": "CNVD",
"id": "CNVD-2017-05422",
"trust": 0.6,
"value": "MEDIUM"
},
{
"author": "CNNVD",
"id": "CNNVD-201703-811",
"trust": 0.6,
"value": "MEDIUM"
}
]
}
],
"sources": [
{
"db": "CNVD",
"id": "CNVD-2017-05422"
},
{
"db": "JVNDB",
"id": "JVNDB-2017-003079"
},
{
"db": "CNNVD",
"id": "CNNVD-201703-811"
},
{
"db": "NVD",
"id": "CVE-2017-7185"
}
]
},
"description": {
"@context": {
"@vocab": "https://www.variotdbs.pl/ref/description#",
"sources": {
"@container": "@list",
"@context": {
"@vocab": "https://www.variotdbs.pl/ref/sources#"
}
}
},
"data": "Use-after-free vulnerability in the mg_http_multipart_wait_for_boundary function in mongoose.c in Cesanta Mongoose Embedded Web Server Library 6.7 and earlier and Mongoose OS 1.2 and earlier allows remote attackers to cause a denial of service (crash) via a multipart/form-data POST request without a MIME boundary string. Cesanta Mongoose Embedded Web Server Library and Mongoose OS are both products of Cesanta, USA. The former is a network library for embedded Web servers; the latter is an open source operating system for the Internet of Things. Mongoose OS is prone to a denial-of-service vulnerability. \nAn attacker can exploit this issue to crash the server, resulting in a denial-of-service condition. #############################################################\n#\n# COMPASS SECURITY ADVISORY\n# https://www.compass-security.com/en/research/advisories/\n#\n#############################################################\n#\n# Product: Mongoose OS\n# Vendor: Cesanta\n# CVE ID: CVE-2017-7185\n# CSNC ID: CSNC-2017-003\n# Subject: Use-after-free / Denial of Service\n# Risk: Medium\n# Effect: Remotely exploitable\n# Authors:\n# Philipp Promeuschel \u003cphilipp.promeuschel@compass-security.com\u003e\n# Carel van Rooyen \u003ccarel.vanrooyen@compass-security.com\u003e\n# Stephan Sekula \u003cstephan.sekula@compass-security.com\u003e\n# Date: 2017-04-03\n#\n#############################################################\n \nIntroduction:\n-------------\nCesanta\u0027s Mongoose OS [1] - an open source operating system for the Internet of Things. Supported micro controllers:\n* ESP32\n* ESP8266\n* STM32\n* TI CC3200\n \nAdditionally, Amazon AWS IoT is integrated for Cloud connectivity. Developers can write applications in C or JavaScript (the latter by using the v7 component of Mongoose OS). \n \nAffected versions:\n---------\nVulnerable:\n * \u003c= Release 1.2\nNot vulnerable:\n * Patched in current dev / master branch\nNot tested:\n * N/A\n \nTechnical Description\n---------------------\nThe handling of HTTP-Multipart boundary [3] headers does not properly close connections when malformed requests are sent to the Mongoose server. \nThis leads to a use-after-free/null-pointer-de-reference vulnerability, causing the Mongoose HTTP server to crash. As a result, the entire system is rendered unusable. \n \n \nThe mg_parse_multipart [2] function performs proper checks for empty boundaries, but, since the flag \"MG_F_CLOSE_IMMEDIATELY\" does not have any effect, mg_http_multipart_continue() is called:\n---------------\u003e8---------------\nvoid mg_http_handler(struct mg_connection *nc, int ev, void *ev_data) {\n[CUT BY COMPASS]\n #if MG_ENABLE_HTTP_STREAMING_MULTIPART\n if (req_len \u003e 0 \u0026\u0026 (s = mg_get_http_header(hm, \"Content-Type\")) != NULL \u0026\u0026\n s-\u003elen \u003e= 9 \u0026\u0026 strncmp(s-\u003ep, \"multipart\", 9) == 0) {\n mg_http_multipart_begin(nc, hm, req_len); // properly checks for empty boundary\n // however, the socket is not closed, and mg_http_multipart_continue() is executed\n mg_http_multipart_continue(nc);\n return;\n}\n---------------8\u003c---------------\nIn the mg_http_multipart_begin function, the boundary is correctly verified:\n---------------\u003e8---------------\n boundary_len =\n mg_http_parse_header(ct, \"boundary\", boundary, sizeof(boundary));\n \n if (boundary_len == 0) {\n /*\n * Content type is multipart, but there is no boundary,\n * probably malformed request\n */\n nc-\u003eflags = MG_F_CLOSE_IMMEDIATELY;\n DBG((\"invalid request\"));\n goto exit_mp;\n }\n---------------8\u003c---------------\nHowever, the socket is not closed (even though the flag \"MG_F_CLOSE_IMMEDIATELY\" has been set), and mg_http_multipart_continue is executed. \nIn mg_http_multipart_continue(), the method mg_http_multipart_wait_for_boundary() is executed:\n---------------8\u003c---------------\nstatic void mg_http_multipart_continue(struct mg_connection *c) {\n struct mg_http_proto_data *pd = mg_http_get_proto_data(c);\n while (1) {\n switch (pd-\u003emp_stream.state) {\n case MPS_BEGIN: {\n pd-\u003emp_stream.state = MPS_WAITING_FOR_BOUNDARY;\n break;\n }\n case MPS_WAITING_FOR_BOUNDARY: {\n if (mg_http_multipart_wait_for_boundary(c) == 0) {\n return;\n }\n break;\n }\n---------------\u003e8---------------\nThen, mg_http_multipart_wait_for_boundary() tries to identify the boundary-string. However, this string has never been initialized, which causes c_strnstr to crash. \n---------------8\u003c---------------\nstatic int mg_http_multipart_wait_for_boundary(struct mg_connection *c) {\n const char *boundary;\n struct mbuf *io = \u0026c-\u003erecv_mbuf;\n struct mg_http_proto_data *pd = mg_http_get_proto_data(c);\n \n if ((int) io-\u003elen \u003c pd-\u003emp_stream.boundary_len + 2) {\n return 0;\n }\n \n boundary = c_strnstr(io-\u003ebuf, pd-\u003emp_stream.boundary, io-\u003elen);\n if (boundary != NULL) {\n[CUT BY COMPASS]\n---------------\u003e8---------------\n \n \nSteps to reproduce\n-----------------\nRequest to HTTP server (code running on hardware device):\n---------------8\u003c---------------\nPOST / HTTP/1.1\nConnection: keep-alive\nContent-Type: multipart/form-data;\nContent-Length: 1\n1\n---------------\u003e8---------------\nThe above request results in a stack trace on the mongoose console:\n---------------8\u003c---------------\nGuru Meditation Error of type LoadProhibited occurred on core 0. Exception was unhandled. \nRegister dump:\nPC : 0x400014fd PS : 0x00060330 A0 : 0x801114b4 A1 : 0x3ffbfcf0 \nA2 : 0x00000000 A3 : 0xfffffffc A4 : 0x000000ff A5 : 0x0000ff00 \nA6 : 0x00ff0000 A7 : 0xff000000 A8 : 0x00000000 A9 : 0x00000085 \nA10 : 0xcccccccc A11 : 0x0ccccccc A12 : 0x00000001 A13 : 0x00000000 \nA14 : 0x00000037 A15 : 0x3ffbb3cc SAR : 0x0000000f EXCCAUSE: 0x0000001c \nEXCVADDR: 0x00000000 LBEG : 0x400014fd LEND : 0x4000150d LCOUNT : 0xffffffff \n \nBacktrace: 0x400014fd:0x3ffbfcf0 0x401114b4:0x3ffbfd00 0x401136cc:0x3ffbfd30 0x401149ac:0x3ffbfe30 0x40114b71:0x3ffbff00 0x40112b80:0x3ffc00a0 0x40112dc6:0x3ffc00d0 0x40113295:0x3ffc0100 0x4011361a:0x3ffc0170 0x40111716:0x3ffc01d0 0x40103b8f:0x3ffc01f0 0x40105099:0x3ffc0210\n---------------\u003e8---------------\n \n \nFurther debugging shows that an uninitialized string has indeed been passed to c_strnstr:\n---------------8\u003c---------------\n(gdb) info symbol 0x401114b4\nc_strnstr + 12 in section .flash.text\n(gdb) list *0x401114b4\n0x401114b4 is in c_strnstr (/mongoose-os/mongoose/mongoose.c:1720). \nwarning: Source file is more recent than executable. \n1715 }\n1716 #endif /* _WIN32 */\n1717 \n1718 /* The simplest O(mn) algorithm. Better implementation are GPLed */\n1719 const char *c_strnstr(const char *s, const char *find, size_t slen) WEAK;\n1720 const char *c_strnstr(const char *s, const char *find, size_t slen) {\n1721 size_t find_length = strlen(find);\n1722 size_t i;\n1723 \n1724 for (i = 0; i \u003c slen; i++) {\n(gdb) list *0x401136cc\n0x401136cc is in mg_http_multipart_continue (/mongoose-os/mongoose/mongoose.c:5893). \n5888 mg_http_free_proto_data_mp_stream(\u0026pd-\u003emp_stream);\n5889 pd-\u003emp_stream.state = MPS_FINISHED;\n5890 \n5891 return 1;\n5892 }\n5893 \n5894 static int mg_http_multipart_wait_for_boundary(struct mg_connection *c) {\n5895 const char *boundary;\n5896 struct mbuf *io = \u0026c-\u003erecv_mbuf;\n5897 struct mg_http_proto_data *pd = mg_http_get_proto_data(c);\n(gdb)\n---------------\u003e8---------------\n \nWorkaround / Fix:\n-----------------\nApply the following (tested and confirmed) patch:\n---------------8\u003c---------------\n$ diff --git a/mongoose/mongoose.c b/mongoose/mongoose.c\nindex 91dc8b9..063f8c6 100644\n--- a/mongoose/mongoose.c\n+++ b/mongoose/mongoose.c\n@@ -5889,6 +5889,12 @@ static int mg_http_multipart_wait_for_boundary(struct mg_connection *c) {\n return 0;\n }\n \n+ if(pd-\u003emp_stream.boundary == NULL){\n+ pd-\u003emp_stream.state = MPS_FINALIZE;\n+ LOG(LL_INFO, (\"invalid request: boundary not initialized\"));\n+ return 0;\n+ }\n+\n boundary = c_strnstr(io-\u003ebuf, pd-\u003emp_stream.boundary, io-\u003elen);\n if (boundary != NULL) {\n const char *boundary_end = (boundary + pd-\u003emp_stream.boundary_len);\n---------------\u003e8---------------\nThe patch has been merged into Mongoose OS on github.com on 2017-04-03 [4]\n \nTimeline:\n---------\n2017-04-03: Coordinated public disclosure date\n2017-04-03: Release of patch\n2017-03-20: Initial vendor response, code usage sign-off\n2017-03-19: Initial vendor notification\n2017-03-19: Assigned CVE-2017-7185\n2017-03-11: Confirmation and patching Philipp Promeuschel, Carel van Rooyen\n2017-03-08: Initial inspection Philipp Promeuschel, Carel van Rooyen\n2017-03-08: Discovery by Philipp Promeuschel\n \nReferences:\n-----------\n[1] https://www.cesanta.com/\n[2] https://github.com/cesanta/mongoose/blob/66a96410d4336c312de32b1cf5db954aab9ee2ec/mongoose.c#L7760\n[3] http://www.ietf.org/rfc/rfc2046.txt\n[4] https://github.com/cesanta/mongoose-os/commit/042eb437973a202d00589b13d628181c6de5cf5b\n",
"sources": [
{
"db": "NVD",
"id": "CVE-2017-7185"
},
{
"db": "JVNDB",
"id": "JVNDB-2017-003079"
},
{
"db": "CNVD",
"id": "CNVD-2017-05422"
},
{
"db": "CNNVD",
"id": "CNNVD-201703-811"
},
{
"db": "BID",
"id": "97370"
},
{
"db": "PACKETSTORM",
"id": "142021"
}
],
"trust": 3.06
},
"external_ids": {
"@context": {
"@vocab": "https://www.variotdbs.pl/ref/external_ids#",
"data": {
"@container": "@list"
},
"sources": {
"@container": "@list",
"@context": {
"@vocab": "https://www.variotdbs.pl/ref/sources#"
}
}
},
"data": [
{
"db": "NVD",
"id": "CVE-2017-7185",
"trust": 3.4
},
{
"db": "BID",
"id": "97370",
"trust": 1.9
},
{
"db": "EXPLOIT-DB",
"id": "41826",
"trust": 1.0
},
{
"db": "JVNDB",
"id": "JVNDB-2017-003079",
"trust": 0.8
},
{
"db": "CNVD",
"id": "CNVD-2017-05422",
"trust": 0.6
},
{
"db": "CNNVD",
"id": "CNNVD-201703-811",
"trust": 0.6
},
{
"db": "PACKETSTORM",
"id": "142021",
"trust": 0.1
}
],
"sources": [
{
"db": "CNVD",
"id": "CNVD-2017-05422"
},
{
"db": "BID",
"id": "97370"
},
{
"db": "JVNDB",
"id": "JVNDB-2017-003079"
},
{
"db": "PACKETSTORM",
"id": "142021"
},
{
"db": "CNNVD",
"id": "CNNVD-201703-811"
},
{
"db": "NVD",
"id": "CVE-2017-7185"
}
]
},
"id": "VAR-201704-1519",
"iot": {
"@context": {
"@vocab": "https://www.variotdbs.pl/ref/iot#",
"sources": {
"@container": "@list",
"@context": {
"@vocab": "https://www.variotdbs.pl/ref/sources#"
}
}
},
"data": true,
"sources": [
{
"db": "CNVD",
"id": "CNVD-2017-05422"
}
],
"trust": 0.921428565
},
"iot_taxonomy": {
"@context": {
"@vocab": "https://www.variotdbs.pl/ref/iot_taxonomy#",
"data": {
"@container": "@list"
},
"sources": {
"@container": "@list",
"@context": {
"@vocab": "https://www.variotdbs.pl/ref/sources#"
}
}
},
"data": [
{
"category": [
"IoT"
],
"sub_category": null,
"trust": 0.6
}
],
"sources": [
{
"db": "CNVD",
"id": "CNVD-2017-05422"
}
]
},
"last_update_date": "2025-04-20T23:23:46.537000Z",
"patch": {
"@context": {
"@vocab": "https://www.variotdbs.pl/ref/patch#",
"data": {
"@container": "@list"
},
"sources": {
"@container": "@list",
"@context": {
"@vocab": "https://www.variotdbs.pl/ref/sources#"
}
}
},
"data": [
{
"title": "Fix crash in multipart handling (mongoose)",
"trust": 0.8,
"url": "https://github.com/cesanta/mongoose/commit/b8402ed0733e3f244588b61ad5fedd093e3cf9cc"
},
{
"title": "Fix crash in multipart handling (mongoose-os)",
"trust": 0.8,
"url": "https://github.com/cesanta/mongoose-os/commit/042eb437973a202d00589b13d628181c6de5cf5b"
},
{
"title": "Patch for Cesanta Mongoose Embedded Web Server Library and Mongoose OS memory error reference vulnerability",
"trust": 0.6,
"url": "https://www.cnvd.org.cn/patchInfo/show/92752"
}
],
"sources": [
{
"db": "CNVD",
"id": "CNVD-2017-05422"
},
{
"db": "JVNDB",
"id": "JVNDB-2017-003079"
}
]
},
"problemtype_data": {
"@context": {
"@vocab": "https://www.variotdbs.pl/ref/problemtype_data#",
"sources": {
"@container": "@list",
"@context": {
"@vocab": "https://www.variotdbs.pl/ref/sources#"
}
}
},
"data": [
{
"problemtype": "CWE-416",
"trust": 1.8
}
],
"sources": [
{
"db": "JVNDB",
"id": "JVNDB-2017-003079"
},
{
"db": "NVD",
"id": "CVE-2017-7185"
}
]
},
"references": {
"@context": {
"@vocab": "https://www.variotdbs.pl/ref/references#",
"data": {
"@container": "@list"
},
"sources": {
"@container": "@list",
"@context": {
"@vocab": "https://www.variotdbs.pl/ref/sources#"
}
}
},
"data": [
{
"trust": 2.0,
"url": "https://github.com/cesanta/mongoose-os/commit/042eb437973a202d00589b13d628181c6de5cf5b"
},
{
"trust": 1.6,
"url": "https://github.com/cesanta/mongoose/commit/b8402ed0733e3f244588b61ad5fedd093e3cf9cc"
},
{
"trust": 1.6,
"url": "https://www.compass-security.com/fileadmin/datein/research/advisories/cve-2017-7185_mongoose_os_use_after_free.txt"
},
{
"trust": 1.2,
"url": "http://www.securityfocus.com/archive/1/archive/1/540355/100/0/threaded"
},
{
"trust": 1.0,
"url": "https://www.exploit-db.com/exploits/41826/"
},
{
"trust": 1.0,
"url": "http://www.securityfocus.com/archive/1/540355/100/0/threaded"
},
{
"trust": 1.0,
"url": "http://www.securityfocus.com/bid/97370"
},
{
"trust": 0.9,
"url": "https://nvd.nist.gov/vuln/detail/cve-2017-7185"
},
{
"trust": 0.8,
"url": "http://cve.mitre.org/cgi-bin/cvename.cgi?name=cve-2017-7185"
},
{
"trust": 0.4,
"url": "https://www.cesanta.com/"
},
{
"trust": 0.4,
"url": "https://github.com/cesanta/mongoose/blob/66a96410d4336c312de32b1cf5db954aab9ee2ec/mongoose.c#l7760"
},
{
"trust": 0.3,
"url": "http://seclists.org/bugtraq/2017/apr/9"
},
{
"trust": 0.1,
"url": "https://www.compass-security.com/en/research/advisories/"
},
{
"trust": 0.1,
"url": "http://www.ietf.org/rfc/rfc2046.txt"
}
],
"sources": [
{
"db": "CNVD",
"id": "CNVD-2017-05422"
},
{
"db": "BID",
"id": "97370"
},
{
"db": "JVNDB",
"id": "JVNDB-2017-003079"
},
{
"db": "PACKETSTORM",
"id": "142021"
},
{
"db": "CNNVD",
"id": "CNNVD-201703-811"
},
{
"db": "NVD",
"id": "CVE-2017-7185"
}
]
},
"sources": {
"@context": {
"@vocab": "https://www.variotdbs.pl/ref/sources#",
"data": {
"@container": "@list"
}
},
"data": [
{
"db": "CNVD",
"id": "CNVD-2017-05422"
},
{
"db": "BID",
"id": "97370"
},
{
"db": "JVNDB",
"id": "JVNDB-2017-003079"
},
{
"db": "PACKETSTORM",
"id": "142021"
},
{
"db": "CNNVD",
"id": "CNNVD-201703-811"
},
{
"db": "NVD",
"id": "CVE-2017-7185"
}
]
},
"sources_release_date": {
"@context": {
"@vocab": "https://www.variotdbs.pl/ref/sources_release_date#",
"data": {
"@container": "@list"
}
},
"data": [
{
"date": "2017-04-26T00:00:00",
"db": "CNVD",
"id": "CNVD-2017-05422"
},
{
"date": "2017-04-04T00:00:00",
"db": "BID",
"id": "97370"
},
{
"date": "2017-05-12T00:00:00",
"db": "JVNDB",
"id": "JVNDB-2017-003079"
},
{
"date": "2017-04-03T18:32:22",
"db": "PACKETSTORM",
"id": "142021"
},
{
"date": "2017-03-20T00:00:00",
"db": "CNNVD",
"id": "CNNVD-201703-811"
},
{
"date": "2017-04-10T15:59:00.503000",
"db": "NVD",
"id": "CVE-2017-7185"
}
]
},
"sources_update_date": {
"@context": {
"@vocab": "https://www.variotdbs.pl/ref/sources_update_date#",
"data": {
"@container": "@list"
}
},
"data": [
{
"date": "2017-04-26T00:00:00",
"db": "CNVD",
"id": "CNVD-2017-05422"
},
{
"date": "2017-04-11T01:02:00",
"db": "BID",
"id": "97370"
},
{
"date": "2017-05-12T00:00:00",
"db": "JVNDB",
"id": "JVNDB-2017-003079"
},
{
"date": "2017-04-11T00:00:00",
"db": "CNNVD",
"id": "CNNVD-201703-811"
},
{
"date": "2025-04-20T01:37:25.860000",
"db": "NVD",
"id": "CVE-2017-7185"
}
]
},
"threat_type": {
"@context": {
"@vocab": "https://www.variotdbs.pl/ref/threat_type#",
"sources": {
"@container": "@list",
"@context": {
"@vocab": "https://www.variotdbs.pl/ref/sources#"
}
}
},
"data": "remote",
"sources": [
{
"db": "CNNVD",
"id": "CNNVD-201703-811"
}
],
"trust": 0.6
},
"title": {
"@context": {
"@vocab": "https://www.variotdbs.pl/ref/title#",
"sources": {
"@container": "@list",
"@context": {
"@vocab": "https://www.variotdbs.pl/ref/sources#"
}
}
},
"data": "Cesanta Mongoose Embedded Web Server Library and Mongoose OS of mongoose.c Service disruption in (DoS) Vulnerabilities",
"sources": [
{
"db": "JVNDB",
"id": "JVNDB-2017-003079"
}
],
"trust": 0.8
},
"type": {
"@context": {
"@vocab": "https://www.variotdbs.pl/ref/type#",
"sources": {
"@container": "@list",
"@context": {
"@vocab": "https://www.variotdbs.pl/ref/sources#"
}
}
},
"data": "lack of information",
"sources": [
{
"db": "CNNVD",
"id": "CNNVD-201703-811"
}
],
"trust": 0.6
}
}
Drag nodes to arrange them. Double-click a related vulnerability to open it, or a source to visit its link. The Physics button on the left tunes the layout and the simulation; the legend at the bottom left hides or shows nodes by kind and by sighting type.
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
Vulnerability timeline
Sightings and recorded dates, grouped by day · UTC
How durations are calculated
Following the VTEM framework (Black Hat USA 2015), time to patch starts when the vendor or a coordinator was informed, total time to patch at discovery, and disclosure to patch at public disclosure; vendor response time runs from the report to its acknowledgement. Time to exploit and time unpatched start at the earliest discovery or report, falling back to public disclosure. Unpatched time ends at the first recorded patch, or the calculation time when no patch is recorded. Exploitation to patch shows the interval between those two events; a published proof of concept is a public exploit, not exploitation.
Each result shows its source dates. A negative interval means the end event came first; when date-only inputs leave the order open, the result says so. Date-only inputs are approximate. The earliest evidence wins: KEV report dates and sightings are labelled as such. Records describing another vulnerability are listed but never calculated from, and a PoC alone does not establish exploitation. Missing patch evidence does not prove that no patch exists. Filters below change the event list only.
Loading timeline…
The approach is described in our paper Mapping CVEs to MITRE ATT&CK Techniques: A Curated Gold-Set Classifier and the Limits of LLM-Assisted Label Expansion.
Browse all ATT&CK techniques and the vulnerabilities related to each.
Related by attack behaviour
Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.