]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
http: prevent custom Authorization headers in redirects
authorDaniel Stenberg <daniel@haxx.se>
Fri, 19 Jan 2018 12:19:25 +0000 (13:19 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 22 Jan 2018 09:00:00 +0000 (10:00 +0100)
... unless CURLOPT_UNRESTRICTED_AUTH is set to allow them. This matches how
curl already handles Authorization headers created internally.

Note: this changes behavior slightly, for the sake of reducing mistakes.

Added test 317 and 318 to verify.

Reported-by: Craig de Stigter
Bug: https://curl.haxx.se/docs/adv_2018-b3bf.html

docs/libcurl/opts/CURLOPT_HTTPHEADER.3
lib/http.c
lib/setopt.c
lib/urldata.h
tests/data/Makefile.inc
tests/data/test317 [new file with mode: 0644]
tests/data/test318 [new file with mode: 0644]

index c5ccb1a53dd90acdc030393607e4eb44c5c5da22..c9f29e393ed5fd9861ba6b442281e4b94ffc14ad 100644 (file)
@@ -5,7 +5,7 @@
 .\" *                            | (__| |_| |  _ <| |___
 .\" *                             \___|\___/|_| \_\_____|
 .\" *
-.\" * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
 .\" *
 .\" * This software is licensed as described in the file COPYING, which
 .\" * you should have received as part of this distribution. The terms
@@ -77,6 +77,16 @@ the headers. They may be private or otherwise sensitive to leak.
 
 Use \fICURLOPT_HEADEROPT(3)\fP to make the headers only get sent to where you
 intend them to get sent.
+
+Custom headers are sent in all requests done by the easy handles, which
+implies that if you tell libcurl to follow redirects
+(\fBCURLOPT_FOLLOWLOCATION(3)\fP), the same set of custom headers will be sent
+in the subsequent request. Redirects can of course go to other hosts and thus
+those servers will get all the contents of your custom headers too.
+
+Starting in 7.58.0, libcurl will specifically prevent "Authorization:" headers
+from being sent to other hosts than the first used one, unless specifically
+permitted with the \fBCURLOPT_UNRESTRICTED_AUTH(3)\fP option.
 .SH DEFAULT
 NULL
 .SH PROTOCOLS
index c1cdf2da0267c8f667c65209c5ed63c5ef2e059e..a5007670d7c23d7eb40bb8b61b9aac5bb5c4e03d 100644 (file)
@@ -714,7 +714,7 @@ Curl_http_output_auth(struct connectdata *conn,
   if(!data->state.this_is_a_follow ||
      conn->bits.netrc ||
      !data->state.first_host ||
-     data->set.http_disable_hostname_check_before_authentication ||
+     data->set.allow_auth_to_other_hosts ||
      strcasecompare(data->state.first_host, conn->host.name)) {
     result = output_auth_headers(conn, authhost, request, path, FALSE);
   }
@@ -1636,6 +1636,14 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
                   checkprefix("Transfer-Encoding:", headers->data))
             /* HTTP/2 doesn't support chunked requests */
             ;
+          else if(checkprefix("Authorization:", headers->data) &&
+                  /* be careful of sending this potentially sensitive header to
+                     other hosts */
+                  (data->state.this_is_a_follow &&
+                   data->state.first_host &&
+                   !data->set.allow_auth_to_other_hosts &&
+                   !strcasecompare(data->state.first_host, conn->host.name)))
+            ;
           else {
             CURLcode result = Curl_add_bufferf(req_buffer, "%s\r\n",
                                                headers->data);
index 66f30ea653608bcb7c0513b14e342d2ee8089a3f..a5ef75c722a946a39140bfc882ea0c1584279175 100644 (file)
@@ -442,7 +442,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
      * Send authentication (user+password) when following locations, even when
      * hostname changed.
      */
-    data->set.http_disable_hostname_check_before_authentication =
+    data->set.allow_auth_to_other_hosts =
       (0 != va_arg(param, long)) ? TRUE : FALSE;
     break;
 
index 4dcd1a322c3979c79a01b1e535509d40b19c39ba..5c04ad172064e573284d91e2ce7d544f1896a1ad 100644 (file)
@@ -1599,7 +1599,7 @@ struct UserDefined {
   bool http_keep_sending_on_error; /* for HTTP status codes >= 300 */
   bool http_follow_location; /* follow HTTP redirects */
   bool http_transfer_encoding; /* request compressed HTTP transfer-encoding */
-  bool http_disable_hostname_check_before_authentication;
+  bool allow_auth_to_other_hosts;
   bool include_header;   /* include received protocol headers in data output */
   bool http_set_referer; /* is a custom referer used */
   bool http_auto_referer; /* set "correct" referer when following location: */
index 7e3ca25d5f42c9576b6484346beccfa914759835..a2cf70bcdec5e99a49f4f8a39d346c1906352286 100644 (file)
@@ -55,7 +55,7 @@ test280 test281 test282 test283 test284 test285 test286 test287 test288 \
 test289 test290 test291 test292 test293 test294 test295 test296 test297 \
 test298 test299 test300 test301 test302 test303 test304 test305 test306 \
 test307 test308 test309 test310 test311 test312 test313 test314 test315 \
-test316                         test320 test321 test322 test323 test324 \
+test316 test317 test318         test320 test321 test322 test323 test324 \
 test325 \
 test350 test351 test352 test353 test354 \
 test393 test394 test395 \
diff --git a/tests/data/test317 b/tests/data/test317
new file mode 100644 (file)
index 0000000..c6d8697
--- /dev/null
@@ -0,0 +1,94 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP proxy
+HTTP Basic auth
+HTTP proxy Basic auth
+followlocation
+</keywords>
+</info>
+#
+# Server-side
+<reply>
+<data>
+HTTP/1.1 302 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake swsclose
+Content-Type: text/html
+Funny-head: yesyes
+Location: http://goto.second.host.now/3170002
+Content-Length: 8
+Connection: close
+
+contents
+</data>
+<data2>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake swsclose
+Content-Type: text/html
+Funny-head: yesyes
+Content-Length: 9
+
+contents
+</data2>
+
+<datacheck>
+HTTP/1.1 302 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake swsclose
+Content-Type: text/html
+Funny-head: yesyes
+Location: http://goto.second.host.now/3170002
+Content-Length: 8
+Connection: close
+
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake swsclose
+Content-Type: text/html
+Funny-head: yesyes
+Content-Length: 9
+
+contents
+</datacheck>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+HTTP with custom Authorization: and redirect to new host
+ </name>
+ <command>
+http://first.host.it.is/we/want/that/page/317 -x %HOSTIP:%HTTPPORT -H "Authorization: s3cr3t" --proxy-user testing:this --location
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<protocol>
+GET http://first.host.it.is/we/want/that/page/317 HTTP/1.1\r
+Host: first.host.it.is\r
+Proxy-Authorization: Basic dGVzdGluZzp0aGlz\r
+Accept: */*\r
+Proxy-Connection: Keep-Alive\r
+Authorization: s3cr3t\r
+\r
+GET http://goto.second.host.now/3170002 HTTP/1.1\r
+Host: goto.second.host.now\r
+Proxy-Authorization: Basic dGVzdGluZzp0aGlz\r
+Accept: */*\r
+Proxy-Connection: Keep-Alive\r
+\r
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test318 b/tests/data/test318
new file mode 100644 (file)
index 0000000..838d1ba
--- /dev/null
@@ -0,0 +1,95 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP proxy
+HTTP Basic auth
+HTTP proxy Basic auth
+followlocation
+</keywords>
+</info>
+#
+# Server-side
+<reply>
+<data>
+HTTP/1.1 302 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake swsclose
+Content-Type: text/html
+Funny-head: yesyes
+Location: http://goto.second.host.now/3180002
+Content-Length: 8
+Connection: close
+
+contents
+</data>
+<data2>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake swsclose
+Content-Type: text/html
+Funny-head: yesyes
+Content-Length: 9
+
+contents
+</data2>
+
+<datacheck>
+HTTP/1.1 302 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake swsclose
+Content-Type: text/html
+Funny-head: yesyes
+Location: http://goto.second.host.now/3180002
+Content-Length: 8
+Connection: close
+
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake swsclose
+Content-Type: text/html
+Funny-head: yesyes
+Content-Length: 9
+
+contents
+</datacheck>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+HTTP with custom Authorization: and redirect to new host
+ </name>
+ <command>
+http://first.host.it.is/we/want/that/page/318 -x %HOSTIP:%HTTPPORT -H "Authorization: s3cr3t" --proxy-user testing:this --location-trusted
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<protocol>
+GET http://first.host.it.is/we/want/that/page/318 HTTP/1.1\r
+Host: first.host.it.is\r
+Proxy-Authorization: Basic dGVzdGluZzp0aGlz\r
+Accept: */*\r
+Proxy-Connection: Keep-Alive\r
+Authorization: s3cr3t\r
+\r
+GET http://goto.second.host.now/3180002 HTTP/1.1\r
+Host: goto.second.host.now\r
+Proxy-Authorization: Basic dGVzdGluZzp0aGlz\r
+Accept: */*\r
+Proxy-Connection: Keep-Alive\r
+Authorization: s3cr3t\r
+\r
+</protocol>
+</verify>
+</testcase>