Web Hosting Talk







View Full Version : Prevent injections


krissauquillo
06-11-2007, 04:27 PM
Would this small .htaccess code work in preventing PHP/SQL injection:

RewriteEngine on
RewriteRule (;|<|>|'|"|%3b|%3c|%3e|%27|%22) 404.shtml [NC]

Or is it..

RewriteEngine on
RewriteRule (\;|\<|\>|\'|\"|%3b|%3c|%3e|%27|%22) 404.shtml [NC]

mwatkins
06-11-2007, 07:32 PM
No, certainly not how you intend, anyway.

Rewrite rules function on URIs, not on POST variables.

Secondly, do you really want to block all <> and so on? what about the words DELETE FROM? DROP TABLE? etc, etc.

Your code either has to do the heavy lifting, or someone else's code (a framework) has to do it for you.

sasha
06-11-2007, 08:47 PM
Preventing injections is as much coding issue as it is a state of mind.

When thinking about injection consider this:

"User is your worst enemy. He will go at any length to harm you and he has unlimited skill and full knowledge of all your code."

With that in mind:
- Initiate ALL variables you use
- Sanitize all input.

azizny
06-11-2007, 10:48 PM
Easy:

* Disable globals
* Clean $_GET/$_POST data on the headers
* Use mysql_escape for queries
* Remove slashes from variables when you know you do not need them as inputs.

You shouldn't have a problem then.

juangake
06-12-2007, 05:07 AM
Gotta love that:

"User is your worst enemy. He will go at any length to harm you and he has unlimited skill and full knowledge of all your code."

Really nice rule... As an example: I usually use this code for any input that I know it just need to be a number.

function FilterStringNumber(&$strtof) { $strtof=preg_replace("/[^.0-9]/","",$strtof); }

So I can use FilterStringNumber($_REQUEST['id']) to eat *Everything* that are not numbers on $_REQUEST['id']

;) Regards,

Juan

pphillips
06-12-2007, 11:21 AM
You can use this function in your queries to prevent sql injections.


function quote_smart($value) {
// Stripslashes
if(get_magic_quotes_gpc()) {
$value = stripslashes($value);
}
// Quote if not integer
if(!is_numeric($value)) {
$value = "" . mysql_real_escape_string($value) . "";
}
return $value;
}


$sql = "INSERT INTO table (id, field1) VALUES ('', '" . quote_smart($_POST['field1']) . "');

dtredwell
06-12-2007, 11:41 AM
instead of filtering out the bits you dont want, why not only accept chars?

pphillips
06-12-2007, 11:50 AM
The best method is a white list method. If your accepting user data it can't be trusted.

You can take your $_POST data and filter out any vars that are not expected. For the vars that are expected you can check if they are the appropriate type you expect, like string, or integer, or array. If they don't match, dump them, and assign what is left to another var such as $clean.

Then you run it through quote_smart before putting it in the database.

The best methods are always to assume the data is potentially corrupt... so a white list method as described above is best.

gophp
06-12-2007, 04:30 PM
In addition to checks like is_numeric, I often attempt to cut the input strings down to a reasonable length (of course they are not cut if the length is as expected). Most stupid buffer overflow bugs are probably fixed, but you never know what else can happen if someone sends you a couple of kilobytes as, let's say, a user ID and you dump that on the database.

function cut($var,$len=64) {
return substr($var,0,$len);
}

(little bit paranoid, but why not?)

pphillips
06-12-2007, 07:38 PM
My only problem with cutting strings down is that your modifying potentially already bad data. In that case, I would just reject the data altogether. It's possible that the attacker is relying on you to modify their data to perform their exploit.

gophp
06-13-2007, 03:16 AM
Yes, but how do you know the data is bad? Bad or invalid? To validate it, you have to do something first, like running a query against a DB, and this is where cutting may help, to my mind.

Anyways, I did not mean cutting everything. In my particular case, if a user wants to perform some operation on his own object (message, data record etc), I verify the object key (numeric ID). If I am given invalid data as ID, for me this will mean that there is no object with this ID and this *user ID*. (The used ID comes from the session of course, and is verified in a different way). So, they can send me whatever IDs they want, but cutting protects the database and then the session+database protects other users' objects.

pphillips
06-13-2007, 11:25 AM
If you have a form with a name field, and you set the maxlength to 50, you can reasonably assume that any input from the name field that is greater than 50 characters is potentially malicious. Additionally, the input should be a string, not an array or an integer.

Likewise, if you have a age drop down field, and you receive a string input you can reasonably assume its bad data - since we are expecting an integer.

It's good to do client side javascript or html validation on your fields - and then, you just dump everything that doesn't conform and wasn't expected when it's posted. Manipulating data and/or accepting variables and data types that aren't expected can be dangerous.

mwatkins
06-13-2007, 12:29 PM
It's good to do client side javascript or html validation on your fields - and then, you just dump everything that doesn't conform and wasn't expected when it's posted. Manipulating data and/or accepting variables and data types that aren't expected can be dangerous.

I was with you until you said the above.

A malicious "user" won't always be using a browser; a script designed to exploit weaknesses isn't going to respect your client side javascript or even execute it - it will POST the values directly. Thus whether or not you do sanity checking on the client, you *must* do it on the server.

Perhaps you meant that.

pphillips
06-13-2007, 03:03 PM
I was with you until you said the above.

A malicious "user" won't always be using a browser; a script designed to exploit weaknesses isn't going to respect your client side javascript or even execute it - it will POST the values directly. Thus whether or not you do sanity checking on the client, you *must* do it on the server.

Perhaps you meant that.

Yes, which is why I wrote "and then, you just dump everything that doesn't conform and wasn't expected when it's posted".

Your PHP is ultimately in control - not the javascript/client side checks. SO, when you get a 500 character string for your age field, which should be a number 1-99 per your form, you remove it completely from your array of post vars. Some people argue that you should modify the data submitted if it isn't what you expect, I argue that if it isn't what you expect, you kill it, remove it from the post array by filtering it out completely and assigning the new $_POST array vars to something else, like $clean.

So, I think we are on the same page =P

mwatkins
06-13-2007, 04:40 PM
I'm on a similar page to you.

When form data arrives at my back end and it isn't of the nature I am expecting, I raise an error in the field on the form and my form library marks the field as such. Something like:

[snip]

if not match(form.get('username'), pattern('[a-zA-Z0-9]*$')):
form.set_error('username',
('Username must only contain letters and/or numbers '
'and no punctuation'))

The form is then redisplayed with the offense(s) so marked. I don't really care what they shove in the field, it won't get past the validation tests. If someone enters "foo bar" in the username field and it doesn't permit spaces, I'm not going to throw out "foo bar" and display an empty field - no, I'm going to redisplay it and hopefully the error message will make life easier for the user correcting it.

These days if a really zippy interactive form is required I would abstract out the validation components of the form handler such that they could be called by client side AJAX methods, but often that's just overkill.