Sandboxing containers with gVisor

Writer: Erno Kuusela, NCSC-FI January 30 2020

Background

Analysis tools aren't immune from vulnerabilities

Analysis tools can be vulnerable to malicious inputs, just like browsers and PDF readers and word processing apps are. Indeed there are some accounts of analysis tool exploitation making the rounds.

Docker and other container runtimes aren't very robust against malicious code running in the sandbox, largely because they are still running under the same Linux kernel as the host. With sufficiently bad luck the analyst's computing environment could be broken into even when using containerized tools.

Mitigations

Our images try to drop root as early as possible, before ingesting untrusted data. Configuring Docker to enable UID namespaces archieves the same effect for all containers, but this is not the default setting in Docker.

Another princple we practice, embodied in our CLI tool, is ensuring the containerized app doesn't have write access to the source files. In practice, this means copying data into countainers instead of volume mounts from the host filesystem.

Defending against kernel and container runtime exploits

A lesser known feature of Docker is that it supports configurable container runtimes. We can swap out Docker's default container runtime for a sandbox runtime that's specifically designed to defend against container breakouts even in presence of malicious code in the container. Google's gVisor user-space kernel provides us with just such a thing.

Installing gVisor

gVisor is easy to set up: You install a single "runsc" binary (or use the project's provided APT source), and run "runsc install" as root to make the necessary changes to Docker's daemon.json configuration file.

See the detailed installation instructions at gVisor's site: https://gvisor.dev/

Usage

After restarting Docker your docker run or cincan run command-lines just need the --runtime=runsc option and you're off! You can verify it's working using ps -ef - you should see a runsc-sandbox process instead of showing names whatever processes are running inside your container. Our CLI tool supports the --runtime switch since version 0.2.6.

If you want to set runsc to be the default runtime, edit Docker's daemon.json config file and put in a "default-runtime": "runsc" config key at the top level.

Read more

  • https://cloud.google.com/blog/products/gcp/open-sourcing-gvisor-a-sandboxed-container-runtime

  • https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html