Simplifying Cross Site Scripting / HTML Injection – Tales from the Crypto

Simplifying Cross Site Scripting / HTML Injection

Some simple statements about Cross Site Scripting / XSS / HTML Injection (all terms for the same thing):

  • Ignore the term “Cross Site Scripting” as a confusing anachronism. Think “HTML Injection” whenever you hear “Cross Site Scripting”, and you won’t go wrong.
  • The problem of XSS can be summed up quite simply as:
    • XSS allows an outsider to re-write your vulnerable web page(s) before your end users see them.
      • That means any part of the web page can be re-written to do anything your web page could do to the end user
      • That means any attack on your users will be trusted as much as your users trust you
      • That means your users’ credentials, session cookies and other secret information is controlled by an attacker
    • XSS is hard to detect, and in some cases impossible for you, the server owner, to detect an attack on your users.
    • XSS is easy to prevent, but requires your developers to be aware of, and work to prevent, the problem.
    • The presence of XSS vulnerabilities may void your compliance with regulatory standards such as PCI, SOX, etc.
      • Allowing outsiders to rewrite your web page may mean that you cannot state that you adequately control access to the collection of financially significant data.
      • PCI requires you develop applications with regard to a recognised standard framework, and specifically points to OWASP. OWASP lists XSS and Injection flaws as two of the “top ten” vulnerabilities to prevent. This is as close as PCI gets to outright stating that XSS prevents compliance from being achievable.
  • All XSS attacks have four components:
    • The Injection
      • Where the attacker provides bad data, either directly to the user, or through a ‘store and replay’ mechanism.
    • The Escape (from “text” / “data” to “code”)
      • The escape is optional – but that option is under the control of the page’s author
      • If the page author requires an escape, the attacker cannot attack without correctly escaping
    • The Attack
      • The attack is mandatory – an XSS attack requires an attack component. Duh.
      • However – where an escape is required by the web page, the attack must follow the escape.
      • There are numerous possible attacks – and more being developed daily. You cannot list all possible attack patterns.
    • The Cleanup
      • The cleanup is optional, at the choice of the attacker, and hides from the user the fact that they have been exploited
      • Many attacks are fast enough to use your users’ credentials that the cleanup is not required. By the time the user notices (often only a second or so), the attacker has stolen the account, made purchases or read off credit card information.
  • Given this component approach, you as a web page author have limited options:
    • You can’t block the cleanup, because it’s too late at that point – the attack has occurred, and besides, the attacker may not be interested in the cleanup. The cleanup is really only useful in demonstrating that subtle attacks can take place, giving attackers months to clean out a credit card.
    • Blocking the attack is a leaky measure – not that it isn’t worth doing in some cases. For instance, browser protections against XSS often block the attack measure because they don’t control the web site, and can’t reasonably block anything else.
    • Blocking the escape is a guaranteed measure. If attacker-supplied code cannot be viewed by the browser as code, there is no possibility of attack.
    • Blocking the injection is also a guaranteed measure, with two caveats – when you block an injection, you have to make sure that the injection hasn’t already occurred, and that it cannot occur from any other sources.
      • This means that if you block injection of code into, say, a database of message forum posts,you have to scan the existing posts to ensure that the injection hasn’t already taken place.
        • Clean your database when you recognise an injection or attack pattern.
      • Any time there is a database that accumulates information for later display, there will be more than one source vying to put data into the database. If injection is possible in one source, injection is likely from other sources, too.
        • Funnel all sources through one injection filter.
      • Preventing an escape from text into code works whether or not all the injections are blocked.
        • Never rely on injection prevention alone.
  • No matter how innovative attackers get, Cross Site Scripting attacks need not occur.
    • Learn how browsers differentiate between text and code.
    • Use that knowledge to ensure that text remains text, and is never seen as code.
    • Let the browser and your web server platform and libraries help you
      • Use an appropriate document object model function to set text values on fields.
      • Instead of composing HTML in a string to include user supplied text, use a <span> or a <div>, and set its innerText property.
    • Don’t sacrifice safety for speed.
      • Don’t build HTML “on the fly”, either while generating the page or displaying it.
        • InnerHTML is a bad thing to set.
    • Don’t try to “test out” XSS vulnerabilities.
      • You (or your testers) are not Ash Ketchum, and therefore cannot “catch ‘em all”.
    • Develop XSS vulnerabilities out of your application
      • Anything you didn’t specifically write as code, is attacker-supplied untrustworthy data.
      • Prevent injections as much as possible by validating that input is correctly formed.
        • Note that you can’t completely validate all input in all cases.
        • The obvious “bad example” is that of a bug reporting system into which security vulnerability reports are placed. If I have to report an issue with an XSS flaw, I’m going to be deliberately and respectfully pasting XSS attack code into your application. So in that case, you cannot possibly validate my information and remove “invalid” code without removing the valuable part of the text!
        • Validation at the Client is for Convenience only – it allows you to quickly say “that’s not right” and have the user correct it.
        • Only validation at the Server is for Security. Anything you ask the client browser to do on your behalf may be ignored.
      • If you have limited resources, focus on preventing the ability to escape from text into code.
        • Do this by encoding output so that each level of processing can accurately and uniformly distinguish between code and data.
          • This means you must know what each level of processing uses as encoding or escaping of character sequences.
          • This also means you must know how many layers of processing there are between you and the user.
  • If you do ONE THING to prevent XSS on your site, output encoding is the one thing to do.
    • Defence in depth says “never do just one thing”. One thing will one day fail to be implemented properly.

Leave a Reply

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