XSS Prevention Guide For Campaign

Introduction

This document serves as a guidance for Campaignusers who build Page templates and explains how to avoid Cross Site Scripting (XSS) vulnerabilities which could be hiding in your Page templates if not taking care off.

Following the rules as set by this document should enable you to build Page templates without XSS vulnerabilities.

Note that if you violate these rules then you're building something that might be vulnerable to Cross Site Scripting (XSS).

JSREPLACE function is DEPRECATED

The JSREPLACE function is insecure and shouldn’t be used any longer.

It is advised to update existing content and migrate to the new functions following this guide.

There are 4 new functions available that must be used as explained is this guide.

All NEW templates should use the new functions. The deprecated JSREPLACE functions should no longer be used for any new templates.

The functions are:

  • HTML_ENCODE (see Rule 1)
  • HTML_ATTR_ENCODE (see Rule 2)
  • JS_ENCODE (see Rule 3)
  • CSS_ENCODE (see Rule 4)

When to use these encoding functions?

The encoding functions must be used when content is dynamically added to the template.

How to use the encoding functions

The functions are intended to be used on content templates that support javascript, for example Page templates.

They must not be used in any other context (such as SQL constraints)

 

RULE 0 - NEVER Insert Data, Except in Allowed Locations

The first rule is to deny all - don’t put data into your HTML document unless it is within one of the slots defined in Rule 1 through Rule 4. (see below)

The reason for Rule 0 is that there are so many strange contexts within HTML that the list of escaping rules gets very complicated.

This includes “nested contexts” like a URL inside a javascript – the encoding rules for those locations are tricky and dangerous.

Never directly in a script

<script>...NEVER PUT DATA HERE...</script>

Never inside an HTML comment

<!--...NEVER PUT DATA HERE...-->

Never in an attribute name

<div ...NEVER PUT DATA HERE...=test />

Never in a tag name

<NEVER PUT DATA HERE... href="/test" />

Never directly in CSS

<style>

...NEVER PUT DATA HERE...

</style>

Never accept actual JavaScript code

Most importantly, never accept actual JavaScript code from an untrusted source and then run it.

For example, a parameter named “callback” that contains a JavaScript code snippet.
No amount of escaping can fix that.

 

RULE 1 - HTML Escape Before Inserting Data into HTML Element Content

This rule is for when you want to put data directly into the HTML body somewhere. This includes inside normal HTML tags like div, p, b, td, etc...

Use the HTML_ENCODE() function in this context.

Copy
Examples :
<body>~(HTML_ENCODE('DATA HERE...'))~</body>
<div>~(HTML_ENCODE('DATA HERE...'))~</div>

 

RULE 2 - Attribute Escape Before Inserting Data into HTML Common Attributes

This rule is ONLY for putting data into typical attribute values like width, name, value, etc...

Use the HTML_ATTR_ENCODE() function in this context.

EXCEPTION: use RULE 3 if you are inserting data into event handler attributes (eg. onmousemove, onclick, etc...)

Never insert data into attributes with a different context

  • href
  • src
  • style
Copy
Inside Unquoted attribute
<div attr=~(HTML_ATTR_ENCODE('DATA HERE...'))~>content
Copy
Inside single quoted attribute
<div attr='~(HTML_ATTR_ENCODE('DATA HERE...'))~'>content
Copy
Inside double quoted attribute
<div attr="~(HTML_ATTR_ENCODE('DATA HERE...'))~">content

ATTENTION - DO NOT USE IN THESE CASES
This must not be used for complex attributes like href, src, style, or any of the event handlers like 'onmouseover', 'onclick', etc...
It is extremely important that event handler attributes follow Rule 3 for HTML JavaScript Data Values

 

RULE 3 - JavaScript Escape Before Inserting Data into JavaScript Data Values

This rule concerns dynamically generated JavaScript code - both script blocks and event-handler attributes.

Use the JS_ENCODE() function in this context.

The only safe place to put data into this code is inside a quoted “data value”.

Including data inside any other JavaScript context is dangerous.

Copy
Inside a quoted string
<script> alert('~(JS_ENCODE('DATA HERE...'))~') </script>
Copy
One side of a quoted expression
<script> x = '~(JS_ENCODE('DATA HERE...'))~' </script>
Copy
Inside quoted event handler
<div onmouseover="x = '~(JS_ENCODE('DATA HERE...'))~'"</div>

Be aware, there are some JavaScript functions that can never safely use data as input - EVEN IF JAVASCRIPT ESCAPED

Copy

For example DON'T do this:

<script>
    window.setInterval('!!...EVEN IF YOU ESCAPE DATA YOU ARE XSSED HERE...!!');
</script>

 

RULE 4 - CSS Escape And Strictly Validate Before Inserting Data into HTML Style Property Values

ONLY do this if you really have no other choice.

This rule is for when you want to put data into a stylesheet or a style tag.

Use the CSS_ENCODE() function in this context. CSS is surprisingly powerful and can be used for numerous attacks. Therefore, it’s important that you only use data in a property value and not into other places in style data.

Copy

Examples of allowed cases

<style>
selector { property : ~(CSS_ENCODE('DATA HERE...'))~; }
</style>

<style>
selector { property : "~(CSS_ENCODE('DATA HERE...'))~"; }
</style>

<span style="property : ~(CSS_ENCODE('DATA HERE...'))~">text</span>

Note: You must stay away from putting data into complex properties like url, behavior, and custom (-moz-binding).
You must not put data into IE’s expression property value which allows JavaScript

WARNING!
There are some CSS contexts that can never safely use data as input - EVEN IF PROPERLY CSS ESCAPED. You will have to ensure that URLs only start with http(s), not javascript, and that properties never start with “expression”.
For example:
{ background-url : "javascript:alert(1)"; } // and all other URLs
{ text-size: "expression(alert('XSS'))"; } // only in IE