28.10.2014 Views

SQL Injection Attacks and Defense - 2009

SQL Injection Attacks and Defense - 2009

SQL Injection Attacks and Defense - 2009

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

244 Chapter 5 • Blind <strong>SQL</strong> <strong>Injection</strong> Exploitation<br />

throughout this chapter: ASCII(SUBSTRING(CURRENT_USER( ),i,1))&2 j =2 j , which<br />

implements the bit-by-bit inference method. If the condition is true (i.e., bit j is a 1-bit), the<br />

query SELECT table_name FROM information_schema.columns WHERE table_name =<br />

(SELECT table_name FROM information_schema.columns) is run, <strong>and</strong> this query has a subquery<br />

that returns multiple rows in a comparison. Because this is forbidden, execution halts with<br />

an error. On the other h<strong>and</strong>, if bit j was a 0-bit, the IF( ) statement returns the value 1.<br />

The true branch on the IF( ) statement uses the built-in information_schema.columns table,<br />

as this exists in all My<strong>SQL</strong> Version 5.0 <strong>and</strong> later databases.<br />

I should point out that when using an application written in PHP with My<strong>SQL</strong> as<br />

the data store, errors arising from the execution of database queries do not generate<br />

exceptions that cause generic error pages. The calling page must check whether mysql_<br />

query( ) returns FALSE, or whether mysql_error( ) returns a non-empty string; if either<br />

condition exists, the page prints an application-specific error message. The result of this<br />

is that My<strong>SQL</strong> errors do not produce HTTP 500 response codes, but rather the regular<br />

200 response code.<br />

<strong>SQL</strong> Server Response Techniques<br />

Consider the following T-<strong>SQL</strong> that can infer one bit of information by asking whether a<br />

vulnerable query returned rows with the statement:<br />

SELECT COUNT(*) FROM reviews WHERE review_author='MadBob' <strong>and</strong><br />

SYSTEM_USER='sa'<br />

If the query returned results the login in use was sa, <strong>and</strong> if no rows came back the login<br />

was something else. You can integrate this quite easily with the binary search <strong>and</strong> bit-by-bit<br />

inference methods to extract the actual login:<br />

SELECT COUNT(*) FROM reviews WHERE review_author='MadBob' AND<br />

ASCII(SUBSTRING(SYSTEM_USER,i,1))>k--<br />

<strong>and</strong><br />

SELECT COUNT(*) FROM reviews WHERE review_author='MadBob' AND<br />

ASCII(SUBSTRING(SYSTEM_USER,i,1))&2 j =2 j<br />

The split <strong>and</strong> balance trick works nicely with response-based inference on <strong>SQL</strong><br />

Server. Combined with a conditional subquery that uses CASE, you can include a string<br />

as part of the search depending on the state of a bit or value. Consider first a binary<br />

search example:<br />

SELECT COUNT(*) FROM reviews WHERE review_author='Mad'+(SELECT CASE WHEN<br />

ASCII(SUBSTRING(SYSTEM_USER,i,1))>k THEN 'Bob' END) + ''

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!