Never leave your docker host publicly exposed!

For the last couple of months, I have been exploring various concepts of container security both from the perspective of attacking a container and defending the same. Containers have already taken a big space in the market. According to Docker, over 3.5 million applications have been placed in containers using Docker technology and over 37 billion containerized applications have been downloaded. One of the biggest advantages it brings is Modernizing Traditional Apps whether its a monolithic architecture or microservices. Moving to the containerized application brings its own security risk. I will be discussing in detail the various attack and defense strategies of Docker Container Security in the next blog. For now, let’s jump into what title says —

According to a report from Palo alto networks, around 23,354 docker containers are over Shodan (it includes both authenticated and unauthenticated publically accessible docker host). A simple search over shodan for docker host will tell you that there are thousands of docker host running with their remote APIs publically exposed.

Shodan Query to list docker host APIs listening on port 2375

By default, the Docker host remote API listens on ports 2735 / 2736 and has no authentication. If the port is not blocked, docker host APIs can be accessed over public internet.

I tried connecting to some of these docker hosts and as expected, most of them were blocked. Letting machines do what they do best, made a python script that finds all the docker host using the shodan search query and tries telnetting to the IP on the port 2735 to check whether the port is open or now and luckily found a docker host with its APIs exposed, thus allowing public connection to it. I will be redacting the original IP to X.X.X.X.

Now, it’s time to penetrate the docker host. I tried listing what all containers were running on the docker host —

docker -H X.X.X.X:2375 ps -a

and found a bunch of them running.

Docker containers listing

Leveling up! A very common practice, most people follow is to build and run their containers by passing arguments to them as environment variables just for a simple reason that your containers might need some credentials/password to run certain services or connect to certain apps, dbs, etc. The below command will give you if there are any environment variables used for the specific container —

docker -H X.X.X.X:2375 exec -i container_id env

I did the same with each and every container which was running at that moment and found one of them using MySQL connection for it. Redacted image —

Docker container environment variables

What I later found that just running inspect container command provides way more details and ton of information about a container including environment variables passed —

docker -H X.X.X.X:2375 inspect container_id

Docker inspect container

Securing your docker container is as important as securing your docker host.

Further what I found was even more interesting, mount volumes come in great use when you want to make your data persistent in containers which is what brings security risk if you mount sensitive docker host file in your container because if someone gets access to your docker container, (s)he can now access your docker host mount points too and if the mount point has write access, the attacker can even modify the data.

docker inspect -f '{{ .Mounts }}' container_id

The above command will list all the mount points mounted for volumes to the container.

Sample image — Mount point listing

Never leave your docker host publicly exposed!

In all, the learning is to never expose your docker host API over the public. By default, it doesn’t have any authentication. If you really need it, make sure either it has authentication set up or it is allowed only for your trusted sources. https://tech.paulcz.net/blog/secure-docker-with-tls/

For any organization which is heavily using containers for running application and services and for organizations which are moving towards a containerized platform should understand and evaluate the security risks around them. Proper security controls need to be set up not only over the docker host but on each container that is being built and run.