I’m currently using the mysqli php extension.
Traditionally I have used mysqli_real_escape_string to escape user input. However I am looking at changing over the code (hopefully in as few steps as possible) to use prepared statements.
I want to be clear on this – provided I use prepared statements to bind all of my variables, can I be confident that sql injection is impossible? (And dispense completely with mysqli_real_escape_string?)
If you correctly bind all your variables you can dramatically reduce the risk of SQL injection. It is still possible to get an SQL injection if you create SQL dynamically for example:
'SELECT * FROM ' . $tablename . ' WHERE id = ?'
But if you avoid things like this it is unlikely you will have problems.
Speaking of security, there is no difference between both methods, if you correctly bind or format your variables.
Binding is just simpler, because it can be used just for any case, while escaping can’t (so, you have to cast some variables instead of escaping/quoting).
Also, bear in mind that no binding nor escaping can make identifier safe. So, if you have to use a field name or operator in your query, you have to use a value, hardcoded in your script.
Here’s my high-level view on the topic.
When using dynamic SQL strings, you are relying on the escaping function working correctly. Unfortunately, this is not always the case, as can be seen in this (admittedly old) example:
Once your data values have been escaped, the SQL string has to be parsed and compiled by the database server. If the escaping function has not done its job properly, or a clever new SQL injection attack has been discovered, there is a chance that the server will mistake data for SQL statements.
If you use prepared statements with parameters, the statement is first parsed and compiled. The data values are combined with the compiled statement when it is executed. This separates the SQL logic from the data values – the opportunity to confuse the two should never occur.
So, yes, you can dispense with
mysqli_real_escape_string, but I would not go so far as to say that using prepared statements with parameters makes SQL injection impossible. It makes it significantly harder, but as with the
mysqli_real_escape_string bug, I guess there’s always the chance that a yet to be discovered (or newly created) bug will make the seemingly impossible, possible.