The usual suspects and what to do about them

I’ve been busy on the Top 10 2007 with Dave Wichers and Jeff Williams. I’m very close to finalizing a draft release right now. This process made me think, how can we eliminate these issues? Why should every developer have to learn how to fix the same problem? We know On some frameworks, some classes of application programming error are history. Obviously, we’re not going to be able to fix business process or logic issues, but I’d prefer people working on that than wasting time searching mountains of code looking for every last vulnerability.

So over the next week or so, whilst I’m traveling and theoretically have more time (i.e. less TiVo!), I’ll pump out what’s wrong with the current model, and propose how it might be fixed. Permanently.

Some of my recommendations will be hard to swallow, but the alternative (“same old, same old”) has failed, and failed miserably for years. It’s time for something new, or in the case where it works real well on another framework, let’s adopt their ideas and maybe even improve on it a bit. Up first is our old friend XSS.

XSS

xss-table001.png

The table shows just how wrong the old way (PHP) is. I made the number up in the difficulty column, arbitrarily setting it to 10 / 10 for the weakest solution, and then thinking carefully about what would be required in the other platforms to come to the same desired point: a safe application. In this round, J2EE using any of of the common presentation layers wins hands down. Sure, you can do bad things in J2EE and .NET, but the important thing is that it is not the default. You have to work at being insecure. But when you need to be, those frameworks allow you to be as insecure as the next guy.

Given the likelihood that a PHP developer is no better or worse than a J2EE or .NET developer, the PHP application requires more care and thought to get right. This means, in the entire universe of webapps (regardless of language), a larger percentage of PHP applications will have XSS issues than other frameworks.

What’s needed to get it right?

With PHP, there’s no real solution other than … a very ballsy decision to make PHP 6 XSS safe by default. PHP 6 is Unicode. Let’s make the Unicode output functions XSS safe by default, and output a E_STRICT warning when apps use print or echo. Obviously, there will need to be a way to output HTML dynamically, but this is the corner case, not the default. Let’s make the devs who need REAL html do the hard work, rather than make all devs do the hardwork, everywhere.

With .NET, all controls need to be XSS safe by default and have an encoding property, and it should be set to true by default. Enough are properly done right now to protect the usual newbie programmer, but it’s wrong to assume that even advanced devs will remember to encode everything. Where a value is stuck into a field that is likely to be displayed without encoding, a warning should show in the debugger.

With J2EE, the java compilation step should issue a warning when the old style <%= … %> is used un-nested. <%= … %> is required to put values into messages and bean:write to do useful work. But if it’s just on its lonesome, that’s XSS right there.

Tomorrow: Injections…

Comments

7 responses to “The usual suspects and what to do about them”

  1. Sam Avatar

    Using JSTL or JSF, proper encoding may be the default, but in JSTL that’s only if you use consistently. Considering that it’s far easier to just use straight EL (${person.name} instead of ), doing the right thing does take a bit of extra work, enough to make developers grumble. And the EL-only alternative, ${fn:escapeXml(person.name)} is just no fun at all. So it isn’t as much a default as we’d hope. I still regularly face resistance from coworkers to using the longer forms, even from experienced developers and contractors who I expect to know better.

    Maybe this is nitpicking, because I still think your basic premise is correct.

    I like the idea of issuing warnings when scriptlets are used. You can even disable it entirely with . I’d like to do the same for bare EL — or better yet, make encoding on bare EL the default.

  2. Sam Avatar

    Dang. I was hoping WordPress would just encode the pointy brackets. What’s missing from the above is “${person.name} instead of [c:out]”. And “disable it entirely with [scripting-invalid].”

  3. vanderaj Avatar

    Sam,

    It’s ironic that on a post about XSS and how hard it is to be right whilst still allowing safe output encoding that even a mature app like WordPress 2.1 still has problems encoding user output in a recognizable and safe way.

    Andrew

  4. Dagfinn Reiersøl Avatar

    How about pushing to make the major PHP template engines XSS safe by default? Some of them are, but Smarty, in particular, isn’t. Maybe it’s not a “real solution” but it would help. Get it on people’s radar screens. Recommend using a “safe” template engine.

  5. Stephen dv Avatar
    Stephen dv

    Hi Andrew,

    The <%= order.comment %> format used by default in Ruby on Rails is also vulnerable to XSS attack. To encode it, there is a convenience form:
    <%= h(order.comment) %>.

    Could you explain a bit more about what you mean by “strong functions”?

    Stephen

  6. vanderaj Avatar

    Stephen,

    The Microsoft AntiXSS libraries encode pretty much everything BUT approximately A-Z, a-z, 0-9 and space. I consider this strong encoding.

    I must admit not having much experience with RoR, and thus I didn’t consider it when writing this entry.

    Andrew

  7. dre Avatar

    For Java, consider this for strong input validation:
    http://jakarta.apache.org/commons/validator/

    Also – I assess J2EE environments a lot and usually have more (specifically XSS) findings than what you give credit for.

    And add that other guy’s HTML Purifier to your PHP strong functions http://www.greebo.net/?p=399

    Maybe add some other languages… but I really like your basic representation of the data. Put this up on OWASP!

Leave a Reply

Your email address will not be published. Required fields are marked *