Consult the XSS Prevention Cheat Sheet [REF-16] for more details on the types of encoding and escaping
that are needed.
Architecture and Design
For any security checks that are performed on the client side, ensure that these checks are duplicated on
the server side, in order to avoid CWE-602. Attackers can bypass the client-side checks by modifying values
after the checks have been performed, or by changing the client to remove the client-side checks entirely.
Then, these modified values would be submitted to the server.
Architecture and Design
If available, use structured mechanisms that automatically enforce the separation between data and code.
These mechanisms may be able to provide the relevant quoting, encoding, and validation automatically,
instead of relying on the developer to provide this capability at every point where output is generated.
Implementation
For every web page that is generated, use and specify a character encoding such as ISO-8859-1 or UTF-8.
When an encoding is not specified, the web browser may choose a different encoding by guessing which
encoding is actually being used by the web page. This can cause the web browser to treat certain sequences
as special, opening up the client to subtle XSS attacks. See CWE-116 for more mitigations related to
encoding/escaping.
Implementation
With Struts, you should write all data from form beans with the bean's filter attribute set to true.
Implementation
To help mitigate XSS attacks against the user's session cookie, set the session cookie to be HttpOnly. In
browsers that support the HttpOnly feature (such as more recent versions of Internet Explorer and Firefox),
this attribute can prevent the user's session cookie from being accessible to malicious client-side scripts
that use document.cookie. This is not a complete solution, since HttpOnly is not supported by all browsers.
More importantly, XMLHTTPRequest and other powerful browser technologies provide read access to HTTP
headers, including the Set-Cookie header in which the HttpOnly flag is set.
Effectiveness: Defense in Depth
Implementation
Assume all input is malicious. Use an "accept known good" input validation strategy, i.e., use a whitelist of
acceptable inputs that strictly conform to specifications. Reject any input that does not strictly conform to
specifications, or transform it into something that does. Do not rely exclusively on looking for malicious or
malformed inputs (i.e., do not rely on a blacklist). However, blacklists can be useful for detecting potential
attacks or determining which inputs are so malformed that they should be rejected outright.
When performing input validation, consider all potentially relevant properties, including length, type of
input, the full range of acceptable values, missing or extra inputs, syntax, consistency across related fields,
and conformance to business rules. As an example of business rule logic, "boat" may be syntactically valid
because it only contains alphanumeric characters, but it is not valid if you are expecting colors such as "red"
or "blue."
When dynamically constructing web pages, use stringent whitelists that limit the character set based on the
expected value of the parameter in the request. All input should be validated and cleansed, not just
parameters that the user is supposed to specify, but all data in the request, including hidden fields, cookies,
headers, the URL itself, and so forth. A common mistake that leads to continuing XSS vulnerabilities is to
validate only fields that are expected to be redisplayed by the site. It is common to see data from the
request that is reflected by the application server or the application that the development team did not
anticipate. Also, a field that is not currently reflected may be used by a future developer. Therefore,
validating ALL parts of the HTTP request is recommended.
Note that proper output encoding, escaping, and quoting is the most effective solution for preventing XSS,
although input validation may provide some defense-in-depth. This is because it effectively limits what will
appear in output. Input validation will not always prevent XSS, especially if you are required to support free-
form text fields that could contain arbitrary characters. For example, in a chat application, the heart
emoticon ("<3") would likely pass the validation step, since it is commonly used. However, it cannot be
directly inserted into the web page because it contains the "<" character, which would need to be escaped
or otherwise handled. In this case, stripping the "<" might reduce the risk of XSS, but it would produce
incorrect behavior because the emoticon would not be recorded. This might seem to be a minor
inconvenience, but it would be more important in a mathematical forum that wants to represent
inequalities.
Even if you make a mistake in your validation (such as forgetting one out of 100 input fields), appropriate
encoding is still likely to protect you from injection-based attacks. As long as it is not done in isolation, input
validation is still a useful technique, since it may significantly reduce your attack surface, allow you to
detect some attacks, and provide other security benefits that proper encoding does not address.