The latest exploit in the series of issues with cloud infrastructure software is called “ContainerDrip” (CVE-2020-15157)and in some cases it can cause you to leak your registry secrets to an attacker. The attack is actually a kind of secret or password leak using request forgery. Your client unintentionally makes an HTTP API request to the attacker’s endpoint where this request contains the container image registry secret. In this post I want to point out the bigger underlying problem, but first the attack.
In a nutshell, when you decide to pull a container image, you download its manifest file first – which describes how this container image actually looks. Container images are made of file system layers, and the manifest file tells you where you can download these layers one-by-one, based on URLs.
Without diving into the specifics, the general mechanics of the attack are that a malicious actor pushes a specially crafted manifest file to a public repository (like docker hub, let’s say “library/gonnastealyoursecret:v1”). In this manifest, they put a layer URL to their own webserver (https://registry.evil.com). Now when someone tries to pull the image above, the containerd (managing images) makes a request toregistry.evil.com with the secret docker registry credentials. This server will authenticate itself correctly using HTTPS, but will take the secret from the request and now the attacker has your docker registry secrets. There are obviously more details, but this is not the point I want to make (see a complete write up at https://darkbit.io/blog/cve-2020-15157-containerdrip).
The conceptual problem I see here is giving your secrets to a semi-authenticated entity. When opening an HTTPS connection against evil.com, you and your browser are making additional efforts to ensure this is the site you wanted to visit. You typed evil.com in your browser address bar and the browser cross-checked the URL with the TLS certificate. In automated DevOps processes, such as docker pull or even other REST API based redirections, there is no human part of the process and if someone fed the system with a malicious URL and automation ended up there, there is nothing you can do – since anyone can get a valid TLS certificate for their domain. Therefore I call these sites semi-authenticated, since the TLS certificate is valid, but we have not validated the reason to end up there.
This bring us to the point here, even with authenticated entities, we should not share secrets. Protocols, like HTTP basic authentication, are outdated because the client shares their secret with the verifier in order to get authenticated. There are many crypto protocols out there which are based on zero-knowledge proofs (asymmetric cryptography) or require the client to prove that they have the secret by asking it to hash a nonce with the secret.
This is why we at ARMO are using zero-knowledge authentication even between verified entities. You should not build your security around a single point of failure.