mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
fix(esp_http_server): reject Content-Length above UINT32_MAX
In httpd_parse.c, cb_headers_complete() converted the HTTP parser's
content_length (uint64_t) to the request's content_len (size_t) via an
unsafe cast through (int). On a 32-bit size_t target a Content-Length
above 4 GiB silently truncated, enabling request smuggling where the
server and an upstream proxy disagree on the body length (CWE-681).
Reject any Content-Length above UINT32_MAX with 413 Content Too Large
before any handler runs. UINT32_MAX is the largest body length the
server can represent in size_t content_len on every target, so this is
the maximum the server can support; no configuration knob is needed.
Closes SEC-102
Closes SEC-229
(cherry picked from commit 9d3f510c7f)
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <sys/param.h>
|
||||
#include <esp_log.h>
|
||||
#include <esp_err.h>
|
||||
@@ -367,9 +368,24 @@ static esp_err_t cb_headers_complete(http_parser *parser)
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
/* In absence of body/chunked encoding, http_parser sets content_len to -1 */
|
||||
r->content_len = ((int)parser->content_length != -1 ?
|
||||
parser->content_length : 0);
|
||||
/* In absence of body/chunked encoding, http_parser sets content_len to ULLONG_MAX */
|
||||
if (parser->content_length != ULLONG_MAX) {
|
||||
/* Content-Length was specified. Reject any value above UINT32_MAX: it is
|
||||
* the largest body length the server can represent in r->content_len on
|
||||
* every target, and rejecting larger values prevents the 64->32-bit
|
||||
* truncation that would otherwise enable request smuggling (CWE-681). */
|
||||
if (parser->content_length > UINT32_MAX) {
|
||||
ESP_LOGW(TAG, LOG_FMT("Content-Length %" PRIu64
|
||||
" exceeds UINT32_MAX; rejecting with 413"),
|
||||
(uint64_t)parser->content_length);
|
||||
parser_data->error = HTTPD_413_CONTENT_TOO_LARGE;
|
||||
parser_data->status = PARSING_FAILED;
|
||||
return ESP_FAIL;
|
||||
}
|
||||
r->content_len = (size_t)parser->content_length;
|
||||
} else {
|
||||
r->content_len = 0;
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, LOG_FMT("bytes read = %" PRId32 ""), parser->nread);
|
||||
ESP_LOGD(TAG, LOG_FMT("content length = %"NEWLIB_NANO_COMPAT_FORMAT), NEWLIB_NANO_COMPAT_CAST(r->content_len));
|
||||
|
||||
Reference in New Issue
Block a user