- Image Development
- Installing SW without proper configuration, e.g. default passwords...
- Exposed credentials in
Dockerfiles
- Malware in 3rd party resources used to build the image
- Vulnerabities in non-updated images
- Source Code Hub (e.g. GitHub)
- Malicious modifications to source code used in the image
- Dependencies Repo (e.g. Artifactory)
- Malicious modifications to dependencies used in the image
- Container Registry (e.g. DockerHub)
- Malicious modifications to (parent) images
- Container Runtime Abuse
- access restricted files on host system
- vulnerable TCP/IP connections
- (unwanted) access to user accounts with (administrative) user privileges
- Kernel exploits
- unlike in a VM, Kernel is shared among all containers and the host
- if a container causes a Kernel panic, it will take down the whole host
- VMs provide better security here, since attacker needs to route an attack through VM kernel and hypervisor before being able to touch the host kernel.
- Denial-of-Service attacks
- containers share kernel resources
- if one container can monopolize access to certain resources, it can starve out other containers
- Container Breakouts
- attacker gaining access to container should not gain access to other containers or host
- default containers are not namespaced, i.e. root in container will be root on host
- take privilege escalation into consideration: user gets elevated privileges
- organize your security around assumption that container breakouts are unlikely, but possible
- Compromising secrets
- when container accesses database or service, it will likely require a secret (e.g. API key, password)
- attacker who gains access to this secret also has access to service
- problem becomes worse in microservice architecture with containers constantly starting and stopping
- Misconfigured application inside of Container
- the usual suspects: SQL injection, cross site scripting... due to exploited application
- (unnecessary) exposed ports...
- Docker Daemon
- Docker API exposed on TCP port / Unix socket
- access restrictions to port / socket
- User Namespaces are supported directly by the docker daemon. This feature allows for the root user in a container to be mapped to a non uid-0 user outside the container
- a way to limit what a process can see, to make it appear as though it’s the only process running on a host
- resources of other processes are hidden from a process
- a process (in a container) can't alter what it can't see
- namespaces do not restrict access to physical resources such as CPU, memory and disk. That access is metered and restricted by a kernel feature called ‘cgroups’
- if you run Docker on a server, it is recommended to run exclusively Docker on the server, and move all other services within containers controlled by Docker
- make use of linux capabilities instead of
root
access- many capabilities that normally require root access can be granted to non-root users via capabilities (e.g. starting a service on a port < 1024)
- restricted permissions for the
root
user in the containers means less attack surfaces if an intruder manages to escalate privileges to a root user within a container - The best practice for users would be to remove all capabilities except those explicitly required for their processes.
- use trusted, signed images only
- each process and container should run with the minimum set of access rights and resources it needs to perform its function
- if one container is compromised, the attacker should still be severely limited in being able to perform actions that provide access to or exploit further data or resources
- steps to reduce the capabilities of containers:
- do not run processes in containers as
root
- mount/run filesystems as read-only
- cut down kernel calls that a container can make
- limit resources that a c container can use to avoid DoS attacks
- do not run processes in containers as
- in multi-tenancy setups, make sure that each tenant is running on its own host
- prevent one user, when breaking out of a container, to access data from another user on the same host
- keep containers processing sensitive information separate from other containers processing less sensitive information
- separating containers on different VMs also prevents DoS attacks
- combine efficiency of containers with security of VMs
Generic process for updating images
- Identify images that need update (application images as well as base images)
- Create update version of each image (or get it from vendor)
- Push to your local registry
- Re-build depending images with
--no-cache
and push to registry - Pull images on each host
- Restart containers
- Remove old images from the host
- vulnerability scanner https://github.com/aquasecurity/trivy
- k8s security testing https://github.com/aquasecurity/kube-bench
- container security https://www.aquasec.com/
- https://docs.docker.com/engine/security/security/
- https://learning.oreilly.com/library/view/docker-security/9781492042297/
- https://www.trendmicro.com/vinfo/us/security/news/security-technology/container-security-examining-potential-threats-to-the-container-environment
- https://medium.com/@teddyking/linux-namespaces-850489d3ccf
- https://medium.com/@beld_pro/how-does-docker-play-with-cgroups-when-i-create-an-instance-6ce24daccfb2
- https://medium.com/@mccode/understanding-how-uid-and-gid-work-in-docker-containers-c37a01d01cf