9.7. XSS Countermeasures

9.7.1. Overview

It explains about Cross-site scripting (hereinafter abbreviated as XSS). Cross Site Scripting is injection of malicious scripts across trusted web sites by deliberately using security defects in the web application. For example, when data entered in Web Application (form input etc.) is output in HTML without appropriate escaping, the characters of tag existing in input value are interpreted as HTML as is. If a script with malicious value is run, attacks such as session hijack occur due to cookie tampering and fetching of cookie values.

9.7.1.1. Stored & Reflected XSS Attacks

XSS attacks are broadly classified into two categories.

Stored XSS Attacks

In Stored XSS Attacks, the malicious code is permanently stored on target servers (such as database). Upon requesting the stored information, the user retrieves the malicious script from the server and ends up running the same.

Reflected XSS Attacks

In Reflected attacks, the malicious code sent as a part of the request to the server is reflected back along with error messages, search results, or other different types of responses. When a user clicks the malicious link or submits a specially crafted form, the injected code returns a result reflecting an occurrence of attack on user’s browser. The browser ends up executing the malicious code because the value came from a trusted server.

Both Stored XSS Attacks and Reflected XSS Attacks can be prevented by escaping output value.

9.7.2. How to use

When the input from user is output as is, the system gets exposed to XSS vulnerability. Therefore, as a countermeasure against XSS vulnerability, it is necessary to escape the characters which have specific meaning in the HTML markup language.

Escaping should be divided into 3 types if needed.

Escaping types:

  • Output Escaping
  • JavaScript Escaping
  • Event handler Escaping

9.7.2.1. Output Escaping

Escaping HTML special characters is a fundamental countermeasure against XSS vulnerability. Example of special characters that require escaping in HTML and example after escaping these characters are as follows:

Before escaping
After escaping
&
&
<
&lt;
>
&gt;
"
&quot;
'
&#39;

To prevent XSS, f:h() should be used in all display items that are to be output as strings. An example of application where input value is to be re-output on different screen is given below.

9.7.2.1.1. Example of vulnerability when output values are not escaped

This example below is given only for reference; it should never be implemented.

Implementation of output screen

<!-- omitted -->
<tr>
    <td>Job</td>
    <td>${customerForm.job}</td>  <!-- (1) -->
</tr>
<!-- omitted -->
Sr. No. Description
(1)
Job, which is a customerForm field, is output without escaping.

Enter <script> tag in Job field on input screen.

input_html_tag

Picture - Input HTML Tag

It is recognized as <script> tag and dialog box is displayed.
no_escape_result

Picture - No Escape Result

9.7.2.1.2. Example of escaping output value using f:h() function

Implementation of output screen

<!-- omitted -->
<tr>
    <td>Job</td>
    <td>${f:h(customerForm.job)}</td>  <!-- (1) -->
</tr>
.<!-- omitted -->
Sr. No. Description
(1)
EL function f:h() is used for escaping.
Enter <script> tag in Job field on input screen.
input_html_tag

Picture - Input HTML Tag

By escaping special characters, input value is output as is without being recognized as <script> tag.
escape_result

Picture - Escape Result

Output result

<!-- omitted -->
<tr>
    <td>Job</td>
    <td>&lt;script&gt;alert(&quot;XSS Attack&quot;)&lt;/script&gt;</td>
</tr>
<!-- omitted -->

Tip

java.util.Date subclass format

It is recommended that you use <fmt:formatDate> of JSTL to format and display java.util.Date subclasses. See the example below.

<fmt:formatDate value="${form.date}" pattern="yyyyMMdd" />

If f:h() is used for setting the value of “value” attribute, it gets converted into String and javax.el.ELException is thrown; hence ${form.date} is used as is. However, it is safe from XSS attack since the value is in yyyyMMdd format.

Tip

String that can be parsed into java.lang.Number or subclass of java.lang.Number

It is recommended that you use <fmt:formatNumber> to format and display the string that can be parsed to java.lang.Number subclasses or java.lang.Number. See the example below.

<fmt:formatNumber value="${f:h(form.price)}" pattern="###,###" />

There is no problem even if the above is a String; hence when <fmt:formatNumber> tag is no longer used, f:h()is being used explicitly so that no one forgets to use f:h().

9.7.2.2. JavaScript Escaping

Escaping JavaScript special characters is a fundamental countermeasure against XSS vulnerability. Escaping is must if it is required to dynamically generate JavaScript based on the outside input.

Example of special characters that require escaping in JavaScript and example after escaping these characters are as follows:

Before escaping
After escaping
'
\'
"
\"
\
\\
/
\/
<
\x3c
>
\x3e
0x0D(Return)
\r
0x0A(Linefeed)
\n

