CVE-2020-12278 (published 2020-04-27T17:15Z)

An issue was discovered in libgit2 before 0.28.4 and 0.9x before 0.99.0. path.c mishandles equivalent filenames that exist because of NTFS Alternate Data Streams. This may allow remote code execution when cloning a repository. This issue is similar to CVE-2019-1352.

Severity: HIGH
CVSS v2 base score: 7.5 (AV:N/AC:L/Au:N/C:P/I:P/A:P)
CVSS v3 base score: 9.8, CRITICAL (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-706
cwe_name: Use of Incorrectly-Resolved Name or Reference
description: The product uses a name or reference to access a resource, but the name/reference resolves to a resource that is outside of the intended control sphere.
extended_description: 
            
            
         
         

Fix information:
repo_url: https://github.com/libgit2/libgit2
commit_details: repo_url: https://github.com/libgit2/libgit2
author: Johannes Schindelin
author_date: 2019-09-18 16:33:18+02:00
msg: path: also guard `.gitmodules` against NTFS Alternate Data Streams

We just safe-guarded `.git` against NTFS Alternate Data Stream-related
attack vectors, and now it is time to do the same for `.gitmodules`.

Note: In the added regression test, we refrain from verifying all kinds
of variations between short names and NTFS Alternate Data Streams: as
the new code disallows _all_ Alternate Data Streams of `.gitmodules`, it
is enough to test one in order to know that all of them are guarded
against.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
repository: repo_url: https://github.com/libgit2/libgit2
repo_name: libgit2/libgit2
description: A cross-platform, linkable library implementation of Git that you can use in your application.
repo_language: C
owner: libgit2
file_changes: filename: path.c
change_type: ModificationType.MODIFY
diff: @@ -1646,7 +1646,7 @@ GIT_INLINE(bool) only_spaces_and_dots(const char *path)
 	const char *c = path;
 
 	for (;; c++) {
-		if (*c == '\0')
+		if (*c == '\0' || *c == ':')
 			return true;
 		if (*c != ' ' && *c != '.')
 			return false;

programming_language: C
filename: dotgit.c
change_type: ModificationType.MODIFY
diff: @@ -116,4 +116,5 @@ void test_path_dotgit__dotgit_modules_symlink(void)
 	cl_assert_equal_b(true, git_path_isvalid(NULL, ".gitmodules", 0, GIT_PATH_REJECT_DOT_GIT_HFS|GIT_PATH_REJECT_DOT_GIT_NTFS));
 	cl_assert_equal_b(false, git_path_isvalid(NULL, ".gitmodules", S_IFLNK, GIT_PATH_REJECT_DOT_GIT_HFS));
 	cl_assert_equal_b(false, git_path_isvalid(NULL, ".gitmodules", S_IFLNK, GIT_PATH_REJECT_DOT_GIT_NTFS));
+	cl_assert_equal_b(false, git_path_isvalid(NULL, ".gitmodules . .::$DATA", S_IFLNK, GIT_PATH_REJECT_DOT_GIT_NTFS));
 }

programming_language: C
repo_url: https://github.com/libgit2/libgit2
commit_details: repo_url: https://github.com/libgit2/libgit2
author: Johannes Schindelin
author_date: 2019-09-18 14:32:05+02:00
msg: Disallow NTFS Alternate Data Stream attacks, even on Linux/macOS

A little-known feature of NTFS is that it offers to store metadata in
so-called "Alternate Data Streams" (inspired by Apple's "resource
forks") that are copied together with the file they are associated with.
These Alternate Data Streams can be accessed via `<file name>:<stream
name>:<stream type>`.

Directories, too, have Alternate Data Streams, and they even have a
default stream type `$INDEX_ALLOCATION`. Which means that `abc/` and
`abc::$INDEX_ALLOCATION/` are actually equivalent.

This is of course another attack vector on the Git directory that we
definitely want to prevent.

On Windows, we already do this incidentally, by disallowing colons in
file/directory names.

While it looks as if files'/directories' Alternate Data Streams are not
accessible in the Windows Subsystem for Linux, and neither via
CIFS/SMB-mounted network shares in Linux, it _is_ possible to access
them on SMB-mounted network shares on macOS.

Therefore, let's go the extra mile and prevent this particular attack
_everywhere_. To keep things simple, let's just disallow *any* Alternate
Data Stream of `.git`.

This is libgit2's variant of CVE-2019-1352.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
repository: repo_url: https://github.com/libgit2/libgit2
repo_name: libgit2/libgit2
description: A cross-platform, linkable library implementation of Git that you can use in your application.
repo_language: C
owner: libgit2
file_changes: filename: path.c
change_type: ModificationType.MODIFY
diff: @@ -1624,8 +1624,12 @@ GIT_INLINE(bool) verify_dotgit_ntfs(git_repository *repo, const char *path, size
 	if (!start)
 		return true;
 
-	/* Reject paths like ".git\" */
-	if (path[start] == '\\')
+	/*
+	 * Reject paths that start with Windows-style directory separators
+	 * (".git\") or NTFS alternate streams (".git:") and could be used
+	 * to write to the ".git" directory on Windows platforms.
+	 */
+	if (path[start] == '\\' || path[start] == ':')
 		return false;
 
 	/* Reject paths like '.git ' or '.git.' */

programming_language: C
filename: nasty.c
change_type: ModificationType.MODIFY
diff: @@ -273,6 +273,16 @@ void test_checkout_nasty__dot_git_colon_stuff(void)
 #endif
 }
 
+/* A tree that contains an entry ".git::$INDEX_ALLOCATION" because NTFS
+ * will interpret that as a synonym to ".git", even when mounted via SMB
+ * on macOS.
+ */
+void test_checkout_nasty__dotgit_alternate_data_stream(void)
+{
+	test_checkout_fails("refs/heads/dotgit_alternate_data_stream", ".git/dummy-file");
+	test_checkout_fails("refs/heads/dotgit_alternate_data_stream", ".git::$INDEX_ALLOCATION/dummy-file");
+}
+
 /* Trees that contains entries with a tree ".git" that contain
  * byte sequences:
  * { 0xe2, 0x80, 0x8c }

programming_language: C