ritter.vg
tech > security > adventures in (in)security > Finding SQL Injection in a Whitebox Environment
7 June 2010 23:11:15 EST

White box testing is when you test a system using the internal design of the system. It's the opposite of black box testing, where you know nothing about how the system is designed, you can't alter it, and you can't garner any additional information (such as reading error logs).

Let's say, hypothetically, you're put in charge of securing a system designed like your average, large to huge, web environment. It's got the HTML, the Javascript, your Web and App servers of varying complexity connecting to one or more databases.

Now let's say, hypothetically, that the Javascript consists of 10,000 lines of minified code doing validation, and the Web/App tier consists of another 100,000 lines of code also potentially doing some validation before constructing incredibly complex dynamic SQL queries. How can we speed things up? Well, we want to bypass the javascript validation completely since we can. And we want to see if our tampered data makes it to the database. Here's where the clever part comes in.

There's two parts to this. Of course bypassing the javascript is simple and there's a dozen firefox plugins for tampering with data - but we're going to go with a slightly more complicated method - we'll use a plugin for Fiddler. We'll rewrite data after it leaves our browser (or computer if you run the proxy on another machine). Here's some simple code to rewrite a specific integer with a slightly modified string.

public class Tamper : IAutoTamper
{
	public void AutoTamperRequestBefore(Session oSession)
	{
		var replaced = false;
		if (oSession.HostnameIs("http://example.com"))
		{
			var headers = oSession.oRequest.headers.ToString(true, true, false);
			if (headers.IndexOf("112350") > -1)
			{
				headers = headers.Replace("112350", "112a350");
				if (!oSession.oRequest.headers.AssignFromString(headers))
					;//Asignment Failed.  Hm
				replaced = true;
			}
			if (oSession.HTTPMethodIs("POST"))
			{
				var body = Encoding.UTF8.GetString(oSession.requestBodyBytes);
				if (body.IndexOf("112350") > -1)
				{
					body = body.Replace("112350", "112a350");
					var bodyBytes = Encoding.UTF8.GetBytes(body);
					oSession.requestBodyBytes = bodyBytes;
					replaced = true;
				}
			}
		}
		if (!replaced)
			oSession["ui-hide"] = "true";
		else
			oSession["ui-color"] = "red";
	}
	public void AutoTamperRequestAfter(Session oSession) { }
	public void AutoTamperResponseBefore(Session oSession) { }
	public void AutoTamperResponseAfter(Session oSession) { }
	public void OnBeforeReturningError(Session oSession) { }
	public void OnLoad() { }
	public void OnBeforeUnload() { }
}

Now Fiddler will only show you the requests which had your sentinel replaced with the new sentinel. So we've successfully fuzzed things by replacing a specific sentinel the new one. So far, this is a step backwards from all the normal fuzzers out there. The step forward is that since this is white box testing - we watch the database queries.

By placing a trace on the server (here I'm using tracing in SQL Server), searching for our sentinel, we can see if any of the requests made from the client make it to the database after being fuzzed. They will probably error in the database, or somewhere after the query, but that's fine - as soon as it made it to the database we got exactly what we wanted.

Now you might argue this is a lot of effort for not-much gain. But you're missing the point. Completely untrained people can attempt SQL Injection simply by testing the site normally, using specific predefined values (for example 112350) - and by watching the traces, you can see if anything came through.

I had other ideas. I have it on good authority you can close and restart the command-line trace in 30 second intervals with <1 second of restart time. As the individual trace files are written out by the restart, dump them to a database and have a page view the table via AJAX refreshes. Now you (or your QA team) can watch the results in near-realtime as you browse around your site causing errors. You'll be able to coordinate your actions with specific injections and QA will able to enter excellent bugs for developers: "I do X, Y, enable the proxy, and then Z; and it produces an injection.".

And, since you're restarting the traces every 30 seconds, you can make the trace values variable. I envisioned a Firefox plugin, where advanced users can specify what they want to replace. They set it, it sends an AJAX call to the proxy server which adds the values into the trace filters. The trace restarts in 30 seconds and sends back the "all-set" to the client. The client then does the actions normally, but the plugin attachs X-Injection-Rewrite headers specifying that Fiddler should replace certain values and with what.

This whole system bypasses the need for a tester to ever look at the javascript or the application code and focus on the important part - if a tampered integer makes it into the database as a string. You can do it for custom strings as well: ASC becoming 'ASChello', or specifying column names for sorting. When you're lucky enough to have a QA Team, you should take advantage of them. QA doesn't even need to know what SQL Injection is, they just need to be told to turn on the proxy, and test every company search box with a specific predetermined company. This isn't the best solution for every situation, but it is a relatively obscure one you can use to leverage an existing QA team.

Comments
Add a comment...
required
required, hidden, gravatared

required, markdown enabled (help)
you type:you see:
*italics*italics
**bold**bold
[stolen from reddit!](http://reddit.com)stolen from reddit!
* item 1
* item 2
* item 3
  • item 1
  • item 2
  • item 3
> quoted text
quoted text
Lines starting with four spaces
are treated like code:

    if 1 * 2 < 3:
        print "hello, world!"
Lines starting with four spaces
are treated like code:
if 1 * 2 < 3:
    print "hello, world!"