Containerization is becoming increasingly common due to portability, ability to isolate application dependencies, scalability, cost effectiveness, and ease of use. The ability to easily package and deploy code has changed the way that organizations work with applications. But like with Windows servers years ago, or AWS today, any time one specific technology gains a significant portion of the market share, it becomes a target for attackers. Here’s what you need to know about the security risks of vulnerable containers.
Some Background on Container Vulnerabilities
When containers were first released, an attacker would have to first discover that an organization was using containerization and then try to find a way to exploit those containers. Today, it’s a safe bet that containers are in use, and if an organization’s containers aren’t secured, they can present a quick way into a company’s infrastructure.
To minimize the risk of your company being breached, you can (and should) follow some of the common best practices out there:
Reduce the number of processes running in your containers to minimize the attack surface.
Run your containers as a non-root user, and make sure your images are patched.
Segment your network, use only signed images, monitor for unusual behavior, and don’t keep credentials on your images.
Doing these practices already puts you ahead of a large portion of the industry. However, if container security were that simple, we could stop this article right here. Companies wouldn’t be coming out with tools to manage the security of your containers, and attacks against containers wouldn’t be increasing rapidly. Since this isn’t the case, we’ve compiled the four categories of container vulnerabilities below along with best practices for reducing risk.
4 Categories of Container Vulnerabilities
Let’s dive into the four categories of container vulnerabilities (application, configuration, network, and image vulnerabilities), what those really mean, what threat they could pose to your organization, and how these container best practices apply to them.
In any application deployment, the first set of vulnerabilities to consider is your application itself. Vulnerabilities within your application, the framework used to write your application, or the libraries that your application depends upon can leave your organization open to attack.
For example, upon adding only a dependency checker and react itself, as seen in the following package.json file, our package-lock.json file (where the list of our dependencies are stored) is 1873 lines long.
More than that, upon running npm-audit we can see that we already have 2 severe vulnerabilities.
To prevent this brand of application exploit, your organization should be scanning for new exploits and vulnerable packages, then comparing that list against dependencies within your application in addition to scanning for vulnerabilities within your application code itself.
That’s not the end of our application vulnerabilities, however. The most secure application can fall prey to improperly configured default settings, weak credential requirements, or misconfigured access controls. It could be storing sensitive information without properly set up encryption, so your organization should also be scanning for weak encryption algorithms as detailed by OWASP here.
Once your application itself is secure, it’s important to look at the next category of docker container vulnerabilities: Configuration Vulnerabilities. These come from misconfigurations in the container, or even the host itself.
While some of these configuration vulnerabilities are addressed through general container best practices such as not running containers as root to prevent privilege escalation, securing container networks, and using HTTPS rather than HTTP, other configuration vulnerabilities like unsecured environment variables and volumes without well configured permissions can pose a threat to your organization as well.
Let’s say your organization has configured a volume, but allows execution of files in the volume. An attacker could potentially leverage that misconfiguration to run malicious code on the host itself, potentially escaping the container and attacking all of the servers within the network, access sensitive data stored on that or other nodes, create a backdoor into the network, or interrupt the availability of the service.
When looking at a docker compose file for this volume, we would see something like this:
services: frontend: image: node:lts volumes: - myapp:/home/node/app volumes: myapp: external: true
While this doesn’t look like it would present much of a vulnerability to the company at first glance, unless we have a solid use case for writing to that myapp volume, we would want to see something more like the following:
services: frontend: image: node:lts volumes: - myapp:/home/node/app:ro volumes: myapp: external: true
The presence of the ro flag after the name of the volume tells Docker that you can’t write anything to that volume.
Network vulnerabilities are a subset of configuration vulnerabilities, but are prevalent and dangerous enough to warrant their own category. These sorts of vulnerabilities stem from configuration errors that can allow more access to the container or the container’s network than the organization originally intended.
These misconfigurations could look like container ports being exposed to the internet (like ssh, or telnet, or a default database port) allowing an attacker to connect to the container without the knowledge of the organization.
It could look like a container being configured to transmit data via HTTPS, allowing for an attacker to listen in on traffic using a network scanner. Your organization could have container networks that aren’t secured, and could allow traffic from one container to access all other containers. In either of these cases, all it would take is one compromised container to further compromise the entire organization.
In order to find container misconfigurations or vulnerabilities, inspect the container and host network configurations. Look at your organization’s DNS settings.
One common issue is running containers with too many ports exposed. You can can look at docker containers and check for exposed ports by running docker ps -a on the docker host machine, and checking under the ports section of the output.
In the example above, we can see two containers running on 8080, which is a red flag. These two containers are not using HTTPS, and if there’s no good reason for them to be running this way, it could present a misconfiguration.
The last container above, localstack, should also be analyzed due to the large number of ports that it has open. In this case, localstack is a tool used to mock up an AWS account and has a good reason to have each of these ports open, but seeing something like this in your own environment should warant further investigation.
In addition to just looking at open ports on your host machine, you can take Nmap or Nessus, and scan for open ports on your network. This could allow you to find vulnerable containers that you didn’t know were running at all. With careful planning for your container networks, you can minimize the threat posed by this sort of misconfiguration.
Finally, something to keep in mind is that every container in your network runs some sort of operating system, be that ubuntu, alpine linux, or something else. These operating systems can have their own vulnerabilities that could allow access to your container, denial of service, privilege escalation, or any number of other exploits. This brings us back to patching and management.
Unfortunately, the only way to manage the risk associated with this category of vulnerabilities is to monitor CVE databases like the ones found here or the National Vulnerability Database here, to look for patches and updated docker images for the base image of each of your containers (for example, leveraging the Ubuntu Security Notices page here), and updating as these fixes and patches come out.
While general containerization best practices can take you a long way with your container security, there is a number of other application, configuration, network, and image vulnerabilities that could pose a risk to your organization. These risks don’t have a quick fix, but rather require scanning, monitoring, and constant re-evaluation of your infrastructure to minimize the risk of a bad actor getting into your networks.
The risks we’ve talked about in this article can be difficult and time consuming to find and manage. That’s why Veracode is launching a new container security product, Veracode Container Security, that can help you scan your images, repositories, directories, and archives throughout the development cycle for vulnerabilities, misconfigurations, embedded secrets, and more. This user-friendly tool allows you to scan fast with simple CLI commands and secure coding processes integrated into your existing CI/CD pipeline to discover potential risks.
We aim to bring you peace of mind knowing that your containerized applications are secure and compliant with industry standards. If you are interested in working with us, reach out to our sales team and see the difference Veracode can make in your organization's security posture.