Houston, we have a vulnerable container

📌 For the following part of this post, I highly recommend to have Docker and osquery installed on your workstation in order to try the examples on your own OS. This will make results more meaningful and help apprehending how osquery works.

We will now switch to a practical example to demonstrate how osquery can help us audit some Docker container security flaws. In this example, we have a Linux server running with a Docker daemon. Let’s pretend someone runs a new container on our server using the command below:

docker run -d --name web01 --privileged --user root nginx:latest

We now have a NGINX container on our system named web01 that runs in a privileged mode with the root user without any security constraints such as AppArmor. In other words, the container has now access to all kernel capabilities and can do almost everything that the host can do. This container web01 is therefore a major security vulnerability and we will now track it down using osquery.

Osquery defines the following SQL tables for Docker components that will be useful for our audit: docker_containers lists all containers that are not stopped nor killed on the host, docker_images offers a view on all the images that are stored on the server and docker_container_processes dives into a specific container to list all his running processes.

📌 These are many more tables available, to dig deeper you can consult the complete osquery table reference or use the .tables command in the osquery interactive shell.

Querying Docker containers

Let’s start with a first audit example. Using the osquery interactive shell and the docker_containers table, we will now perform our first SQL query to track containers such as web01 that are running as privileged. This query will give the name, image and status of the containers running on the host as privileged.

We will continue using the docker_containers table to track environment variables. Using the SQL LIKE syntax with % , we can inspect the whole env_variables column that contains all environment variables available in the container. In the query above, we will only match the containers that have the NGINX_VERSION environment variable. This is a very trivial example, but we can also track containers that would have a PASSWORD , SECRET or TOKEN variable, leading to potential disclosure of sensitive information.

When running containers in production, Docker also offers the possibility to use AppArmor for enhanced security. With AppArmor, you can define and enforce a security profile for each container: this will restrict the capabilities of the container and ensure that it has only access to a limited set of resources. The SQL query defined above tracks all containers that do not have an AppArmor profile using the security_options column.

More advanced queries

One critical aspect when working with Docker is to ensure that only a limited group of users can access the daemon. For this slightly more complex query, we will be using the users table that contains all users, the groups table and the user_groups table that maps the users with their corresponding groups. As you can see, we select the group named docker and list all usernames that belongs to this group.

This query underlines one of the major advantages of using osquery: we can easily aggregate data from different tables and quickly gain more insights on different concepts of our systems.

Now that we have used a subquery and SQL join in our previous query to gain more insights on multiple tables, we will continue on this path and track the containers that are running with a root process. Using the osquery table docker_container_processes , we can find the web01 container that is running the NGINX process with a root user.

In osquery, some tables require an argument to work: the file table for example, requires a path argument to avoid a complete exploration of your filesystem. Since the Docker process table also requires a container id argument to work, we are using a subquery that selects all container identifiers.