Are dynamic mysql queries with sql escaping just as secure as prepared statements?

I have an application which would greatly benefit by using dynamic mysql queries in combination with mysql (mysqli) real escape string. If I ran all data received from the user through mysql real escape would it be just as secure as using mysql prepared statements?


Yes, but a qualified yes.

You need to properly escape 100% of the input. And you need to properly set character sets (If you're using the C API, you need to call the mysql_set_character_set() instead of SET NAMES). If you miss one tiny thing, you're vulnerable. So it's yes, as long as you do everything right...

And that's the reason a lot of people will recommend prepared queries. Not because they are any safer. But because they are more forgiving...


Definitely NO.

While question in the title is ambiguous and can be interpreted as "Are dynamic mysql queries with every it's part properly formatted..." and thus have a positive answer, the question in the body is not:

If I ran all data received from the user through mysql real escape would it be just as secure as using mysql prepared statements?

If you look to this question closer, you will understand that this is just a magic quotes incarnation! The very purpose of this disgraced, deprecated and removed feature is exactly to "run all user input through escape".
Everyone knows nowadays that magic quotes are bad. Why positive answer then?

Okay, it seems that it needs to be explained again, why bulk escaping is bad.

The root of the problem is a quite strong delusion, shared by almost every PHP user:
Everyone have a strange belief that escaping do something on "dangerous characters" (what are they?) making them "safe" (how?). Needless to say that it's but a complete rubbish.

The truth is:

  • Escaping do not "sanitize" anything.
  • Escaping has nothing to do with injections.
  • Escaping has nothing to do with user input.

Escaping is merely a string formatting and nothing else.
When you need it - you need it despite of injection possibility.
When you don't need it - it won't help against injection even a little.

Speaking of difference with prepared statements, there is at least one issue (which already mentioned many times under sql-injection tag):
a code like this

$clean = mysql_real_escape_string($_POST['some_dangerous_variable']);
$query = "SELECT * FROM someTable WHERE somevalue = $clean";

will help you NOT against injection.
Beause escaping is just a string formatting facility, not injection preventer by any means.
Go figure.

However, escaping have something in common with prepared statements:
Them both doesn't guarantee you from injection if

  • you are using it only against notorious "user input", not as a strict rule for the building ANY query, despite of data source.
  • in case you need to insert not data but identifier or a keyword.

To be safe in these circumstances, see my answer explaining FULL sql injection protection how-to

Long story short: you can consider yourself safe only if you make 2 essential corrections and one addition to your initial statement:

If I ran all data received from the user through mysql real escape and always enclose it in quotes (and, as ircmaxell mentioned, mysqli_set_charset() is used to make mysqli_real_escape string() actually do it's work (in such a rare occasion of using some odd encoding like GBK)) would it be just as secure as using mysql prepared statements?

Following these rules - yes, it would be as secure as native prepared statements.


I think @ircmaxell got it right on.

As a follow-up, be on the lookout for this kind of thing.
I used to do it all the time:

<?php

//sanitize the dangerous posted variable...
$clean = mysql_real_escape_string($_POST['some_dangerous_variable']);

//...and then forget to use it!
$query = "SELECT * FROM someTable WHERE somevalue = '{$_POST['some_dangerous_variable']}'";

?>

And when I say "used to do it", what I mean is that I eventually gave up and just started using prepared statements!