107 lines
3.7 KiB
Diff
107 lines
3.7 KiB
Diff
From 1a3609e402a062ef7b11f197fe96c28cabca132c Mon Sep 17 00:00:00 2001
|
|
From: Jonathan Nieder <jrnieder@gmail.com>
|
|
Date: Sat, 18 Apr 2020 20:57:22 -0700
|
|
Subject: [PATCH] fsck: reject URL with empty host in .gitmodules
|
|
|
|
Git's URL parser interprets
|
|
|
|
https:///example.com/repo.git
|
|
|
|
to have no host and a path of "example.com/repo.git". Curl, on the
|
|
other hand, internally redirects it to https://example.com/repo.git. As
|
|
a result, until "credential: parse URL without host as empty host, not
|
|
unset", tricking a user into fetching from such a URL would cause Git to
|
|
send credentials for another host to example.com.
|
|
|
|
Teach fsck to block and detect .gitmodules files using such a URL to
|
|
prevent sharing them with Git versions that are not yet protected.
|
|
|
|
A relative URL in a .gitmodules file could also be used to trigger this.
|
|
The relative URL resolver used for .gitmodules does not normalize
|
|
sequences of slashes and can follow ".." components out of the path part
|
|
and to the host part of a URL, meaning that such a relative URL can be
|
|
used to traverse from a https://foo.example.com/innocent superproject to
|
|
a https:///attacker.example.com/exploit submodule. Fortunately,
|
|
redundant extra slashes in .gitmodules are rare, so we can catch this by
|
|
detecting one after a leading sequence of "./" and "../" components.
|
|
|
|
Helped-by: Jeff King <peff@peff.net>
|
|
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
|
|
Reviewed-by: Jeff King <peff@peff.net>
|
|
---
|
|
fsck.c | 10 +++++++---
|
|
t/t7416-submodule-dash-url.sh | 32 ++++++++++++++++++++++++++++++++
|
|
2 files changed, 39 insertions(+), 3 deletions(-)
|
|
|
|
--- a/fsck.c
|
|
+++ b/fsck.c
|
|
@@ -1105,17 +1105,21 @@ static int check_submodule_url(const cha
|
|
/*
|
|
* URLs which escape their root via "../" can overwrite
|
|
* the host field and previous components, resolving to
|
|
- * URLs like https::example.com/submodule.git that were
|
|
+ * URLs like https::example.com/submodule.git and
|
|
+ * https:///example.com/submodule.git that were
|
|
* susceptible to CVE-2020-11008.
|
|
*/
|
|
if (count_leading_dotdots(url, &next) > 0 &&
|
|
- *next == ':')
|
|
+ (*next == ':' || *next == '/'))
|
|
return -1;
|
|
}
|
|
|
|
else if (url_to_curl_url(url, &curl_url)) {
|
|
struct credential c = CREDENTIAL_INIT;
|
|
- int ret = credential_from_url_gently(&c, curl_url, 1);
|
|
+ int ret = 0;
|
|
+ if (credential_from_url_gently(&c, curl_url, 1) ||
|
|
+ !*c.host)
|
|
+ ret = -1;
|
|
credential_clear(&c);
|
|
return ret;
|
|
}
|
|
--- a/t/t7416-submodule-dash-url.sh
|
|
+++ b/t/t7416-submodule-dash-url.sh
|
|
@@ -124,6 +124,38 @@ test_expect_success 'fsck rejects relati
|
|
grep gitmodulesUrl err
|
|
'
|
|
|
|
+test_expect_success 'fsck rejects empty hostname' '
|
|
+ git checkout --orphan empty-host &&
|
|
+ cat >.gitmodules <<-\EOF &&
|
|
+ [submodule "foo"]
|
|
+ url = http:///one.example.com/foo.git
|
|
+ EOF
|
|
+ git add .gitmodules &&
|
|
+ test_tick &&
|
|
+ git commit -m "gitmodules with extra slashes" &&
|
|
+ test_when_finished "rm -rf dst" &&
|
|
+ git init --bare dst &&
|
|
+ git -C dst config transfer.fsckObjects true &&
|
|
+ test_must_fail git push dst HEAD 2>err &&
|
|
+ grep gitmodulesUrl err
|
|
+'
|
|
+
|
|
+test_expect_success 'fsck rejects relative url that produced empty hostname' '
|
|
+ git checkout --orphan messy-relative &&
|
|
+ cat >.gitmodules <<-\EOF &&
|
|
+ [submodule "foo"]
|
|
+ url = ../../..//one.example.com/foo.git
|
|
+ EOF
|
|
+ git add .gitmodules &&
|
|
+ test_tick &&
|
|
+ git commit -m "gitmodules abusing relative_path" &&
|
|
+ test_when_finished "rm -rf dst" &&
|
|
+ git init --bare dst &&
|
|
+ git -C dst config transfer.fsckObjects true &&
|
|
+ test_must_fail git push dst HEAD 2>err &&
|
|
+ grep gitmodulesUrl err
|
|
+'
|
|
+
|
|
test_expect_success 'fsck permits embedded newline with unrecognized scheme' '
|
|
git checkout --orphan newscheme &&
|
|
cat >.gitmodules <<-\EOF &&
|
|
--
|
|
1.8.3.1
|
|
|