Protecting Your Users Against DOM-Based XSS attacks

Cross-site scripting (XSS) is one of the most common ways hackers attack websites. XSS vulnerabilities permit a malicious user to execute arbitrary chunks of JavaScript when other users visit your site.

XSS is the most common publicly reported security vulnerability, and part of every hacker’s toolkit.

Risks

Prevalence Rare
Rating prevelance on a298cccc3e525887223509d0e6fe9a464d7d7f60574014de1fe402608154d354 Rating prevelance on a298cccc3e525887223509d0e6fe9a464d7d7f60574014de1fe402608154d354 Rating prevelance on a298cccc3e525887223509d0e6fe9a464d7d7f60574014de1fe402608154d354
Exploitability Easy
Rating exploitability on 6b817c6c589f0911378579408b6cbfc6d82345849ae2da559b8d11602b9a987b Rating exploitability on 6b817c6c589f0911378579408b6cbfc6d82345849ae2da559b8d11602b9a987b Rating exploitability on 6b817c6c589f0911378579408b6cbfc6d82345849ae2da559b8d11602b9a987b
Impact Harmful
Rating impact on 48bdb4077813afe9762f27e229e64207ec59c3891a54a3adf931c2c91a6d99bd Rating impact on 48bdb4077813afe9762f27e229e64207ec59c3891a54a3adf931c2c91a6d99bd Rating impact on 48bdb4077813afe9762f27e229e64207ec59c3891a54a3adf931c2c91a6d99bd

DOM-based XSS attacks have all the risks associated with the other types of XSS attack, with the added bonus that they are impossible to detect from the server side. Any page that uses URI fragments is potentially at risk from XSS attacks.

Protection

Protecting against DOM-based XSS attacks is a matter of checking that your JavaScript does not interpret URI fragments in an unsafe manner. There are a number of ways to ensure this.

Use a JavaScript Framework

Frameworks like Ember, AngularJS and React use templates that makes construction of ad-hoc HTML an explicit (and rare) action. This will push your development team towards best practices, and make unsafe operations easier to detect.

Audit Your Code Carefully

Sometimes a full JavaScript framework is too heavyweight for your site. In that case, you will need to regularly conduct code reviews to spot locations that reference window.location.hash. Consider coming up with agreed coding standards on how URI fragments are to be written and interpreted, and centralize this logic in a core library.

If you use JQuery, carefully check any code that uses the html(...) function. If you are constructing raw HTML on the client-side on the back of untrusted input, you may have a problem, whether the input comes from a URI fragment or not. Use the text(...) function whenever possible.

If you are using direct the native DOM APIs, avoid using the following properties and functions:

Instead, set text content within tags wherever possible:

Parse JSON Carefully

Do not evaluate JSON to convert it to native JavaScript objects - for example, by using the eval(...) function. Instead use JSON.parse(...).

Detect Unsafe Code Using Development Tools

Google has released a Chrome plug-in that can identify insecure practices commonly found in client-side code.

Don’t Use URI Fragments At All!

The most secure code is the code that isn’t there. If you don’t need to use URI fragments, then don’t! Write a unit test to scan your JavaScript for mentions of window.location.hash, and have it fail if the pattern is found. When there is a need to use URI fragments, then you can discuss how to ensure their safe use.

Implement a Content-Security Policy

Modern browsers support Content-Security Policies that allow the author of a web-page to control where JavaScript (and other resources) can be loaded and executed from. XSS attacks rely on the attacker being able to run malicious scripts on a user’s web page - either by injecting inline <script> tags somewhere within the <html> tag of a page, or by tricking the browser into loading the JavaScript from a malicious third-party domain.

By setting a content security policy in the response header, you can tell the browser to never execute inline JavaScript, and to lock down which domains can host JavaScript for a page:

Content-Security-Policy: script-src 'self' https://apis.google.com
By whitelisting the URIs from which scripts can be loaded, you are implicitly stating that inline JavaScript is not allowed.

The content security policy can also be set in a <meta> tag in the <head> element of the page:

<meta http-equiv="Content-Security-Policy" 
      content="script-src 'self' https://apis.google.com">

This approach will protect your users very effectively! However, it may take a considerable amount of discipline to make your site ready for such a header. Inline scripts tags are considered bad practice in modern web-development - mixing content and code makes web-applications difficult to maintain - but are common in older, legacy sites.

To migrate away from inline scripts incrementally, consider makings use of CSP Violation Reports. By adding a report-uri directive in your policy header, the browser will notify you of any policy violations, rather than preventing inline JavaScript from executing:

Content-Security-Policy-Report-Only: script-src 'self'; report-uri http://example.com/csr-reports

This will give you reassurance that there are no lingering inline scripts, before you ban them outright.

Further Reading

Is your website vulnerable to DOM-based XSS attacks?

Netsparker n 834848961a0bf6ec5556448ff47f421d0b1204a572877a59717064b1088e8c43 Check today. Scan your website for DOM-based XSS and other vulnerabilities with the