XSS prevention cheat sheet
The best strategies for preventing Cross Site Scripting can be found in OWASP's
XSS prevention cheat sheet. Several important notes include:
- You MUST use the escape syntax for the part of the HTML document you're putting untrusted data into. There is no single escape function that can be applied for all output contexts (HTML, CSS, JavaScript). ESAPI has an API that provides encoding rules for a particular output context. Refer to the OWASP's prevention rules for more details.
- It is impossible to secure a JavaScript context with escaping. This is an important note because there is no defense to this scenario except to eliminate the output of dynamic content within your JavaScript context entirely.
XSS and JSTL
JSTL used appropriately will protect you from an XSS attack within your HTML context. For example, this a valid JSTL solution:
<%-- XSS safe --%>
<c:out value="${untrusted_data}" escapeXml="true" />
By default, the excapeXml attribute is "true" within the out tag so you don't have to explicitly declare it.
The JSTL expression language alone will
NOT protect you from an XSS attack. For example this is not safe and
MUST be avoided for all untrusted data:
<%-- Not XSS safe --%>
${untrusted_data}
XSS input validation
Validating input characters for malicious data should not be your only method of prevention. It is recommended to always escape untrusted data on the output side because you account for all data regardless of where the data originated from. Maybe the data was maliciously altered in the database or perhaps your third-party vendor sent harmful data outside HTTP. Input validation does not account for those scenarios and should not be used as your only defense. Output escaping with ESAPI or JSTL covers all bases regardless of where the data originated from. If you prefer to validate user input for XSS you may use regular expressions. A whitelist strategy of allowing positive characters is preferred. For example, the regular expression code below is a whitelist pattern that only allows certain characters as valid input:
public final class ValidationUtils {
/* Whitelist validation example. Only allow alphanumerics and special characters: -@&., */
public final static Pattern VALID_TEXT_FIELD_PATTERN = Pattern.compile("[A-Za-z0-9-@&\\.,\\s]*");
public static final boolean isValid(Pattern pattern, final String value) {
return pattern.matcher(value).matches();
}
}
XSS and JSON
If you are using JSON on the client-side make sure you also validate your JSON content for malicious data. Douglas Crockford, in his recent book
JavaScript: The Good Parts recommends using JSON.parse() for all untrusted content. JSON.parse() will throw an exception if the text contains anything dangerous.