SQL Injection, Quotes and PHP

不羁岁月 提交于 2019-12-05 16:03:55

There is nothing like "universal sanitization". Let's call it just quoting, because that's what its all about.

When quoting, you always quote text for some particular output, like:

  1. string value for mysql query
  2. like expression for mysql query
  3. html code
  4. json
  5. mysql regular expression
  6. php regular expression

For each case, you need different quoting, because each usage is present within different syntax context. This also implies that the quoting shouldn't be made at the input into PHP, but at the particular output! Which is the reason why features like magic_quotes_gpc are broken (always assure it is switched off!!!).

So, what methods would one use for quoting in these particular cases? (Feel free to correct me, there might be more modern methods, but these are working for me)

  1. mysql_real_escape_string($str)
  2. mysql_real_escape_string(addcslashes($str, "%_"))
  3. htmlspecialchars($str)
  4. json_encode() - only for utf8! I use my function for iso-8859-2
  5. mysql_real_escape_string(addcslashes($str, '^.[]$()|*+?{}')) - you cannot use preg_quote in this case because backslash would be escaped two times!
  6. preg_quote()

mysql_real_escape_string deserves your attention.

However direct queries are a quagmire and no longer considered safe practice. You should read up on PDO prepared statements and binding parameters which has a side benefit of quoting, escaping, etc. built-in.

BEST practice is always to use prepared statements. This makes SQL injection impossible. This is done with either PDO or mysqli. Forget about all the mysql_* functions. They are old and obsolete.

joschi

Question: Could anyone explain me, what's best practice to handle PHP and Mysql when it comes to quotes?

That's easy: Use prepared statements, e. g. with PDO::prepare or mysqli_prepare.

Don't waste the effort using mysql_real_escape_string() or anything like that. Just use prepared statements with PDO and SQL injection is impossible.

I usually use the PHP functions stripslashes and strip_tags on the variables as they come in via $_POST (or $_GET, depending on what you use) and mysql_real_escape_string during the query. (I'm not sure if this is "right" but it's worked for me so far.) You can also use PHP's built in validate filters to check things like email addresses, url's, data types, etc. PDO is supposedly decent at preventing SQL injection but I haven't had any experience with it yet.

The basic workflow should be

$data = $_POST['somefield which will go into the database'];

... do data validation ...

if (everything ok) {
    $escaped_data = escape_function($data);
    $sql = " ... query here with $escaped_data ... ";
    do_query($sql);
}

Basically, data that's been escaped for database insertion should ONLY be used for database insertion. There's no point in pre-processing everything and overwriting all data with db-escaped values, when only 2 or 3 of 50(say) values actually go anywhere near the db.

Ditto for htmlspecialchars. Don't send data through htmlspecialchars unless it's headed for an HTML-type display.

Don't store data in the DB formatted for one particular purpose, because if you ever need the data in a different form for some other purpose, you have to undo the escaping. Always store raw/unformatted data in the db. And note: the escaping done with mysql_real_escape_string() and company does not actually get stored in the db. It's there only to make sure the data gets into the database SAFELY. What's actually stored in the db is the raw unescaped/unquoted data. Once it's in the database, it's "safe".

e.g. consider the escaping functions as handcuffs on a prisoner being transferred. While the prisoner is inside either jail, cuffs are not needed.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!