"Given the threat that the SHA-1 hash poses, one might think that there would be a stronger incentive for somebody to support this work. But, as Bjarmason continued, that incentive is not actually all that strong. The project adopted the SHA-1DC variant of SHA-1 for the 2.13 release in 2017, which makes the project more robust against the known SHA-1 collision attacks, so there does not appear to be any sort of imminent threat of this type of attack against Git. Even if creating a collision were feasible for an attacker, Bjarmason pointed out, that is only the first step in the development of a successful attack. Finding a collision of any type is hard; finding one that is still working code, that has the functionality the attacker is after, and that looks reasonable to both humans and compilers is quite a bit harder — if it is possible at all."
But you could also hide it as a fake lookup table or inline XPM or something like that.
This seems true yet there are no demos or documented attacks using this method.
I think practically speaking it’s kind of a pain to do.
Sha1 has a collision attack. We are far away from a preimage attack
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@gm...;
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.
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.
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?
Example: `git commit -a -S -m 'signed commit'` signs the SHA-1 hash directly.
Even if the SHA-1 digest is rehashed with a secure hashing algorithm, SHA-256, it would hide the fact that the reference is to an insecure hashing algorithm. The project itself needs to be rehashed with a secure hashing algorithm for signing to be secure.
How does that work? My understanding was that a git gpg signature only signs the project at that commit state.
It says nothing about past (or future) commits outside of a digest reference to past commits, which if that digest wasn't upgraded, would be considered insecure.
Said another way: Git does not rehash past commits, or the present commit, when gpg signing. A commit itself only includes the SHA-1 digest of the previous commit.
The old signatures will still be SHA-1. But if you try to replace any part of a commit, the SHA-256 won't match. So the combination of "the commit is an ancestor of multiple securely signed commits in this repo" and "the SHA1 on the signature matches" is enough to know you have the right data in most use cases.
This is very similar to the following: Instead of rehashing, i.e. replacing old hashes with new hashes, add the new hashes alongside the old ones, and sign the new hashes, together with the time mark, by a trusted authority. The old hashes and signatures then remain valid indefinitely as long as the new hashes and signatures are verified successfully.
I don't know if this would survive additional commits on top as I'm not familiar enough with git's internals.
I think the actual issue here is environment accreditation not allowing the use of sha-1 at all, but that is still rare. It'll become a much larger issue if a future FIPS standard ever disallows sha-1, because that will impact a ton of environments. It means git won't even work on your servers any more.
As noted in the article, an SHA-1 collision attack does not appear practical now, but that is a situation that can change.
Not to say that this attack is in any way practical, yet. Just that some providers don't require active involvement to try and attempt it.