$ sudo apt-get install -y leiningen [...] $ lein new scratch [...] $ cd scratch $ lein repl Downloading: org/clojure/clojure/1.3.0/clojure-1.3.0.pom from repository central at http://repo1.maven.org/maven2 Transferring 5K from central Downloading: org/sonatype/oss/oss-parent/5/oss-parent-5.pom from repository central at http://repo1.maven.org/maven2 Transferring 4K from central Downloading: org/clojure/clojure/1.3.0/clojure-1.3.0.jar from repository central at http://repo1.maven.org/maven2 Transferring 3311K from central [...]
lein downloads some random JARs from a website over
HTTP1, with, as far as far I can tell, no verification that
what I’m asking for is what I’m getting (has nobody ever heard of
Man-in-the-Middle attacks in Maven land?). It downloads a
.sha1 file to
(presumably) do integrity checking, but that’s no safety net – if I can
serve you a dodgy
.jar, I can serve you an equally-dodgy
.sha1 file, too
(also, SHA256 is where all the cool kids are at these days). Finally,
jarsigner tells me that there’s no signature on the
.jar itself, either.
It gets better, though. The
repo1.maven.org site is served by the
fastly.net2 pseudo-CDN3, which adds another
set of points in the chain which can be subverted to hijack and spoof
traffic. More routers, more DNS zones, and more servers.
I’ve seen Debian take a kicking more than once because packages aren’t individually signed, or because packages aren’t served over HTTPS. But at least Debian’s packages can be verified by chaining to a signature made by a well-known, widely-distributed key, signed by two Debian Developers with very well-connected keys.
This repository, on the other hand… oy gevalt. There are OpenPGP (GPG)
signatures available for each package (tack
.asc onto the end of the
.jar URL), but no attempt was made to download the signatures for the
.jar I downloaded. Even if the signature was downloaded and checked,
there’s no way for me (or anyone) to trust the signature – the signature
was made by a key that’s signed by one other key, which itself has no
signatures. If I were an attacker, it wouldn’t be hard for me to replace
that key chain with one of my own devising.
Even ignoring everyone living behind a government- or company-run intercepting proxy, and everyone using public wifi, it’s pretty well common knowledge by now (thanks to Edward Snowden) that playing silly-buggers with Internet traffic isn’t hard to do, and there’s no shortage of evidence that it is, in fact, done on a routine basis by all manner of people. Serving up executable code to a large number of people, in that threat environment, with no way for them to have any reasonable assurance that code is trustworthy, is very disappointing.
Please, for the good of the Internet, improve your act, Maven. Putting
HTTPS on your distribution would be a bare minimum. There are attacks on
SSL, sure, but they’re a lot harder to pull off than sitting on public wifi
hijacking TCP connections. Far better would be to start mandating
signatures, requiring signature checks to pass, and having all signatures
chain to a well-known, widely-trusted, and properly secured trust root.
Signing all keys that are allowed to upload to
maven.org with a “maven.org
distribution root” key (itself kept in hardware and only used offline), and
then verifying that all signatures chain to that key, wouldn’t be insanely
difficult, and would greatly improve the security of the software supply
chain. Sure, it wouldn’t be perfect, but don’t make the perfect the enemy
of the good. Cost-effective improvements are possible here.
Yes, security is hard. But you don’t get to ignore it just because of that, when you’re creating an attractive nuisance for anyone who wants to own up a whole passel of machines by slipping some dodgy code into a widely-used package.
To add insult to injury, it appears to ignore my
http_proxyenvironment variable, and the
repo1.maven.orgserver returns plain-text error responses with
Content-Type: text/xml. But at this point, that’s just icing on the shit cake. ↩
At one point in the past, my then-employer (a hosting provider) blocked Fastly’s caching servers from their network because they took down a customer site with a massive number of requests to a single resource, and the incoming request traffic was indistinguishable from a botnet-sourced DDoS attack. The requests were coming from IP space registered to a number of different ISPs, with no distinguishing rDNS (
184-106-82-243.static.cloud-ips.comdoesn’t help me to distinguish between “I’m a professionally-run distributed proxy” and “I’m a pwned box here to hammer your site into the ground”). ↩
Pretty much all of the new breed of so-called CDNs aren’t actually pro-actively distributing content, they’re just proxies. That isn’t a bad thing, per se, but I rather dislike the far-too-common practice of installing varnish (and perhaps mod_pagespeed, if they’re providing “advanced” capabilities) on a couple of AWS instances, and hanging out your shingle as a CDN. I prefer a bit of truth in my advertising. ↩