Sunday 19 June 2011

XSS (Part 4) - A New Hope

So this is my last post in my series on XSS and I hope to follow up on my previous 3 posts by offering more detail on how you might implement a solution to XSS by progressing through the stages of the XSS Mitigation Maturity Model (MMM).

There isn't much point in offering any advice for the None and Basic levels; there is nothing to do for the None level, and the Basic level is what people currently do if they follow the advice online.

The purpose of the Intermediate level is to automate output encoding.  The reason this is an advantage over the Basic level is it takes the burden off of developers to manually apply (the correct) output encoding everywhere in the application.  Relying on developers to do this perfectly is unreasonably and to be honest not really where you want them focusing their efforts.

If you are fortunate you may be using a web development framework that offers automated contextual output encoding, however I am not familiar with enough different frameworks to know how broadly supported such a capability is; I'm going to assume not very.  Implementing this yourself involves extending your framework that writes data and code to web pages to understand the context of where the data or code is being written.  Typically this will have mixed results, it will work well for simple pages, but not so well for complex pages or pages where a combination of data and code is written simultaneously.  This limitation is acceptable though as we can use it to isolate those areas where we cannot use automated contextual output encoding and make those areas the focus of XSS testing.  For testing purposes your security team should be able to come up with a suitable range of tests or tools that test for basic XSS attack vectors.

Whereas the Intermediate maturity level can be applied to existing code with a manageable amount of effort, the Advanced maturity level implies creating a web page that is designed to be secure against XSS.  It's important to understand that the design of a web page should never just be about mitigating XSS, that wouldn't be very practical, but we can design pages so that speed, size and functionality are not the only considerations; we also consider security.

At the beginning of my first post in this series I talked about FireFox 4 as offering exciting new defenses against XSS, I was referring to it implementing the Content Security Policy (CSP) proposed standard.  The CSP allows a browser to restrict the scripts that run in the page to a white list provided by the server (as an HTTP header).

The CSP does impose constraints though, namely the page is not allowed any in-line script, instead all script must be sourced via HTML script tags.  Whilst this may seem like an unrealistic burden, it is just a design criteria, and in fact it is one that is satisfied by following the design guidelines of Unobtrusive Javascript.  The Unobtrusive Javascript approach offers numerous advantages (including making it easy to optimise for speed and size, and separating functionality from presentation), but does need to be designed into the construction of web pages and be understood by developers who implement it.

While implementing the CSP in your web app will be invaluable in defending against XSS, contextual output encoding still needs to be applied.  However, the constraints of the CSP and Unobtrusive Javascript make the accurate automated output encoding of data and code much easier as the context is trivial to determine; all Javascript will be in Javascript files, all CSS will be in CSS files, and the CSP will stop any Javascript or CSS from being written to HTML files.  To be fair it's Unobtrusive Javascript that helps the most as even without the CSP if you contextually apply output encoding that will eliminate most XSS (except perhaps in HTML attributes and the use of "javascript:" protocol handler).

As with the Intermediate level, any exceptions to designing security into a web page need to rigorously tested.

So there you have it.  It wasn't that painful was it?  Clearly I have only touched upon the topics involved and you would have to do some research yourself in order to flesh out a detailed technical solution at each maturity level.  But hopefully this post has given you some ideas about where to start.

Saturday 11 June 2011

XSS (Part 3) - XSS defences grow up.

My previous posts laid out the technical solution to XSS but raised the issue that knowing the technical solution isn't enough to remove the XSS vulnerabilities in your application.  The purpose of this post is to sound out some ideas on a systematic approach to mitigating XSS.

When it comes to integrating security into a larger business process we fortunately have some prior art to draw on, namely the several Security Development Lifecycle frameworks that exist today, such as Microsoft's SDL, BSIMM, etc.  These frameworks take an approach to security whereby they attempt to lay out a strategy and well defined goals that can be integrated into you software development process.  Some of them also use an optimised or maturity model so that security can be integrated in stages rather than trying to shift the mountain that is your 'current practice' all in one go.

