mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 03:00:34 +03:00
Merge branch 'feat/check_crlf_http_server_response_headers_v5.4' into 'release/v5.4'
feat(esp_http_server): adds check for crlf in response creation (v5.4) See merge request espressif/esp-idf!47501
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2018-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -178,6 +178,12 @@ esp_err_t httpd_resp_set_hdr(httpd_req_t *r, const char *field, const char *valu
|
|||||||
return ESP_ERR_HTTPD_INVALID_REQ;
|
return ESP_ERR_HTTPD_INVALID_REQ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Reject CRLF in header field or value */
|
||||||
|
if (strpbrk(field, "\r\n") || strpbrk(value, "\r\n")) {
|
||||||
|
ESP_LOGW(TAG, LOG_FMT("rejecting header with CRLF: %.32s"), field);
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
struct httpd_req_aux *ra = r->aux;
|
struct httpd_req_aux *ra = r->aux;
|
||||||
struct httpd_data *hd = (struct httpd_data *) r->handle;
|
struct httpd_data *hd = (struct httpd_data *) r->handle;
|
||||||
|
|
||||||
@@ -209,6 +215,12 @@ esp_err_t httpd_resp_set_status(httpd_req_t *r, const char *status)
|
|||||||
return ESP_ERR_HTTPD_INVALID_REQ;
|
return ESP_ERR_HTTPD_INVALID_REQ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Reject CRLF in status */
|
||||||
|
if (strpbrk(status, "\r\n")) {
|
||||||
|
ESP_LOGW(TAG, LOG_FMT("rejecting status with CRLF: %.32s"), status);
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
struct httpd_req_aux *ra = r->aux;
|
struct httpd_req_aux *ra = r->aux;
|
||||||
ra->status = (char *)status;
|
ra->status = (char *)status;
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
@@ -228,6 +240,12 @@ esp_err_t httpd_resp_set_type(httpd_req_t *r, const char *type)
|
|||||||
return ESP_ERR_HTTPD_INVALID_REQ;
|
return ESP_ERR_HTTPD_INVALID_REQ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Reject CRLF in content type */
|
||||||
|
if (strpbrk(type, "\r\n")) {
|
||||||
|
ESP_LOGW(TAG, LOG_FMT("rejecting content type with CRLF: %.32s"), type);
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
struct httpd_req_aux *ra = r->aux;
|
struct httpd_req_aux *ra = r->aux;
|
||||||
ra->content_type = (char *)type;
|
ra->content_type = (char *)type;
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ httpd_handle_t test_httpd_start(uint16_t id)
|
|||||||
|
|
||||||
/* Currently this only tests for the number of tasks.
|
/* Currently this only tests for the number of tasks.
|
||||||
* Heap leakage is not tested as LWIP allocates memory
|
* Heap leakage is not tested as LWIP allocates memory
|
||||||
* which may not be freed immedietly causing erroneous
|
* which may not be freed immediately causing erroneous
|
||||||
* evaluation. Another test to implement would be the
|
* evaluation. Another test to implement would be the
|
||||||
* monitoring of open sockets, but LWIP presently provides
|
* monitoring of open sockets, but LWIP presently provides
|
||||||
* no such API for getting the number of open sockets.
|
* no such API for getting the number of open sockets.
|
||||||
@@ -244,6 +244,41 @@ TEST_CASE("Max Allowed Sockets Test", "[HTTP SERVER]")
|
|||||||
TEST_ASSERT(httpd_start(&hd, &config) != ESP_OK);
|
TEST_ASSERT(httpd_start(&hd, &config) != ESP_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("httpd_resp_set_hdr rejects CRLF in header field and value", "[HTTP SERVER][security]")
|
||||||
|
{
|
||||||
|
httpd_req_t fake_req = {0};
|
||||||
|
|
||||||
|
/* \r\n in value */
|
||||||
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG,
|
||||||
|
httpd_resp_set_hdr(&fake_req, "X-Field", "val\r\nX-Injected: pwned"));
|
||||||
|
/* bare \n in value */
|
||||||
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG,
|
||||||
|
httpd_resp_set_hdr(&fake_req, "X-Field", "val\nX-Injected: pwned"));
|
||||||
|
/* \r\n in field name */
|
||||||
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG,
|
||||||
|
httpd_resp_set_hdr(&fake_req, "X-Field\r\nX-Injected: pwned", "val"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("httpd_resp_set_status rejects CRLF in status string", "[HTTP SERVER][security]")
|
||||||
|
{
|
||||||
|
httpd_req_t fake_req = {0};
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG,
|
||||||
|
httpd_resp_set_status(&fake_req, "200 OK\r\nX-Injected: pwned"));
|
||||||
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG,
|
||||||
|
httpd_resp_set_status(&fake_req, "200 OK\nX-Injected: pwned"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("httpd_resp_set_type rejects CRLF in content type", "[HTTP SERVER][security]")
|
||||||
|
{
|
||||||
|
httpd_req_t fake_req = {0};
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG,
|
||||||
|
httpd_resp_set_type(&fake_req, "text/html\r\nX-Injected: pwned"));
|
||||||
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG,
|
||||||
|
httpd_resp_set_type(&fake_req, "text/html\nX-Injected: pwned"));
|
||||||
|
}
|
||||||
|
|
||||||
void app_main(void)
|
void app_main(void)
|
||||||
{
|
{
|
||||||
unity_run_menu();
|
unity_run_menu();
|
||||||
|
|||||||
Reference in New Issue
Block a user