Skip to content

Commit 3f7851e

Browse files
dschoethomson
authored andcommitted
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>
1 parent 64c612c commit 3f7851e

File tree

6 files changed

+17
-2
lines changed

6 files changed

+17
-2
lines changed

src/path.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1624,8 +1624,12 @@ GIT_INLINE(bool) verify_dotgit_ntfs(git_repository *repo, const char *path, size
16241624
if (!start)
16251625
return true;
16261626

1627-
/* Reject paths like ".git\" */
1628-
if (path[start] == '\\')
1627+
/*
1628+
* Reject paths that start with Windows-style directory separators
1629+
* (".git\") or NTFS alternate streams (".git:") and could be used
1630+
* to write to the ".git" directory on Windows platforms.
1631+
*/
1632+
if (path[start] == '\\' || path[start] == ':')
16291633
return false;
16301634

16311635
/* Reject paths like '.git ' or '.git.' */

tests/checkout/nasty.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,16 @@ void test_checkout_nasty__dot_git_colon_stuff(void)
273273
#endif
274274
}
275275

276+
/* A tree that contains an entry ".git::$INDEX_ALLOCATION" because NTFS
277+
* will interpret that as a synonym to ".git", even when mounted via SMB
278+
* on macOS.
279+
*/
280+
void test_checkout_nasty__dotgit_alternate_data_stream(void)
281+
{
282+
test_checkout_fails("refs/heads/dotgit_alternate_data_stream", ".git/dummy-file");
283+
test_checkout_fails("refs/heads/dotgit_alternate_data_stream", ".git::$INDEX_ALLOCATION/dummy-file");
284+
}
285+
276286
/* Trees that contains entries with a tree ".git" that contain
277287
* byte sequences:
278288
* { 0xe2, 0x80, 0x8c }
Binary file not shown.
Binary file not shown.
Binary file not shown.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
b8edf3ad62dbcbc983857a5bfee7b0181ee1a513

0 commit comments

Comments
 (0)