Skip to main content

Reflected cross-site scripting (XSS)

Need

Implementation of input validation and output encoding to prevent the execution of malicious scripts

Context

  • Usage of Java for building scalable and robust applications
  • Usage of javax.servlet for building Java web applications with servlets
  • Usage of java.io for input and output operations in Java programming

Description

Non compliant code

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

public class VulnerableServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String user = request.getParameter("user");
out.println("<h1>Hello, " + user + "</h1>");
}
}

The above code represents a servlet that processes a GET request and responds with a greeting message that includes the user's name. The user's name is obtained from the request parameters, specifically the "user" parameter.

The vulnerability lies in the line where the user's name is directly appended to the HTML content that is sent back to the client:

out.println("<h1>Hello, " + user + "</h1>");

This line is vulnerable to Reflected Cross-Site Scripting (XSS) attacks. If an attacker can control the "user" parameter, they can inject malicious scripts that will be executed in the context of the victim's browser.

For example, an attacker might send a link to the victim that looks like this:

http://yourwebsite.com/VulnerableServlet?user=<script>malicious_code_here</script>

When the victim clicks on this link, the malicious script will be executed in their browser. This could lead to a variety of harmful effects, such as stealing the victim's session cookies or performing actions on their behalf.

Steps

  • Validate and sanitize user input
  • Encode user input before displaying it in the web content
  • Implement a Content Security Policy (CSP)
  • Use a web application firewall (WAF)
  • Implement input validation and output encoding as part of secure coding practices

Compliant code

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

public class SecureServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String user = request.getParameter("user");
String safeUser = Encode.forHtml(user);
out.println("<h1>Hello, " + safeUser + "</h1>");
}
}

The above code fixes the Reflected Cross-Site Scripting (XSS) vulnerability in the original servlet. The vulnerability was due to the fact that the servlet was directly using user input in the generation of HTML content without any validation or sanitization. This could allow an attacker to inject malicious scripts into the web page, which would then be executed in the context of the victim's browser.

The fix involves using the OWASP Java Encoder library to encode the user input before it is used in the HTML content. The Encode.forHtml(user) method will encode special characters that have significance in HTML (such as &lt;, >, &, #, and =) into their corresponding HTML entities. This means that if an attacker tries to inject a script, the script tags and other special characters will be treated as literal text and not as part of the HTML markup.

This fix also includes setting the content type of the response to "text/html", which tells the browser to interpret the response as HTML. This is a good practice to follow, as it helps to prevent certain types of content sniffing attacks.

In addition to this code-level fix, it is recommended to implement a Content Security Policy (CSP) to restrict the sources from which scripts can be loaded, use a web application firewall (WAF) to block malicious requests, and follow secure coding practices such as input validation and output encoding.

References