‘One of the most prominent ways for attackers to gain a foothold is by using known exploitable vulnerabilities. These are bugs in organizations’ deployed software that can be manipulated to an attacker’s advantage. But updating and patching software is a tedious task. Instead, you can just deploy an intrusion prevention system (IPS) that will detect and prevent exploitation attempts.’
Numerous sales reps trying to sell IPS software

The typical IPS pitch describes a true silver bullet. Intrusion prevention system proponents claim super-hero capabilities: intercept traffic, match it against an attack database, then block bad traffic while allowing good traffic to pass. Wow! With a mythical defense laid out by this fantasy description, why would anyone ever bother to patch software?!

When something sounds too good to be true, it probably is. A vulnerability is a bug, which can usually be exploited in numerous (even infinite) ways in today’s complex environments. Some exploitation methods appear similar to legitimate requests; the IPS has milliseconds to distinguish between the two. Yet there is a balance between false positives, false negatives, and performance. You’ll never win all three.

Let’s have a look at CVE-2018-11776 on the NIST site, for example. This is a remote code execution in Apache Struts that permits execution of arbitrary code. Below is what a sample exploitation looks like on the wire.

Subsequently, the folks at Snort (a popular, open source intrusion prevention system) wrote a signature to detect and block such exploitation attempts.

Here’s a Snort extraction (boldfacing ours):

alert tcp $EXTERNAL_NET any -> $HOME_NET $HTTP_PORTS ( msg:"SERVER-APACHE Apache Struts OGNL getRuntime.exec static method access attempt"; flow:to_server,established; http_uri; content:"@java.lang.Runtime@getRuntime("; content:".exec",within 10; metadata:policy balanced-ips drop,policy connectivity-ips drop,policy max-detect-ips drop,policy security-ips drop; service:http; reference:cve,2018-11776; reference:url,cwiki.apache.org/confluence/display/WW/S2-057; classtype:attempted-admin; sid:47634; rev:1; )

The above exploitation (matched by the Snort signature) is but one manifestation of this vulnerability. There are likely many other ways to exploit it without ever being detected by the Snort signature. Essentially, the latter looks for the string ‘@java.lang.Runtime@getRuntime(‘ and ‘.exec’ within a specific range of ten characters.

Here are a few ways an attacker could easily bypass this signature and leverage the vulnerability:

  • add dummy data to distance ‘.exec’ from ‘getRunTime(‘ by more than ten characters
  • use a different function instead of exec
  • use tokenization
  • or at least six other ways

This next code exploits the same server and is missed by the Intrusion Prevention System signature. It uses variables in the code (the distance between the two words being greater than ten—the magic IPS signature constant):

"${(#_memberAccess["allowStaticMethodAccess"]=true,#a=@java.lang.Runtime@getRuntime(),#x=new java.lang.StringBuilder(),#a.exec('{0}').getInputStream(),#b=new java.io.InputStreamReader(#a),#c=new  java.io.BufferedReader(#b),#d=new char[51020],#c.read(#d),#sbtest=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),#sbtest.println(#d),#sbtest.close())}"

All such methods are likely going to bypass the IPS and exploit the server. This is why I would feel far more secure about a cloud environment where servers are continuously patched, rather than ostensibly protected by a “state-of-the-art” IPS.

Orca specializes in AWS Cloud SecurityGoogle Cloud Platform Security, and Microsoft Azure Cloud Security.