I really like this approach.  I think this approach can be applied to mitigating threats as well.  Even better, I'm going to give it a catchy name, a Mitigation Maturity Model (MMM).  Alliteration fans go wild.

The reason why I think a maturity approach works well for mitigations (admittedly not all of them), is that it is a business reality that the ideal technical solution cannot magically be applied to any large application.

To make this more concrete I have come up with an XSS MMM.
  1. (None) - No specific mitigation.  Input validation may prevent some XSS.
  2. (Basic) - Manual mitigation.  Specific output encoding is being applied on a 'best efforts' basis.  Developers have been trained in the problem and the solution and perhaps an encoding library has been developed to simplify the process.  There is no testing for XSS.
  3. (Intermediate) - Automate mitigation.  Automatic contextual output encoding is being done based on a 'best effort' at detecting where code/data is being written to HTML/JS/CSS.  There are likely some exceptions to this in certain places where the complexity makes automating the process difficult, but most pages get the benefit.  Developers receive mandatory training on the dangers.  Testing is focused on those areas that do not get autmated encoding.
  4. (Advanced) -  Mitigation by design.  Rigerous automated contextual output encoding is applied,  made possible by the complete separation of HTML from JS from CSS.  A handful of exceptions exist but these are rigerously tested.
As much as it pains me to say it, the security community could probably come up with a better XSS MMM than I have.  To be honest I hope they do.  There are some purposeful omissions as well, things like penetration testing haven't been explicitly called out since that should be part of a larger framework.  I have also been vague from a technical point of view and focused more on the 'what' needs to be done than the 'how' you would actually do it.  The reason for that is simply that there is unlikely one solution at each maturity level that would suit everyone.  However, in my next post I hope to provide some concrete technical solutions at each maturity level that would hopefully be applicable to many situations.

I also believe that the MMM can actually be applied separately to existing code and new code; they needn't be at the same level.  It makes sense that new code should aim to be at a higher maturity level than existing code.  The effort to mature exsiting code can be considerable, and it's always going to be a business decision to spend time refactoring old code.

Finally, one last parting shot at the XSS mitigation advice out on the Internet today.  If we look at the XSS MMM as I have laid it out, at what maturity level would the standard advice of contextual output encoding sit?  Basic.  It's no wonder then that XSS is still such a massive problem on the Internet if that is the maturity level of the advice the security community is offering.

Saturday 4 June 2011

XSS (Part 2) - Down the rabbit hole

So my last post was all about how the common advice on solving XSS is to use input validation and output encoding.  Then I pulled the rug from underneath you and said I disagreed.  Does my arrogance know no limits!

Well perhaps.  But I think I have an argument here.  Everyone's situation is different but let's imagine a scenario where you have a large web application, with numerous developers, and you are forced by PCI compliance nobly decide to rid your application of XSS.

Following the standard advice would involve sending an email to the development team telling them to use contextual output encoding (I'll assume input validation is already in place).  You may provide the technical details on how to do this and even a library for them to use.  You then relax back in your chair with a certain satisfaction that is akin to saving the world from some great evil.

Evil on the other hand is not so easily defeated.  The development team gets back to your with some questions to clarify a couple of points:
 - do they have to output encode everything in all existing pages?
 - who is going to tell the business of the delays this will cause and/or pay for all the extra work?
 - who is going to do the regression testing on the changes to existing pages?
 - how to we test?
 - will developers get any training? (some of the new guys and graduates don't understand anything about security)
 - what will happen if we don't do output encoding and just ignore you?
 - do you really expect, with all the other pressures we have, for us to get this 100% right, all the time on every page?

Um, err ... Google!  Help me Google!  ... Google?  Didn't I just do some epic research on Google about XSS?  Why were none of these issues raised?

These issues weren't raised because output encoding is the correct technical solution to XSS, it just isn't the real problem you have to solve when you need to mitigate XSS.

This, like many technical solutions, needs to be solved by introducing process into your business.  This is where the security community has really let down program managers, technical leads and developers of the world.  I'll limit that criticism to XSS for now, although I have no doubt it applies to numerous other problems.

My next post will contain some suggestions to solve XSS through process and not (just) technology.