1From a91c22a072cbb32e296f1efba3502f1b7775dfaf Mon Sep 17 00:00:00 2001 2From: Daniel Stenberg <daniel@haxx.se> 3Date: Sun, 26 Jun 2022 11:00:48 +0200 4Subject: [PATCH] cookie: apply limits 5 6- Send no more than 150 cookies per request 7- Cap the max length used for a cookie: header to 8K 8- Cap the max number of received Set-Cookie: headers to 50 9 10Bug: https://curl.se/docs/CVE-2022-32205.html 11CVE-2022-32205 12Reported-by: Harry Sintonen 13Closes #9048 14 15Upstream-Status: Backport [https://github.com/curl/curl/commit/48d7064a49148f0394] 16Signed-off-by: Robert Joslyn <robert.joslyn@redrectangle.org> 17--- 18 lib/cookie.c | 14 ++++++++++++-- 19 lib/cookie.h | 21 +++++++++++++++++++-- 20 lib/http.c | 13 +++++++++++-- 21 lib/urldata.h | 1 + 22 4 files changed, 43 insertions(+), 6 deletions(-) 23 24diff --git a/lib/cookie.c b/lib/cookie.c 25index 1b8c8f9..8a6aa1a 100644 26--- a/lib/cookie.c 27+++ b/lib/cookie.c 28@@ -477,6 +477,10 @@ Curl_cookie_add(struct Curl_easy *data, 29 (void)data; 30 #endif 31 32+ DEBUGASSERT(MAX_SET_COOKIE_AMOUNT <= 255); /* counter is an unsigned char */ 33+ if(data->req.setcookies >= MAX_SET_COOKIE_AMOUNT) 34+ return NULL; 35+ 36 /* First, alloc and init a new struct for it */ 37 co = calloc(1, sizeof(struct Cookie)); 38 if(!co) 39@@ -816,7 +820,7 @@ Curl_cookie_add(struct Curl_easy *data, 40 freecookie(co); 41 return NULL; 42 } 43- 44+ data->req.setcookies++; 45 } 46 else { 47 /* 48@@ -1354,7 +1358,8 @@ static struct Cookie *dup_cookie(struct Cookie *src) 49 * 50 * It shall only return cookies that haven't expired. 51 */ 52-struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, 53+struct Cookie *Curl_cookie_getlist(struct Curl_easy *data, 54+ struct CookieInfo *c, 55 const char *host, const char *path, 56 bool secure) 57 { 58@@ -1409,6 +1414,11 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, 59 mainco = newco; 60 61 matches++; 62+ if(matches >= MAX_COOKIE_SEND_AMOUNT) { 63+ infof(data, "Included max number of cookies (%u) in request!", 64+ matches); 65+ break; 66+ } 67 } 68 else 69 goto fail; 70diff --git a/lib/cookie.h b/lib/cookie.h 71index 0ffe08e..7411980 100644 72--- a/lib/cookie.h 73+++ b/lib/cookie.h 74@@ -81,10 +81,26 @@ struct CookieInfo { 75 */ 76 #define MAX_COOKIE_LINE 5000 77 78-/* This is the maximum length of a cookie name or content we deal with: */ 79+/* Maximum length of an incoming cookie name or content we deal with. Longer 80+ cookies are ignored. */ 81 #define MAX_NAME 4096 82 #define MAX_NAME_TXT "4095" 83 84+/* Maximum size for an outgoing cookie line libcurl will use in an http 85+ request. This is the default maximum length used in some versions of Apache 86+ httpd. */ 87+#define MAX_COOKIE_HEADER_LEN 8190 88+ 89+/* Maximum number of cookies libcurl will send in a single request, even if 90+ there might be more cookies that match. One reason to cap the number is to 91+ keep the maximum HTTP request within the maximum allowed size. */ 92+#define MAX_COOKIE_SEND_AMOUNT 150 93+ 94+/* Maximum number of Set-Cookie: lines accepted in a single response. If more 95+ such header lines are received, they are ignored. This value must be less 96+ than 256 since an unsigned char is used to count. */ 97+#define MAX_SET_COOKIE_AMOUNT 50 98+ 99 struct Curl_easy; 100 /* 101 * Add a cookie to the internal list of cookies. The domain and path arguments 102@@ -97,7 +113,8 @@ struct Cookie *Curl_cookie_add(struct Curl_easy *data, 103 const char *domain, const char *path, 104 bool secure); 105 106-struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, const char *host, 107+struct Cookie *Curl_cookie_getlist(struct Curl_easy *data, 108+ struct CookieInfo *c, const char *host, 109 const char *path, bool secure); 110 void Curl_cookie_freelist(struct Cookie *cookies); 111 void Curl_cookie_clearall(struct CookieInfo *cookies); 112diff --git a/lib/http.c b/lib/http.c 113index 4433824..2c8b0c4 100644 114--- a/lib/http.c 115+++ b/lib/http.c 116@@ -2709,12 +2709,14 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, 117 } 118 119 #if !defined(CURL_DISABLE_COOKIES) 120+ 121 CURLcode Curl_http_cookies(struct Curl_easy *data, 122 struct connectdata *conn, 123 struct dynbuf *r) 124 { 125 CURLcode result = CURLE_OK; 126 char *addcookies = NULL; 127+ bool linecap = FALSE; 128 if(data->set.str[STRING_COOKIE] && 129 !Curl_checkheaders(data, STRCONST("Cookie"))) 130 addcookies = data->set.str[STRING_COOKIE]; 131@@ -2732,7 +2734,7 @@ CURLcode Curl_http_cookies(struct Curl_easy *data, 132 !strcmp(host, "127.0.0.1") || 133 !strcmp(host, "[::1]") ? TRUE : FALSE; 134 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); 135- co = Curl_cookie_getlist(data->cookies, host, data->state.up.path, 136+ co = Curl_cookie_getlist(data, data->cookies, host, data->state.up.path, 137 secure_context); 138 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); 139 } 140@@ -2746,6 +2748,13 @@ CURLcode Curl_http_cookies(struct Curl_easy *data, 141 if(result) 142 break; 143 } 144+ if((Curl_dyn_len(r) + strlen(co->name) + strlen(co->value) + 1) >= 145+ MAX_COOKIE_HEADER_LEN) { 146+ infof(data, "Restricted outgoing cookies due to header size, " 147+ "'%s' not sent", co->name); 148+ linecap = TRUE; 149+ break; 150+ } 151 result = Curl_dyn_addf(r, "%s%s=%s", count?"; ":"", 152 co->name, co->value); 153 if(result) 154@@ -2756,7 +2765,7 @@ CURLcode Curl_http_cookies(struct Curl_easy *data, 155 } 156 Curl_cookie_freelist(store); 157 } 158- if(addcookies && !result) { 159+ if(addcookies && !result && !linecap) { 160 if(!count) 161 result = Curl_dyn_addn(r, STRCONST("Cookie: ")); 162 if(!result) { 163diff --git a/lib/urldata.h b/lib/urldata.h 164index e006495..54faf7d 100644 165--- a/lib/urldata.h 166+++ b/lib/urldata.h 167@@ -707,6 +707,7 @@ struct SingleRequest { 168 #ifndef CURL_DISABLE_DOH 169 struct dohdata *doh; /* DoH specific data for this request */ 170 #endif 171+ unsigned char setcookies; 172 BIT(header); /* incoming data has HTTP header */ 173 BIT(content_range); /* set TRUE if Content-Range: was found */ 174 BIT(upload_done); /* set to TRUE when doing chunked transfer-encoding 175