Unikernels Prevent Living off the Land and GTFOBins

I was recently asked about whether or not unikernels reduce living off the land and prevent abuse of gtfo binaries. A lot of people who have not deployed unikernels don't understand the constraints they put on a system that prevent lol binaries from being a commonly viable attack vector.

Why? Largely two reasons:

Unikernels don't have users to escalate privileges to.

When we say unikernels have no users what are we really saying? There is no interactive userland. You can't ssh or telnet into these things. You can't work in a shell as that implies every single command you type into the shell, being a new program, doesn't actually work since unikernels can only run one program per vm. It is common to find references to a user in a /etc/passwd file, however, those are stubs and aren't used for authorization or authentication purposes. They are fake.

Sysadmins and devops have been abusing the unix user system for many years now. In fact if you go spin up a ubuntu instance on aws right now you'll be able to intantly 'sudo su' up and almost no one ever fixes this even though many software packages still like to have their own users/groups. It's a complete broken mess. Unikernels come at this from a different angle and state that if you are only running one and only one program than there is no perceived permission difference from other programs or other users (running other programs).

The whole point of getting root on a classic linux system from merely a lower privileged user is that now you can do whatever you want. Also, to be clear here since some folks are confused - root does not mean you are running things in ring 0. You can run programs you weren't able to run before, access files you weren't allowed to look at, get rid of software or users you weren't able to do, install rootkits, reboot the system, format/corrupt the drive, rewrite memory.. the list is endless right? The moment you take away this interactive control and the ability to run other programs you're just left with the instruction pointer and hopefully some writeable && executable memory. Whoop de doo dah. Most hackers that would be happy with these primitives *still expect* to be able to eventually get some sort of interactive environment that they can run their software on and that's really the crux of the issue.

Second, you can't run other programs on a unikernel based system other than the one that is already running.

Living off the land typically indicates that an attacker has already landed on your system and now they want to escalate privileges or further establish their presence. They might find themselves in an environment that might be considered locked down and only as a normal user. So there is no concept of a 'land and expand' on a unikernel system. Whatever vulnerability you've taken advantage of needs to run your payload in-situ.

There are a handful of perceived advantages to 'living off the land' and that's probably why it was given a moniker. The main advantage to living off the land is that you don't necessarily need to introduce new tooling or download new programs and potentially trigger alerts to the SOC team. I feel this is slightly far fetched and why I don't necessarily think this terminology is good to use even for normal linux systems. At the end of the day someone who wants to attack your systems always wants to run their own programs.

It should be noted that these so-called gtfobins are all just random binaries that you'd find on a ubuntu/debian/arch/etc. system. While so-called distroless containers will more than likely be a much better option than a full blown ubuntu server they too will still include a lot of these binaries including images from rapidfort, chainguard and the other so-called "zero cve" image providers.

For our purposes we are mainly comparing against linux here today as linux server workloads are what unikernels replace. While many windows applications that are running .net or java can also run as unikernels any sort of interactive gui-based program is not something unikernels do.

GTFOBin Functions

We've already talked about why you simply can't run most (we'll address the few cases where we do see a possibility) of these random binaries on a unikernel, even if they exist on the filesystem, but let's dive a little deeper into each one assuming you could.

  • Shell

    An interactive shell doesn't make any sense on a unikernel since each command you type into the shell is a new program and that by definition doesn't work. A lot of people think we are 'denying' this through seccomp or something. We actually flat out dont have support in the kernel for running multiple programs. It is not like linux or bsd (or most general purpose operating systems) in that respect.

  • Command

    A command is just an interactive program that you are running. Anytime you type 'cd' or 'ls' or 'cat' you are running a command but you are also running another program and that is not something that unikernels don't do.

  • Reverse Shell

    A reverse shell simply opens a socket to a remote host and then pipes the input to a shell. Again you can't run other programs on a unikernel other than the one that is running.

  • Non-interactive reverse shell

    This is essentially the same as the above but is not a full blown shell - really just for running single commands.

  • bind shell

    A bind shell is the opposite of a reverse shell and not commonly used simply because there is typically a firewall that would prevent an inbound connection from coming in. At the end of the day though this is still a shell that doesn't work under unikernels.

  • non-interactive bind shell

    A non-interactive bind shell is the same as above but only allows for simple commands.

  • file upload

    This technically can be done if your unikernel was using an interpreter like ruby or node.js. For instance you could find a vulnerability that lets you upload custom ruby/javascript to the server and then execute it and that code could exfil some data. However, this is only under the circumstance that you are using the same binary as the one you attacked. So if it's a node.js system it needs to be javascript. It's not the situation where you can simply call a python or ruby interpreter as that is a different program.

  • file download

    This is the same situation as above - technically this is possible assuming you are using the same binary. You will need to ensure that the script you are running can be called from the existing running process though. You can't simply 'shell out' and call a new script. So if you have a route to '/mycompromisedpath' and that points at a folder that you put your script into then this could work.

  • file write

    Like the above, this is possible assuming you are using the same binary and it can access some file you put into it's path. Technically you can insert some executable code into an executable if you have a write && exec primitive but that doesn't really have anything to do with gtfobins.

  • file read

    Same as above, doable if it's the same binary and you have some in an executable path.

  • library load

    This can be done under the same circumstances as above. Important to note that nanos has a special exec protection feature that can be enabled to prevent this.

  • suid

    Suid bits aren't recognized on unikernels as there is only one set of permissions.

  • sudo

    Sudo implies that you can escalate or change permissions to a different user but there are no users on unikernels and thus even if sudo was on the filesystem from, perhaps a docker to unikernel import, you can't call it.

  • capabilities

    Unikernels don't have the notion of capabilities as that implies different sets of permissions which unikernels don't do.

  • limited suid

    Limited suid is like suid but immediately drops privileges after invoking. Again, this is not relevant for unikernels.

So as you can see many of the gtfobins simply don't work in unikernels because of a unikernels single process nature. While attacks against things such as interpreters are still technically viable they are constrained under certain conditions and it's never the case that an attacker can call other random binaries on the system, assuming they were there to begin with.

There are a handful of other "living off the land" lists that if you're interested you should check out the living off the living off the land.

If you're on team blue or work in a devsecops/devops team you should seriously consider provisioning your sytem with unikernels and completely obliterate this set of techniques. If you need help out - reach out - don't be a stranger.

Stop Deploying 50 Year Old Systems

Introducing the future cloud.

Ready for the future cloud?

Ready for the revolution in operating systems we've all been waiting for?

Schedule a Demo