Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Westi on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

PHP Query String Security Filter

Status
Not open for further replies.

ggggus

Programmer
Jul 5, 2003
114
I created my own filter to secure my queries from input form hacking, but I think I was over zealous.

Does anyone know the right balance? I want to make the query string safe, but I want to filter as little as possible.

I've got magic quotes off on the server, and I've been filtering the apostrophe and writing it to the database as the html equivalent of ' Is that taking it too far?

***************************************
J. Jacobs
 
I forgot to mention I'm using MySQL as of right now, but might make a move to postresql in the future, so I'd like a filter that I don't have to re-write later.

***************************************
J. Jacobs
 
i tend now to use an abstraction class (db.php) and let it take the strain of doing all the necessary escaping. I turn off all magic quotes in site, do my own validation on submitted form data (as irrespective of the db you still want clean data) and then rely on the db.php class to do the rest. this will make your migration to postgres really easy too.
 
Not necessarily too far, but mysql_real_escape_string() will probably do what you want as far as preventing injection. Field validation is still best, since filtering won't verify that the field contents are correct.
 
of course filtering is always important...although I'm not filtering for much in the custom forum I'm designing...filter some curse words out, but not much else. I just wanted to protect from injection. I made a custom function (see below) but I figured that was probably taking it too far... I've never read a good article on injection that stated what exactly need to be gotten rid of...just that you needed to watch out for it, with a few basic examples, mainly focusing on the quotation mark.

Code:
function get_htmlspecialchars($given, $quote_style = ENT_QUOTES)
{
	return CurseFilter(htmlspecialchars(html_entity_decode( stripslashes($given), $quote_style ), $quote_style ));
}

function CurseFilter($text)
{
	$curse_words = array("xxxx","xxxx","xxxxxxx","xxxxxxx","xxxxx","xxxxx");
	foreach($curse_words as $value)
	{
		$match_value = "/\b".$value."\b/i";
		$text = preg_replace($match_value,"curse",$text);
	}
	return($text);
}

***************************************
J. Jacobs
 
ggggus said:
I just wanted to protect from injection
It depends on what you mean by 'injection' i.e. SQL Injection, Code Injection, XXS or all of the above...

SQL injection for MySQL can be taken care of pretty easily with mysql_real_escape_string(), type casting, and quotes.

mysql_real_escape_string() will handle all the quote issues with a value. (I have yet to see an exploit of a quote not being escaped)

Type casting can be used on integers. mysql_real_escape_string() will not escape ';'s which can be a problem with variables that are used as integers in a statement (hence the use of 'string' in the function name).
For example:
Code:
//normal post value
$_POST['column_id'] = '15';

//hacking attempt 
$_POST['column_id'] = '15; DELETE FROM [i]table_name[/i]';

//sql where $_POST['column_id'] is used...
$sql = 'SELECT *
        FROM [i]table_name[/i]
        WHERE [i]column_id[/i] = '.mysql_real_escape_string($_POST['column_id']);
As you can see the value for $_POST['column_id'] is still a security threat when using mysql_real_escape_string().

To prevent such an attack I prefer to use type casting. It is faster than using the ctype functions and a lot faster than using regular expressions. So my code validation for an integer will look something like:
Code:
if ((int)$_POST['column_id'] != $_POST['column_id']) {
   trigger_error('not a valid integer');
}

//or if you want to try to clean it (not a good idea)
$_POST['column_id'] = (int)$_POST['column_id'];

Finally, MySQL (and some other dbs), will allow you to put quotes around all values including integers. So another way to mitigate the threat above would be:
Code:
$sql = 'SELECT *
        FROM [i]table_name[/i]
        WHERE [i]column_id[/i] = "'.mysql_real_escape_string($_POST['id_column']).'"';
Just to be safe I usually use all three on integers, but this could be over kill.

Some general rules I live by when dealing with security...

Filter all external data; this means anything that does not originate in your script, whether it is coming from $_SERVER, a database, or user input, consider it tainted until it has been filtered.

Do not try to clean data; if it fails your validation routine, then reject it and display a friendly error message.

Always use a 'white list' approach when possible i.e.
Code:
switch ($_POST[‘subject’]) {
    case ‘pre-purchase questions’:
    case ‘customer support’:
    case ‘other’:
        $subject = $_POST[‘subject’];
        break;
    default:
        trigger_error();
}

And as Chris Shiflett always says: 'filter input, escape output'
 
This is the end of my previous post, for some reason the site would not accept the post with this on the end...

Here are two sites centered around PHP Security, both provide a wealth of information along with links to numerous other resources.
PHP Security Consortium
the Hardened-PHP Project
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top