Skip to main content

Stored cross-site scripting (XSS)

Need

Prevention of persistent cross-site scripting (XSS) attacks

Context

  • Usage of Java 8 for developing applications with enhanced features and performance
  • Usage of javax.servlet-api for developing Java servlets

Description

Non compliant code

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;

public class VulnerableServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String userComment = request.getParameter("comment");
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html><body>");
out.println("<h1>User Comment</h1>");
out.println("<p>" + userComment + "</p>"); // vulnerable line
out.println("</body></html>");
}
}

The above servlet is vulnerable to Stored Cross-Site Scripting (XSS) attacks. This vulnerability arises from the fact that the servlet takes user input from the "comment" parameter and directly includes it in the HTML response without any sanitization or encoding.

In the doPost method, the request.getParameter("comment") is used to get the user input from the request. This user input is directly injected into the HTML response using out.println("<p>" + userComment + "</p>"). This line of code is vulnerable because it does not sanitize or encode the user input before including it in the HTML response.

An attacker could exploit this vulnerability by sending a POST request with JavaScript code in the "comment" parameter. This JavaScript code would then be stored on the server and included in the HTML response whenever this page is viewed. This could allow the attacker to steal sensitive information, such as session cookies, or perform actions on behalf of the user without their consent.

Steps

  • Sanitize user input: Before displaying any user input on the web page, make sure to sanitize it to remove any potentially malicious code. This can be done by using a library or framework that provides input validation and sanitization functions.
  • Use output encoding: When displaying user input on the web page, make sure to properly encode it to prevent any interpreted characters from being executed as code. This can be done by using output encoding functions provided by the programming language or framework.
  • Implement Content Security Policy (CSP): CSP is a security mechanism that allows you to specify which sources of content are allowed to be loaded on a web page. By implementing CSP, you can restrict the execution of any injected scripts.
  • Use a web application firewall (WAF): Implementing a WAF can help detect and block malicious requests, including those attempting to exploit XSS vulnerabilities.
  • Regularly update and patch dependencies: Keep all libraries, frameworks, and components used in the application up to date to ensure any known vulnerabilities are patched.
  • Educate developers: Provide training and awareness programs to developers to ensure they understand the risks and best practices for preventing XSS vulnerabilities.

Compliant code

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import org.owasp.encoder.Encode;

public class FixedServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String userComment = request.getParameter("comment");
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html><body>");
out.println("<h1>User Comment</h1>");
String safeUserComment = Encode.forHtml(userComment);
out.println("<p>" + safeUserComment + "</p>"); // fixed line
out.println("</body></html>");
}
}

The above code fixes the Stored Cross-Site Scripting (XSS) vulnerability by sanitizing the user input before it is displayed on the web page.

The user's comment is retrieved from the request parameter as before, but now it is passed through the Encode.forHtml() method from the OWASP Java Encoder library. This method encodes special characters that have significance in HTML to their corresponding HTML entities, effectively preventing them from being interpreted as code.

For example, the less-than character &lt; would be encoded as &lt;, the greater-than character > would be encoded as &gt;, and so on. This way, even if the user's comment contains potentially malicious JavaScript code, it will be displayed as plain text on the web page, rather than being executed as code.

This fix assumes that the OWASP Java Encoder library is available in the classpath. If it's not, it can be added as a dependency in the project's build file. For Maven, the dependency would look like this:

&lt;dependency>
&lt;groupId>org.owasp.encoder&lt;/groupId>
&lt;artifactId>encoder&lt;/artifactId>
&lt;version>1.2.2&lt;/version>
&lt;/dependency>

Please note that this fix only addresses the specific XSS vulnerability in the provided code snippet. To fully protect the application from XSS and other web vulnerabilities, it's recommended to follow all the steps mentioned earlier, including implementing a Content Security Policy (CSP), using a web application firewall (WAF), regularly updating and patching dependencies, and educating developers about secure coding practices.

References