
How to take over the computer of a Maven Central user - akerl_
http://blog.ontoillogical.com/blog/2014/07/28/how-to-take-over-any-java-developer/
======
moxie
At Open Whisper Systems, we wrote a small open source gradle plugin called
"gradle-witness" for this reason. Not just because dependencies could be
transported over an insecure channel, but also because dependencies could be
compromised if the gradle/maven repository were compromised:

[https://github.com/whispersystems/gradle-
witness](https://github.com/whispersystems/gradle-witness)

It allows you to "pin" dependencies by specifying the sha256sum of the jar
you're expecting.

~~~
shortstuffsushi
That's interesting, doesn't Maven offer a checksum option to begin with? I
feel like just the other day, someone was saying "who ever uses checksums
anyway," but a package manager run over insecure methods seems like the
perfect time to do so.

~~~
yourad_io
From the article:

> When JARs are downloaded from Maven Central, they go over HTTP, so a man in
> the middle proxy can replace them at will. It’s possible to sign jars, but
> in my experimentation with standard tools, these signatures aren’t checked.
> The only other verification is a SHA1 sum, which is also sent over HTTP.

~~~
shortstuffsushi
I agree that they aren't checked by default, you'd need to implement it (as
the parent commenter seemed to be doing with their gradle plugin). Regarding
the sums being sent over HTTP as well, seems that you'll need a checksum for
your checksum. Ultimately, though, it just seems that it'd be best to avoid
this while it's over HTTP.

------
technomancy
For Leiningen at least the goal is eventually to be able to flip a switch that
will make it refuse to operate in the presence of unsigned dependencies. We're
still a ways away from that becoming a reality, but the default is already to
refuse to deploy new libraries without an accompanying signature.

Edit: of course, the question of how to determine which keys to trust is still
pretty difficult, especially in the larger Java world. The community of
Clojure authors is still small enough that a web of trust could still be
established face-to-face at conferences that could cover a majority of
authors.

The situation around Central is quite regrettable though.

~~~
weavejester
Leiningen also uses Clojars over HTTPS by default, I believe, so even without
a web of trust, Clojars is still more secure than Central.

~~~
technomancy
Technically true, but practically this doesn't mean anything.

No one uses Clojars on its own, so if an attacker were able to perform a MITM
attack, they could inject a spoofed library into the connection to Central
even if the library should be fetched from Clojars.

------
akerl_
It's not specifically named in the article, but the software shown with the
firewall popup is Little Snitch, and it's great:

[http://www.obdev.at/products/littlesnitch/index.html](http://www.obdev.at/products/littlesnitch/index.html)

------
brianefox
The project to offer ssl free to every user of Maven Central is already
underway. Stay tuned for details.

~~~
ontoillogical
Author here.

Brian are you speaking as a representative of Sonatype, or are you a 3rd
party?

~~~
brianefox
As a representative of Sonatype.

The reality of cross build injection has been discussed for many years, I even
linked to an XBI talk in my blog post announcing the availability of SSL.

The reality is that prior to moving to a CDN, it was going to be pretty
intensive to offer SSL on the scale of traffic we were seeing. The priority at
that time was ensuring higher availability and providing multiple data centers
with worldwide loadbalancing.

On our first CDN provider, they could not perform SSL certificate validation
and thus were themselves susceptible to a MITM attack. So the decision at that
point was to run SSL off of the origin server. We wanted to make it
essentially free but wanted to ensure that the bandwidth was available for
those that cared to use it, hence the small donation.

The situation is different today with our new CDN, they can validate the
certificates all the way through and that's how we intend to deploy it.

We won't be able to enable full https redirections for all traffic since this
would cause havok in organizations that are firewall locked and for tools that
don't follow redirects. Each tool would need to adopt the new url. I've
already suggested this change occur in Maven once we launch.

~~~
hrjet
I am not familiar with Sonatype and what relation it has with maven, but have
you considered adding BitTorrent protocol to maven? This might help reduce
traffic considerably.

------
heavenlyhash
SSL would have partially mitigated this attack, but it's not a full solution
either. SSL is transport layer security -- you still fully trust the remote
server not to give you cat memes. What if this wasn't necessary? Why can't we
embed the hash of the dependencies we need in our projects directly? That
would give us end-to-end confidence that we've got the right stuff.

This is exactly why I built mdm[1]: it's a dependency manager that's immune to
cat memes getting in ur http.

Anyone using a system like git submodules to track source dependencies is
immune to this entire category of attack. mdm does the same thing, plus works
for binary payloads.

Build injection attacks have been known for a while now. There's actually a
great publication by Fortify[2] where they even gave it a name: XBI, for Cross
Build Injection attack. Among the high-profile targets even several years ago
(the report is from 2007): Sendmail, IRSSI, and OpenSSH! It's great to see
more attention to these issues, and practical implementations to double-
underline both the seriousness of the threat and the ease of carrying out the
attack.

Related note: signatures are good too, but still actually _less_ useful than
embedding the hash of the desired content. Signing keys can be captured;
revocations require infrastructure and online verification to be useful.
Embedding hashes in your version control can give all the integrity guarantees
needed, without any of the fuss -- you should just verify the signature at the
time you first commit a link to a dependency.

[1] [https://github.com/polydawn/mdm/](https://github.com/polydawn/mdm/)

[2]
[https://www.fortify.com/downloads2/public/fortify_attacking_...](https://www.fortify.com/downloads2/public/fortify_attacking_the_build.pdf)

~~~
michaelt

      Why can't we embed the hash of the dependencies we need 
      in our projects directly?
    

There's a lot of stuff in Maven, like the versions plugin and the release
plugin, to update dependencies to the latest version. This stuff is useful for
continuous integration and automated deployment, especially when your project
is split into lots of modules to allow code reuse.

With code signing, you can (or hypothetically could, I don't know if anyone
does this) check the latest version is signed by the same key as the previous
version - whereas just pinning the hash wouldn't allow that.

I agree pinning the hash is useful if the signing key is captured.

~~~
heavenlyhash
I typically find that in practice, strong links between a project and its
dependencies are not a drawback.

If large amounts of your code change across different projects at the same
time, those projects don't have a very stable API nor are the evidentally
actually developing separately, so there's no major reason to pretend they are
isolated or introduce a binary release protocol between them. Projects like
this will probably find the greatest ease of operation by just sticking to one
source repository -- otherwise, commits for a single "feature" are already
getting smeared across multiple repositories, and stitching them back together
with some hazy concept of "latest" at a particular datetime isn't helping
anyone.

The biggest indicator of over-coupled projects that are going to face friction
is when ProjectCore depends on ProjectWhirrlyjig, but the Whirrlyjig test code
still lives in ProjectCore. This tends to make it very difficult to make
releases of ProjectWhirrlyjig with confidence, since they won't be tested
until getting to ProjectCore. If projects are actually maintaining stable
features on their own in isolation, this shouldn't be what your flow looks
like.

Projects that _are_ well isolated generally don't seem to have a hard time
committing to stable (if frequent) release cycles. Furthermore, it actually
encourages good organizational habits, because it actively exerts pressure
against making changes that would cross-cut libraries or make it difficult to
create tests isolated to a single project.

In contrast, tools that regularly update to "the latest" version invariably
seem to bring headaches down the road.

Getting "the latest" is ambiguous. It means that your build will not be
reproducible in any automated way, whether it's one week or one hour from now.
It's a moving target. Can you do a `git bisect` if something goes wrong and
you need to track down a change?

Getting "the latest" also doesn't take into account branching. This is
something a team I'm currently on is poignantly aware of: feature branches are
used extensively, and when this concept spans projects, we found "latest"
ceases to mean anything contextually useful.

If you're working on projects where a CI server is actually part of the core
feedback loop (say your test suite has gotten too unwieldy for any single
developer to run before pushing), then a fetch "latest" can be helpful to
enable this during development. But even if jenkins informs you the build is
green, it's important to remember this won't be reproducible in the future;
you should make an effort to get back to precisely tracked dependencies as
soon as possible.

mdm deals with this by letting you use untracked versions of your dependency
files... but it will consistently _show that_ in `git status` commands, so
that you A) _know_ that your current work isn't reproducible by anyone else
and B) everyone is encouraged to make an effort to get back on track ASAP.

------
femto113
Perhaps as a stopgap Maven Central (or a concerned third party?) could publish
all of the SHA1 hashes on a page that is served via HTTPS. This would at least
allow tools to detect the sort of attack described in the article.

------
jontro
This is a horrible policy made by sonatype. A better alternative of
mavencentral should be created...

~~~
einrealist
It is not the fault of Sonatype. We should not trust Central right away. If I
worry about malicious artifacts from Central, I must host my own repository
and manage artifacts myself. And that way, I can just map other repositories I
trust more.

~~~
lmm
Trusting Central > Trusting everyone on the network path between you and
central.

------
finnn
Evilgrade
([https://github.com/infobyte/evilgrade](https://github.com/infobyte/evilgrade))
is a similar tool that works on a wider variety of insecure updaters. Perhaps
a module could be written? Maybe one already exists, I haven't played with it
in a while

------
MrSourz
I'm torn on how I feel about security being a paid feature in this case. Here
the onus is being placed on the user, yet many won't be conscious of the
choice they're making.

The _tiff_ mentioned in the article was interesting to read. >
[https://twitter.com/mveytsman/status/491298846673473536](https://twitter.com/mveytsman/status/491298846673473536)

~~~
homulilly
There's two problems with this that I see. The first is, as you said, that a
lot of people won't even realize they need to pay for secure downloads.

I also feel like in the case of something like a package manager, this
potentially harms the wider community in ways that charging for features in a
specific piece of software doesn't.

~~~
technomancy
Technically paying for an auth token is not sufficient. The token cannot be
used directly by Maven or Leiningen, but only by a Nexus proxying repository
manager. Not a big deal if you work at a professional Clojure shop, but a huge
hassle if you're freelance or just getting started.

------
avz
Exposing your users to MITM attacks in order to encourage donations? Pure
evil.

~~~
ternaryoperator
That's a little paranoid. Let's see, we'll completely ruin our rep and our
core business activity just so you're forced to donate--not to us, but to this
open source group over here. Dude, put down the pipe.

~~~
shawnz
Isn't it exactly what they are doing, though? The only reason you would want
HTTPS is to prevent MITM attacks. By making it a premium feature, they are
making MITM attack mitigation a premium feature.

------
jimrandomh
My main experience with Maven has been downloading some source code, and
having to use Gradle to compile it. It went and downloaded a bunch of
binaries, insecurely. There were no actual unsatisfied dependencies; it was
just downloading pieces of Gradle itself.

I would've much rather had a Makefile. Build scripts and package managers need
to be separate.

~~~
yourad_io
> Build scripts and package managers need to be separate.

This. Especially when there's broken links, you're gonna have a bad (and long)
time.

------
jc4p
jCenter is the new default repository used with Android's gradle plugin, I
haven't used it myself yet but it looks like the site defaults to HTTPS for
everything:
[https://bintray.com/bintray/jcenter](https://bintray.com/bintray/jcenter)

~~~
jbaruch_s
Full disclosure - I am a developer Advocate with JFrog, the company behind
Bintray.

So,jcenter is a Java repository in Bintray
([https://bintray.com/bintray/jcenter](https://bintray.com/bintray/jcenter)),
which is the largest repo in the world for Java and Android OSS libraries,
packages and components. All the content is served over a CDN, with a secure
https connection. JCenter is the default repository in Goovy Grape
([http://groovy.codehaus.org/Grape](http://groovy.codehaus.org/Grape)), built-
in in Gradle (the jcenter() repository) and very easy to configure in every
other build tool (maybe except Maven) and will become even easer very soon.

Bintray has a different approach to package identification than the legacy
Maven Central. We don't rely on self-issued key-pairs (which can be generated
to represent anyone, actually and never verified in Maven Central). Instead,
similar to GitHub, Bintray gives a strong personal identity to any contributed
library.

If you really need to get your package to Maven Central (for supporting legacy
tools) you can do it from Bintray as well, in a click of a button or even
automatically.

Hope that helps!

~~~
vorg
You mention both Bintray and Groovy. Look at the Bintray download stats for
Groovy [1] and it reports 170,000 downloads in the past month. But 100,000 of
them happen on just 6 days, 40,000 of those on just 1 day (18 July). Click on
country and see that 120,000 of them came from China. Comparing the numbers
suggests 100,000 downloads of Groovy from Bintray during July were faked.
Another 900,000 downloads of Groovy were faked during April and May. I'm not
sure I trust JCenter when the 2 technologies you recommend for it have
together been used to fake _one million downloads_.

[1]
[https://bintray.com/groovy/maven/groovy/view/statistics](https://bintray.com/groovy/maven/groovy/view/statistics)

[2]
[http://groovy.codeplex.com/wikipage?title=Blog07#2](http://groovy.codeplex.com/wikipage?title=Blog07#2)

~~~
jbaruch_s
I am not sure how the fact that Bintray is DDOSed from China (and still fully
operational without any interruption) dismisses your trust in Bintray.

I am also not sure how you figured out those are fake downloads. For sure the
script that DDOSes Bintray from China won't use Groovy, but it's a still a
valid download. Not for showcasing how popular Groovy is (they factor out
those things when talking about the numbers), but for the raw statistics - for
sure. The file was downloaded, wasn't it?

Please elaborate?

------
tensor
The biggest problem with this policy is that new users, or even experienced
ones, are likely not aware of it. This is a very serious problem that should
be addressed quickly.

edit: and with websites everywhere routinely providing SSL, it seem crazy that
it has to be a paid feature for such a critical service.

~~~
sitkack
Funny thing is that CERT doesn't have a problem with shenanigans like this.
They are more concerned with buffer overflows than by-design stupidity.

------
clarkm
So in principle, it's doing the same thing as:

    
    
        $ curl http://get.example.io | sh
    

which we all know is bad. But in this case, it's hidden deep enough that most
people don't even know it's happening.

~~~
yonran
Downloading from HTTP is not an issue (as far as integrity is concerned) if
maven were to validate the downloads against some chain of trust. But
apparently it is not.

Now I am wondering what tool actually uses those .asc files that I have to
generate using mvn gpg:sign-and-deploy-file when I upload new packages to
sonatype...

~~~
technomancy
Running `lein deps :verify` does this.

~~~
brl
How does it know what the correct signing key is?

edit: Looked up answer myself. Lein downloads whatever key the signature
claims to be made with from public keyservers. How does this provide any
additional security over not bothering to verify signatures?

~~~
technomancy
The difference is that you could track down the keys either directly from the
author or by someone who has already personally verified and signed the
author's key. In practice this is very difficult, and using a key that you
haven't gotten your friends and co-workers to sign is not any better than
skipping the signing altogether.

~~~
brl
Even if you have carefully installed the correct key from the author, if your
download is intercepted and an attacker sends you a bogus artifact and
signature it looks like Lein will just retrieve the attackers key from the
keyserver and validate the signature.

~~~
technomancy
This is true; at the time of implementation so few Clojure libraries were
signed that taking it the rest of the way was not a clear win.

But clearly the job isn't finished; even if Clojure developers do a good job
of signing packages and signing each others keys, (which is not generally true
today) it still needs to distinguish between signed packages and trusted
packages. Hopefully the next version can add this. But as with anything that
requires extra steps from the developer community, a thorough solution is
going to take time.

------
pjlegato
All of Maven central is only 180gb, according to
[https://maven.apache.org/guides/mini/guide-mirror-
settings.h...](https://maven.apache.org/guides/mini/guide-mirror-
settings.html)

How hard would it be to just mirror it to S3 and use it from there via HTTPS?

~~~
technomancy
> How hard would it be to just mirror it to S3 and use it from there via
> HTTPS?

Trivial.

Now ask: how hard would it be to pay the bandwidth charges, assuming it were a
public bucket. I don't know the answer, but it's a much more interesting
question.

~~~
pjlegato
Yes, a very interesting question. It'd be very expensive.

It occurs to me that BitTorrent technically solved the problem of high
bandwidth costs long ago; millions of people transfer 1.1TB files around every
day without worrying about bandwidth costs at all.

Can we come up with a similar system for jars? Why are we still relying on
central servers for this at all?

------
chetanahuja
If I understand this correctly, maven based builds can contain dependencies on
libraries hosted on remote servers. golang build system has (or had) something
similar too. Witnessing this trend take hold is astonishing and horrifying in
equal parts. Not just as a security problem (which is clearly obvious) but
also a huge hole in software engineering practices. How can anyone run a
production build where parts of your build are being downloaded from untrusted
third party sources in real time? How do you ensure repeatable, reliable
builds? How do you debug production issues with limited knowledge of what
version of various libraries are actually running in production?

~~~
buerkle
It's fairly easy to setup a local server containing all your jars and still
use maven or ivy. I do that at my current employer.

~~~
chetanahuja
But in that case why maintain two separate repositories? One for "our code"
and one for external. I'm assuming the code in these repositories is open
source... right? Why not simply check in the version to be used right in your
local SCM?

~~~
lmm
There are a bunch of different SCMs. It's nice to decouple "hold released
builds at specific versions" from your general development repository.

------
jnbiche
npm has the same problem of sending packages over http, but it's even worse
since on average each node package uses about a billion other packages and
because injecting malicious code in JavaScript is incredibly easy.

And to be clear, just http here is not the issue. It's http combined with lack
of package signing. apt runs over http, but it's a pretty secure system
because of its efficient package signing. Package signing is even better than
https alone since it prevents both MITM attacks _and_ compromise of the apt
repository.

In fact, apt and yum were pretty ahead of their time with package signing.
It's a shame others haven't followed their path.

~~~
seldo
npm by default uses HTTPS, and has for more than 3 years. It's a little
confusing because the loglines all say "http" in green, but if you actually
look at the URLs being downloaded they are all to
[https://registry.npmjs.org/](https://registry.npmjs.org/)

------
GaryRowe
I wrote a Maven plugin to avoid this.

It's available under MIT licence: [https://github.com/gary-
rowe/BitcoinjEnforcerRules](https://github.com/gary-
rowe/BitcoinjEnforcerRules)

------
sitkack
luarocks has the same problem. You don't need SSL, you need the packages to be
signed.

------
0x0
I wonder how many enterprise apps have been backdoored through this flaw over
the years by now.

~~~
sitkack
I'd immediately backdoor the rt.jar and the compiler so that future binaries
have the backdoor. Trusting trust ...

------
dandelany
Sorry to nitpick, but you might wanna fix this typo: s/pubic/public :)

------
buckey
Yeah have you ever wrote code on the play platform? There is your proof of
concept at least on earlier versions static injection using annotations ...
It's also how spring works and almost all dynamic ... Hell you can jit your
code don't even need to compile it into a class the run time can do it for you
... That why I always compile my jar files so they can't be read as a
compressed file anyway pretty cool sounds like you could have a lot of fun
with someone doing this ... You could turn there computer into anything you
want using Java command line functionality .... I.e. System.get(os.name) if
windows do this if OS X do this if lunix do this using Java.lang.runtime.exec
then after you open the back door to there computer time for socket
connections and getoutputstream etc... Anyway point being java is a cross
platform lang so there is a world of possibilities and most of the time they
are running this from an IDE so if you inject a sudo call who knows what could
happen

------
SanderMak
The vulnerability even has a name: Cross-build injection attacks. I wrote
about it some time ago [1], [2]. The complete answer includes verifying the
(now mandatory) PGP signatures [3] of artifacts in Maven Central. But you need
a web-of-trust for that and the whole process is rather impractical currently.

[1]
[http://branchandbound.net/blog/security/2012/03/crossbuild-i...](http://branchandbound.net/blog/security/2012/03/crossbuild-
injection-how-safe-is-your-build/) [2]
[http://branchandbound.net/blog/security/2012/10/cross-
build-...](http://branchandbound.net/blog/security/2012/10/cross-build-
injection-in-action?src=archive) [3]
[http://branchandbound.net/blog/security/2012/08/verify-
depen...](http://branchandbound.net/blog/security/2012/08/verify-dependencies-
using-pgp/)

~~~
tomjen3
Instead of going WOT, why not just get a specific SHA hash, instead of a
specific version?

~~~
SanderMak
Sure, you could obtain a hash out-of-band and pin to that. Not much more
convenient given you have to do it for all transitive dependencies and Maven-
plugin dependencies as well.

------
akerl_
Thanks to whomever changed the title; I didn't like the original title, but
couldn't come up with a better accurate one.

------
wernerb
This is indeed a problem that needs to be addressed at some point. The MITM
possibility has been mentioned before at SE
[http://stackoverflow.com/questions/7094035/how-secure-is-
usi...](http://stackoverflow.com/questions/7094035/how-secure-is-using-maven)

------
fiatmoney
So if they need some money, what is a better revenue model for them?

\- charge some token amount of money to projects (harms the ecosystem,
probably not a good idea)

\- charge some amount for projects to host old versions, or for users to
access old versions (same idea as the first, just less so)

\- charge for access to source jars

\- paid javadoc hosting

\- rate-limiting for free users (the "file locker" model; particularly
effective at convincing people sharing an office IP into paying up)

Any others?

~~~
ontoillogical
They claim the money is a donation to a open source software project, so they
don't even need the money.

------
passive
For those of you in the Python world concerned about such a thing, check out
Peep: [https://pypi.python.org/pypi/peep](https://pypi.python.org/pypi/peep)

It's a pip wrapper that expects you to provide hashes for your dependencies in
requirements.txt.

There was a lightning talk at PyCon this year, it seems super easy to use
(though admittedly I'm not using it regularly yet).

------
joncp
The problem goes deeper. That firewall (Little Snitch) updates itself over
port 80, so most likely unencrypted.

------
jgalt212
> When can this happen? If you ever use a public wifi network in a coffee shop

Just don't do this. There is no such thing as a free lunch (or wifi).

~~~
graue
I do it. I always thought, "What's the harm? Everything important is over SSL
these days". Apparently not!

------
iancarroll
What firewall is that? Looks nice.

~~~
MBlume
[http://www.obdev.at/products/littlesnitch/index.html](http://www.obdev.at/products/littlesnitch/index.html)

------
qwerta
We store jars in git repo...

------
abalone
I understand the need to raise money for projects, but the attitude[1] that
security is an optional "premium" feature needs to end.

It should be no different from shipping broken code. You can't just say, "oh,
well we offer a premium build that actually works, for users that want that."
Everybody needs it.

Evernote made this mistake initially when SSL was originally a premium
feature. They fixed it.

Granted, there are degrees of security but protection from MITM attacks is
fundamental. (Especially for executable code!)

[1]
[https://twitter.com/mveytsman/status/491298846673473536](https://twitter.com/mveytsman/status/491298846673473536)

UPDATE: @weekstweets just deleted the tweet I was referencing where he
described security as a premium feature "for users who desire it" or words to
that effect.

~~~
gregso
But will users in aggregate pay more when extra effort and resources are
expended on security? Will you?

If the answer is no, then the smart developer has no financial incentive to do
so, and every reason to segment security out as a premium feature.

Maybe MITM vulnerability counts as broken code. But as always, markets win. I
don't think the status quo will change until users consider security
assurances worth hard dollars.

~~~
abalone
By that logic, smart developers have no financial incentive to fix bugs unless
it's for a paid upgrade.

Think through that a little more and I think you'll find there is long-term
ROI in the form of customer trust and goodwill. You'll buy the product because
it works and won't hurt you, and basic security should be part of "won't hurt
you".

~~~
serf
>> By that logic, smart developers have no financial incentive to fix bugs
unless it's for a paid upgrade.

Right! And that's actually a valid model. Ask HP about what it'll cost to
upgrade the firmware on your enterprise server..

~~~
abalone
It's valid, but the claim was that it's the _only_ valid model for smart
developers, which is false.

------
foo-licious
It's java who cares?

