Most of my work at Immunity is focused on the large-scale detection of vulnerabilities in web applications. Naturally, a good portion of my effort has gone towards detecting SQL injections (SQLi). Not only are they among the most common vulnerabilities to be found, but they are often the most critical, as they can get an attacker's foot in the door.
Of course, in order for an SQLi to be useful, there has to be some measurable response from the database that is being injected into. Timing attacks have proven to be the most reliable method for detecting an SQLi, as they do not rely onany output from the database making it through to the interface layer of the target web page or service. Commonly, this type of vulnerability is known as a "blind" SQL injection.The basic idea behind an SQLi timing attack is to use SLEEP commands to force the database on the back end to delay its response. You then ask the database a series of true/false questions. If a response comes back at least "sleep_time" seconds later, you know that the answer is true.
An SQLi detection (top) and a test run against a page with no SQLi (bottom)
This simple technique almost guarantees the validity of an SQLi vulnerability, however it comes with several challenges. Real world attacks often involve VPNs, proxies, and other technologies that can add considerable uncertainty to response times. A good timing attack algorithm has to be able to account for these variables and at the same time strive to keep sleep times as low as possible. Which leads to the second major challenge of timing attacks: efficiency.
Even with an attack against a local web server, the algorithm I am working with is only capable of pulling data from a database at ~2kbit/s. That's not nearly fast enough when the goal is to download the target's entire database. So how can we speed up the process? That is the main question I am asking right now in my research, and there are a number of roads to go down in searching for the answer. To sample a few potential solutions:
- Unblinding: The database exists, after all, to provide data to the interface layer. Can we move the data we want somewhere where we can actually see it?
- Get curious: Why ask just one question?
- Distribute: Nobody likes a DoS, so architectures are more commonly accounting for traffic spikes. How many questions can the database answer at the same time?
- Prediction: If we have some of the data, can we predict the rest?
In my talk at Infiltrate, I'll be demonstrating some of these ideas. Know of another technique? Let me know and I may shamelessly implement it!