Every answer here covers only part of the problem.
In fact, there are four different query parts which we can add to it dynamically:
In fact, there are four different query parts which we can add to it dynamically:
- a string
- a number
- an identifier
- a syntax keyword.
and prepared statements covers only 2 of them
But sometimes we have to make our query even more dynamic, adding operators or identifiers as well.
So, we will need different protection techniques.
So, we will need different protection techniques.
In general, such a protection approach is based on whitelisting. In this case every dynamic parameter should be hardcoded in your script and chosen from that set.
For example, to do dynamic ordering:
For example, to do dynamic ordering:
$orders = array("name","price","qty"); //field names
$key = array_search($_GET['sort'],$orders)); // see if we have such a name
$orderby = $orders[$key]; //if not, first one will be set automatically. smart enuf :)
$query = "SELECT * FROM `table` ORDER BY $orderby"; //value is safe
However, there is another way to secure identifiers - escaping. As long as you have an identifier quoted, you can escape backticks inside by doubling them.
As a further step we can borrow a truly brilliant idea of using some placeholder (a proxy to represent the actual value in the query) from the prepared statements and invent a placeholder of another type - an identifier placeholder.
So, to make long story short: it's a placeholder, not prepared statement can be considered as a silver bullet.
So, a general recommendation may be phrased as
As long as you are adding dynamic parts to the query using placeholders (and these placeholders properly processed of course), you can be sure that your query is safe.
As long as you are adding dynamic parts to the query using placeholders (and these placeholders properly processed of course), you can be sure that your query is safe.
Still there is an issue with SQL syntax keywords (such as
AND, DESC and such) but white-listing seems the only approach in this case.Update
Although there is a general agreement on the best practices regarding SQL injection protection, there are still many bad practices as well. And some of them too deeply rooted in the minds of PHP users. For instance, on this very page there are (although invisible to most visitors) more than 80 deleted answers - all removed by the community due to bad quality or promoting bad and outdated practices. Worse yet, some of bad answers aren't deleted but rather prospering.
For example, there are still(1) many(2) answers(3) suggesting(4) you(5) manual string escaping - an outdated approach that is proven to be insecure.
Or there is a slightly better answer that suggests just another method of string formatting and even boasts it as ultimate panacea. While of course it is not. This method is no better than regular string formatting yet it keeps all its drawbacks: it is applicable to strings only and, as any other manual formatting, it's essentially optional, not obligatory measure, prone to human error of any sort.
I think that all this because of one very old superstition, supported by such authorities like OWASP orPHP manual, which proclaims equality between whatever "escaping" and protection from SQL injections.
Despite of what PHP manual said for ages,
*_escape_string by no means makes data safe, and never has been intended to. Beside of being useless for any SQL part other than string, manual escaping is wrong because it is manual as opposite to automated.
And OWASP makes it even worse, stressing on escaping user input which is an utter nonsense: there should be no such words in the context of injection protection. Every variable is potentially dangerous - no matter of the source! Or, in other words - every variable have to be properly formatted to be put into query - no matter of the source again. It's destination that matters. The moment a developer starts to separate the sheep from the goats (thinking whether some particular variable "safe" or not) he does his first step to disaster. Not to mention that even the wording suggests bulk escaping at the entry point, resembling the very magic quotes feature - already despised, deprecated and removed.
Which is leaving us no choice other than prepared statements.
If you're still not convinced, here is a step-by step explanation I wrote, The Hitchhiker's Guide to SQL Injection protection, where I explained all these matters in detail, and even compiled a section entirely dedicated to bad practices and their disclosure.
No comments:
Post a Comment