Mar 13, 2011

Separating code from data... are we there yet?

Disclaimer: The opinions in this post are entirely my own and should not be associated with any current or previous employer of mine.

Mixing code and data has been a big (and I mean BIG) problem for decades in security. Setting security design flaws aside, having the ability to transform data into code has led to some of the biggest and probably most notorious examples of why software security really matters. Period.

While there is a lot of progress in handling this problem in native code (examples are plenty: GS, SafeSEH, DEP, ASLR, etc.), where does this leave web? Unlike native applications, the web has one major disadvantage: it relies heavily on parsers that help with the execution of dynamically written code. Browser security aside, there have been a few initiatives to help developers separate code from data through validating data on input or rendering data in a safe format. Although they've been done with a noble intent, I am still not convinced that this is a comprehensive enough solution. Here is why:
  1. Input validation. Input validation limits the user in submitting data... both malicious and legitimate; therefore limiting the application's usability and the its users' productivity. For instance, should the folks maintaining the input validation need to be aware of every context in which their data is used (e.g. database query, JavaScript/JSON, HTML, etc.)?

  2. Output encoding/escaping. Output encoding/escaping is useful for transforming data into a format that is then interpreted as data within the context where the data will be used. However, the major question here is what is the actual context in which the data will be used? In the following sample snippet the data passes through at least 2 different contexts (HTML and JavaScript):
    <html>
    <head>
    <script>
    document.write('<div id="' + [USER_CONTROLLED_DATA] + '">bla</div>');

    So naturally the question: how should the encoding/escaping be done in such cases? According to which context should the encoding/escaping be tailored?

  3. Contextual escaping via templates. In most cases and if (a big IF) properly enforced, templates are a good thing to use. Needless to say, with their help development teams can streamline a solution to the problem. From that point on lint and checks on commit are the way to go. However, what if the templates are not strictly enforced? What if the development team provides special cases where data should not be escaped? What if data from upstream already comes escaped/encoded?

So where does this leave web? I suspect the biggest challenge is to separate the channels through which code and data are communicated. Avoiding or limiting the use of code parsers and eval() (or equivalents of it) for parsing data are definitely steps in the right direction...

P.S. - This post has been picking a lot on cross-site scripting as an example. However, the same logic holds for other types of security issues that arise from injection based attacks.

No comments: