When running third-party applications in your cloud environments, you inherently put your workloads at greater risk. This is especially the case when the third-party software exposes some API function to the public web. Apache Struts 2 is a popular open source cross-platform web application framework, used by many developers in their day-to-day work. Recently, we at Team Nautilus captured an interesting attack on an Apache Struts 2 container, which we’ll break down in this blog.
We’ll explore and investigate this attack using Tracee, Aqua’s runtime security and forensics tool. Tracee enables us to trace running containers and applications and to easily understand how the attack happened. Oh, and did I mention that Tracee is open source and free for everyone to use?
Exploiting Apache Struts: Initial access attack
This attack exploits CVE-2017-5638, which allows remote code execution (RCE) under the privileges of the Apache web server. We won’t go into the nitty-gritty of this vulnerability and exploit, since it’s not the goal of this blog. Instead, we’ll focus on tracing this exploit with Tracee.
Using Tracee’s network capture features, we can get a sense of what this exploit looks like from a networking angle:
- We can see the first HTTP GET request, the purpose of which is to find out whether the server is vulnerable.
- Then a second HTTP GET request, which exploits the server and contains the initial execution command line.
Here’s how those two requests look in Wireshark:
We can easily see the exploit command line in the second HTTP request. It’s pretty simple — use either curl or wget to download a shell script, then run it with the standard shell sh. Oddly enough, there’s an alternative exploit command line for Windows.
Now that we know what command line the exploit was supposed to run, we can check the Tracee event log that contains all the execve syscalls to see if the exploit ran successfully and what the context was:
We learn from this log line that the process http-apr-8080-e is running the web application and was exploited to run the command sent by the attacker. The command ran successfully and returned the value 0 (success).
Post-exploit shell script
Continuing with our investigation, we’ll use Tracee’s artifact capturing feature, which is used to capture new written files and more, to read the attacker’s post-exploit shell script. Tracee will collect for us any files that were downloaded to our container during runtime, providing much better visibility into what actually happened with our container.
Now that we have the post-exploit shell script, we can thoroughly investigate the attack.
Defense evasion
The shell script’s first goal is to evade detection by security solutions:
- Disabling firewalls, allowing traffic, deleting LD.PRELOAD, impairing defenses and preparing the ground for the script’s next actions
- Removing competing malware and software processes from crontab and deleting their persistence in the container
- Killing competing malware and software processes such as cryptominers, cloud agents, and known malware. Those multiple pkill commands continue for about 70 different processes
Once again, we can confirm the execution of those pkill commands with Tracee’s event log:
Moving to the very end of the script, we find the attackers’ attempt to delete log files to cover their tracks and avoid detection after the fact:
Execution
This is the main part of the script and overall attack. First, the attack script sets up variables and a get() function, which are used to download malware later in the script.
We can see an IP address of the command-and-control (C&C) server, which will be used together with the get() function later in the script.
Next, we have a small, simple loop the purpose of which is to download and execute the main malware binary, a cryptominer. The binary is packed by UPX to avoid detection via hashes. It plays two roles in the attack: to perform cryptomining and lateral movement, meaning that it seeks to expand and run more cryptominers on more container instances. I’ll get into more details about this later in the blog.
Discovery and lateral movement
Getting to the final function of the post-exploit script, there’s an attempt to gather credential keys, known hosts, and known users:
After the attempt to gather all the available credential information in the container, there’s a loop designed to connect to neighboring systems through SSH using those credentials. Then it downloads and executes the same script on those lateral systems.
In the attack that we detected, the adversaries didn’t manage to gather any credentials, hence the script failed to connect to neighboring systems through SSH. But no need to worry; the main malware will attempt to find more targets on its own.
Using Tracee’s event log, we can look into every single action that the malware performed — right from being executed by the post-exploit script (thus by sh) to its very core loop.
Here we see a single TCP SYN packet that was sent by the malware process bb54dc as part of a massive scan to find open SSH (port 22) and Redis (port 6379) ports in the internal network of the container. In total, the malware sent over 24,000 packets to those two ports until the container exited. The scan was unsuccessful, and not a single SYN ACK packet was sent back since the malware couldn’t find any of the neighboring containers.
Cryptomining
Next, the malware runs a different instance of the same binary, with a different process name. Then it connects back to its C&C server—the same as in the script—downloads a ‘coinminer’ variant and executes it.
One of the notable actions that the attackers performed to support the cryptomining effort was trying to load the msr kernel module, which is supposed to boost the speed of the mining process.
The MITRE table
Summary
Although this is a well-known attack exploiting the Apache Struts vulnerability, we looked at it from a different angle and used Tracee to understand what occurred in the container, which made the investigation much easier. When you deploy third-party applications such as Apache Struts 2, runtime analysis can help you secure them and grasp what the software is actually doing.
With the relentless speed of the modern DevOps cycle, keeping track of all the workloads and software running in your cloud environment is almost impossible. Tracee is a major step forward in tracing and alerting on runtime attacks and exploits — no matter what code, build, or version your container applications are running.