| Backport of: |
| |
| From f4113cac0c88b4f36ee6f3abf3218034440a68e3 Mon Sep 17 00:00:00 2001 |
| From: Blake Burkhart <bburky@bburky.com> |
| Date: Tue, 22 Sep 2015 18:06:04 -0400 |
| Subject: [PATCH] http: limit redirection to protocol-whitelist |
| |
| Previously, libcurl would follow redirection to any protocol |
| it was compiled for support with. This is desirable to allow |
| redirection from HTTP to HTTPS. However, it would even |
| successfully allow redirection from HTTP to SFTP, a protocol |
| that git does not otherwise support at all. Furthermore |
| git's new protocol-whitelisting could be bypassed by |
| following a redirect within the remote helper, as it was |
| only enforced at transport selection time. |
| |
| This patch limits redirects within libcurl to HTTP, HTTPS, |
| FTP and FTPS. If there is a protocol-whitelist present, this |
| list is limited to those also allowed by the whitelist. As |
| redirection happens from within libcurl, it is impossible |
| for an HTTP redirect to a protocol implemented within |
| another remote helper. |
| |
| When the curl version git was compiled with is too old to |
| support restrictions on protocol redirection, we warn the |
| user if GIT_ALLOW_PROTOCOL restrictions were requested. This |
| is a little inaccurate, as even without that variable in the |
| environment, we would still restrict SFTP, etc, and we do |
| not warn in that case. But anything else means we would |
| literally warn every time git accesses an http remote. |
| |
| This commit includes a test, but it is not as robust as we |
| would hope. It redirects an http request to ftp, and checks |
| that curl complained about the protocol, which means that we |
| are relying on curl's specific error message to know what |
| happened. Ideally we would redirect to a working ftp server |
| and confirm that we can clone without protocol restrictions, |
| and not with them. But we do not have a portable way of |
| providing an ftp server, nor any other protocol that curl |
| supports (https is the closest, but we would have to deal |
| with certificates). |
| |
| [jk: added test and version warning] |
| |
| Signed-off-by: Jeff King <peff@peff.net> |
| Signed-off-by: Junio C Hamano <gitster@pobox.com> |
| |
| Upstream-Status: Backport |
| |
| http://archive.ubuntu.com/ubuntu/pool/main/g/git/git_2.5.0-1ubuntu0.1.debian.tar.xz |
| |
| CVE: CVE-2015-7545 #4 |
| Singed-off-by: Armin Kuster <akuster@mvista.com> |
| |
| --- |
| Documentation/git.txt | 5 ----- |
| http.c | 17 +++++++++++++++++ |
| t/lib-httpd/apache.conf | 1 + |
| t/t5812-proto-disable-http.sh | 9 +++++++++ |
| 4 files changed, 27 insertions(+), 5 deletions(-) |
| |
| Index: git-2.5.0/Documentation/git.txt |
| =================================================================== |
| --- git-2.5.0.orig/Documentation/git.txt 2015-12-11 12:47:18.707849212 -0500 |
| +++ git-2.5.0/Documentation/git.txt 2015-12-11 12:47:18.703849183 -0500 |
| @@ -1095,11 +1095,6 @@ |
| |
| - any external helpers are named by their protocol (e.g., use |
| `hg` to allow the `git-remote-hg` helper) |
| -+ |
| -Note that this controls only git's internal protocol selection. |
| -If libcurl is used (e.g., by the `http` transport), it may |
| -redirect to other protocols. There is not currently any way to |
| -restrict this. |
| |
| |
| Discussion[[Discussion]] |
| Index: git-2.5.0/http.c |
| =================================================================== |
| --- git-2.5.0.orig/http.c 2015-12-11 12:47:18.707849212 -0500 |
| +++ git-2.5.0/http.c 2015-12-11 12:47:34.171959268 -0500 |
| @@ -8,6 +8,7 @@ |
| #include "credential.h" |
| #include "version.h" |
| #include "pkt-line.h" |
| +#include "transport.h" |
| #include "gettext.h" |
| |
| int active_requests; |
| @@ -340,6 +341,7 @@ |
| static CURL *get_curl_handle(void) |
| { |
| CURL *result = curl_easy_init(); |
| + long allowed_protocols = 0; |
| |
| if (!result) |
| die("curl_easy_init failed"); |
| @@ -399,6 +401,21 @@ |
| #elif LIBCURL_VERSION_NUM >= 0x071101 |
| curl_easy_setopt(result, CURLOPT_POST301, 1); |
| #endif |
| +#if LIBCURL_VERSION_NUM >= 0x071304 |
| + if (is_transport_allowed("http")) |
| + allowed_protocols |= CURLPROTO_HTTP; |
| + if (is_transport_allowed("https")) |
| + allowed_protocols |= CURLPROTO_HTTPS; |
| + if (is_transport_allowed("ftp")) |
| + allowed_protocols |= CURLPROTO_FTP; |
| + if (is_transport_allowed("ftps")) |
| + allowed_protocols |= CURLPROTO_FTPS; |
| + curl_easy_setopt(result, CURLOPT_REDIR_PROTOCOLS, allowed_protocols); |
| +#else |
| + if (transport_restrict_protocols()) |
| + warning("protocol restrictions not applied to curl redirects because\n" |
| + "your curl version is too old (>= 7.19.4)"); |
| +#endif |
| |
| if (getenv("GIT_CURL_VERBOSE")) |
| curl_easy_setopt(result, CURLOPT_VERBOSE, 1); |
| Index: git-2.5.0/t/lib-httpd/apache.conf |
| =================================================================== |
| --- git-2.5.0.orig/t/lib-httpd/apache.conf 2015-12-11 12:47:18.707849212 -0500 |
| +++ git-2.5.0/t/lib-httpd/apache.conf 2015-12-11 12:47:18.703849183 -0500 |
| @@ -119,6 +119,7 @@ |
| RewriteRule ^/smart-redir-temp/(.*)$ /smart/$1 [R=302] |
| RewriteRule ^/smart-redir-auth/(.*)$ /auth/smart/$1 [R=301] |
| RewriteRule ^/smart-redir-limited/(.*)/info/refs$ /smart/$1/info/refs [R=301] |
| +RewriteRule ^/ftp-redir/(.*)$ ftp://localhost:1000/$1 [R=302] |
| |
| <IfDefine SSL> |
| LoadModule ssl_module modules/mod_ssl.so |
| Index: git-2.5.0/t/t5812-proto-disable-http.sh |
| =================================================================== |
| --- git-2.5.0.orig/t/t5812-proto-disable-http.sh 2015-12-11 12:47:18.707849212 -0500 |
| +++ git-2.5.0/t/t5812-proto-disable-http.sh 2015-12-11 12:47:18.703849183 -0500 |
| @@ -16,5 +16,14 @@ |
| |
| test_proto "smart http" http "$HTTPD_URL/smart/repo.git" |
| |
| +test_expect_success 'curl redirects respect whitelist' ' |
| + test_must_fail env GIT_ALLOW_PROTOCOL=http:https \ |
| + git clone "$HTTPD_URL/ftp-redir/repo.git" 2>stderr && |
| + { |
| + test_i18ngrep "ftp.*disabled" stderr || |
| + test_i18ngrep "your curl version is too old" |
| + } |
| +' |
| + |
| stop_httpd |
| test_done |