3 ms·
(I'm the "Bjarmason" quoted in the article) To elaborate a bit: One thing that makes a viable attack against Git especially hard is that aside from the hash it
by avar 4y ago
(I'm the "Bjarmason" quoted in the article)
To elaborate a bit: One thing that makes a viable attack against Git especially hard is that aside from the hash it's using has a behavior of never replacing an already hashed object[1].
So let's say I have a tool that can take a given file & SHA-1 pair and produce a collision, the next step is quite hard. I could in this scenario produce a file with an exploit whose hash matches that of Linus's kernel/pid.c or whatever.
But how do I get that object to propagate among forks of linux.git to distribute my exploited code?
If I e.g. push it to a fork of linux.git on a hosting provider that Linus uses the the remote "git-index-pack" process will hash my colliding object, but before it stores it check whether such an object ID exists in its object store, if it does it'll drop it on the floor. You don't need to store data you've already got in a content-addressable filesystem.
Which is not to say that a hash collision is a non-issue, and Git should certainly be migrating from SHA-1. There's no disagreement about that in the Git development community.
But it matters for how much you should panic how the software you're using could be exploited in the case of a hash collision.
Also, the scenario above presupposes a preimage attack, which is a much worse attack on a hash function than a collision attack. Currently no viable preimage attack on SHA-1 exists, only a collision attack.
Which means that before any of the above I'd have to have produced a viable version of say kernel/pid.c that Linus was willing to merge, knowing that my evil twin of that version is something I intended to exploit people with.
Then I'd need to patiently wait for that version to make it into a release, knowing that even a one-byte change to the file would foil my plans...
1. On the topic of running with scissors: I wrote a patch to disable that collision check for an ex employer, it helped in that I/O-bound setup, and we were confident in the lessened security being a non-issue for us in that particular setup. The patch never made it into git's mainline. The patch won't apply anymore, but the embedded docs elaborate on the topic: https://lore.kernel.org/git/20181113201910.11518-1-avarab@gmail.com/ https://lore.kernel.org/git/20181113201910.11518-1-avarab@gm...;
- mvkg 4y agoRegarding the collision attack replacement check, do you know if that is carried over into other git implementations (e.g. libgit2)?
- avar 4y agoI had to look, but in the case of libgit2 yes they have. Like git they have a way to select SHA-1 backends, and the default is the SHA1DC library. But, even supposing a libgit2 that didn't use SHA1DC I think most users would be protected in practice if the "git" they use used SHA1DC. Hosting providers, local editors etc. use libgit2 for a lot of things, but I think in most cases (certainly in the case of the popular hosting providers) it's some version of "/usr/bin/git" that's handling your push, and actually propagating your objects. For stopping a colliding hash it's enough that any part of the chain of propagation is able to stop it.
- rurban 4y agoand with the Linux workflow every reviewer usually adds his -s signed by me tag, which changes the hash. so all the collision effort is gone.
- avar 4y agoI think you're confused here (or maybe I am). In this scenario you e.g. would be replacing the blob object for kernel/pid.c. Whereas the GPG signature facility in git is creating a "tag" object with a signature of the preceding part of the object envelope, and that envelope refers to another object type. E.g. in the case of signed tags usually a commit object. So if you are able to replace the blob the GPG signature will still be valid, since it relies on signing the SHA-1 DAG. There is e.g. the third-party git-evtag[1] which gets around this problem by recursively unpacking the signed content, which does give you the advantages of the stronger hash. But this isn't how signed content in Git itself currently works. I think there was some recent-ish discussion of having something like that in git itself, and perhaps I've missed something, but I'm pretty sure I didn't miss the tag signing code doing a full object walk, which is what you'd need for signing a SHA-1 Git repository in a way that didn't piggy-back on SHA-1's security.
- rurban 4y agoNot -S (gpg-sign), but -s (signoff). Add a Signed-off-by trailer
- avar 4y agoAh, sorry. I entirely misunderstood & misread what you were saying. But in that case you'd still have the same collision, as surely what you're producing a collision for is the tree or blob object(s) you're asking to be merged in, as opposed to the hash for the commit object (which will change as you amend it). No?
- rurban 4y agoyou merge commits, not blobs