About this series
If you know yourself but not the enemy, for every victory gained you will also suffer a defeat. – Sun Tzu, “Art of War”
When you’re on the Blue Team, you’re expected to understand the systems you have to secure and the configurations to look out for. New vulnerabilities and attack paths are constantly being discovered, and it seems like there is an ever-growing list of things to not do wrong. Sometimes, though, we need to think beyond lists of vulnerabilities and put ourselves in the shoes of an attacker.
In this series, we will dissect not just what an attacker can do to get access to credentials, but also what they would do after getting that initial access. We will walk through a different threat scenario in each part of the series and tell stories of malicious hackers that are either true, based on a true incident, or reasonably theoretical.
Finding a leaked TLS private key
For this threat scenario, we will be exploring the potential abuse of secrets baked into container images; specifically, RSA private keys used in TLS certificates. The company in our scenario, Poor Corp, uses Docker Hub to publicly host their container images. One day, a malicious hacker is scanning images on Docker Hub for secrets that have been added to containers during their build process. That’s when they stumble upon Poor Corp’s old GitLab container image.
The hacker found a couple of files added to an image layer with the .crt and .key extensions. When the hacker downloads the image and checks the contents of the .key file, they see the following:
-----BEGIN RSA PRIVATE KEY-----
... (valid key contents) ...
-----END RSA PRIVATE KEY-----
Then, the hacker checks the certificate. The certificate is a wildcard TLS certificate, valid for all subdomains of Poor Corp’s domain. When the GitLab image was built, Poor Corp added their TLS certificate and private key so that the company’s developers would be able to access GitLab from outside of their internal network.
Masquerading as Poor Corp
Now that the hacker has a wildcard certificate, they can impersonate Poor Corp’s domain. However, to do that they will also need one of Poor Corp’s subdomains to go to a computer that the hacker controls. Time for some DNS tampering.
The hacker has a few different options. If Poor Corp was a large company like Google, the hacker could go to a busy place with a WiFi Pineapple (a little box full of antennas enabling an attacker to steal user data by setting up rogue wireless access points) and spoof their Single Sign On (SSO) in a captive portal. Anyone that connects to the rogue device would see their credentials stolen. Unfortunately for the hacker, Poor Corp isn’t universally used for authentication like Google. Instead, our hacker finds a different attack vector: subdomain takeover.
Knowing that they can spoof any subdomain of Poor Corp, the hacker immediately starts checking all the DNS records on Poor Corp’s domain. Soon enough, they find an A record (the "A" stands for "address") that points to GitHub Pages. Poor Corp recently migrated from GitLab to GitHub, and they put a demo website's code in the GitHub repository and published it with GitHub pages.
Poor Corp took down their GitHub Pages test repo but forgot to clean up the DNS record that pointed to it. The hacker spins up a new GitHub account, creates a clone of Poor Corp’s SSO, adds the leaked TLS certificate and key, and publishes the clone on GitHub Pages. When they set up GitHub Pages, they configure it to be at the subdomain with the abandoned A record. Now the attacker controls Poor Corp’s subdomain and has a valid TLS certificate for it!
Using the SSO clone, the hacker sends a spear-phishing email to a couple of IT administrators at Poor Corp. Both fall for the spoofed page at the valid domain, and the attacker now has privileged credentials in Poor Corp’s network! From there on, the attacker can lay low in the network and look for high-value targets while masquerading as either admin. Eventually, the hacker can steal Poor Corp’s valuable data and deploy ransomware.
Lessons learned
Now that we’ve covered the full scenario, let’s look at what went wrong.
First up is the leaked TLS private key. Poor Corp added their wildcard certificate to their GitLab image, but they didn’t consider that anyone could steal the private key from the Docker image once published on Docker Hub. Rather than adding sensitive files and hardcoded environment variables to their containers while they were being built, Poor Corp should have used runtime environment variables and mounted volumes to pass secrets into the container—by the way, ggshield, the secrets detection CLI from GitGuardian, has a command for scanning Docker images. If you find that you’ve also made this mistake, you need to immediately revoke any certificates or credentials that were exposed.
The other thing Poor Corp did wrong was forgetting about the abandoned GitHub Pages DNS record. Sites published on GitHub pages will always use the same IP addresses:
- 185.199.108.153
- 185.199.109.153
- 185.199.110.153
- 185.199.111.153
When your A record points to GitHub pages, any requests to that subdomain will go to whatever GitHub repo has that subdomain configured. Since Poor Corp abandoned its GitHub pages repo, it left the door open for the hacker to create their own with the same subdomain. Subdomain takeovers are nothing new, but there are always new ways to exploit them as technology evolves. It will always be crucial to keep your public DNS records up to date.
Hopefully, this scenario gave you some things to investigate in your environment and piqued your interest in container and code security. Exposed credentials are a huge initial access vector for threat actors. As a defender, you need to be aware of new ways that credentials can be leaked, and you also need to stay ahead of attackers and cut off the potential paths of attack that they can take after finding leaked secrets.