Equifax Breach Hindsight - What If They Used Containers?
What are the chances that your name, address and social security number have been stolen? If you are an American citizen, the answer is ‘about 50/50’. The reason, perhaps not surprisingly, is a recent data breach. Records of 143M customers of Equifax, a large credit reporting company, were stolen.
According to Equifax’s report, attackers had unauthorized access to internal assets from mid-May, up until June of 2017. Equifax announced the hack on Sep. 7th, and released a video apology from their CEO. They also setup a website, for their customers to check whether their information was hacked.
In their statement, Equifax reassured its customers that there was “No Evidence of Unauthorized Access to Core Consumer or Commercial Credit Reporting Database”. Not a very reassuring statement if you are a victim. Or perhaps it is a method of assuring their business partners that they still have credible data to sell?
This breach is certainly filled with controversy. The lack of security measures on customer's data, the unfilled CISO position, the late disclosure to the public, articles about executives selling their stocks, and (apparently illegal) disclaimers the company initially made their customers agree to, if they wanted Identity Theft Protection; these all raise interesting questions about security and policy. Instead of diving into all of these topics, let’s practice our hindsight skills by inspecting the technical aspects of the breach.
On Sep. 9th, Baird Equity published a report, claiming that the breach happened “via the Apache Struts flaw”. Which flaw was that? There were roughly 4 major exploits (enabling remote code execution) in Apache Struts in 2017 (CVE-2017-12611, CVE-2017-9805, CVE-2017-9791 and CVE-2017-5638). One of them was disclosed two days before Equifax’s announcement, and another on the same day.
This perhaps led Quartz to claim (and then somewhat retract) that one of the more recent vulnerabilities was responsible for the hack. It also led the Apache Struts Project Management Committee to respond, pointing out (quite rightly IMHO) that “the security breach was already detected in July, which means that the attackers either used an earlier announced vulnerability on an unpatched Equifax server or exploited a vulnerability not known at this point in time -- a so-called Zero-Day-Exploit”.
Web application vulnerabilities are not uncommon. Instead of trying to guess which specific vulnerability the attackers used, let us examine how web applications can be better protected from similar attacks.
Attacking Apache Struts
Apache Struts offer a convenient method for developers to build dynamic web applications, where users can upload their own content. This means that the server has to do a lot of deserialization of untrusted data uploaded by the users. This process is prone to vulnerabilities, because deserializing an untrusted object may unintentionally result in code execution.
To demonstrate how these types of vulnerabilities can be used by attackers, I used one of the more recent Apache Struts vulnerability (CVE-2017-9805). “...This particular vulnerability allows a remote attacker to execute arbitrary code on any server running an application built using the Struts framework and the popular REST communication plugin.
The weakness is caused by the way Struts deserializes untrusted data…” I set up a victim tomcat server container which used the vulnerable Struts REST plugin. I used another container - attacker - to run the exploit (based on this python script). On the wire, we can easily identify the offending payload that ends up executing, by building a process and giving it a command. The following figure shows how we basically upload a shell, by writing to a file.
Once the exploit triggers code execution, all we need to do is write a war file (archive basically) inside the tomcat webapps folder. For demonstration purposes, I used this simple webshell example. The following video shows how an attacker can exploit this vulnerability and use the webshell to persist and run arbitrary commands inside on the server. Note, that even though the demo is performing the exploit on the same container, all of the mentioned exploits can be executed remotely.
When attackers go for web servers, they usually want to:
(a) Get access to sensitive data on the web server.
(b) Remain persistent.
(c) Access additional internal resources.
To accomplish the first step (a), they need to exploit some vulnerability.
Uploading a webshell allows the attacker all of the benefits we mentioned: the ability to execute arbitrary code on the web server, and persistency: the shell is just another web application. Also, from the internal web server, the attacker can pivot to additional servers and resources.
Security Advantages of Using Containers
But what if you are running Apache Struts (like I did) inside a container? The mere use of containers already stacks obstacles that the attacker has to deal with. Containers don’t live as long as Web servers. Sometimes minutes or only seconds. To remain persistent (remember that the hackers had access for two months!) the attacker has to work much harder to continuously attack and infect the web application - increasing his chances of being caught.
Another major problem for the attacker is that he’s not successfully compromising a web server, only a container. The container is isolated from the underlying machine, and from other containers. Also, containers by default have far fewer privileges than regular processes, so making an escape from a container is a task that usually involves kernel exploitation - not easy.
When we look at the network, we again find advantages of using containers. Most containers in
production environments communicate over a separate network. This makes the pivoting efforts of the attacker much harder, as he may only have access to other containers and not to the underlying infrastructure.
All of these additional, inherent security layers the containers provide, make the attacker’s job much harder, and the chances of him giving up or being caught increase.
To sum up, containerization of applications, when done properly, shrinks the potential impact and longevity of attacks, and limits the ability of an attacker to perform reconnaissance and move laterally to other targets.
Making it Even Better with Container Security
While the use of containers already gives you an edge over attackers, it does not mean that these attacks can’t happen - they only require more effort and skill. There are some simple, and some advanced, security features for containers that can help mitigate against similar threats.
Some security mechanism simply patch specific exploits, or offer (so-called) Zero Day Protection against similar exploits. These may - or may not - work, depending on the exploit (after all, Equifax’s past CSO endorsed FireEye’s Zero-Day Protection).
A better security approach would be to profile the behavior of your containerized application. If your container suddenly starts executing arbitrary commands or running executables then it is probably a sign that it was compromised. The profile is not only limited to system calls or file access. The network connections of each container can also be protected with profiled firewall rules. These rules will prevent a compromised container from trying to access other containers, the underlying infrastructure or simply communicate with a Command & Control server.
So would the Equifax breach have happened if they’d been using containers? Hindsight is 20/20 and we don’t know the exact details of the modus operandi, so we can’t say with certainty. However, it’s likely that such a breach would have been more difficult with containers, and that if successful, it would have been less persistent, not as widespread, and mitigated sooner.