206 lines
7.8 KiB
Diff
206 lines
7.8 KiB
Diff
commit db19f8dacf2c9ebfc3cafbc52be6c4ed4f8d8ee7
|
|
Author: Daniel Stenberg <daniel@haxx.se>
|
|
Date: Sun Jun 26 11:00:48 2022 +0200
|
|
|
|
[Backport] cookie: apply limits
|
|
|
|
Offering: RTOS
|
|
CVE: CVE-2022-32205
|
|
Reference: upstream_commit_id=48d7064a49148f03942380967da739dcde1cdc24
|
|
|
|
DTS/AR: DTS2022063005656
|
|
type: LTS
|
|
reason: fix CVE-2022-32205 for curl.
|
|
weblink:https://github.com/curl/curl/commit/48d7064a49148f03942380967da739dcde1cdc24
|
|
|
|
- Send no more than 150 cookies per request
|
|
- Cap the max length used for a cookie: header to 8K
|
|
- Cap the max number of received Set-Cookie: headers to 50
|
|
|
|
Bug: https://curl.se/docs/CVE-2022-32205.html
|
|
CVE-2022-32205
|
|
Reported-by: Harry Sintonen
|
|
Closes #9048
|
|
|
|
Conflicts:
|
|
lib/http.c
|
|
|
|
adapted reason:
|
|
9bc3cebc927(misc: remove strlen for Curl_checkheaders + Curl_checkProxyheaders)
|
|
introduces the following changes
|
|
- if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(data, "Cookie"))
|
|
+ if(data->set.str[STRING_COOKIE] &&
|
|
+ !Curl_checkheaders(data, STRCONST("Cookie")))
|
|
This commit is not introduced in 7.78.0, so The change is adapted in this version.
|
|
|
|
c495dcd02e885fc3f3(http: consider cookies over localhost to be secure)
|
|
introduces the following changes
|
|
1. add "!strcmp(host, "127.0.0.1") ||" "!strcmp(host, "[::1]") ? TRUE : FALSE;"
|
|
2. The parameter of the Curl_cookie_getlis is changed.
|
|
- co = Curl_cookie_getlist(data->cookies,
|
|
- data->state.aptr.cookiehost?
|
|
- data->state.aptr.cookiehost:
|
|
+ co = Curl_cookie_getlist(data->cookies, host, data->state.up.path,
|
|
+ secure_context);
|
|
This commit is not introduced in 7.78.0, so The change is adapted in this version.
|
|
|
|
b8072192926(misc: reduce strlen() calls with Curl_dyn_add())
|
|
introduces the following changes
|
|
- result = Curl_dyn_add(r, "Cookie: ");
|
|
+ result = Curl_dyn_addn(r, STRCONST("Cookie: "));
|
|
This commit is not introduced in 7.78.0, so The change is adapted in this version.
|
|
|
|
Signed-off-by: jiahuasheng <jiahuasheng@h-partners.com>
|
|
|
|
diff --git a/lib/cookie.c b/lib/cookie.c
|
|
index ee0b43484..573edf657 100644
|
|
--- a/lib/cookie.c
|
|
+++ b/lib/cookie.c
|
|
@@ -469,6 +469,10 @@ Curl_cookie_add(struct Curl_easy *data,
|
|
(void)data;
|
|
#endif
|
|
|
|
+ DEBUGASSERT(MAX_SET_COOKIE_AMOUNT <= 255); /* counter is an unsigned char */
|
|
+ if(data->req.setcookies >= MAX_SET_COOKIE_AMOUNT)
|
|
+ return NULL;
|
|
+
|
|
/* First, alloc and init a new struct for it */
|
|
co = calloc(1, sizeof(struct Cookie));
|
|
if(!co)
|
|
@@ -808,7 +812,7 @@ Curl_cookie_add(struct Curl_easy *data,
|
|
freecookie(co);
|
|
return NULL;
|
|
}
|
|
-
|
|
+ data->req.setcookies++;
|
|
}
|
|
else {
|
|
/*
|
|
@@ -1346,7 +1350,8 @@ static struct Cookie *dup_cookie(struct Cookie *src)
|
|
*
|
|
* It shall only return cookies that haven't expired.
|
|
*/
|
|
-struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
|
|
+struct Cookie *Curl_cookie_getlist(struct Curl_easy *data,
|
|
+ struct CookieInfo *c,
|
|
const char *host, const char *path,
|
|
bool secure)
|
|
{
|
|
@@ -1401,6 +1406,11 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
|
|
mainco = newco;
|
|
|
|
matches++;
|
|
+ if(matches >= MAX_COOKIE_SEND_AMOUNT) {
|
|
+ infof(data, "Included max number of cookies (%u) in request!",
|
|
+ matches);
|
|
+ break;
|
|
+ }
|
|
}
|
|
else
|
|
goto fail;
|
|
diff --git a/lib/cookie.h b/lib/cookie.h
|
|
index 0ffe08e63..74119808b 100644
|
|
--- a/lib/cookie.h
|
|
+++ b/lib/cookie.h
|
|
@@ -81,10 +81,26 @@ struct CookieInfo {
|
|
*/
|
|
#define MAX_COOKIE_LINE 5000
|
|
|
|
-/* This is the maximum length of a cookie name or content we deal with: */
|
|
+/* Maximum length of an incoming cookie name or content we deal with. Longer
|
|
+ cookies are ignored. */
|
|
#define MAX_NAME 4096
|
|
#define MAX_NAME_TXT "4095"
|
|
|
|
+/* Maximum size for an outgoing cookie line libcurl will use in an http
|
|
+ request. This is the default maximum length used in some versions of Apache
|
|
+ httpd. */
|
|
+#define MAX_COOKIE_HEADER_LEN 8190
|
|
+
|
|
+/* Maximum number of cookies libcurl will send in a single request, even if
|
|
+ there might be more cookies that match. One reason to cap the number is to
|
|
+ keep the maximum HTTP request within the maximum allowed size. */
|
|
+#define MAX_COOKIE_SEND_AMOUNT 150
|
|
+
|
|
+/* Maximum number of Set-Cookie: lines accepted in a single response. If more
|
|
+ such header lines are received, they are ignored. This value must be less
|
|
+ than 256 since an unsigned char is used to count. */
|
|
+#define MAX_SET_COOKIE_AMOUNT 50
|
|
+
|
|
struct Curl_easy;
|
|
/*
|
|
* Add a cookie to the internal list of cookies. The domain and path arguments
|
|
@@ -97,7 +113,8 @@ struct Cookie *Curl_cookie_add(struct Curl_easy *data,
|
|
const char *domain, const char *path,
|
|
bool secure);
|
|
|
|
-struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, const char *host,
|
|
+struct Cookie *Curl_cookie_getlist(struct Curl_easy *data,
|
|
+ struct CookieInfo *c, const char *host,
|
|
const char *path, bool secure);
|
|
void Curl_cookie_freelist(struct Cookie *cookies);
|
|
void Curl_cookie_clearall(struct CookieInfo *cookies);
|
|
diff --git a/lib/http.c b/lib/http.c
|
|
index c4427f15a..18a6921f1 100644
|
|
--- a/lib/http.c
|
|
+++ b/lib/http.c
|
|
@@ -2707,12 +2707,14 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
|
|
}
|
|
|
|
#if !defined(CURL_DISABLE_COOKIES)
|
|
+
|
|
CURLcode Curl_http_cookies(struct Curl_easy *data,
|
|
struct connectdata *conn,
|
|
struct dynbuf *r)
|
|
{
|
|
CURLcode result = CURLE_OK;
|
|
char *addcookies = NULL;
|
|
+ bool linecap = FALSE;
|
|
if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(data, "Cookie"))
|
|
addcookies = data->set.str[STRING_COOKIE];
|
|
|
|
@@ -2722,7 +2724,7 @@ CURLcode Curl_http_cookies(struct Curl_easy *data,
|
|
|
|
if(data->cookies && data->state.cookie_engine) {
|
|
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
|
|
- co = Curl_cookie_getlist(data->cookies,
|
|
+ co = Curl_cookie_getlist(data, data->cookies,
|
|
data->state.aptr.cookiehost?
|
|
data->state.aptr.cookiehost:
|
|
conn->host.name,
|
|
@@ -2741,6 +2743,13 @@ CURLcode Curl_http_cookies(struct Curl_easy *data,
|
|
if(result)
|
|
break;
|
|
}
|
|
+ if((Curl_dyn_len(r) + strlen(co->name) + strlen(co->value) + 1) >=
|
|
+ MAX_COOKIE_HEADER_LEN) {
|
|
+ infof(data, "Restricted outgoing cookies due to header size, "
|
|
+ "'%s' not sent", co->name);
|
|
+ linecap = TRUE;
|
|
+ break;
|
|
+ }
|
|
result = Curl_dyn_addf(r, "%s%s=%s", count?"; ":"",
|
|
co->name, co->value);
|
|
if(result)
|
|
@@ -2751,7 +2760,7 @@ CURLcode Curl_http_cookies(struct Curl_easy *data,
|
|
}
|
|
Curl_cookie_freelist(store);
|
|
}
|
|
- if(addcookies && !result) {
|
|
+ if(addcookies && !result && !linecap) {
|
|
if(!count)
|
|
result = Curl_dyn_add(r, "Cookie: ");
|
|
if(!result) {
|
|
diff --git a/lib/urldata.h b/lib/urldata.h
|
|
index 4979b9aff..0430ac4e5 100644
|
|
--- a/lib/urldata.h
|
|
+++ b/lib/urldata.h
|
|
@@ -705,6 +705,7 @@ struct SingleRequest {
|
|
#ifndef CURL_DISABLE_DOH
|
|
struct dohdata *doh; /* DoH specific data for this request */
|
|
#endif
|
|
+ unsigned char setcookies;
|
|
BIT(header); /* incoming data has HTTP header */
|
|
BIT(content_range); /* set TRUE if Content-Range: was found */
|
|
BIT(upload_done); /* set to TRUE when doing chunked transfer-encoding
|