WAF evasion techniques for Command Injection
Let’s talk about Command Injection; I’m going to talk about this specifically from the perspective of Web Application Firewalls (like BIG-IP Advanced WAF, BIG-IP Next WAF, F5 Distributed Cloud WAF and so on) but these concepts are generally applicable anywhere user-input is used to construct commands run on the system, directly or indirectly.
So, what is Command Injection? To quote OWASP, who put it very nicely:
Command injection is an attack in which the goal is execution of arbitrary commands on the host operating system via a vulnerable application. Command injection attacks are possible when an application passes unsafe user supplied data (forms, cookies, HTTP headers etc.) to a system shell. In this attack, the attacker-supplied operating system commands are usually executed with the privileges of the vulnerable application. Command injection attacks are possible largely due to insufficient input validation.
This attack differs from Code Injection, in that code injection allows the attacker to add their own code that is then executed by the application. In Command Injection, the attacker extends the default functionality of the application, which execute system commands, without the necessity of injecting code.
Like I say, in this case I’m going to talk about command injection to web applications, but they can happen in almost any piece of software that works on untrusted user input. Perhaps the most famous example of a command injection vulnerability is Shellshock, a suite of vulnerabilities in the Unix Bash shell and if you needed any proof that they can be hard things to find as a defender, Shellshock lived, undiscovered (or at least undisclosed, we’ve no way of proving that no malicious entities knew of the bug!) for 25 years from 1989 to 2014, in one of the most widely used pieces of software in the world.
The original Shellshock vulnerability involved a maliciously crafted environment variable containing (malicious) commands after a function definition, e.g.
env x=’() { :;}; echo vulnerable’ bash -c “echo test”
On a vulnerable system, running the above commands would display “vulnerable” because of Bash continuing to execute the (injected) commands following the function definition. Injecting a command here requires the"| use of two specific characters plus the command, the semi-colon and space characters.
If you imagine a web application passing commands to bash on a vulnerable system, you’ll see that it would be possible to block this attack simply by blocking requests containing semi-colon or space (or indeed having a signature for the full function definition and trailing semi-colon of “{ :;};”)
Bypassing protections
Any time there is a WAF in front of a vulnerable system – and sometimes even when there isn’t – an attacker must try to evade the rules preventing them from simply injecting their chosen command.
You’ll often see this when attackers or scanners are looking for SQL injection vulnerabilities in web applications, replacing characters like ‘ with %27 or the space with %20 (and many other tricks), or using chunks of existing text with the SUBSTRING() function to construct queries without having to use the actual text.
Many of the same tricks work for command injection vulnerabilities, and I’d like to talk about a specific example here because it’s one I hadn’t considered until it turned up in some real life traffic..
Bypassing WAF signatures using Environment Variables
Remember I just said you could construct SQL queries using sub-strings of existing text? Well, if your target system is Windows-based and you know there’s a command injection vulnerability but you’re unable to exploit it due to character blocks or similar restrictions, then good news! Windows environment variables might be what you’re looking for..
Environment variables exist in most operating systems, and Microsoft ones are no exception – they date back to DOS and were one of the enhancements Microsoft brought to the table over and above CP/M (unlike the 8.3 filenames, which came right from CP/M!); their behaviour has been pretty much the same throughout, and there have always been a number of ‘default’ environment variables like the PATH, TMP & TEMP. Current versions of Windows add a number of additional default environment variables like PROGRAMDATA, PROGRAMFILES etc.
Windows also allows the shell to return just a part of the environment variable value using the following syntax:
%VARIABLE:~start_pos,end_pos%
How is this useful to us, you ask?
Let’s say you know you can inject a command, but you need a space in your command line; you want to inject “ping 127.0.0.1” but the space is dropped or the request is blocked by a WAF looking for “ping <IP>”, well then you just need an environment variable you know will have a space in it!
%PROGRAMFILES%, by default, is going to be set to C:\Program Files on most systems, which has a space right there in the middle! All we need to do to get to it is use it as %PROGRAMFILES:~10,1%, for example:
ping%PROGRAMFILES:~10,1%127.0.0.1
Go ahead, fire up a command prompt, and try it out! You could even construct the whole command that way:
%PROGRAMFILES:~3,1%%SYSTEMROOT:~4,2%%PROGRAMFILES:~6,1%%PROGRAMFILES:~10,1%127.0.0.1
Again, fire up a command prompt and give that a try!
Protect against bypasses with BIG-IP Advanced WAF
Now here’s the good news: ASM includes signatures, by default, for all of those useful Windows environment variables (and the same for many other systems, too), so if you were to try the above on a vulnerable system with the right signatures in the policy, you’d still be blocked – like this:
All these signatures are part of the Predictable Resource Location Signatures signature set, so you’ll want to make sure you either have all signatures of Medium or above, or at least this set assigned to your policy:
Summary
Command Injection is a huge topic, much bigger than I can talk about in one blog post here, but hopefully this shows you one way an attacker might try to evade protection in front of a vulnerable Windows system, and some ways in which you can protect it — BIG-IP Advanced WAF or F5 Distributed Cloud WAF both have signatures for this kind of evasion.