Apache Struts Honeypot Scanning
Last week, Wei talked about how we leveraged data from our honeypots to refine our strike for CVE-2017-5638. In the week that followed, I've tracked our honeypot activity, looking for patterns and changes in the drive-by attempts abusing this Apache Struts vulnerability. For those that are not in the know, Struts is an Apache MVC web application framework for Java applications. Apache Struts 2 has recently celebrated its 10th birthday and, while old, has a large established base of existing applications. Bits might rot, but they never fully leave the Internet. If you are interested in specifics about the vulnerability, I suggest you first read Wei's blog.
The attacks on our honeypots are relatively low volume, but have become more refined as time has progressed. Below is a graph of number of detected Apache Struts attacks over the last week and a half. The following data was pulled direct from our honeypot logs using the power of regular expressions to match this attack. This is a very similar approach to how intrusion detection systems (IDSs) detect attacks in a network, however we are analyzing logs instead of network traffic.
Our busiest day got up to 46 attempts, which might sound like a quite a lot of exploits, but when we are used to seeing thousands of attacks per hour, this can easily get lost in the noise. The exploits all had similar patterns to this:
I've highlighted the relevant piece of exploit code, and we can see it is a type of command injection. In this example, you can see that this attack is checking the operating system (OS) to format a correct command for execution. We see a lot of SQLi in our web honeypots, but command injection is rarer. What's most interesting is that out of 207 attempts seen, this specific non-altered exploit was run 16 times, making it 7% of all exploit attempts, and all of them were run on the first day of public disclosure (March 8th). On that day alone, this specific pattern accounted for 66% of all drive-by apache struts exploits. This indicates that the first set of attacks were surveying the number of servers that could be compromised. This data was found by counting all raw payloads against their SHA hash.
As you can see, based on the raw payloads, almost every request was received once, except for a very few SHA hashes at the left side. This creates a “tail-like” pattern, were most hits are unique. This is not surprising when hashing across all fields of a HTTP request, since many elements like Host header fields, request methods, URLs, and others can change between each attack—either as an evasion or simply because the target changes (a different honeypot attacked results in a different Host header).
To refine this data, I hashed only the value of the Content-Type header to see if there were more similarities between the exploits:
This might look a lot like the previous graph, but while the first graph has 169 unique samples, the second has only 38. 38 is a much more manageable number to look at versus 169.
Of these 38 exploits, all but one made use of an arbitrary variable called #cmd, which is then passed in some way to java.lang.ProcessBuilder. Script kiddies are nothing if not predictable when it comes to reusing code.
Using more regular expressions, I filtered these 37 hashes down to 6 attack classes. This was accomplished by grabbing text between the start pattern (#cmd=' and ending pattern java.lang.ProcessBuilder.
The final regex ended up being:
While a good regex for analyzing our logs, it is not ideal for identifying this attack for an IPS/IDS. There are better patterns to grab that don't rely on the #cmd parameter, since this is an attacker-defined variable name, and not required for the exploit to work.
Below are the attack classes and counts of each:
Scanning/Probing - 11
These attempts were first seen after the Cisco TALOS advisory was released. They are basic fingerprinting methods, attempting to classify systems as either Windows or Linux, issuing basic commands like echo or whoami. Here is a classic example, similar to the above example:
Others in this class probed for /etc/passwd, netstat -anl, ifconfig, and other typically Linux-based files and commands to retrieve info from compromised systems for later attack.
Drive-By Downloads - 24
Drive-by downloads are attempts to use command injection to instruct a system to download a secondary binary on the system to execute. These binaries can be ELF-32, Windows PE32, or even scripting languages such as Perl or Python. In this case, since Apache Struts is multiplatform (it can run on both Windows, Linux, and BSD), we saw all these types of binaries dropped.
ELF-32 - 19
The most popular dropper was a script that looked like this:
This one tries to disable any firewall that might be present on the system, then execute an ELF-32 binary. Most of these came back from VirusTotal and others as XORDDoS or similar.
Some of the hashes dropped by this included:
Windows PE32 - 2
We also found a Windows binary that tries to get dropped by building a VBS script on the fly and then executing it:
The file caly.exe was detected with a SHA of 39178b53f41b34e250957af3198a9744f5d5675e4502884e8a45c860a44d46c7.
Perl/Python - 3
We saw one-offs for droppers that dropped off Perl bots that connected to IRC servers, Python scripts that abused urllib methods, and even a script that concatenated a set of commands to instruct Windows' FTP to download a secondary binary.
AltCoin (XMR) Miners - 2
Possibly one of the most interesting attacks on our honeypots was the attempt to drop an 'altcoin' miner on them. This particular cryptocurrency was Monero (also known as XMR). Below is one example, although there was different version that attempted to maintain persistence through modifying runlevel scripts.
One of Monero's features over Bitcoin is anonymity, however since this attacker used a public pool address to collect the coins, you can see how much they have collected:
18.22 XMR is currently trading at about $370 USD. That's a handsome profit for a few hours of work. If someone tells you they aren't a target, they don't understand attacker motivations. Sometimes you aren't the target, sometimes it's just your resources they want.
So far, we haven't seen this attack obfuscated in a complex manner and the hit rate is still relatively low. This could indicate a few things… Perhaps the number of vulnerable servers is low. Maybe there are easier targets to take over. Servers running services like Struts are probably managed better than Internet-connected devices, which could lead to a quicker patch cycle. At this point, the above is all conjecture, but odds are, if there are vulnerable systems on the Internet, they've been compromised at this point.