You might think that using an "escaping" function like mysqli::real_escape_string() on every input is just as safe as using prepared statements.
Except:
Escaping doesn't work for numeric inputs, only quoted strings and quoted dates.
Escaping has some unexpected cases where it doesn't work. These are edge cases, but they exist. See some examples in answers for SQL injection that gets around mysql_real_escape_string()
Escaping is harder when writing code. Doing it correctly is time-consuming and meticulous, and easy to get wrong. Developers are often tempted to skip it.
Developers who care about preventing SQL injection recommend using query parameters instead for several reasons, including but not limited to the following:
Query parameters also work for numeric values.
Code that uses query parameters is easier to write and read, and less prone to mistakes. We expect that once they have the habit of using query parameters, developers use this method more reliably, and therefore vulnerabilities are less likely.
For example, you could write code like the following:
$sql = "INSERT INTO mytable (col1, col2, col3, col4, col5, col6)
VALUES ('" . mysqli_real_escape_string($_POST['col1']) . "', "
. $mysqli->real_escape_string($_POST['col2']) . "', '"
. $mysqli->real_escape_string($_POST['col3']) . "', '"
. $mysqli->real_escape_string($_POST['col4']) . ", '"
. $mysqli->real_escape_string($_POST['col5']) . "', '"
. $mysqli->real_escape_string($_POST['col6']) . "')";
Can you spot the mistakes? With enough time, I’m sure you can. But it will slow down your coding and may give you eyestrain as you look for missing quote characters and other mistakes.
But it’s so much easier to write this, and easier to read it afterwards:
$sql = "INSERT INTO mytable (col1, col2, col3, col4, col5, col6)
VALUES (?, ?, ?, ?, ?, ?)";
Query parameters are safe for more data types, and they help you write code more quickly, with fewer mistakes. That's a big win.
Like the other comments above, I disagree with your claim that MySQLi doesn't support query parameters. It's clearly shown in the documentation: https://www.php.net/manual/en/mysqli.prepare.php
If you have some wrapper code that uses MySQLi but doesn't support mysqli::prepare()
, then I recommend you stop using that wrapper code. Either write features for your framework so that it uses query parameters, or else get another framework.
Also answers like "change" your framework" or NOT adequate!
Look, here's the truth: if you can't write code that handles user input safely, then you shouldn't accept user input.
You suppose there are ways of using preg_replace()
but there aren't. There are so many ways of injecting code (either SQL or Javascript), that you would end up filtering out many legitimate user comments as well. How would your users react if your web app stripped quotes and apostrophes from their comments? What other characters do you need to strip out?
Query parameters are the most effective solution for this problem. Your resistance to them is absurd.
It's like an electrician who asks, "How can I prevent getting shocked? But I can't use insulated gloves or tools, so don't suggest that."