I looked around everywhere and I can't find the answer to my question.
I'm using the latest PHP for server-side scripting and MySQL for my database. The character set is utf8mb4
if that makes a difference.
Until now, I have used prepared statements to protect myself from SQL injection. However, since most of my queries are only executed once, the code is really slow. When I use $conn->query()
instead, and $conn->real_escape_string()
for all my variables, it's faster.
However, $conn->real_escape_string()
is also slow because there's a roundtrip at each call. But I don't understand why there's a need for a roundtrip because I feel like that escaping function can just be programmed in PHP.
From the docs, a function would look like this:
Characters encoded are NUL (ASCII 0), \n, \r, \, ', ", and Control-Z.
function sanitize($str)
{
str_replace(array('\\', "\0", "\n", "\r", "'", '"', "\x1a"), array('\\\\', '\\0', '\\n', '\\r', "\\'", '\\"', '\\Z'), $str);
}
Assuming I made sure it's in the right encoding and that it's not empty.
This was posted as a comment in one of the docs. By the way, str_replace
works with Unicode.
However, I thought of something that makes a little more sense. Looking at this page, I can stretch this a lot further. For a statement like this:
$sql = "UPDATE ipsum SET lorem=$str WHERE id=1337";
Can't I just do (and I'm checking beforehand to make sure it's a UTF-8):
function sanitize($str)
{
return "'" .str_replace(array("\\", "'"), array("\\\\", "\\'"), $str) . "'";
}
And that will prevent SQL injections? Why not? I can't think of an input for which it will fail.
If not, is there a better PHP function that can protect against SQL injection better?
Thanks in advance! You can test SQL here.
UPDATE: Received the responses I expected. To clarify, I'm not asking for you to give your classic preaches of "prepared statements are the best thing ever do it or die." If I wanted that, I'd ask on Yahoo! Answers and not here.
I'd like to know why my method (the second one) is not secure (or if it is). It'd also be nice to include a discussion of what real_escape_string
or prepared statements actually do to sanitize the data. Both MySQL and PHP are open source, and I'm sure someone knows what's happening when these functions are called.
I simply don't understand why a roundtrip is needed to sanitize strings. How can a method like that not be implemented in PHP?
UPDATE 2: I have iterated through all the unicode characters (0x0000 to 0x1F77F, found this on Wikipedia) and noticed that, if real_escape_string()
only escapes single characters and not phrases (which according to the docs it does), under utf8mb4
charset, the characters that change are:
unicode 0 => \0
unicode 10 =>\n
unicode 13 =>\r
unicode 26 =>\Z
unicode 34 =>\"
unicode 39 =>\'
unicode 92 =>\\
So even though it's utf8mb4
, it isn't different from what the docs say (guess because UTF-8 is standard). So why is this not implementable in PHP?
Here's a PHP script which combines all these unicodes and sanitizes them. Here's a SQL fiddle.