Even recent releases use MD5 and SHA1 checksums, and both algorithms are vulnerable to collisions, so we should not trust those checksums. This is known. But at least there's a PGP signature, and that we can trust, right? Not so fast. (Some of) those signatures also use SHA1!
The danger does not appear immediate, but it appears one should start migrating to more secure signatures, and eventually forbid artifacts signed only with SHA1.
Caveat: I am not a security expert, but https://security.stackexchange.com/a/152176.
Realistically, since SHA1 is currently vulnerable to collision attacks and not preimage attacks, an attacker cannot yet create a JAR that matches an already published one, as long as the publisher is trusted; and when we run an artifact we trust its author. It is possible one could create two JARs with the same digest, get the non-malicious one signed and distribute the malicious one.
However, artifacts are supposed to be permanent, so artifacts published now will be subject to any future preimage attacks.
I took a recent artifact and inspected its signature. GPG tells us that the signature uses digest algorithm SHA1
:
that is, the author only signed the SHA1 hash/digest of the file, and not for instance a SHA256 hash. To double-check this,
I have used two other tools, following https://lists.gnupg.org/pipermail/gnupg-users/2010-May/038707.html.
$ wget http://repo1.maven.org/maven2/org/apache/spark/spark-core_2.12/2.4.0/spark-core_2.12-2.4.0.pom
$ wget http://repo1.maven.org/maven2/org/apache/spark/spark-core_2.12/2.4.0/spark-core_2.12-2.4.0.pom.asc
$ gpg --verbose --verify spark-core_2.12-2.4.0.pom.asc
gpg: armor header: Version: GnuPG v1
gpg: assuming signed data in 'spark-core_2.12-2.4.0.pom'
gpg: Signature made Mon Oct 29 08:55:18 2018 CET
gpg: using RSA key 0x6BAC72894F4FDC8A
gpg: using pgp trust model
gpg: Good signature from "Wenchen Fan (CODE SIGNING KEY) <[email protected]>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.
Primary key fingerprint: 9B31 1CB5 38F2 1588 6143 5661 6BAC 7289 4F4F DC8A
gpg: binary signature, digest algorithm SHA1, key algorithm rsa4096
$ pgpdump spark-core_2.12-2.4.0.pom.asc
Old: Signature Packet(tag 2)(540 bytes)
Ver 4 - new
Sig type - Signature of a binary document(0x00).
Pub alg - RSA Encrypt or Sign(pub 1)
Hash alg - SHA1(hash 2)
Hashed Sub: signature creation time(sub 2)(4 bytes)
Time - Mon Oct 29 08:55:18 CET 2018
Sub: issuer key ID(sub 16)(8 bytes)
Key ID - 0x6BAC72894F4FDC8A
Hash left 2 bytes - a2 f2
RSA m^d mod n(4094 bits) - ...
-> PKCS-1
$ gpg --list-packets spark-core_2.12-2.4.0.pom.asc
# off=0 ctb=89 tag=2 hlen=3 plen=540
:signature packet: algo 1, keyid 6BAC72894F4FDC8A
version 4, created 1540799718, md5len 0, sigclass 0x00
digest algo 2, begin of digest a2 f2
hashed subpkt 2 len 4 (sig created 2018-10-29)
subpkt 16 len 8 (issuer key ID 6BAC72894F4FDC8A)
data: [4094 bits]
@JLLeitschuh Indeed, you should check PGP signatures, and if you don’t, you’re trusting the host (and on http also the network) — but ideally it should not be new that you should (not sure if that’s actually done by Maven).
I think SHA-256 wouldn’t change that: if the host is compromised, it can trivially give the SHA-256 digest of the malicious artifact — it can’t fake a signed digest. If you have, somehow, a SHA-1 hash that you can trust, but not an artifact you trust, then the attack I describe might apply. But the only way I know to get a trusted SHA-1 hash is to have it PGP-signed.
This gist was about something else: if you do check PGP signatures, are you safe? As soon as you have a preimage attack on SHA1, you can’t.