mirror of
https://github.com/curl/curl.git
synced 2025-02-17 14:59:45 +08:00
cookie: apply limits
- 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
This commit is contained in:
parent
7230b19a2e
commit
48d7064a49
14
lib/cookie.c
14
lib/cookie.c
@ -482,6 +482,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)
|
||||
@ -821,7 +825,7 @@ Curl_cookie_add(struct Curl_easy *data,
|
||||
freecookie(co);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data->req.setcookies++;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
@ -1375,7 +1379,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)
|
||||
{
|
||||
@ -1430,6 +1435,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;
|
||||
|
21
lib/cookie.h
21
lib/cookie.h
@ -83,10 +83,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
|
||||
@ -99,7 +115,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);
|
||||
|
13
lib/http.c
13
lib/http.c
@ -2711,12 +2711,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, STRCONST("Cookie")))
|
||||
addcookies = data->set.str[STRING_COOKIE];
|
||||
@ -2734,7 +2736,7 @@ CURLcode Curl_http_cookies(struct Curl_easy *data,
|
||||
!strcmp(host, "127.0.0.1") ||
|
||||
!strcmp(host, "[::1]") ? TRUE : FALSE;
|
||||
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
|
||||
co = Curl_cookie_getlist(data->cookies, host, data->state.up.path,
|
||||
co = Curl_cookie_getlist(data, data->cookies, host, data->state.up.path,
|
||||
secure_context);
|
||||
Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
|
||||
}
|
||||
@ -2748,6 +2750,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)
|
||||
@ -2758,7 +2767,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_addn(r, STRCONST("Cookie: "));
|
||||
if(!result) {
|
||||
|
@ -698,6 +698,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
|
||||
|
Loading…
Reference in New Issue
Block a user