Hacker News new | ask | show | jobs
by tshadwell 3736 days ago
Some notes:

1) Never blacklist. Seriously, unless you are in the business of writing and securing browser parsers, you are never going to catch everything. There are many vectors not listed on OWASP's XSS Filter Evasion Cheat Sheet. See https://www.w3.org/TR/html5/scripting-1.html#restrictions-fo... for an idea of what you're up against.

Because of the incredible number of ways you can cause security vulnerabilities through injection, in 2016 unless you're sending Content-Type text/plain always try and use secure templates. https://github.com/cure53/DOMPurify is nice, but there are likely good options for your language.

I say use secure templating because you need highly contextual encoding. As this article points out, escapes for HTML will not work in Javascript. Neither will they work for URLs. Single quotes are not escaped in most URLencoding schemes for example.

Many an application has been hacked due to a well-meaning engineer trying to prevent open redirect by only allowing urls with '/' at the front in links, not realising that '//x.com' also takes you out to x.com, or preventing '/' at all, not realising that '@x.com' will take you to x.com, or that '../../..' injection can cause requests to any endpoint on the same domain.

2) Javascript is not your only enemy, and it is not by any means your most fierce. You can use CSS to exfiltrate secret tokens: http://mksben.l0.cm/2015/10/css-based-attack-abusing-unicode...

Practically any injection can 'redress' your page so it appears drastically different from a user, which is potentially more powerful than just script injection. You can bypass same origin policy boundaries by coercing the user into making input into an invisible iframe if the stars is aligned.

3) Though this article talks about input validation a lot, it doesn't talk about actually how to do this defensively. You need to construct terse expressions that limit to input data you know can only be safe. Many an application has been hacked by specifiying /#[A-Fa-f]{3,6}|.*/ for hex colour codes.

Wherever you can, do not deal with raw DBMS language strings (SQL, Javascript) and string interpolation, that's a huge red flag. Instead use a driver / wrapper that provides injection safety and use prepared statements.

4) Unless you really want to invest time into learning web security and doing CTFs, don't try to write your own filters. For example, the suggestion that escaping "'" to "\'" can be bypassed simply by adding a "\" just before the open quote. "'" -> "\'", but "\'" -> "\\'", closing whatever single-quoted string you're in.

5) Serialization is not secure escaping in some contexts. For example, if your endpoint identifies as text/html, but instead returns JSON, I'm going to send some HTML in the JSON string and send a user to the endpoint directly to get XSS.

6) HTML is not your only enemy. XML documents can exfiltrate secrets through XXE and can be coerced into XSS with XHTML islands. Flash is a terrifying thing because it for the most part ignores Content-Types (see: https://miki.it/blog/2014/7/8/abusing-jsonp-with-rosetta-fla...). Requests that flash applications make are just as injectable as any other.

Unfortunately, though this article might cover a fair portion of encoding security, huge issues like effective and secure CSRF protection is not discussed. That's a story for another day. One day there will be a thorough and true guide to security in webapp development, but that is not this day.

3 comments

I say use secure templating because you need highly contextual encoding. As this article points out, escapes for HTML will not work in Javascript

I just wanted to reinforce this comment because I work in infosec (mostly web app security) and many of our clients make mistakes in this area. If you don't encode depending on context, you're going to have a bad time.

Most developers are aware of URL encoding and HTML encoding but then you also need to consider other encoding techniques for contexts such as JavaScript and CSS. As an example the single quote when:

URL encoded is %27

HTML encoded is '

JS encoded is \x27

CSS encoded is \000027

It gets way too difficult and cumbersome to manually write encoding code for all these different contexts and deal with the endless number of edge cases. Don’t go hunting for single quotes or angled brackets and then replace them what what you think it should be. Rather, you should rely on encoding libraries available in your framework. As an example, in .NET you can import the AntiXSS package and then you have a number of library functions such as CSSEncode(), HTMLEncode() and JavascriptEncode() at your disposal. Similar libraries exist for other major development frameworks.

To add as well: html attribute encoding vs html encoding as another context.
> Never blacklist.

http://www.ranum.com/security/computer_security/editorials/d...

"The Six Dumbest Ideas in Computer Security"

    #1) Default Permit
    ...
    #2) Enumerating Badness
    ..,
The unfortunately common assumption that security is about preventing badness has done an incredible amount of damage to security. We see it in everywhere. A huge amount of so-called "security" products (such as antivirus) are a futile exercise in trying to enumerate all of the bad things in the world.

The better approach is using proper recognizers built from explicit, formal grammars whenever possible. Meredith and Sergey's explained this problem very well in their talk[1] at 28c3. Define the grammar for valid inputs, use a parser generator to avoid bugs, and move on to the next problem instead of endlessly adding checks for bad input.

[1] https://media.ccc.de/v/28c3-4763-en-the_science_of_insecurit...

So, in other words..

    for bad_thing in life:
        delete(bad_thing)

    # program crashes