5 ms·
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
by heavenlyhash 12y ago
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_the_build.pdf https://www.fortify.com/downloads2/public/fortify_attacking_...
- michaelt 12y agoWhy 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 12y agoI 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.