Version User Scope of changes
Jun 17 2008, 6:14 AM EDT (current) sanjivnidamboor 2104 words added
Jun 17 2008, 6:11 AM EDT sanjivnidamboor

Changes

Key:  Additions   Deletions
Abstract
SQL Injection
is the process of corrupting the information sent between a page and a
database. This process can result in arbitrary SQL code execution, and
possibly even the compromising of a server as was done in the famous
apache.org hack which resulted from the SQL server running on root
permissions.

What on earth is SQL?
SQL stands for
Sructured Query Language. What does this mean? A query is used to
communicate with a database. Whether it be to insert new information,
extract necessary information, update information, or delete
information, a query is necessary to accomplish the transaction.
Therefor a structured query languages provides a standard for commands
to interact with a database.

Where are queries used?
Queries
are used any time a page has to check information against something
stored in a database. For example, anytime you log into your account
here on the forums, a query is formed which checks the username and
password you entered, to see if they match any pairs in the database.
Almost any time you interact with a form on the internet, at least one
query is usually involved.

What do queries look like?

Queries
are generally comprised of 4 common types. These types are SELECT,
UPDATE, INSERT and DELETE statements. As there names imply, they handle
the different functions associated with the database, for example, a
login script would look something like this:

CODESELECT * FROM `users` WHERE username = 'THE USERNAME YOU ENTERED' && `password` = 'THE PASSWORD YOU ENTERED';

In
this case, there is a table in our database named users which as we
would expect, holds user information. what this does is return any row
where the username field in the table matches your input to username,
and the password matches your password input. If a row is returned,
there was success, if not, the login information was incorrect.

How is this exploited?
If
you've read my previous article, it's probably becoming clear to you
that web hacking often focuses around the fact that programmers do not
quarantine and filter the data which they should. As you've seen in the
previous SQL statement, the data you enter is directly inserted to the
query. This, once again, is how we exploit a vulnerability and inject
our own SQL code. So enough jibber-jabbering, and let's take a look at
an injection.

Simple SQL Injection Example
Let's stick
with our user login system example here. As with most login systems,
our will ask for a username and password, then check it against a
database.
Let's watch what happens when we enter unexpected data that we shouldn't be entering.
For the username we enter:

Code:
' OR '1'='1
and for the password we enter:

Code:
' OR '1'='1
Now
at this moment, you might think this is extremely strange, and I would
agree with you, but lets watch what happens when it gets put into the
form of a query:

CODESELECT * FROM `users` WHERE username = '' OR '1'='1' && `password` = '' OR '1'='1'

Ahh,
very interesting. For those of you who have taken some simple algebra
courses, they usually cover AND and OR logic. What happens here is it
checks for a field where the username is equal to 'nothing' (what we
put in was '') OR where '1'='1' since one ALWAYS equals one, this check
passes. Same goes for password, we check for a location where password
= '' (nothing) which it wont, OR '1' = '1' which will make the second
check pass.

Now you might be asking, well, if it's checking
usernames against nothing and passwords against nothing, which account
will you be logged in to once the check passes?

Generally speaking, the script will return the first row from the database (usually an administrator account as an added bonus)

