Oct 20

Everyone's seen the following in almost every SQL injection tutorial on the planet:

UNION ALL SELECT 0,0,0,0,0 FROM users

This is the standard method of SQL injection: slide in a UNION statement to join two SELECT statements together and thus get the data you're looking for. This is fun, but it often produces ugly and hard to interpret results. Most SQL injection tutorials also discuss how to audit the perfect application - one that gives you the full SQL query every time you get an error, as well as helpful tips on fixing syntax errors. Unfortunately, in most cases, you don't get this luxury. In many cases you'll see something like this:

Warning:  mysql_fetch_array(): supplied argument is not a valid MySQL result resource in blah blah blah on line 9

To PHP developers, this error may make perfect sense, but to most people it does not. Basically, in PHP, when you want to get SQL output, you either use mysql_fetch_array() or mysql_fetch_assoc() (there are others but we won't worry about them for now). Here's a typical example of selecting some simple data from a table and printing it out:

$sqlcon = mysql_connect('localhost', 'user', 'pass');
mysql_select_db('test', $sqlcon);
$query = "SELECT firstname,lastname FROM users WHERE id = " . $_GET['id'];
$dat = mysql_query($query);
$dat = mysql_fetch_array($dat);
echo("Hello, " . $dat[1] . $dat[0] . "!");

This will essentially print the second SQL result returned by the query. mysql_fetch_assoc() works in a similar way, using associative arrays (keys with non-numeric keys) to handle data. This is obviously vulnerable to SQL injection using the standard UNION ALL SELECT statement. So why the error? Well basically, when you have an improper SQL statement, it still queries it, suppressing errors, and when it returns no results, the mysql_fetch_* statement will fail because it doesn't know how to handle the empty result.

Another thing some people have a hard time understanding is columns. UNION SELECT statements require that the number of columns in each SELECT statement is the same. This is where the 0,0,0,0,0,user,password or 1,2,3,user,4,5,6,password comes from. When you SELECT an integer from a table, it simply returns that number. Thus, you'll see the number 0 on your page a lot if you use the 0's, etc. I recommend using 1,2,3,4, etc. when discovering SQL injection because it allows you to determine where specific variables are referenced.

A cool trick a lot of people have picked up on that you may not have noticed is using the CONCAT statement to make input more readable.

UNION ALL SELECT 0,0,0,concat(user, 0x20, 0x3a, 0x20, password)

The above will produce something similar to this

administrator : 5f4dcc3b5aa765d61d8327deb882cf99

Another thing I see people doing: including WHERE clauses when they aren't necessary. Maybe this is a personal thing, but I would rather get ALL the user data than 1 user's data.

SELECT * FROM users WHERE id=1

This will usually give you the administrator's SQL information. But there's no reason to limit it; generally leaving out the WHERE clause will provide you with the data for EVERY user (however, sometimes this doesn't work due to various code differences).

Here's another important one: comments. Often, the original SQL statement isn't compatible with what you are trying to do and it fucks up the whole thing, giving you an error. To avoid this, you leave a trailing comment in order to blank out the rest of the query. There are several options, namely /* and –. Just add them to the end of your query so that this

SELECT name,interests,signature FROM users WHERE id=-99 UNION ALL SELECT email,0,password FROM users AND ip = '$_SERVER[REMOTE_ADDR]'

(which causes an error) turns into

SELECT name,interests,signature FROM users WHERE id=-99 UNION ALL SELECT email,0,password FROM users/* AND ip = '$_SERVER[REMOTE_ADDR]'

If you see the mysql_fetch_array or mysql_fetch_assoc errors, you won't get the nice clean SQL injection you would like to have. Instead, you'll have to figure out syntax errors on your own. SQL is very picky, so if you don't have your syntax just right, it will definitely be an irritating experience. Common syntax errors include, but aren't limited to:

  1. Incorrect number of columns - just keep adding ,0 to your SELECT statement until it stops giving you the error
  2. Incorrect table name - you have to guess the name of the table by yourself (hint: this list of names might help) It also helps to download the script when you are unsure of table names: they're almost always easy to find in the installation SQL files and such of the script
  3. Improper WHERE statements - if you use a WHERE statement, make sure types match up; ie: you need single quotes for strings and no quotes for numbers
  4. Parentheses - if the original query has parentheses, you first need to properly end the first query before beginning the second
  5. When using integers (ie: member ids, post ids, etc.), it's best to use a non-existent index like -99 or -1. This helps make sure your output is delivered to you. Don't worry about why, it just does. Trust me.
  6. Table prefixes - many CMS and forum softwares use prefixes for table names, so make sure you take advantage of errors and use all the information given to you. If you can't get an error including table prefixes, try to find a prefix column in the configuration table of the software or download the software and find the default (which, in my experience is the most common)

So, for everyone at home, hopefully this list has helped you hone your SQL-injection-finding skills a little bit. This isn't meant to be an extensive reference or a newbie's guide, but more a list of tips from someone who's had to learn the hard way. If you keep these things in mind, read all error messages, learn SQL syntax, and keep a watchful eye out, you'll be an SQL injection master in no time.

  • Digg
  • StumbleUpon
  • del.icio.us
  • Reddit

Leave a Comment

Please note: Comment moderation is enabled and may delay your comment. There is no need to resubmit your comment.