How to cleanse a string to avoid SQL Injection and

2019-02-19 14:06发布

问题:

Is there a way to, in as little code as possible, to filter a string for both SQL injection and the most common forms of attack?

In my scripts I'm using the following, I would like to know whether it's reasonably safe and whether someone else has a suggestion:

$cleanName    = htmlspecialchars(addslashes($dirtyName));

See how I filtered it both for html chars and for quotes and double-quotes.

NOTE: I'm using addslashes() rather than mysql_real_escape_string() because I don't want to hardcode the DB I'm using into my code.

Is this ok?

Thanks in advance

回答1:

Probably not... you need to escape your raw text for each purpose separately for which you are going to use it:

  • For GET requests, use urlencode.
  • For HTML output, use htmlentities.
  • For calling as a command via system, use escapeshellcmd.
  • For passing arguments to a command via system: use escapeshellargs.
  • For passing a database parameter: use mysql_real_escape_string.

There's no "universal" solution for magically escaping text. Keep raw text internally, and escape it for the appropriate purpose.



回答2:

If you don't mind recoding your connection and a couple extra lines of you code you can't beat PDO for security. It uses the C backend to prepare and execute your mysql queries. So instead of string concatenation you get predefined sections in the query that must be value XYZ. One of the guys here on stackoverflow explained it like this:

Imagine a hotdog stand. You walk up to the hotdog stand and say I'd like a hot dog with 3 toppings. Ketchup, mustard and we will let the next random stranger tell us the third topping. A sql injector might walk up and say, "ketchup, mustard and 'give me all the money in the drawer'". Standard concat queries have no way of discerning that it is an invalid response and therefore hand over what was requested. A prepared statement will respond with "I dont have a condiment called,"give me all the money in the drawer".

PDO prepared statements are essentially injection proof. You still have other vulnerabilities like cookie/session hijacking etc, but at least injection is off the table.



回答3:

Not to rain on Kerrek's parade, but there is one, relatively, universal solution. I use the following and it's always worked:

$safe_value = mysql_real_escape_string( strip_tags( trim( $value ) ), $db_connection ); // This is if you aren't storing any html tags

$safe_value = mysql_real_escape_string( html_entities( trim( $value ) ), $db_connection ); // This is if you are storing html tags

Hope this helps.



回答4:

If you know exactly what kind of input you are expecting, better use preg_replace() If you know that you only expect alpha-numerics:

<?php
if (isset($_GET['page'])) {
 $page = preg_replace('/[^a-z0-9]/', '', $_GET['page']);
 include_once($includeDir.'/'.$page.'.php');
}
?>

The above should prevent all attacks executed via GET or POST too, but it assumes you only expect alphanumeric input. Well, I mostly had in mind directory traversal attack, but if you use the GET variable to query a database or display it as a html entity should prevent any attack. A http://mydomain.tld?index.php?page=../../etc/passwd request won't read your passwd file from your website's /var/www document root but will only try to include a etcpasswd.php file