9.7.2.2.1. Example of vulnerability when output values are not escaped

Example of occurrence of XSS problem is given below.

This example below is given only for reference; it should never be implemented.

<html>
  <script  type="text/javascript">
      var aaa = '${warnCode}';
      alert(aaa);
  </script>
</html>
Attribute name Value
warnCode
';alert('XSS Attack!');aaa='message

As shown in the above example, in order to dynamically generate JavaScript elements such as generating the code based on the user input, string literal gets terminated unintentionally leading to XSS vulnerability.

javascript_xss_screen_no_escape_result

Picture - No Escape Result

Output result

<script type="text/javascript">
    var aaa = '';alert('XSS Attack!');aaa='message';
    alert(aaa);
</script>

Tip

Dynamically generated JavaScript code depending on user input carries a risk of any script being inserted; hence an alternate way should be considered or it should be avoided as much as possible unless there is a specific business requirement.

9.7.2.2.2. Example of escaping output value using f:js() function

To prevent XSS, it is recommended that you use EL function f:js() for the value entered by user.

Usage example is shown below.

<script type="text/javascript">
    var aaa = '${f:js(warnCode)}';  // (1)
    alert(aaa);
</script>
Sr. No. Description
(1)
By using f:js() of EL function, the value is set as variable after escaping the value entered by user.
javascript_xss_screen_escape_result

Picture - Escape Result

Output result

<script  type="text/javascript">
    var aaa = '\';alert(\'XSS Attack!\');aaa=\'message';
    alert(aaa);
</script>

Warning

When the value including the script tag is output by escaping with f:js(), without using HTML escaping, and when document.write() is used,

XSS vulnerability occur because it outputs by making the browser interpret it as HTML source. An example is shown below, however such an implementation should never be performed.

JSP

<script  type="text/javascript">
   var aaa = '${f:js(warnCode)}';
   document.write(aaa);
</script>
Attribute name Value
warnCode
<script>alert('XSS Attack!');</script>

Output results

<script  type="text/javascript">
   var aaa = '\x3cscript\x3ealert(\'XSS Attack!\');\x3c\/script\x3e';
   document.write(aaa);
</script>

It can be seen that escaping is possible only by verifying output results only for source. However, since it is a code to store the character string of the contents <script>alert('XSS Attack!');</script> in variable aaa, if document.write(aaa); is implemented, <script>alert('XSS Attack!');</script> is output as HTML source. As a result, the script is executed.

When you want the browser to output the value, it is preferable to use f:h()to escape HTML special characters, without using JavaScript.

JSP

${f:h(warnCode)}

Output results

&lt;script&gt;alert(&#39;XSS Attack!&#39;);&lt;/script&gt;

If you venture to use f:js()and output by document.write(), additional XSS measures such as any of the following are required.

  • Provide a JavaScript function for HTML escaping and escape argument of document.write().
  • Escape for character string literal of JavaScript by f:js(), after performing HTML escape for the value for which user input value is set by f:h().

9.7.2.3. Event handler Escaping

To escape the value of event handler of javascript, f:hjs() should be used instead of f:h() or f:js(). It is equivalent to ${f:h(f:js())}.

This is because, when ');alert("XSS Attack");// ``\  is specified as event handler value such as \ ``<input type="submit" onclick="callback('xxxx');">, different script gets inserted, after escaping the value in character reference format, escaping in HTML needs to be done.

9.7.2.3.1. Example of vulnerability when output values are not escaped

Example of occurrence of XSS problem is given below.

<input type="text" onmouseover="alert('output is ${warnCode}') . ">
Attribute name Value
warnCode
'); alert('XSS Attack!'); //
When the above values are set, string literal is terminated unintentionally leading to XSS attack.

XSS dialog box is displayed on mouse over.

eventhandler_xss_screen_no_escape_result

Picture - No Escape Result

Output result

<!-- omitted -->
<input type="text" onmouseover="alert('output is'); alert('XSS Attack!'); // .') ">
<!-- omitted -->

9.7.2.3.2. Example of escaping output value using f:hjs() function

Example is shown below:

<input type="text" onmouseover="alert('output is ${f:hjs(warnCode)}') . ">  // (1)
Sr. No. Description
(1)
Value after escaping by EL function f:hjs() is set as an argument of javascript event handler.
XSS dialog is not output on mouse over.
eventhandler_xss_screen_escape_result

Picture - Escape Result

Output result

<!-- omitted -->
<input type="text" onmouseover="alert('output is \&#39;); alert(\&#39;XSS Attack!\&#39;);\&quot; \/\/ .') ">
<!-- omitted -->