There are two types of XSS flaws:
Each of reflected and stored XSS can occur on the server or on the client (which is also known as DOM based XSS), depending on when the malicious data gets injected in HTML markup.
Input validation and sanitization: Input validation and data sanitization are the first line of defense against untrusted data. Apply white list validation wherever possible.
Output encoding for correct context: When a browser is rendering HTML and any other associated content like CSS, javascript etc., it follows different rendering rules for each context. Hence Context-sensitive output encoding is absolutely critical for mitigating risk of XSS.
Here are the details about applying correct encoding in each context:Context | Code Sample | Encoding Type |
---|---|---|
HTML Entity | <span> UNTRUSTED DATA</span> | Convert & to &
Convert < to < Convert > to > Convert " to " Convert ' to ' Convert / to / |
HTML Attribute Encoding | <input type="text" name="fname" value=" UNTRUSTED DATA"> | Except for alphanumeric characters, escape all characters with the HTML Entity &#xHH;
format, including spaces. (HH = Hex Value)
|
URI Encoding | <a href="/site/search?value= UNTRUSTED DATA">clickme</a> | Except for alphanumeric characters, escape all characters with ASCII values less
than 256 with the HTML Entity &#xHH; format, including spaces. (HH = Hex Value)
|
JavaScript Encoding | <script>var currentValue='
UNTRUSTED DATA';</script>
<script>someFunction(' UNTRUSTED DATA');</script> |
Ensure JavaScript variables are quoted. Except for alphanumeric characters, escape all characters with ASCII values less than 256 with \uXXXX unicode escaping format (X = Integer), or in xHH (HH = HEX Value) encoding format. |
CSS Encoding | <div style="width: UNTRUSTED DATA;">Selection</div> | Except for alphanumeric characters, escape all characters with ASCII values less than 256 with the \HH (HH= Hex Value) escaping format. |
HTTPOnly cookie flag: Preventing all XSS flaws in an application is hard. To help mitigate the impact of an XSS flaw on your site, set the HTTPOnly flag on session cookie and any custom cookies that are not required to be accessed by JavaScript.
Implement Content Security Policy (CSP): CSP is a browser side mechanism which allows creating whitelists for client side resources used by the web application, e.g. JavaScript, CSS, images, etc. CSP via special HTTP header instructs the browser to only execute or render resources from those sources. For example, the CSP header below allows content only from example site's own domain (mydomain.com) and all its sub domains.
Content-Security-Policy: default-src 'self' *.mydomain.com
Source: XSS Prevention Cheat Sheet[1]
The demo web application is vulnerable to stored XSS attack on profiles form. On form submit, the first and last name field values are submitted to the server, and without any validation get saved in database. The values are then sent back to the browser without proper escaping to be shown at the top right menu.
Two measures can be taken to mitigate XSS risk:
server.js
, enable the HTML Encoding using template engine's auto escape flag.
swig.init({ root: __dirname + "/app/views", autoescape: true //default value });
// Enable session management using express middleware app.use(express.session({ secret: "s3Cur3", cookie: { httpOnly: true, secure: true } }));
An important observation when handling output encoding to prevent XSS is the notion of context.
When output encoding is performed, it must match the context in which it is being injected to. For example, if a user input is being injected to an HTML element then it will require different encoding semantics to escape malicious input than if it were injected to say an HTML attribute or a JavaScript context altogether (such as in a script tag).
An example for how to take advantage and exploit this mis-understanding exists on the profile page. See code references in
profile.js
and profile.html