SQL Injection Full Guide
Seeing as everyone posts about wanting to know about SQL injection, but lacks basic knowledge of the most simplest SQL queries, I have written the following article.
However I'd like some of the people who know their SQL, to add to it, and hopefully we can get a really good indepth complete guide to SQL injection and how to prevent it. It will then be added as an article and also added to a new "Tutorial" section comming to HBH in a couple of months.
I used these notes to explain SQL Injection at the HBH Con, and after the demonstrations and talks, everyone seemed to understand it… but its alot easier to understand if you have someone sitting next to you explaining it, along with visual aids and demonstrations.
So please read my article below and post comments / additions / edits etc.
SQL Injection
What it is: SQL is a language used to communicate between applications and databases. Most commonly used on web servers and website is: MySQL. SQL Injection, by definitions means injecting your own SQL queries to pull information from the database that is not currently accessible. Primarily it affects websites and only content, however many applications also connect to databases online and offline. Such as Amazons “Seller Desktop” it gives to re-seller merchants.. This program could be edited with a HEX editor or debugger to possible allow for SQL injections into amazons database. So you can see that not just websites are affected by SQL injection.
**Why it works: ** SQL works because there are current SQL queries around a website, and by injecting your own, you are already using the existing connection between the website and the database, thus not needing to provide any credentials. Basically your “piggy backing” your own SQL query onto an existing query that's already hard coded into the website.
The reason SQL Injection works, is because variables are not properly stripped of dangerous characters. This allows someone to inject whatever their wish. The same code problem can also cause XSS problems, due to they're being no protection over what is input.
We'll use a unsecure version of HBH has an example. The login function looks like this:
Username = Mr_Cheese Password = PassCheese
The code behind this section will grab the username “Mr_Cheese” and look up in the database and return all information from the user account “Mr_Cheese” where the password also equals “PassCheese”.
The query would look like this:
SELECT * FROM hbh_users WHERE user_name = 'Mr_Cheese' AND password = 'PassCheese'
The code for the query would look like this (in PHP):
Mysql_query( “SELECT * FROM hbh_users WHERE user_name = '{$_POST['username']}' AND password = '{$_POST['password']}'”);
So what if we were to manipulate some variables and change the query?
If we wanted to login as Mr_Cheese and didn't know the password, we would want the query to read like this:
SELECT * FROM hbh_users WHERE username = Mr_Cheese
However, the query thats already hardcoded into the website has AND password = '' at the end of it. So we need to manipulate the query.
We would then want the query to look like this:
SELECT * FROM hbh_users WHERE username = 'Mr_Cheese' AND password = 'test' OR username = 'Mr_Cheese'
This query will look in teh database for:
Username = Mr_Cheese with password “test”
Username = Mr_Cheese (note no password is checked)
Because #1 wont return anything becuse the user / pass do not match, the query will only 1 row.. which is where the username = Mr_Cheese. Which is what we want.
How to exploit it:
So now we need to manipulate our query to get the query in the website to look like the query above.
We would post this information:
Username = Mr_Cheese Password = test' OR username = 'Mr_Cheese' /*
The /* at the end comments out everything after it. Which will help to get rid of any extra bit of query that might come after the password check.
The query in the website will now run like this:
Mysql_query( “SELECT * FROM hbh_users WHERE user_name = 'Mr_Cheese' AND password = test' OR username = 'Mr_Cheese' /'“);*
So now the query will return all information from this account.
You can also SQL injection from other points and across tables. This method is slightly more advanced than the above, but can be mastered with an understanding of the more simpler SQL Injections (see above).
i.e you have a news page with a SQL query, but you want to grab info from the users table.
News.php?id=12 <- pulls the news with the news id of 12
News.php?id=-1 UNION SELECT null, null, null, username, password, null, null FROM hbh_users WHERE username = 'Mr_Cheese'
The above (using the UNION SELECT) will look for 2 things
News post of id -1
Jump to the users table and find username and password for Mr_Cheese
Because -1 is an invalid news post number, it will only return the second row. You also have to make sure that the number of “null” in the query match the number of fields in the table, otherwise the query will get confused because field numbers do not match up. (A field in a database is a column heading)
If you fancy variety you can also replace null with 1,2,3,4.. does exactly the same thing.
How to fix it:
Luckily fixing this issue is fairly easy, in PHP there's functions that can be used to clean the input.
Such as:
Addslashes() this addles \ to any character. The query then reads the \' and counts the ' as an input, instead of part of the query. However, this can be bypassed by using upside down question marks, which the query will count as single quotes and it won't have slashes added to it.
Mysql_escape_string() this is the best function to use, as its part of the mysql function collection, so this will be the best at detecting any query like characters and ensuring that they do not affect the query.
Tips:
To really get to grips with SQL Injections, it's twice as hard to learn the injections before learning SQL. Once you have an understanding of SQL queries, its far simpler to structure your own SQL Injections and improve your own code to stop attacks. Same princible when learning buffer overflow and format string. One learns the code before they learn to exploit it.
really good on the basics. i usually find that lazy programmers which there seem to be an abundance of double up on quotes so you have to use \' at the start and /* at the end. First thing i usually try for table names is the ' having 1=1– and if that works the group by. For number or colums i usually go for the ' Order by. If i get the number of rows i then use the ' union select all 1,2,3 if there were three colums. That usually gets me more information includeing the database name. Once i have all that crap i figure out what kind of var is used in each of the said colums using the ' union select sum(colum) from table. Finally once I have ALL that info i normally go the route of ' insert into tablename values(value1,value2,value3)– Just one path to take and usually found it the easiest when you have the options available. One path to take of many.
wow this is brilliant, i've been looking for the last couple of days for stuff about sql injections, and all i seemed to find was security websites, and they didnt seem to tell me much, but actuall they did, they told me exactly what you told me just in a lot harder way of explaining, this has cleared the sql injections thing up for me thanks mr cheese. :p
im gonna look at XSS now :D
spyware wrote:
- You didn't explain the UNION statement
- the null part was a bit vague
well, the whole point of this thread is to get everyones input, so we can build a really easy to understand, informative article on SQL injection. So your input is welcome.
bonanza - I'm glad my article helped you. :)
I love it. Although my knowledge of SQL injection is extremely limited I am working on it now. Very good article, just a few pieces of input:
Mr_Cheese wrote: Username = Mr_Cheese Password = test' OR username = 'Mr_Cheese' /*
The /* at the end comments out everything after it. Which will help to get rid of any extra bit of query that might come after the password check.
The query in the website will now run like this:
Mysql_query( “SELECT * FROM hbh_users WHERE user_name = 'Mr_Cheese' AND password = test' OR username = 'Mr_Cheese' /'“);*
So now the query will return all information from this account.
while on the topic of comments, wouldn't it be much simpler, just to go
Username: Mr_Cheese' /* Password:
?
Mr_Cheese wrote: This query will look in teh database for:
Username = Mr_Cheese with password “test”
Username = Mr_Cheese (note no password is checked)
Because #1 wont return anything becuse the user / pass do not match, the query will only 1 row.. which is where the username = Mr_Cheese. Which is what we want.
maybe clean up that wording a little bit, also typo "teh"
nice article tho :happy:
bonanza wrote: wow this is brilliant, i've been looking for the last couple of days for stuff about sql injections, and all i seemed to find was security websites, and they didnt seem to tell me much, but actuall they did, they told me exactly what you told me just in a lot harder way of explaining, this has cleared the sql injections thing up for me thanks mr cheese. :p
im gonna look at XSS now :D
Not sure id go from SQL injection to XSS. Cant say XSS is usefull all that often. But thats just from my experience. Usually just if you can put it in something like a guest book, Or in somecases if you get into the admin rights on a site you can post things there which makes XSS helpful. Like i said just an oppion.
bonanza wrote: wow this is brilliant, i've been looking for the last couple of days for stuff about sql injections, and all i seemed to find was security websites, and they didnt seem to tell me much, but actuall they did, they told me exactly what you told me just in a lot harder way of explaining, this has cleared the sql injections thing up for me thanks mr cheese. :p
im gonna look at XSS now :D
Please don't think that by reading this single article that you are finished with the entire realm of database exploitation.
@Cheese: Perhaps we should add a section about different brands of databases and the differences between their error messages and available functions? We could add a section on fingerprinting, so people would know what they're dealing with rather then pouring random queries.
lesserlightsofheaven wrote:
Please don't think that by reading this single article that you are finished with the entire realm of database exploitation.
@Cheese: Perhaps we should add a section about different brands of databases and the differences between their error messages and available functions? We could add a section on fingerprinting, so people would know what they're dealing with rather then pouring random queries.
Seems like good idea the whole Oracle mysql thing threw me off a few times