How to access a particular account
Well,
that's all well and good, but how to access a particular account you
have an interest in this way? Simply change the username field to the
desired username and leave the password as the injection code. That
way, the script will first check that there is a username in the
database that matches yours (hopefully if you're trying to get into a
particular account it actually exists :tongue and secondly, will
check if that password equals '' (which it wont) OR if 1=1 which it
will, and you should be logged in as that particular user.

Error Generating
Error
generating is an important part of SQL injections. All parameters of a
script must be tested to see if you may be able to cause a syntax
error. Some good techniques for generating errors are adding a single '
to mismatch the quote count, adding things like a legitimate value with
quotes added, such as value' or 'value adding OR statements with
nothing after them such as value' OR or value OR.

Other good ways are to add a semi colon (which is the terminating character in an SQL statement)

Also,
another very good technique in generating errors in pages which use the
INSERT statement. by adding commas, you can throw off the column count
for example if you were to input: value,value,value you could generate
a column count mismatch.

Any form of SQL syntax error is a good sign which may lead to a successful injection.

Methods Of Injection
Well,
at this point you may be thinking, "Well, this is all well and good,
but how do i actually use this stuff?" Don't fret, information is on
the way.

An extremely common method of injection is the end of a
url which receives data via the GET protocol and uses it to query the
database for information.

If you have read my previous article
on XSS, I've mentioned the GET protocol previously and you can skip
this. For those who haven't or who forgot, the GET protocol is used to
supply data to a PHP page for processing. Whenever you see a question
mark (?) on the end of a url like this:

Code:
http://example.com/userprofile.php?id=1
This
means that an id with the value of 1 is being supplied to the page.
This is used very often for user profile pages as i have used in this
example. What then happens is that id will be used in a query such as
this:

CODESELECT * FROM `user_information` WHERE `id` = 'THE ID SUPPLIED TO THE PAGE'

As
discussed earlier, if this information is not filtered, we will have a
prime target for injection. Attempt a few of the injection testing
techniques discussed earlier, if you generate an error this script is
vulnerable to SQL injections.

Another method of injection are
the ever-vulnerable form fields. Test these techniques on any and all
form fields on a page, keep trying and hopefully you will stumble
across a nice error.

NOTE: Many times, administrators will
forget to check values that come from things like select boxes, or
check boxes as they think they will only be from the expected values.
However, these values are easily changed. They can be changed through
several means, you can google for some techniques or request a tutorial
in my thread.

Table Enumeration
Table name and column
enumeration is also a very important part of SQL injections. Generating
errors is fine, but if you can't figure out column and table names it
will likely do you no good.

The method of extracting table names
and column names depends upon which sql server is being run. The most
common sql server i have come across is running MySQL, so I will focus
on that, but with a little research the information can be adapted to
other types.

The interesting tables you're looking for in this
case are stored in the system tables INFORMATION_SCHEMA.TABLES and
INFORMATION_SCHEMA.COLUMNS respectively.

What we can do is what is called a UNION ALL which will merge the results from one query with those from another.

One
of the pitfalls of UNION ALL is the fact that it must return the same
number of columns as the first query, and data of the same type. So for
example imagine this query.

CODESELECT username, password, email, socialsecurity, phonenumber FROM `users` WHERE `id` = '234'

In
order to inject a UNION here you would need to be selecting 5 values as
well, most likely 3 strings (words) and 2 integer (number) values.

An
easy way to get around the data type necessity is to select NULL (which
means nothing) and select what you need in the correct place.

Unfortunately,
the way to determine the quantity to select and which field will be
selecting a string (words) which you need since table and column names
are strings. A union query will usually start out with one field added
like this as your input:

CODEhttp://example.com/userprofile.php?id=234' UNION SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE '1' = '1

Which will result in the query from before being changed to:

CODESELECT
username, password, email, socialsecurity, phonenumber FROM `users`
WHERE `id` = '234' UNION SELECT TABLE_NAME FROM
INFORMATION_SCHEMA.TABLES WHERE '1' = '1'

As we can tell
from this, this query will fail because the UNION selects one field
while the original query selects five. We can use trial and error to
determine how many fields are being selected. (Since as hackers, we
cannot generally see the actual SQL code being executed)

eventually through trial and error (or through an educated guess: read below) we will end up with an injection like this:

CODEhttp://example.com/userprofile.php?id=234'
UNION SELECT TABLE_NAME, NULL, NULL, NULL, NULL FROM
INFORMATION_SCHEMA.TABLES WHERE '1' = '1

Which will now
select the same amount of fields as the original query. However, this
only selects the FIRST table in the information schema, which may not
be the one we're looking for.

SIDE NOTE: Educated
guessing is a good way to determine how many fields are being selected.
For example, if there is a system which allows you to input a username
and it retrieves his id, email, and phone number and displays it to
you, it would be a good bet to start with 3 (id, email, phone number as
3 separate fields means you should attempt to select 3 as a good
starting place as well) This wont always work because sometimes
webmasters do strange things and select values they don't use (or use
but do not display)

Let's say the first table name you've found
is called example1 you can apppend to the WHERE query using 'not in'
command which means it cannot be from anything in the list supplied to
the clause. To make sure it doesnt select example1 again this time, we
add it like this:

CODEhttp://example.com/userprofile.php?id=234'
UNION SELECT TABLE_NAME, NULL, NULL, NULL, NULL FROM
INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME NOT IN ('example1') AND '1'
= '1

Let's say this time it selects example2 and we still don't want that, just add it to your list.

CODEhttp://example.com/userprofile.php?id=234'
UNION SELECT TABLE_NAME, NULL, NULL, NULL, NULL FROM
INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME NOT IN ('example1',
'example2') AND '1' = '1

Ahh great, let's say for sake of
argument it returns something like admin_users table this time. Great!
we now have a table name we can definitely use.

The way the
columns work is that they are linked by table name, so once we have
that, we can work the same way to find out all column names like so:

CODEhttp://example.com/userprofile.php?id=234'
UNION SELECT COLUMN_NAME, NULL, NULL, NULL, NULL FROM
INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'the_table_name

From
here on out we can do the same working with NOT IN as we did before to
find all the table names we want, after that it's a simple union select
from the table and the information we want is ours.

CODEhttp://example.com/userprofile.php?id=234'
UNION SELECT column1, column2, column3, column4, column5 FROM
table_name_we_found WHERE '1' = '1

NOTE: This example
assumes you want to select 5 columns from one table and that they are
of matching types to the original SELECT. The five columns are just
examples of the column names you might have come across

Blind SQL Injection
Blind
SQL Injection refers to SQL injection without the ability to read error
messages from the database. To sum it up, a user must work off whether
the script returns an admin-defined error message or if it runs
successfully. If it runs successfully, yet you've injected some code,
the script is succeptible to SQL injection even though you can't see
it's error messages. Further examination of this topic is beyond the
scope of this introductory article, but with requests I will gladly
write one in the future.

Conclusion
Remember to comment if any doubt, suggestion etc! Thanks ;)

-Sanjiv Nidamboor (Site Admin)
Allcomputertricks.com