Thou shalt not trust thy neighbour's password

Posted 2016-06-24 19:20:05.000000

Last month I retweeted Eric M.J.’s announcement of Hex v0.12.0. The feature that caught my attention most of all was the addition of package checksums to mix.lock. As I mentioned in my tweet, I had to cut the section on dependencies from my ElixirConf.EU talk due to time constraints. Let’s try to rectify that here.

npm-gate and typosquatting

Before diving in, let’s look at two recent incidents involving package managers that you may have heard about.

Back in March there was npm-gate, in which a disgruntled JavaScript developer decided to pull a small but widely used package from the NodeJS package repository, npm.

More recently there was the revelation that a student was able to get thousands of developers to run code that could easily have been malicious, simply by uploading packages with names similar to popular dependencies.

Both episodes got quite a lot of (mainstream) media coverage, for instance at Ars Technica.

The weakest link?

Those two stories illustrate a few important points about software dependencies:

Think about this for a minute: while you are busy hardening your server’s Linux configuration, tuning your load balancer’s TLS settings and keeping your certificate’s private key safe, the weakest link in your security posture might be some unknown developer’s password hygiene. What if some developer somewhere used the same credentials for GitHub as for that dating site that was hacked last week?

Elixir, Mix and Hex

This is of course a generic issue that applies, to a greater or lesser extent, to all programming languages. So what does it mean for the Erlang/Elixir ecosystem and the Hex package manager?

There are a couple of things you should know:

Compile-time execution

In Elixir, compiling code means executing code: this is an inherent part of the language design. For instance, defmodule takes a do block that is executed at compile time to produce that module’s BEAM binary. This means an untrusted dependency will have an opportunity to run code not just on your deployment machines, but also on your build server and/or your laptop, where it could potentially access your (corporate) network.

Keep in mind that many Mix tasks automatically trigger compilation, e.g. mix ecto.migrate and mix app.tree, as well as iex -S mix. In practice, after you’ve pulled in new or updated dependencies you should review them before you run any further Mix tasks.

Fetching dependencies

Remember that the mix.exs file that specifies a project’s dependencies is also code, which means this file gets evaluated as part of the mix deps.get task. I’m assuming you don’t inject malicious code into your own mix.exs file, but what about your dependencies?

If you pull in dependencies through Git or using a path reference, mix deps.get will recursively evaluate the mix.exs files of those projects. In case of Git this could potentially lead to unwanted execution of code that was just downloaded, before you had a chance to review it to decide whether it is safe to compile!

Update: I posted a question to the elixir-lang-core mailing list to collect feedback on ways to mitigate this risk. I’d love to hear from you.

The good news is that Hex instead uses package metadata to determine further dependencies that need to be pulled in. In other words, the mix.exs file of Hex packages is not evaluated during mix deps.get. Hex ignores any non-Hex dependencies a package might have, so there should be no surprise code executions from Git repositories while fetching Hex packages.

Hex package integrity

There is currently no support in Hex for signed packages, but the metadata for each package does contain a SHA-256 checksum of the package contents. During package installation the checksum over the downloaded files is compared against the checksum in the hex.pm registry, and any mismatch causes Hex to abort.

Since the registry data is retrieved over HTTPS and is itself protected by a signature, the checksum provides reasonable assurance that the files you just downloaded match the ones submitted to hex.pm. The weakest link here is, once again, the original developer’s credentials.

This is where the checksum in mix.lock comes in: any unexpected modifications to the package contents after you’ve locked in your dependencies will be flagged. So while you should still take extra care when adding or updating dependencies, there should be no nasty surprises when fetching locked-in dependencies during deployment.

Recommendations

In order to protect yourself from the risks described above, disconnect from the network and only code in machine language using a hex editor you wrote yourself. And don’t forget to wear your tinfoil hat.

For the slightly less paranoid:


Back