From de47e687225dd480389dbe84ae7ac595014a1083 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 15 Sep 2022 09:22:45 +0200 Subject: [PATCH 1/5] fix CVE-2022-32221, setopt: when POST is set, reset the 'upload' field Reported-by: RobBotic1 on github Fixes #9507 Closes #9511 Signed-off-by: zhouhaifeng --- lib/setopt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/setopt.c b/lib/setopt.c index 4cc3e76b3..6edd187ac 100644 --- a/lib/setopt.c +++ b/lib/setopt.c @@ -630,6 +630,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) } else data->set.method = HTTPREQ_GET; + data->set.upload = FALSE; break; case CURLOPT_HTTPPOST: -- Gitee From b9e0e9b46936e02c278571cfb602efddeea3722b Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 15 Sep 2022 09:23:33 +0200 Subject: [PATCH 2/5] fix CVE-2022-32221, test1948: verify PUT + POST reusing the same handle Reproduced #9507, verifies the fix Signed-off-by: zhouhaifeng --- tests/data/Makefile.inc | 2 +- tests/data/test1948 | 73 +++++++++++++++++++++++++++++++++++ tests/libtest/Makefile.inc | 5 +++ tests/libtest/lib1948.c | 79 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 tests/data/test1948 create mode 100644 tests/libtest/lib1948.c diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc index b2f490715..c2dc0b265 100644 --- a/tests/data/Makefile.inc +++ b/tests/data/Makefile.inc @@ -217,7 +217,7 @@ test1800 test1801 \ test1908 test1909 test1910 test1911 test1912 test1913 test1914 test1915 \ test1916 test1917 test1918 \ \ -test1933 test1934 test1935 test1936 \ +test1933 test1934 test1935 test1936 test1948 \ \ test2000 test2001 test2002 test2003 test2004 \ \ diff --git a/tests/data/test1948 b/tests/data/test1948 new file mode 100644 index 000000000..550231d4f --- /dev/null +++ b/tests/data/test1948 @@ -0,0 +1,73 @@ + + + +HTTP +HTTP POST +HTTP PUT + + + +# Server-side + + +HTTP/1.1 200 OK +Date: Thu, 01 Nov 2001 14:49:00 GMT +Content-Type: text/html +Content-Length: 6 + +hello + + +HTTP/1.1 200 OK +Date: Thu, 01 Nov 2001 14:49:00 GMT +Content-Type: text/html +Content-Length: 6 + +hello +HTTP/1.1 200 OK +Date: Thu, 01 Nov 2001 14:49:00 GMT +Content-Type: text/html +Content-Length: 6 + +hello + + + +# Client-side + + +http + + + +CURLOPT_POST after CURLOPT_UPLOAD reusing handle + + +lib%TESTNUMBER + + + +http://%HOSTIP:%HTTPPORT/%TESTNUMBER + + + +# Verify data after the test has been "shot" + + +PUT /%TESTNUMBER HTTP/1.1 +Host: %HOSTIP:%HTTPPORT +Accept: */* +Content-Length: 22 +Expect: 100-continue + +This is test PUT data +POST /1948 HTTP/1.1 +Host: %HOSTIP:%HTTPPORT +Accept: */* +Content-Length: 22 +Content-Type: application/x-www-form-urlencoded + +This is test PUT data + + + diff --git a/tests/libtest/Makefile.inc b/tests/libtest/Makefile.inc index c2d0a6e8e..d1b1f0b0c 100644 --- a/tests/libtest/Makefile.inc +++ b/tests/libtest/Makefile.inc @@ -61,6 +61,7 @@ noinst_PROGRAMS = chkhostname libauthretry libntlmconnect \ lib1591 lib1592 lib1593 lib1594 lib1596 \ lib1905 lib1906 lib1907 lib1908 lib1910 lib1911 lib1912 lib1913 \ lib1915 lib1916 lib1917 lib1918 lib1933 lib1934 lib1935 lib1936 \ + lib1948 \ lib3010 chkdecimalpoint_SOURCES = chkdecimalpoint.c ../../lib/mprintf.c \ @@ -699,6 +700,10 @@ lib1936_SOURCES = lib1936.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) lib1936_LDADD = $(TESTUTIL_LIBS) lib1936_CPPFLAGS = $(AM_CPPFLAGS) +lib1948_SOURCES = lib1948.c $(SUPPORTFILES) +lib1948_LDADD = $(TESTUTIL_LIBS) +lib1948_CPPFLAGS = $(AM_CPPFLAGS) + lib3010_SOURCES = lib3010.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) lib3010_LDADD = $(TESTUTIL_LIBS) lib3010_CPPFLAGS = $(AM_CPPFLAGS) diff --git a/tests/libtest/lib1948.c b/tests/libtest/lib1948.c new file mode 100644 index 000000000..7c891a2ca --- /dev/null +++ b/tests/libtest/lib1948.c @@ -0,0 +1,79 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2022, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * SPDX-License-Identifier: curl + * + ***************************************************************************/ + +#include "test.h" + +typedef struct +{ + char *buf; + size_t len; +} put_buffer; + +static size_t put_callback(char *ptr, size_t size, size_t nmemb, void *stream) +{ + put_buffer *putdata = (put_buffer *)stream; + size_t totalsize = size * nmemb; + size_t tocopy = (putdata->len < totalsize) ? putdata->len : totalsize; + memcpy(ptr, putdata->buf, tocopy); + putdata->len -= tocopy; + putdata->buf += tocopy; + return tocopy; +} + +int test(char *URL) +{ + CURL *curl; + CURLcode res = CURLE_OUT_OF_MEMORY; + + curl_global_init(CURL_GLOBAL_DEFAULT); + + curl = curl_easy_init(); + if(curl) { + const char *testput = "This is test PUT data\n"; + put_buffer pbuf; + + /* PUT */ + curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); + curl_easy_setopt(curl, CURLOPT_HEADER, 1L); + curl_easy_setopt(curl, CURLOPT_READFUNCTION, put_callback); + pbuf.buf = (char *)testput; + pbuf.len = strlen(testput); + curl_easy_setopt(curl, CURLOPT_READDATA, &pbuf); + curl_easy_setopt(curl, CURLOPT_INFILESIZE, (long)strlen(testput)); + res = curl_easy_setopt(curl, CURLOPT_URL, URL); + if(!res) + res = curl_easy_perform(curl); + if(!res) { + /* POST */ + curl_easy_setopt(curl, CURLOPT_POST, 1L); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, testput); + curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)strlen(testput)); + res = curl_easy_perform(curl); + } + curl_easy_cleanup(curl); + } + + curl_global_cleanup(); + return (int)res; +} -- Gitee From 7e6e88f212df82a24bbf774bb4bf0eebdd08c4e3 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 12 Oct 2022 10:47:59 +0200 Subject: [PATCH 3/5] fix CVE-2022-42916, url: use IDN decoded names for HSTS checks Reported-by: Hiroki Kurosawa Closes #9791 Signed-off-by: zhouhaifeng --- lib/url.c | 93 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 49 insertions(+), 44 deletions(-) diff --git a/lib/url.c b/lib/url.c index 0d74884c9..8b35f9457 100644 --- a/lib/url.c +++ b/lib/url.c @@ -1994,9 +1994,56 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, return CURLE_OUT_OF_MEMORY; } + hostname = data->state.up.hostname; + + if(hostname && hostname[0] == '[') { + /* This looks like an IPv6 address literal. See if there is an address + scope. */ + size_t hlen; + conn->bits.ipv6_ip = TRUE; + /* cut off the brackets! */ + hostname++; + hlen = strlen(hostname); + hostname[hlen - 1] = 0; + + zonefrom_url(uh, data, conn); + } + + /* make sure the connect struct gets its own copy of the host name */ + conn->host.rawalloc = strdup(hostname ? hostname : ""); + if(!conn->host.rawalloc) + return CURLE_OUT_OF_MEMORY; + conn->host.name = conn->host.rawalloc; + + /************************************************************* + * IDN-convert the hostnames + *************************************************************/ + result = Curl_idnconvert_hostname(data, &conn->host); + if(result) + return result; + if(conn->bits.conn_to_host) { + result = Curl_idnconvert_hostname(data, &conn->conn_to_host); + if(result) + return result; + } +#ifndef CURL_DISABLE_PROXY + if(conn->bits.httpproxy) { + result = Curl_idnconvert_hostname(data, &conn->http_proxy.host); + if(result) + return result; + } + if(conn->bits.socksproxy) { + result = Curl_idnconvert_hostname(data, &conn->socks_proxy.host); + if(result) + return result; + } +#endif + #ifndef CURL_DISABLE_HSTS + /* HSTS upgrade */ if(data->hsts && strcasecompare("http", data->state.up.scheme)) { - if(Curl_hsts(data->hsts, data->state.up.hostname, TRUE)) { + /* This MUST use the IDN decoded name */ + if(Curl_hsts(data->hsts, conn->host.name, TRUE)) { char *url; Curl_safefree(data->state.up.scheme); uc = curl_url_set(uh, CURLUPART_SCHEME, "https", 0); @@ -2099,26 +2146,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, (void)curl_url_get(uh, CURLUPART_QUERY, &data->state.up.query, 0); - hostname = data->state.up.hostname; - if(hostname && hostname[0] == '[') { - /* This looks like an IPv6 address literal. See if there is an address - scope. */ - size_t hlen; - conn->bits.ipv6_ip = TRUE; - /* cut off the brackets! */ - hostname++; - hlen = strlen(hostname); - hostname[hlen - 1] = 0; - - zonefrom_url(uh, data, conn); - } - - /* make sure the connect struct gets its own copy of the host name */ - conn->host.rawalloc = strdup(hostname ? hostname : ""); - if(!conn->host.rawalloc) - return CURLE_OUT_OF_MEMORY; - conn->host.name = conn->host.rawalloc; - +#ifdef ENABLE_IPV6 if(data->set.scope_id) /* Override any scope that was set above. */ conn->scope_id = data->set.scope_id; @@ -3671,29 +3699,6 @@ static CURLcode create_conn(struct Curl_easy *data, if(result) goto out; - /************************************************************* - * IDN-convert the hostnames - *************************************************************/ - result = Curl_idnconvert_hostname(data, &conn->host); - if(result) - goto out; - if(conn->bits.conn_to_host) { - result = Curl_idnconvert_hostname(data, &conn->conn_to_host); - if(result) - goto out; - } -#ifndef CURL_DISABLE_PROXY - if(conn->bits.httpproxy) { - result = Curl_idnconvert_hostname(data, &conn->http_proxy.host); - if(result) - goto out; - } - if(conn->bits.socksproxy) { - result = Curl_idnconvert_hostname(data, &conn->socks_proxy.host); - if(result) - goto out; - } -#endif /************************************************************* * Check whether the host and the "connect to host" are equal. -- Gitee From 8b633ad5f3110a440e9e4e2d0f0029be1db3b3d4 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 6 Oct 2022 14:13:36 +0200 Subject: [PATCH 4/5] fix CVE-2022-42915, http_proxy: restore the protocol pointer on error Reported-by: Trail of Bits Closes #9790 Signed-off-by: zhouhaifeng --- lib/http_proxy.c | 1 - lib/url.c | 9 --------- 2 files changed, 10 deletions(-) diff --git a/lib/http_proxy.c b/lib/http_proxy.c index a7f7aa353..3927e9455 100644 --- a/lib/http_proxy.c +++ b/lib/http_proxy.c @@ -209,7 +209,6 @@ static void connect_done(struct Curl_easy *data) /* retore the protocol pointer */ data->req.p.http = s->prot_save; - s->prot_save = NULL; infof(data, "CONNECT phase completed!"); } } diff --git a/lib/url.c b/lib/url.c index 8b35f9457..cd2250f55 100644 --- a/lib/url.c +++ b/lib/url.c @@ -735,15 +735,6 @@ static void conn_shutdown(struct Curl_easy *data, struct connectdata *conn) DEBUGASSERT(data); infof(data, "Closing connection %ld", conn->connection_id); -#ifndef USE_HYPER - if(conn->connect_state && conn->connect_state->prot_save) { - /* If this was closed with a CONNECT in progress, cleanup this temporary - struct arrangement */ - data->req.p.http = NULL; - Curl_safefree(conn->connect_state->prot_save); - } -#endif - /* possible left-overs from the async name resolvers */ Curl_resolver_cancel(data); -- Gitee From 32fa01f50b67b20075680196326a2c84b6a35570 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 6 Oct 2022 14:14:25 +0200 Subject: [PATCH 5/5] fix CVE-2022-42915, test445: verifies the protocols-over-http-proxy flaw and fix Signed-off-by: zhouhaifeng --- lib/url.c | 1 - tests/data/Makefile.inc | 2 +- tests/data/test445 | 61 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 tests/data/test445 diff --git a/lib/url.c b/lib/url.c index cd2250f55..10d6ade8c 100644 --- a/lib/url.c +++ b/lib/url.c @@ -2137,7 +2137,6 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, (void)curl_url_get(uh, CURLUPART_QUERY, &data->state.up.query, 0); -#ifdef ENABLE_IPV6 if(data->set.scope_id) /* Override any scope that was set above. */ conn->scope_id = data->set.scope_id; diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc index c2dc0b265..4368ddf3d 100644 --- a/tests/data/Makefile.inc +++ b/tests/data/Makefile.inc @@ -69,7 +69,7 @@ test409 test410 \ \ test430 test431 test432 test433 test434 \ \ -test442 test443 test444 \ +test442 test443 test444 test445 \ \ test490 test491 test492 test493 test494 \ \ diff --git a/tests/data/test445 b/tests/data/test445 new file mode 100644 index 000000000..0406c0f9a --- /dev/null +++ b/tests/data/test445 @@ -0,0 +1,61 @@ + + + +HTTP +HTTP proxy + + + +# +# Server-side + + +HTTP/1.1 503 no just no +Date: Tue, 09 Nov 2010 14:49:00 GMT +Server: test-server/fake +Accept-Ranges: bytes +Content-Length: 6 +Connection: close + +-foo- + + + +# +# Client-side + + +gopher +dict +http +ftp +imap +ldap +mqtt +pop3 +rtsp +scp +sftp +smb +smtp + + +http-proxy + + +Refuse tunneling protocols through HTTP proxy + + +-x http://%HOSTIP:%PROXYPORT/%TESTNUMBER -p gopher://127.0.0.1 dict://127.0.0.1 http://moo https://example telnet://another ftp://yes ftps://again imap://more ldap://perhaps mqtt://yes pop3://mail rtsp://harder scp://copy sftp://files smb://wird smtp://send + + + +# +# Verify data after the test has been "shot" + +# refused in the CONNECT + +56 + + + -- Gitee