Why can you register interpreters as non-root and why do these custom interpreters take precedence?
EDIT: Checked on may dated ubuntu laptop, /proc/sys/fs/binfmt_misc/register is root:root owned with --w-------. An important detail that the article omits and that changes this "vulnerability".
To be fair, the article is not claiming that binfmt_misc is a security vulnerability, or at least I didn't come away with that impression (and the word "vulnerability" doesn't appear in the page either.) It's just being pointed out that you can use it as a pretty sneaky way to leave yourself a backdoor, which I think it is, among many.
> provides a nifty way (once the attacker has gained root rights on the machine) to create a little backdoor to regain root access when the original access no longer works
so it does imply it needs root rights
but it's an example of why it's a bad idea to "cleanup" a system from a virus without a full reinstall
it also matters for other reasons, as some ways to gain root are unreliable and don't persist reboot and you don't want to hide that you have root access
It's not omitted by the article, the threat model is stated explicitly:
> TL;DR: binfmt_misc provides a nifty way (once the attacker has gained root rights on the machine) to create a little backdoor to regain root access when the original access no longer works.
Before knowing about binfmt, I always wondered how wine is able is able to execute .exe files directly, i.e. ./prog.exe instead of wine ./prog.exe. Turns out the wine package (at least on Arch) comes with a handler for them and the Arch wiki mentions that you may want to remove it for security reasons.
It can also be used to automatically execute jar files with "java -jar". I don't think arch is set up to do that automatically, but it is fairly easy to do[1].
binfmt can also be used to register qemu for binaries for foreign architectures. This allows running programs compiled for another architecture, and makes it really simply to run podman/docker containers with images for other architectures.
Traditionally I've seen these adapters primarily used to pass binaries for other architectures to QEMU and similar.
Years ago on FreeBSD I created a "Volkswagen mode" by using the similar `imgact_binmisc` kernel module to register a handler for binaries with the system's native ELF headers. It took a bit of hacking to make it all work with the native architecture, but when it was done, the handler would simply execute the binary, drop its return code, and return 0 instead - effectively making the system think that every command was "successful"
The system failed to boot when I finally got it all working (which was expected) but it was a fun adventure to do something so pointless and silly.
It would be a similarly clever place to maintain persistence and transparently inject bytecode or do other rude things on FreeBSD as well
Yup, using this approach it's possible to build/use aarch64 containers on an x86 machine. This technique means that a much smaller set of operations are being emulated (doesn't have to emulate the entire kernel etc)
For something I was building, it enabled me to get a full aarch64 compilation done, with a native toolkit, without having to run a full emulation layer. The time savings of doing it this way vs full emulation were huge. Off the top of my head, emulated it was taking over an hour to do the full build, whereas within a container it was only about 10-15 minutes.
Another reason I compile my own kernels and disable features like this. I also disable loadable kernel modules.
Of course this makes standard support channels... Difficult.
Why can you register interpreters as non-root and why do these custom interpreters take precedence?
EDIT: Checked on may dated ubuntu laptop, /proc/sys/fs/binfmt_misc/register is root:root owned with --w-------. An important detail that the article omits and that changes this "vulnerability".
You can't. This is a classic example of an "other side of this airtight hatchway"[1] problem.
[1]: https://devblogs.microsoft.com/oldnewthing/20060508-22/?p=31...
To be fair, the article is not claiming that binfmt_misc is a security vulnerability, or at least I didn't come away with that impression (and the word "vulnerability" doesn't appear in the page either.) It's just being pointed out that you can use it as a pretty sneaky way to leave yourself a backdoor, which I think it is, among many.
> provides a nifty way (once the attacker has gained root rights on the machine) to create a little backdoor to regain root access when the original access no longer works
so it does imply it needs root rights
but it's an example of why it's a bad idea to "cleanup" a system from a virus without a full reinstall
it also matters for other reasons, as some ways to gain root are unreliable and don't persist reboot and you don't want to hide that you have root access
It's not omitted by the article, the threat model is stated explicitly:
> TL;DR: binfmt_misc provides a nifty way (once the attacker has gained root rights on the machine) to create a little backdoor to regain root access when the original access no longer works.
binfmt_misc helped me out a lot some years ago
I had a build system which was able to cross compile.
And a test system which wasn't able to handle cross compiled/emulated/remote code but needed to run test on cross compiled code.
In the end with binfmt the test system never knew it was running the code with qemu instead of native and "just worked".
Sounds like a useful trick for getting a coding agent to run/test/debug cross compiling rules.
https://search.nixos.org/options?show=boot.binfmt.emulatedSy...
Set this one line setting on a nixos system, and it can run foreign binaries. Magic.
Before knowing about binfmt, I always wondered how wine is able is able to execute .exe files directly, i.e. ./prog.exe instead of wine ./prog.exe. Turns out the wine package (at least on Arch) comes with a handler for them and the Arch wiki mentions that you may want to remove it for security reasons.
It can also be used to automatically execute jar files with "java -jar". I don't think arch is set up to do that automatically, but it is fairly easy to do[1].
[1]: https://wiki.archlinux.org/title/Binfmt_misc_for_Java
binfmt can also be used to register qemu for binaries for foreign architectures. This allows running programs compiled for another architecture, and makes it really simply to run podman/docker containers with images for other architectures.
Traditionally I've seen these adapters primarily used to pass binaries for other architectures to QEMU and similar.
Years ago on FreeBSD I created a "Volkswagen mode" by using the similar `imgact_binmisc` kernel module to register a handler for binaries with the system's native ELF headers. It took a bit of hacking to make it all work with the native architecture, but when it was done, the handler would simply execute the binary, drop its return code, and return 0 instead - effectively making the system think that every command was "successful"
The system failed to boot when I finally got it all working (which was expected) but it was a fun adventure to do something so pointless and silly.
It would be a similarly clever place to maintain persistence and transparently inject bytecode or do other rude things on FreeBSD as well
Yup, using this approach it's possible to build/use aarch64 containers on an x86 machine. This technique means that a much smaller set of operations are being emulated (doesn't have to emulate the entire kernel etc)
For something I was building, it enabled me to get a full aarch64 compilation done, with a native toolkit, without having to run a full emulation layer. The time savings of doing it this way vs full emulation were huge. Off the top of my head, emulated it was taking over an hour to do the full build, whereas within a container it was only about 10-15 minutes.
Another reason I compile my own kernels and disable features like this. I also disable loadable kernel modules. Of course this makes standard support channels... Difficult.