Before you begin attempting to hack via SQL Injection, you first must understand what is happening and the commands that are being run. When you see a website that looks similar to this:
There is actually an SQL query being run to load the page associated with the number 18. That query might look something like this:
SELECT * FROM Pages WHERE pageid = ‘18’
In this query, the page to be displayed is being selected from the table ‘Pages’ and from the column ‘pageid’ where the pageid is equal to ‘18’
This is why you are able to add extra commands to the query or throw off the syntax because part of the query being run is publicly displayed. (The number 18)
This is where “The Magic Quote” comes in, if you’re looking at that same page
and you add a single quote (‘), it will throw off the syntax of the query.
www.example.com/index.php?pageid=18’ results in the query of
SELECT * FROM Pages WHERE pageid = ‘18’’
(Notice the extra quote)
This results in either an error, something on the page not being displayed, or a complete blank page.
Some commands I will be using in this tutorial are:
UNION ALL – Combine multiple columns
SELECT – Selecting the information you want
ORDER BY – Orders columns by alphabetical or numerical order
LIMIT – The number of the selected field to be displayed
FROM – Selecting where you want to pull the information you want from.
CONCAT – Short for concatenate which means to combine two strings into a one.
GROUP_CONCAT – Grouping all values from a concatenated string
Finding a vulnerable site
Let’s get started. I will be using the website: www.bandimere.com
Using this URL: http://www.bandimere.com/events/even…hp?eventID=358
let’s see what happens when I add an extra quote to 358
As you can see, none of the details of the event loaded. Now let’s make the query a true statement. By adding AND 1=1– to the end of the url, it will make the query look like this:
SELECT * FROM [Table_Name] WHERE evendID = ‘18’ AND 1=1--
Since 1 DOES equal 1, this statement is true and the page will load successfully.
But what if we change it to AND 1=2–?
http://www.bandimere.com/events/even…hp?eventID=358 AND 1=2–[/url]
This time, the page does not load correctly because 1 does NOT equal 2. Understand?
You also may be wondering why I am adding a double dash (–) at the end of each url. The double dash is used to comment out code in MySQL. In HTML, to write a comment without it being displayed, you use <!— In php, // or #. Each language has the ability to add comments in the code that aren’t displayed publicly. We add — at the end of the url to comment out any other commands that the query may be running.
Now that we know the target is vulnerable, we must find the table names in the database. There are a certain amount of columns from the database displayed on the current page, and we must find how many there are. We do this by appending the command “ORDER BY” to the end of the URL. If the page loads correctly, then there are atleast that many columns. If the page loads with an error or something missing, then we know there are not that many columns. http://www.bandimere.com/events/even…8 ORDER BY 3–
Finding the number of columns displayed on the current page is a trial and error process. Keep guessing numbers until you reach the highest number you can without the page loading incorrectly.
In the picture below you can see that I used the command “Order by 3” and the page loads, thus there is atleast 3 columns. In the second picture you can see that I ordered the columns by 10, but the page didn’t load – Woops, too high of a number.
After a short time, I have found out that there are 5 columns.
Extracting data from those tables and columns
Now that we know the number of columns, we want to combine them all and have them displayed on the page. We do this using the UNION ALL SELECT command, where UNION means to join, ALL means all of the columns we found, and SELECT-ing the columns 1 through 5.
If you did this step correctly, the page should load normally. Now what we want to do is call an eventID that does not exist. Since there will be no information associated with an eventID that doesn’t exist, the page will load but the actual column numbers will be displayed instead of the information that would be contained in them when calling a legitimate eventID.
Some examples of invalid or nonexistent tables are: NULL, -1, 99999999999999
Let’s use -1 and see what happens:
Looking at the page now, you should see some column numbers. In this case, you’ll see the numbers 2,3 and 4. These are where we are going to extract data from.
There are several commands you can use to try and gain more information about the website you are hacking. By replacing one of the numbers in the url that is displayed on the page with the command user() , you can see what user is currently being used on the website. You can also find the version of MySQL you are running by replacing 2,3 or 4 with the command version() (Or @@VERSION) and the name of the current database by using the command database()
In MySQL 5.1+, there is a default database which holds information about existing tables and columns, it is named information_schema.
To get the information we want, we will be using information_schema.tables and information_schema.columns.
At this time pick a number that is being displayed on the page, I will be using the number 3. In the url, replace that number with “table_name” (without quotes) and at the end of the URL FROM information_schema.tables .
My URL looks like this:
When you do this, you are running a query that tells the SQL DB to return the names of the tables in information_schema.tables. As you can see, there is a table named “CHARACTER_SETS”, this doesn’t really interest us though, because we’re looking for tables that contain users and passwords, which are usually named something along the lines of user, users, members, admin, etc.
Unfortunately, this command only displays one table so we are going to use the group_concat() command. (This command means to pull the data from multiple places and display all of the input in one place.) So go back to where you wrote table_name at in the url, and this time replace it with group_concat(table_name) .
Your URL should look like this:
Now you should see LOTS of table names being displayed. If there is not enough room on the page for all of the tables to be displayed, you will have to use the LIMIT command, but we will get to that later.
After browsing though the table names, two of them stick out to me – Administrators and Member.
At this time I would write down or keep some form of reminder, noting that there are two tables named Administrators and Member.
Time to find the column names. We will be using the same command, group_concat() but instead of concatenating table names, we are going to get column names. And instead of pulling the names from information_schema.tables, it will be from information_schema.columns.
Your URL should look like this now:
As you can see there are a TON of columns being displayed, in fact there are so many that the page cuts them off. As a general rule (95% of the time) table names and column names that are in all capital letters are default tables/columns and are of no use to us. When you start finding names that are in lowercase, you know you’ve found the ones you’re looking for.
This is where the tedious part comes in. We must now use the LIMIT command, and guess the number of the column name that will give us sensitive information. (Like username, password, etc.)
At the end of the url, add LIMIT 0,1 and change group_concat(column_name) to just concat(column_name) because group_concat() does not work with the LIMIT command.
http://www.bandimere.com/events/even…ns LIMIT 0,1–
Now it lists the first column available, adjust 0,1 to 27,1 or 154,1 or even 300,1 until you find the column names that are useful to you. Keep in mind; the columns go in the same order as the table names did. So since the table “Administrators” was the second table after the default tables, it will be relatively close in number to the default column names.
The table “Member” was further down the list, so the correlating number will be higher.
The last default column is number 346:
http://www.bandimere.com/events/even… LIMIT 346,1–
Which means the columns in the Administrators table are coming up.
348,1 – User
349,1 – fd_Password
Aha! We have found the column names in the Administrators table. Now what we must do is run a query that pulls out the information from those columns in that table.
In the URL, replace concat(column_name) with (User,fd_Password) and at the end of the URL, instead of pulling the information out of information_schema.columns, we are going to be pulling it from the table Administrators.
So our URL should look like this:
Or to clean things up a bit, you can use the hex number 0x3a (which is a colon : ) to separate the username and password.
And look at that! Usernames and passwords from the Administrator table!
Now that you have a user and password, find an admin login on the web page and have fun!
Here is a small section on the “Member” table:
The LIMIT numbers for the columns in Member were 498,1 and 499,1, and the column names were emailAddr and password.
To get all of the users, use the same command as above, but use those column names instead of the ones for the table Administrators, and make sure you are pulling the information from the table Member!
http://www.bandimere.com/events/even… FROM Member–
Since there are so many users in this table that they get cut off, you can either use the LIMIT command to get each one, or I like to add the hex character 0x0a, which means new line. It still doesn’t display ALL of the users, but it will display more:
http://www.bandimere.com/events/even… FROM Member–
And that’s it. I hope you learned something from this tutorial and enjoyed reading it! If you have any questions feel free to ask.