Skip to content
Permalink
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
dscho authored and ethomson committed Dec 10, 2019
1 parent 64c612c commit 3f7851e
Show file tree
Hide file tree
Showing 6 changed files with 17 additions and 2 deletions.
8 changes: 6 additions & 2 deletions src/path.c
Expand Up @@ -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.' */
Expand Down
10 changes: 10 additions & 0 deletions tests/checkout/nasty.c
Expand Up @@ -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 }
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
b8edf3ad62dbcbc983857a5bfee7b0181ee1a513

0 comments on commit 3f7851e

Please sign in to comment.