Patrick Williams | f1e5d69 | 2016-03-30 15:21:19 -0500 | [diff] [blame^] | 1 | Backport of: |
| 2 | |
| 3 | From f4113cac0c88b4f36ee6f3abf3218034440a68e3 Mon Sep 17 00:00:00 2001 |
| 4 | From: Blake Burkhart <bburky@bburky.com> |
| 5 | Date: Tue, 22 Sep 2015 18:06:04 -0400 |
| 6 | Subject: [PATCH] http: limit redirection to protocol-whitelist |
| 7 | |
| 8 | Previously, libcurl would follow redirection to any protocol |
| 9 | it was compiled for support with. This is desirable to allow |
| 10 | redirection from HTTP to HTTPS. However, it would even |
| 11 | successfully allow redirection from HTTP to SFTP, a protocol |
| 12 | that git does not otherwise support at all. Furthermore |
| 13 | git's new protocol-whitelisting could be bypassed by |
| 14 | following a redirect within the remote helper, as it was |
| 15 | only enforced at transport selection time. |
| 16 | |
| 17 | This patch limits redirects within libcurl to HTTP, HTTPS, |
| 18 | FTP and FTPS. If there is a protocol-whitelist present, this |
| 19 | list is limited to those also allowed by the whitelist. As |
| 20 | redirection happens from within libcurl, it is impossible |
| 21 | for an HTTP redirect to a protocol implemented within |
| 22 | another remote helper. |
| 23 | |
| 24 | When the curl version git was compiled with is too old to |
| 25 | support restrictions on protocol redirection, we warn the |
| 26 | user if GIT_ALLOW_PROTOCOL restrictions were requested. This |
| 27 | is a little inaccurate, as even without that variable in the |
| 28 | environment, we would still restrict SFTP, etc, and we do |
| 29 | not warn in that case. But anything else means we would |
| 30 | literally warn every time git accesses an http remote. |
| 31 | |
| 32 | This commit includes a test, but it is not as robust as we |
| 33 | would hope. It redirects an http request to ftp, and checks |
| 34 | that curl complained about the protocol, which means that we |
| 35 | are relying on curl's specific error message to know what |
| 36 | happened. Ideally we would redirect to a working ftp server |
| 37 | and confirm that we can clone without protocol restrictions, |
| 38 | and not with them. But we do not have a portable way of |
| 39 | providing an ftp server, nor any other protocol that curl |
| 40 | supports (https is the closest, but we would have to deal |
| 41 | with certificates). |
| 42 | |
| 43 | [jk: added test and version warning] |
| 44 | |
| 45 | Signed-off-by: Jeff King <peff@peff.net> |
| 46 | Signed-off-by: Junio C Hamano <gitster@pobox.com> |
| 47 | |
| 48 | Upstream-Status: Backport |
| 49 | |
| 50 | http://archive.ubuntu.com/ubuntu/pool/main/g/git/git_2.5.0-1ubuntu0.1.debian.tar.xz |
| 51 | |
| 52 | CVE: CVE-2015-7545 #4 |
| 53 | Singed-off-by: Armin Kuster <akuster@mvista.com> |
| 54 | |
| 55 | --- |
| 56 | Documentation/git.txt | 5 ----- |
| 57 | http.c | 17 +++++++++++++++++ |
| 58 | t/lib-httpd/apache.conf | 1 + |
| 59 | t/t5812-proto-disable-http.sh | 9 +++++++++ |
| 60 | 4 files changed, 27 insertions(+), 5 deletions(-) |
| 61 | |
| 62 | Index: git-2.5.0/Documentation/git.txt |
| 63 | =================================================================== |
| 64 | --- git-2.5.0.orig/Documentation/git.txt 2015-12-11 12:47:18.707849212 -0500 |
| 65 | +++ git-2.5.0/Documentation/git.txt 2015-12-11 12:47:18.703849183 -0500 |
| 66 | @@ -1095,11 +1095,6 @@ |
| 67 | |
| 68 | - any external helpers are named by their protocol (e.g., use |
| 69 | `hg` to allow the `git-remote-hg` helper) |
| 70 | -+ |
| 71 | -Note that this controls only git's internal protocol selection. |
| 72 | -If libcurl is used (e.g., by the `http` transport), it may |
| 73 | -redirect to other protocols. There is not currently any way to |
| 74 | -restrict this. |
| 75 | |
| 76 | |
| 77 | Discussion[[Discussion]] |
| 78 | Index: git-2.5.0/http.c |
| 79 | =================================================================== |
| 80 | --- git-2.5.0.orig/http.c 2015-12-11 12:47:18.707849212 -0500 |
| 81 | +++ git-2.5.0/http.c 2015-12-11 12:47:34.171959268 -0500 |
| 82 | @@ -8,6 +8,7 @@ |
| 83 | #include "credential.h" |
| 84 | #include "version.h" |
| 85 | #include "pkt-line.h" |
| 86 | +#include "transport.h" |
| 87 | #include "gettext.h" |
| 88 | |
| 89 | int active_requests; |
| 90 | @@ -340,6 +341,7 @@ |
| 91 | static CURL *get_curl_handle(void) |
| 92 | { |
| 93 | CURL *result = curl_easy_init(); |
| 94 | + long allowed_protocols = 0; |
| 95 | |
| 96 | if (!result) |
| 97 | die("curl_easy_init failed"); |
| 98 | @@ -399,6 +401,21 @@ |
| 99 | #elif LIBCURL_VERSION_NUM >= 0x071101 |
| 100 | curl_easy_setopt(result, CURLOPT_POST301, 1); |
| 101 | #endif |
| 102 | +#if LIBCURL_VERSION_NUM >= 0x071304 |
| 103 | + if (is_transport_allowed("http")) |
| 104 | + allowed_protocols |= CURLPROTO_HTTP; |
| 105 | + if (is_transport_allowed("https")) |
| 106 | + allowed_protocols |= CURLPROTO_HTTPS; |
| 107 | + if (is_transport_allowed("ftp")) |
| 108 | + allowed_protocols |= CURLPROTO_FTP; |
| 109 | + if (is_transport_allowed("ftps")) |
| 110 | + allowed_protocols |= CURLPROTO_FTPS; |
| 111 | + curl_easy_setopt(result, CURLOPT_REDIR_PROTOCOLS, allowed_protocols); |
| 112 | +#else |
| 113 | + if (transport_restrict_protocols()) |
| 114 | + warning("protocol restrictions not applied to curl redirects because\n" |
| 115 | + "your curl version is too old (>= 7.19.4)"); |
| 116 | +#endif |
| 117 | |
| 118 | if (getenv("GIT_CURL_VERBOSE")) |
| 119 | curl_easy_setopt(result, CURLOPT_VERBOSE, 1); |
| 120 | Index: git-2.5.0/t/lib-httpd/apache.conf |
| 121 | =================================================================== |
| 122 | --- git-2.5.0.orig/t/lib-httpd/apache.conf 2015-12-11 12:47:18.707849212 -0500 |
| 123 | +++ git-2.5.0/t/lib-httpd/apache.conf 2015-12-11 12:47:18.703849183 -0500 |
| 124 | @@ -119,6 +119,7 @@ |
| 125 | RewriteRule ^/smart-redir-temp/(.*)$ /smart/$1 [R=302] |
| 126 | RewriteRule ^/smart-redir-auth/(.*)$ /auth/smart/$1 [R=301] |
| 127 | RewriteRule ^/smart-redir-limited/(.*)/info/refs$ /smart/$1/info/refs [R=301] |
| 128 | +RewriteRule ^/ftp-redir/(.*)$ ftp://localhost:1000/$1 [R=302] |
| 129 | |
| 130 | <IfDefine SSL> |
| 131 | LoadModule ssl_module modules/mod_ssl.so |
| 132 | Index: git-2.5.0/t/t5812-proto-disable-http.sh |
| 133 | =================================================================== |
| 134 | --- git-2.5.0.orig/t/t5812-proto-disable-http.sh 2015-12-11 12:47:18.707849212 -0500 |
| 135 | +++ git-2.5.0/t/t5812-proto-disable-http.sh 2015-12-11 12:47:18.703849183 -0500 |
| 136 | @@ -16,5 +16,14 @@ |
| 137 | |
| 138 | test_proto "smart http" http "$HTTPD_URL/smart/repo.git" |
| 139 | |
| 140 | +test_expect_success 'curl redirects respect whitelist' ' |
| 141 | + test_must_fail env GIT_ALLOW_PROTOCOL=http:https \ |
| 142 | + git clone "$HTTPD_URL/ftp-redir/repo.git" 2>stderr && |
| 143 | + { |
| 144 | + test_i18ngrep "ftp.*disabled" stderr || |
| 145 | + test_i18ngrep "your curl version is too old" |
| 146 | + } |
| 147 | +' |
| 148 | + |
| 149 | stop_httpd |
| 150 | test_done |