CSV injection - Java

CSV injection - Java

Need

Prevention of CSV injection attacks

Context

  • Usage of Java 8 for developing applications with enhanced features and performance
  • Usage of javax.servlet-api for developing Java web applications using Servlet technology

Description

Non compliant code

        import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class CSVServlet extends HttpServlet {

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String data = request.getParameter("data");
        response.setContentType("text/csv");
        response.setHeader("Content-Disposition", "attachment; filename=\\"data.csv\\"");
        response.getWriter().write(data);
    }
}
        
        

In this code, we have a Servlet that accepts POST requests and writes the received data directly into a CSV file that is sent back to the client as an attachment. The Servlet gets the data from the request parameter named "data" and writes it into the CSV file without any sanitization or validation.

This code is vulnerable to CSV injection because an attacker can send a POST request with malicious data, such as Excel formulas. When the exported CSV file is opened in Excel, these formulas will be executed, leading to potential security issues.

For example, an attacker could inject a formula like =1+1 into the "data" field. When the CSV file is opened in Excel, the formula will be executed and the cell will display the result of the operation, in this case 2.

More dangerously, an attacker could inject a formula that calls a system function or accesses external resources, leading to potential data leakage, system compromise, or other security issues.

The vulnerability lies in the line:

                String data = request.getParameter("data");

            


The data is fetched from the request parameter without any sanitization or validation, and directly written into the CSV file. This allows an attacker to inject arbitrary data, including malicious formulas, into the CSV file.

Steps

  • Validate and sanitize user input: Before using the 'data' parameter, validate and sanitize it to ensure it does not contain any malicious content.
  • Escape special characters: When writing the 'data' parameter to the CSV file, escape any special characters that could be interpreted as formulas by Excel.
  • Use a CSV library: Instead of manually writing the 'data' parameter to the CSV file, use a CSV library that handles the formatting and escaping of data automatically.
  • Set the content type correctly: Ensure that the 'Content-Type' header is set to 'text/csv' to indicate that the response is a CSV file.
  • Set the content disposition correctly: Set the 'Content-Disposition' header to specify the filename and attachment disposition of the CSV file.

Compliant code

        import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.text.StringEscapeUtils;

public class CSVServlet extends HttpServlet {

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String data = request.getParameter("data");
        // Validate and sanitize the data
        if (data != null && !data.isEmpty()) {
            // Escape special characters
            data = StringEscapeUtils.escapeCsv(data);
        }
        response.setContentType("text/csv");
        response.setHeader("Content-Disposition", "attachment; filename=\\"data.csv\\"");
        response.getWriter().write(data);
    }
}
        
        

The above code fixes the CSV Injection vulnerability by validating, sanitizing, and escaping special characters in the user input.

1. Validate and sanitize user input: The code checks if the 'data' parameter is not null and not empty. This is a basic validation to ensure that the 'data' parameter contains some value.

2. Escape special characters: The code uses the StringEscapeUtils.escapeCsv(data) method from the Apache Commons Text library to escape any special characters in the 'data' parameter that could be interpreted as formulas by Excel. This method escapes the characters by adding a single quote (') before them.

3. Use a CSV library: The Apache Commons Text library is used to handle the escaping of data. This library provides utilities for manipulating and interpreting text, including a method for escaping CSV data.

4. Set the content type correctly: The 'Content-Type' header is set to 'text/csv' to indicate that the response is a CSV file.

5. Set the content disposition correctly: The 'Content-Disposition' header is set to specify the filename and attachment disposition of the CSV file. This ensures that the file is downloaded with the correct name and format.

References