summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/git/git/CVE-2020-11008-7.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-devtools/git/git/CVE-2020-11008-7.patch')
-rw-r--r--meta/recipes-devtools/git/git/CVE-2020-11008-7.patch206
1 files changed, 206 insertions, 0 deletions
diff --git a/meta/recipes-devtools/git/git/CVE-2020-11008-7.patch b/meta/recipes-devtools/git/git/CVE-2020-11008-7.patch
new file mode 100644
index 0000000000..5e3b6f1454
--- /dev/null
+++ b/meta/recipes-devtools/git/git/CVE-2020-11008-7.patch
@@ -0,0 +1,206 @@
1From 68acf8724e9cb2f67664dd980581c0022401daf0 Mon Sep 17 00:00:00 2001
2From: Jonathan Nieder <jrnieder@gmail.com>
3Date: Sat, 18 Apr 2020 20:54:13 -0700
4Subject: [PATCH 10/12] credential: treat URL without scheme as invalid
5
6libcurl permits making requests without a URL scheme specified. In
7this case, it guesses the URL from the hostname, so I can run
8
9 git ls-remote http::ftp.example.com/path/to/repo
10
11and it would make an FTP request.
12
13Any user intentionally using such a URL is likely to have made a typo.
14Unfortunately, credential_from_url is not able to determine the host and
15protocol in order to determine appropriate credentials to send, and
16until "credential: refuse to operate when missing host or protocol",
17this resulted in another host's credentials being leaked to the named
18host.
19
20Teach credential_from_url_gently to consider such a URL to be invalid
21so that fsck can detect and block gitmodules files with such URLs,
22allowing server operators to avoid serving them to downstream users
23running older versions of Git.
24
25This also means that when such URLs are passed on the command line, Git
26will print a clearer error so affected users can switch to the simpler
27URL that explicitly specifies the host and protocol they intend.
28
29One subtlety: .gitmodules files can contain relative URLs, representing
30a URL relative to the URL they were cloned from. The relative URL
31resolver used for .gitmodules can follow ".." components out of the path
32part and past the host part of a URL, meaning that such a relative URL
33can be used to traverse from a https://foo.example.com/innocent
34superproject to a https::attacker.example.com/exploit submodule.
35Fortunately a leading ':' in the first path component after a series of
36leading './' and '../' components is unlikely to show up in other
37contexts, so we can catch this by detecting that pattern.
38
39Reported-by: Jeff King <peff@peff.net>
40Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
41Reviewed-by: Jeff King <peff@peff.net>
42
43Upstream-Status: Backport
44CVE: CVE-2020-11008 (7)
45Signed-off-by: Li Zhou <li.zhou@windriver.com>
46---
47 credential.c | 7 +++++--
48 fsck.c | 47 +++++++++++++++++++++++++++++++++++++++++--
49 t/t5550-http-fetch-dumb.sh | 7 ++-----
50 t/t7416-submodule-dash-url.sh | 32 +++++++++++++++++++++++++++++
51 4 files changed, 84 insertions(+), 9 deletions(-)
52
53diff --git a/credential.c b/credential.c
54index 22649d5..1e1aed5 100644
55--- a/credential.c
56+++ b/credential.c
57@@ -360,8 +360,11 @@ int credential_from_url_gently(struct credential *c, const char *url,
58 * (3) proto://<user>:<pass>@<host>/...
59 */
60 proto_end = strstr(url, "://");
61- if (!proto_end)
62- return 0;
63+ if (!proto_end) {
64+ if (!quiet)
65+ warning(_("url has no scheme: %s"), url);
66+ return -1;
67+ }
68 cp = proto_end + 3;
69 at = strchr(cp, '@');
70 colon = strchr(cp, ':');
71diff --git a/fsck.c b/fsck.c
72index 0f21eb1..30eac29 100644
73--- a/fsck.c
74+++ b/fsck.c
75@@ -978,6 +978,34 @@ static int submodule_url_is_relative(const char *url)
76 }
77
78 /*
79+ * Count directory components that a relative submodule URL should chop
80+ * from the remote_url it is to be resolved against.
81+ *
82+ * In other words, this counts "../" components at the start of a
83+ * submodule URL.
84+ *
85+ * Returns the number of directory components to chop and writes a
86+ * pointer to the next character of url after all leading "./" and
87+ * "../" components to out.
88+ */
89+static int count_leading_dotdots(const char *url, const char **out)
90+{
91+ int result = 0;
92+ while (1) {
93+ if (starts_with_dot_dot_slash(url)) {
94+ result++;
95+ url += strlen("../");
96+ continue;
97+ }
98+ if (starts_with_dot_slash(url)) {
99+ url += strlen("./");
100+ continue;
101+ }
102+ *out = url;
103+ return result;
104+ }
105+}
106+/*
107 * Check whether a transport is implemented by git-remote-curl.
108 *
109 * If it is, returns 1 and writes the URL that would be passed to
110@@ -1024,15 +1052,30 @@ static int check_submodule_url(const char *url)
111 return -1;
112
113 if (submodule_url_is_relative(url)) {
114+ char *decoded;
115+ const char *next;
116+ int has_nl;
117+
118 /*
119 * This could be appended to an http URL and url-decoded;
120 * check for malicious characters.
121 */
122- char *decoded = url_decode(url);
123- int has_nl = !!strchr(decoded, '\n');
124+ decoded = url_decode(url);
125+ has_nl = !!strchr(decoded, '\n');
126+
127 free(decoded);
128 if (has_nl)
129 return -1;
130+
131+ /*
132+ * URLs which escape their root via "../" can overwrite
133+ * the host field and previous components, resolving to
134+ * URLs like https::example.com/submodule.git that were
135+ * susceptible to CVE-2020-11008.
136+ */
137+ if (count_leading_dotdots(url, &next) > 0 &&
138+ *next == ':')
139+ return -1;
140 }
141
142 else if (url_to_curl_url(url, &curl_url)) {
143diff --git a/t/t5550-http-fetch-dumb.sh b/t/t5550-http-fetch-dumb.sh
144index b811d89..1c9e5d3 100755
145--- a/t/t5550-http-fetch-dumb.sh
146+++ b/t/t5550-http-fetch-dumb.sh
147@@ -321,11 +321,8 @@ test_expect_success 'git client does not send an empty Accept-Language' '
148 '
149
150 test_expect_success 'remote-http complains cleanly about malformed urls' '
151- # do not actually issue "list" or other commands, as we do not
152- # want to rely on what curl would actually do with such a broken
153- # URL. This is just about making sure we do not segfault during
154- # initialization.
155- test_must_fail git remote-http http::/example.com/repo.git
156+ test_must_fail git remote-http http::/example.com/repo.git 2>stderr &&
157+ test_i18ngrep "url has no scheme" stderr
158 '
159
160 test_expect_success 'redirects can be forbidden/allowed' '
161diff --git a/t/t7416-submodule-dash-url.sh b/t/t7416-submodule-dash-url.sh
162index afdd255..249dc3d 100755
163--- a/t/t7416-submodule-dash-url.sh
164+++ b/t/t7416-submodule-dash-url.sh
165@@ -60,6 +60,38 @@ test_expect_success 'trailing backslash is handled correctly' '
166 test_i18ngrep ! "unknown option" err
167 '
168
169+test_expect_success 'fsck rejects missing URL scheme' '
170+ git checkout --orphan missing-scheme &&
171+ cat >.gitmodules <<-\EOF &&
172+ [submodule "foo"]
173+ url = http::one.example.com/foo.git
174+ EOF
175+ git add .gitmodules &&
176+ test_tick &&
177+ git commit -m "gitmodules with missing URL scheme" &&
178+ test_when_finished "rm -rf dst" &&
179+ git init --bare dst &&
180+ git -C dst config transfer.fsckObjects true &&
181+ test_must_fail git push dst HEAD 2>err &&
182+ grep gitmodulesUrl err
183+'
184+
185+test_expect_success 'fsck rejects relative URL resolving to missing scheme' '
186+ git checkout --orphan relative-missing-scheme &&
187+ cat >.gitmodules <<-\EOF &&
188+ [submodule "foo"]
189+ url = "..\\../.\\../:one.example.com/foo.git"
190+ EOF
191+ git add .gitmodules &&
192+ test_tick &&
193+ git commit -m "gitmodules with relative URL that strips off scheme" &&
194+ test_when_finished "rm -rf dst" &&
195+ git init --bare dst &&
196+ git -C dst config transfer.fsckObjects true &&
197+ test_must_fail git push dst HEAD 2>err &&
198+ grep gitmodulesUrl err
199+'
200+
201 test_expect_success 'fsck permits embedded newline with unrecognized scheme' '
202 git checkout --orphan newscheme &&
203 cat >.gitmodules <<-\EOF &&
204--
2051.9.1
206