4 ms·
This feels like a distinction without a difference. Escaping outputs is just one way of sanitizing inputs. Sometimes it works. Sometimes it doesn't. The author
by throwawayjava 7y ago
This feels like a distinction without a difference.
Escaping outputs is just one way of sanitizing inputs. Sometimes it works. Sometimes it doesn't. The author of this post even realizes that their prognostication is not general and then offers the advice to "be sure to get security review"...
At the end of the day, you need to make sure that any untrusted source is treated in a safe way by every sink and does not otherwise interfere with system specs (e.g., mangling user output). Whether that happens at line 5 (where the input is read) or line 155 (where the command is generated) doesn't really matter. Or to be more precise, is determined by whatever design patterns the framework developer chose.
What matters at the end of the day is that command injection isn't possible and the system's specs (including UI/UX specs) are respected.
Crucially, both input and output constraints are informed by the nature of both the source and the sink. Hence the existence of libraries like DomPurify and HTMLPurifier, which consider one very particular type of sink. Sometimes you will write code in domains where others haven't written excellent libraries but where sanitization (of either input or output) is needed. E.g., embedded systems.
I'd replace the author's advice with "carefully specify the semantics of your sources and sinks", which is ultimately what the author's actual advice (basically, "use trusted libraries and, when not, be sure to get security review") boils down to.
- tptacek 7y agoNot really, no. Output filtering is done in the context of a specific output domain. Input sanitization isn't; the developer who builds sanitization has to guess at all the possible output domains. "Filter outputs not inputs" is a very old appsec truism.
- eandre 7y agoI think the confusion comes from that not everybody thinks of "passing data to the database layer" as an output, but only an input to the next layer. If you think of this input as an output from the previous layer, then your advice makes perfect sense. But I don't think everyone thinks that way so it might help to clarify what "output" means in this context.
- jessaustin 7y agoNo, that's clearly input. That data shouldn't be sanitized, but it should be passed to the database via parameterized query.
- throwawayjava 7y agoOutput filtering is input sanitization. wtf is is that you think you are filtering? Inputs! > the developer who builds sanitization has to guess at all the possible output domains. No they don't. They need to carefully understand/document all the places input might be used and ensure no command injections are possible. In some cases (e.g., web apps, where everything is string) that works relatively well... Until, of course, you're the one writing the input sanitization logic in the HTML purifier / prepared statements generator. And those code bases do have occasional CVEs. So, random PHP dev can put faith in a library but the system itself never gets away from having to sanitize input! Output filtering has the complimentary problem -- you need to understand every possible input. That's not always trivial like it is in PHP-based websites. Think about e.g. an embedded system santiziing potentially adverarial time series data (what does this mean / how do you detect it? Harder, right?). Or a compiler. The blog post author even points this out: "...In these cases you’re best off using a proper SQL parser (like this one) to ensure it’s a well-formed SELECT query – but doing this correctly is not trivial, so be sure to get security review." Ultimately, "Filter outputs not inputs" is incomplete advice that kinda sorta works well for the most part in web apps. The correct advice is, again, "carefully specify the semantics of your sources and sinks".
- zAy0LfpBZLC8mAC 7y ago> Output filtering has the complimentary problem -- you need to understand every possible input. No, you simply need to understand the encoding rules of the sink. Which is precisely why "sanitizing input" is plain nonsense: Whether a particular unescaped character has some meta character function is not a property of the character, but of the output language, so you can not possibly "sanitize input" in any meaningful sense, unless you mean by that "randomly garble the input".
- wglb 7y ago>you need to understand every possible input. This is often not possible. When I talk to developers about this, I point use database storage as an example. There may be computations behind the scenes that mangle the nicely input-sanitized database contents. Concatenation with other values, string work, data from some other system. Thus, data that was sanitized upon input is now questionable for output. This is well-intentioned, but leads to a false sense of security, and sometimes mangles perfectly good input. And in some applications, for example, ones that must process data in a forensic environment, any change to the input is prohibited. Thus, the only useful way to think about this is that the contents of the database is toxic and must be sanitized on output. Simply working with the input gives the programmer no useful idea about what is in the database when it comes time to output it. Frameworks these days help significantly with providing tools to properly parameterize SQL. However, it is unlikely that they handle all the cases. Consider an example where user input from a web page is used to build a column name or table name. This isn't covered by frameworks. That needs to be carefully processed in the code. >Ultimately, "Filter outputs not inputs" is incomplete advice that kinda sorta works well for the most part in web apps. The correct advice is, again, "carefully specify the semantics of your sources and sinks". It is in fact the primary advice that should be followed. So sanitization of input is a good idea, but if output is not properly encoded, somebody else is likely to profit.
- 0xff00ffee 7y ago> I'd replace the author's advice with "carefully specify the semantics of your sources and sinks", I think that's the abstraction, but the author is presenting it in a way that requires repeating frequently simply because new programmers arrive ready to do damage every day, and the two forms of input sanitization are a great intro into how the Real World (tm) conspires against you.