shift or die

security. photography. foobar.

Introducing tmpnix - an alternative to static binaries for post exploitation

Background

If you are a penetration tester or red teamer, you might have run into the situation that you have gotten access to a Linux machine or container (either compromising it or by having been given white-box test access to the system in order to test the defense-in-depth mechanisms). Now wouldn’t it be useful for further exploration or post-exploitation if you had tmux on that machine? Or socat? Or strace? Or gdb? Or frida? Or r2? Or $tool_of_your_choice? What do you usually do? You go for static binaries, either compiling them yourself, which might turn out to be fiddly, or you trust a random person on the internet who was kind enough to compile it for you.

Let me present an alternative: Nix. In case you did not hear about it, it is a purely functional package manager (and also the corresponding functional language to define those packages). One of the very useful things about it is that it will built self-contained packages which include all the dependencies that are needed to run it. So you could just build your favourite tool using Nix (which has a lot of packages readily available) and copy it to the compromised machine, right? Well, unfortunately, Nix binaries and the corresponding shared libraries by default live under /nix, which will probably not exist and not be writable in the likely case that you are not root.

I read in the past that it is possible (but not encouraged, because you loose the possibility to make use of the binary cache Nix provides for you) to change that directory. So I set out to build a Nix that lives under /tmp (or optionally under /var/tmp or some other directory you have write access to) so one could just copy binaries to a location of ones choice and then execute nearly anything. It turned out a bit more tricky than expected but I managed. \o/.

So let me introduce a dockerized version of that work (if you want to do the same manually, just look through the Dockerfile to see what I do) which enables you to compile arbitrary Nix packages and bundle them up into a tarball which contains everything that is needed to run that binary from /tmp/nix.

Quick start usage

$ git clone https://git.alech.de/alech/tmpnix
$ cd tmpnix
$ docker build base -t tmpnix-base
$ docker build bootstrapped -t tmpnix
$ docker volume create tmpnix
$ docker run tmpnix search '.*strace.*'
$ docker run --mount source=tmpnix,destination=/tmp/nix tmpnix build nixpkgs.strace

After finishing to build, the script will tell you how to copy the tar-ball containing the build result and all of its run-time dependencies from the container. Once you copied the tarball from the container, use tar xjf <tarball> -C / to unpack with / as a destination.

Future work

Since this might be also super-useful to help with building cross-compiled binaries for e.g. ARM/Android/etc. and Nix already supports this, the next step is to add support for that. First manual attempts looks like this is feasible but some work in figuring out the correct runtime dependencies is still needed. Also, maybe a little web interface that lets you search for packages, build them and download the built tarballs might be added. We’ll see.