Injection: my (new) point of view
WARNING! TIME-DIMENSIONAL RIFT!
This is an old article, information may be outdated and/or quite cringe, proceed at your own risk!
Until recently, if you asked me what the first position of the OWASP Top 10 is about, I would have talked about how SQL injection is still a dangerous vulnerability despite being around for so long.
And boy, if I was wrong.
Well, snì1, it’s not that it is wrong, but the fact is that the first OWASP Top 10 security risk is not (entirely) defined around SQL injection.
Pff, obvious, you’d say, if you just read the definition. But I fell for this by a combination of assumptions and explanations given by others that did not contemplate actually understanding what is written in the definition itself. One person brought light into this, and I’d like to share here their - and now also my - point of view.
Sources and sinks#
Consider a generic application: no limits, apart from being open to a user input. They generally take this input and, following the execution of some code, obtain a result. Let’s model this situation as a funnel: the input, the source, comes from the top, goes down the execution, and ends out of the nozzle. Here we have a sink, that is a sensible function that operates on the code.
However, what exactly is a sensible function? Don’t hold your breath, I’ll tell you now: it boils down to a function that contains a parser.
Every parser is therefore the responsible of an injection vulnerability? No, only those in which the data context is mixed up with the command context.
Let’s unravel the jargon here with a brief example: when we make a SQl query just by concatenating part of query with input data from a form, old style, we mix up data and command context: the SQL parser in mysqli.query() can’t understand if a command it founds in its input string comes from us or is a DROP TABLE from who has sent a form.
The important bit is, every parser is at risk then: from XML to PHP, from Javascript to shell scripting, and everything in between. SQLExec()? eval()? fread()? something.parse()? All of these can be misused. This definition includes also things such as path traversal and even stack overflow attacks.
What does stack overflow attacks have in common with all this? Just look at how it is exploited, by writing assembly code in the stack, a data region. By mixing up data and commands.
So what are the mitigations? Data validation comes to the mind, but just by thinking strategically a best solution can be found: if the problems comes from confusion between the contexts, let’s just divide them. If this is possible, we obtain the best solution to the injection problem. Citing two cases: we mitigate SQL injection with prepared statements, and we mitigate stack overflow attacks by forcing the stack to be non-executable.
-
Italian for “yes and no” ↩︎