Hacker News new | ask | show | jobs
by vlovich123 1247 days ago
I wonder if just shuffling it on every release (even minor) isn’t sufficient (and actually even publishing that order). That doesn’t have full security benefit (attackers have a finite set of options) but keeps reproducible builds and the ability to distribute pre-linked binaries while raising the attack complexity significantly since no two machines are likely running the exact same version. That means an exploit has to try several different versions. Taking this a step further, create link N randomly sorted copies per version and randomly distribute those. Now the space to search through is large and the probability of picking the correct gadget variant goes down with 1/MN where there are M releases being attacked and N variants per release that might be installed (a targeted attack or an attack of a specific version only gets 1/N). Additionally, deterministic builds maintain your ability to audit binaries and their providence fairly easily (only grows linearly) while the risk of noticing the attempt without a successful exploit is N-1/N.

I’m not saying it’s perfect but it seems like a reasonable defense for binary distribution. As someone who used to run Gentoo, I’d say most people are in favor of the faster times to install a new package.

EDIT: extending this idea further, I wonder if compilers can’t offer a random seed to supply that causes a random layout of the sections within a built execution so that even statically linked binaries benefit from this.

2 comments

For binary distributions, how about shipping object files and linking them on install with mold? This should be faster than compiling from source, just marginally slower than installing pre-linked binaries, and each build will be as unique as it gets.
The size of the distributed binary gets very large because you're shipping a lot of code that ends up getting eliminated by the linker. Also if you want to do any kind of LTO, then I don't see how you do it in your model. (which is significant for the larger applications like Chrome that have the likely attack surface). Not every binary on the system actually needs this either.

Finally, the main problem with this idea is that you can't audit malware because there's no way to maintain a source of truth about what the binary on a given system should be. Distributing randomly linked copies solves that because you can have a deterministic mapping based on machine characteristics (you do have to keep this hash secure but it's feasible). You'd basically be maintaining N copies of your distro with randomly built binaries with the user being given a random one to install.

And to be clear, my better idea is to do this at the compiler level so that you randomize the relative location of functions. That way it's impossible to find any gadget to grab onto and you have to get information leakage from the machine you're attacking & this information leakage has to be repeated for each machine you want to compromise.

Randomizing the link order per release does not solve anything, for this to really work as an mitigation layer, you need to have few different randomly linked versions and randomly give these to the end users. Just randomizing the build does not solve anything as there still is exactly one layout that everyone uses.

On another note: automating this on gentoo is cool exercise, but almost certainly if you just build everything locally, the memory layout will be random enough that writing shellcode blindly presents an interesting challenge. (different compiler flags, various probabilistic optimization passes… all that leads to the functions in same object file having different sizes)

> Randomizing the link order per release does not solve anything, for this to really work as an mitigation layer, you need to have few different randomly linked versions and randomly give these to the end users. Just randomizing the build does not solve anything as there still is exactly one layout that everyone uses.

First, it does. At scale, the probability of everyone running the exact version of every piece of software is 0. If you want, go take a look and see how many users are running a given version of Android.

Also, did you miss when I wrote

> Taking this a step further, create link N randomly sorted copies per version and randomly distribute those

I agree, doing it per version is only just a small amount of coverage. We're in agreement that generating N randomized copies and distributing those evenly is a stronger position because it makes the cost MN where you have M releases that are still running and N variants per release.

This is generally less useful with automatic updates for security patches because then you do want everyone to be running the same, latest, version.