Shellshock mitigation with BIG-IP iRules
Yesterday, NIST released information on a new network exploitable vulnerability in the GNU Bash shell as demonstrated by vectors involving parts of OpenSSH sshd, the mod_cgi, and mod_cgid modules in the Apache HTTP Server, scripts executed by DHCP clients, and other situations where setting the environment around a bash process occurs. Vulnerability CVE-2014-6271, or Shellshock as everyone is calling it, allows remote attackers to execute arbitrary code on the target systems. Redhat has a great overview in their security blog posting on the topic.
What makes this vulnerability serious is the fact that server-side CGI applications running under the Apache Web Server with mod_cgi or mod_cgid are susceptible.
F5's Jeff Costlow is maintaining an article on the Shellshock vulnerability so make sure you check back to that article for F5's official stance.
The first step to mitigation is to setup a plan to patch the bash shell on all of your systems. In the interum, if you believe that any of your backend servers are vulnerable (if they are Unix-based then they likely are) and you are fronting them with a BIG-IP, below is an iRule solution you can apply to your Virtual Servers that will protect your servers against attacks.
Block-Shellshocked
The Block-Shellshock iRule searches for the pattern "*() {*" in the URI and in the HTTP headers. It is rare that this pattern of characters will occur in a URI or HTTP Header so we believe the number of false-positives will be minimal. If the pattern is found, an audit entry will be written to the system log with the client ip as well as the URI, and optionally the HTTP header, that the attack was detected. I chose to issue a reject on the connection. If you want to be more polite to the hackers, you can substitute the "reject" with a 403 - Forbidden.
"*() \{*"when HTTP_REQUEST { set pattern
; if { [string match $pattern [HTTP::uri]] } { log local0. "Detected CVE-2014-6271 attack from '[IP::client_addr]' in URI '[HTTP::uri]'"; reject; } else { foreach header_name [HTTP::header names] { foreach header_value [HTTP::header values $header_name] { if { [string match $pattern $header_value] } { log local0. "Detected CVE-2014-6271 attack from '[IP::client_addr]' in HTTP Header $header_name = '$header_value'; URI = '[HTTP::uri]'"; reject; break; } } } } }
Block-Shellshock-full
The first iRule gives a more detailed audit if the attack is detected. In the case where that is not a concern and you are more concerned with performance, the HTTP::request method can be used to perform a single search across all of the request header information. This does not cover the POST body, but at this point there is no indication that the exploit is exposed within the body portion of a POST request. This irule reports the client IP along with the requested URI that is the source of the attack.
"*() \{*"when HTTP_REQUEST { if { [string match
[HTTP::request]] } { log local0. "Detected CVE-2014-6271 attack from '[IP::client_addr]'; URI = '[HTTP::uri]'"; reject; } }
We will be monitoring this vulnerability over the coming weeks and update the iRule solution if a more optimal one becomes available. Please leave a comment if you have any suggestions. And, make sure you monitor Jeff's article for updates.
Special Considerations
Please be aware that this iRule will reject any connections containing the string "() {" in the URI or header. While we are confident that this is not a valid pattern for standard headers, there could be situations where custom application values contain this string pattern and this iRule would cause issues to those applications. We suggest running the longer iRule and actively monitoring the system log for false positives. If you find a case where your custom application is being blocked, you can customize the first iRule to exclude the header your application relies on.
- Gary_ZhuNimbostratusWe have below User-Agent string, I know it does not match your pattern, but very close. Is it possible that string pattern might reject a valid User-Agent ? RFC does not say you cannot have ( and ) and then {. By the way, reject is much better than 403 error that I set. Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SIMBAR ={0D6844D1-DC9B-11E1-B086-00A0C6000000}; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; InfoPath.1; OfficeLiveConnector.1.3; OfficeLivePatch.0.0; .NET4.0C; .NET4.0E)
- Tomasz_125022NimbostratusBlock-Shellshock-full iRule contains errors in log sctring ($header_value, $header_value) :-) These variables do not exist. I use: If it is determined that the vulnerability exists in the payload , this iRule will inspect the entire HTTP request for the pattern. But it reports only UserAgent value (most common attacks) and reject the source of the attack. when HTTP_REQUEST { set pattern "*(*)*\{*"; set uri [HTTP::header Host][HTTP::uri]; set UserAgent [HTTP::header "User-Agent"]"; if { [string match $pattern [HTTP::request]] } { log local0. "Detected CVE-2014-6271 attack from '[IP::client_addr]' in uri = $uri and UserAgent = $UserAgent"; reject; } }
- Anthony_GraberEmployeeThe second iRule will not work in that form because the variables header_name and header_value don't exist.
- JRahmAdminI updated the second rule to remove the header reference in the log statement since it would generate a Tcl error.
- Ian_124377NimbostratusAre you sure the 2nd iRule will scan the POST data? The doc on HTTP::request seems to suggest it does not scan POST data. "Returns the raw HTTP request headers as a string. You can access the request payload (e.g. POST data) by triggering payload collection with the HTTP::collect command and then using HTTP::payload in the HTTP_REQUEST_DATA event."
- Carlos_Rubio_69NimbostratusAbout this couple of iRules (which btw I've joined into a single one), I´m concerned about it´s impact on performance. I have several web portals with many users on everyone. If I check every request, and for every request I check it´s URI and (even more) every single header, I think this could lead to a very high resources consumption. Any of you have had any issue about performance after enable this irule (on several VS's)? Thanks in advance.
- Thanks for the feedback everyone. It seems the most likely false-positive would be in the user agent. What if we modified the iRule to block all headers that match except the user agent. If the UA matches, then empty it out and send it on. That would allow the slim case of UAs that match the pattern through with the downside that the backend app wouldn't have the true UA. Is that acceptable? @Carlos - As for the impact on performance, I went with a simple string match on the content. Regular expressions are a bit more costly but the glob-style matching in string match is much faster. Even with regular expressions, the impact should be minimal (in the microseconds for a single match). We have customers doing header string tests in production and have not had performance issues reported that I'm aware of. @Ian - You are correct. HTTP::request only returns the request portion and not the body. I will update the article with that info. Thanks for keeping me honest!
- Shibu_NarendranNimbostratusAs per the problem description, bash allows arbitrary code execution as mentioned below. $ env var='() { ignore this;}; echo vulnerable' bash -c /bin/true If one tries with any other combination other than "() {" , it does not execute the code. In that case, why do we need a regEx kind of check on combination of "(" and ")" and "{" appearing on other combinations? As mentioned here by others, it might block legitimate users with user-agent headers containing ( ) { scattered in succession. What is the problem with the solution of custom signature in the ASM – by rejecting “() {“ pattern in header values?
- @Shibu - you bring up good points. At the time I wrote the article, we couldn't determine that the exploit was limited to a "() {..." pattern so I took the route of making the search broader to make sure all bases were covered. Since then, it has been suggested that some User-Agent strings may lead to false positives. We are investigating this now. As for ASM, if you are using that product, then a custom signature is a great idea. This solution was geared for customers who are not using ASM and have iRules fronting their servers.
- Shibu_NarendranNimbostratusSorry. My apologies- I posted multiple times since it did not appear in the first attempt.