While a lot of online websites and blogs are explaining the vulnerability damage, providing PoC scripts and repetitive information, here we will look into another angle of this vulnerability!

Without a doubt you’ve heard earlier last week that Shellshock was landed, allowing hackers to easily exploit many web servers that used the free and open source Bash command line shell, managed by the GNU Project. This latest computer vulnerability is ranked as one of the most powerful exploits possible in the IT world, and one of the easiest to take advantage of. The US government-backed National Vulnerability Database rated Shellshock 10/10 for severity.

A network-based intrusion detection system (NIDS) can analyze traffic in real time by logging packets on IP networks. By matching packets against a known set of malicious signatures, an IPS can alert the network analyst to an attack and stop it before it succeeds. Almost all IPS vendors (such as Symantec, Cisco, and SNORT) have released an emergency signature update in response to the Shellshock vulnerability. As a security admin, one of the easiest countermeasures was to update your IPS signature before patching up the affected Linux device, or maybe even the Linux vendor has not released a patch yet.

However, what happens when analysts receive more alerts than they can reasonably correlate to an event? Or when an attacker uses a custom, coordinated, hand-made tool to craft malicious packets against an IPS sensor? Often they become overwhelmed and may miss important attack details.

The Game

In order to overwhelm the target system or hide a legitimate attack from the analyst, we will write a toolkit that generates an overwhelming number of alerts to mess around the IPS as well as the analyst who deals with it. Additionally, the good side of this toolkit is that an analyst could use this tool to verify that an IPS can correctly identify a Shellshock attack :)

SNORT has released an update of five signatures to address all the potential attack vectors of Shellshock. Excluding the last one, all of them have several things in common, which are:

1- Direction; from Outside (WAN) > Inside (Home)

2- HTTP ports (80,443) or predefined list for non-well-known ports

3- Connection has to be established (Very tricky one); this means that the TCP 3-way handshake should be already in place before SNORT considers this an attack. More on this later…

4-Content, which is the flaw in the Bash to begin with, in a format of string or URL encoding “() {” , “%3D%28%29+%7B

The last signature handles an internal attack (within local network) on an affected DHCP server.

alert tcp $EXTERNAL_NET any -> $HOME_NET $HTTP_PORTS (msg:"OS-OTHER Bash CGI environment variable injection attempt"; flow:to_server,established; content:"%3D%28%29+%7B"; fast_pattern:only; metadata:policy balanced-ips drop, policy security-ips drop, ruleset community, service http; reference:cve,2014-6271; reference:cve,2014-7169; classtype:web-application-activity; sid:31975; rev:3;)

alert tcp $EXTERNAL_NET any -> $HOME_NET $HTTP_PORTS (msg:"OS-OTHER Bash CGI environment variable injection attempt"; flow:to_server,established; content:"() {"; fast_pattern:only; http_client_body; metadata:policy balanced-ips drop, policy security-ips drop, ruleset community, service http; reference:cve,2014-6271; reference:cve,2014-7169; classtype:web-application-activity; sid:31976; rev:3;)

alert tcp $EXTERNAL_NET any -> $HOME_NET $HTTP_PORTS (msg:"OS-OTHER Bash CGI environment variable injection attempt"; flow:to_server,established; content:"() {"; fast_pattern:only; http_uri; metadata:policy balanced-ips drop, policy security-ips drop, ruleset community, service http; reference:cve,2014-6271; reference:cve,2014-7169; classtype:web-application-activity; sid:31977; rev:3;)

alert tcp $EXTERNAL_NET any -> $HOME_NET $HTTP_PORTS (msg:"OS-OTHER Bash CGI environment variable injection attempt"; flow:to_server,established; content:"() {"; fast_pattern:only; http_header; metadata:policy balanced-ips drop, policy security-ips drop, ruleset community, service http; reference:cve,2014-6271; reference:cve,2014-7169; classtype:web-application-activity; sid:31978; rev:3;)

alert udp $HOME_NET 67 -> $HOME_NET 68 (msg:"OS-OTHER Malicious DHCP server bash environment variable injection attempt"; flow:stateless; content:"() {"; fast_pattern:only; content:"|02 01 06 00|"; depth:4; metadata:policy balanced-ips drop, policy security-ips drop, ruleset community, service dhcp; reference:cve,2014-6271; reference:cve,2014-7169; classtype:attempted-admin; sid:31985; rev:3;)

The most efficient way to craft such HTTP requests with these criteria is to use a customizable web browser. For this demonstration, I used Mechanize (stateful programmatic web browsing in Python). The Mechanize module can be installed in several ways, maybe the simplest one is via PIP (pip install mechanize) or by downloading the package and then:

python setup.py install

The Attack

**Disclaimer: the script is tested within a controlled lab environment; use it in public at your own risk! **

Components used:

Attacker: Kali Linux 1.0.9

Python: 2.7.3

SNORT: Snort GPLv2 Community Rules; Update: Sep-30 2014 11:28

Vulnerable server: Apache 2.2.14; PHP Version 5.3.1

import mechanize
def main():
        UserAgent =[('User-agent','() {')]
        browser = mechanize.Browser()
        browser.set_handle_robots(False)
        browser.addheaders=UserAgent
        try:
            page = browser.open('http://192.168.1.100/cgi-bin/%3D%28%29+%7B')
        except Exception,e:
            pass
main()

The script is quite simple and self-explanatory. We set a custom malicious user-agent that contains () { and we asked our browser to navigate to a remote URL with encoded URL %3D%28%29+%7B.
The sent GET request will appear as follows:

And fair enough, SNORT raised three flags on this request as malicious.

Extra Mile / Distributed Attack

As we saw, with 5 lines of Python we raised 3 flags on SNORT, so you can imagine the noisy output logs on SNORT if we were to inject a simple infinite loop in the script.

Depending on the IPS configuration, the sensor may block the offender IP address after exceeding a certain number of malicious warnings. If so, the attacker may respond with IP spoofing, but wait a minute! Do you remember the tricky part of the SNORT signature? In order to raise a flag, the traffic has to be already established [TCP 3-way handshake should be completed]. This will defeat the IP spoofing attack simply because the attacker will fail to accomplish this part.

One possible solution is to use Botnet, a simpler one is to use a proxy chain. Directing Mechanize to use a proxy requires only two more lines!

 proxy = {'http':'X.X.X.X:PORT#'}
browser.set_proxies(proxy)

Where X.X.X.X is Proxy IP address.

Port# is the listening port (usually 8080).

And that’s it!

References

SNORT Blog

http://blog.snort.org/2014/09/snort-community-ruleset-out-of-band.html

NVD

http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2014-6271