Calling it "sanitization" implies that the data is somehow dirty, so naturally it should be cleaned as soon as possible, and after that it's safe. But all that accomplishes in general is corrupting the data, often in an unrecoverable way, and then opening up security vulnerabilities because the specific use doesn't happen to exactly match the sanitization done in advance.
It's great to validate the data on input and make it conform to the correct domain of values, but conflating this with output formats and expecting this to take care of downstream security as well just leads to incorrect data along with security vulnerabilities.
PHP's long-ago-removed magic quotes feature was an example of this confusion in action. It not only mangled incoming strings containing single quotes in an effort to prevent SQL injection, but did so in a way that left some databases completely exposed, depending on their quoting syntax.
SQL injection is avoided at the point of usage. Trying to sanitize your input against it is an extremely bad practice. The same is true about HMTL injection (whether you call it XSS or something else).
Log4j is an example of not interpreting text that the developer was never aware that was code. It's kinda of the extreme opposite of escaping your text on usage.
> The only code that knows what characters are dangerous is the code that’s outputting in a given context. And of course use your SQL engine’s parameterized query features so it properly escapes variables when building SQL: ... This is sometimes called “contextual escaping”.
The "context" is that you are outputting to the database engine.
> your SQL engine’s parameterized query features so
> it properly escapes variables when building SQL
This is wrong. Parameterized queries do not build an SQL string by escaping the input. The input is actually sent to the database separately from the SQL.Well, in all sane implementations, anyway. PHP has an PDO::ATTR_EMULATE_PREPARES option that does build SQL from a parameterized query. And, of course, Wordpress has $wpdb->prepare() that returns an SQL string with the parameter escaped. Also, so far as I know, one cannot run a prepared statement from the SQLite CLI, so no parameterized queries there either:
https://stackoverflow.com/questions/20065990/how-to-prepare-...
In the general case there are certainly many examples of security vulnerabilities created by wrong serialization of data into the wire protocols of services, but maybe not specifically for this situation of query parameters. But maybe there are, I have no idea really. Either way, it's not the application developer's responsibility at that point, it's the responsibility of the people who developed the database driver.
Your blanket observation is not necessarily true of all databases or database drivers. You found three counter-examples yourself, but there's no reason to not consider them "sane". It's not less correct than for databases that do support prepared statements in the driver protocol.
Up to this day, the official way to deal with XSS in .Net is by doing sanitization at the receiving point. I imagine the article is directed at that.
That's so old and obvious advice that I'm surprised people keep posting here and upvoting. And even more surprised when people keep disagreeing here.
The article title says NOT to sanitize inputs. perhaps it's that nuance doesn't fit in a headline, but eh...
Data should only be sanitized in transit and not stored in an sanitized form. That's what the article is really saying.
It seems like this article is using this differentiation. In my experience, it's very common. It's not worth arguing about.
Validating or sanitizing input input is a reasonably good defense against certain other things. E.g. zeroes in values you'll later divide by, when it's too late to return an error; multi-gigabyte names; information that you want to avoid storing like credit card numbers. That sort of use case doesn't really have a whole lot to do with the article, though.
With this logic, someone could use a SQL injection. It wouldn't be sanitized as the INSERT is happening, so the SQL injection would be executed.
EDIT: I know he goes on to talk about escaping characters, but the title of the post is "Don't try to sanitize input". My point is simply that SQL injections happen on input, not output. His example of escaping the SQL is at odds with the title of the post.
Unfortunately, that's just life. There's no way around it. One way or another you're going to be doing something or you're going to get owned.
"So the better approach is to store whatever name the user enters verbatim, and then have the template system HTML-escape when outputting HTML, or properly escape JSON when outputting JSON and JavaScript."