I'd like to set up a hardened Docker instance, mostly for running micro-services such as statically compiled golang applications. What I'm looking for is to protect the host OS from a rogue container and containers from one another. I tried to summarize the situation with the following scenario.
Scenario:
We have a server running a minimal OS such as alpine linux (busybox-based OS), with SElinux and grsec installed, activated and correctly configured.
On this server runs a Docker instance with 2 running containers, A and B and a volume V.
The container A contains a statically compiled application with no dependencies, networked to the public Internet (web app or public API). This application contains a HUGE bug something like arbitrary code execution/upload/full reverse shell the worse you can think of. This container is also networked to the volume V as upload destination, database, etc.
The host OS contains a flag that can only be read when root (enforced by SElinux).
The container B also contains a flag and an application but no connection to the outside world.
Attacker:
- Human, knows about the huge bug in the application.
- He wants to get the flags. The data in V isn't important.
- He's not a spy agency but still a high-grade security specialist.
- May have access to some zero-days we aren't aware of.
Assumptions:
- The linux kernel has bugs but grsec is enough to cover that. Can't be an attack vector unless grsec is deactivated
- Grsec and SElinux don't have bugs and aren't mis-configured.
- A user root in the container is root outside the container (maybe some day this won't be true anymore...)
- Docker is a real-world Docker. No known-bugs but has been affected by bugs in the past and it could happen again.
- A log system for future investigation is already properly set up.
Goal:
- Protect the flags. Probably not possible since we assume that Docker has bugs.
- Reducing the attack surface.
- Make the attacker's life difficult.
- Set an alarm that trigger if the attacker tries to get the flags. Preferably way before he managed to get them.
Questions:
- How realistic are my assumptions?
- How would you achieve those goals?
- How goods are my following suggestions?
- Any general security advice for Docker?
My suggestions:
- Configure SElinux such as no user can write on A, and no user can execute files on V.
Use an extremely minimal Docker image, without any userland. Something like:
FROM scratch COPY app / ENTRYPOINT ["/app"]
De-escalate privilege before running the app. (Not sure what is the proper way to do that...)
- A fake busybox user-land? Something that would trigger an alarm if we try to call
/bin/sh
,/bin/ls
or anything like that.