Log injection - Java

Log injection - Java

Need

Secure logging mechanism

Context

  • Usage of Java for building cross-platform applications
  • Usage of javax.servlet for building Java web applications with Servlet technology
  • Usage of Apache Log4j for logging and debugging purposes

Description

Non compliant code

        import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import org.apache.log4j.Logger;

public class LogInjectionServlet extends HttpServlet {
    private Logger logger = Logger.getLogger(LogInjectionServlet.class);

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");

        if (username == null) {
            username = "";
        }

        logger.info("User login attempt: " + username);
    }
}
        
        

In the above code, we have a servlet LogInjectionServlet that handles POST requests. It fetches the username parameter from the incoming request and logs it using log4j Logger.

The vulnerability lies in the fact that the code directly uses the user input (i.e., username) in the log entry without any validation, sanitization, or escaping. If an attacker provides a malicious string as the username, it can manipulate the log entries, leading to a log injection attack.

For instance, an attacker can provide the username as admin\\n[ERROR] System shutdown, which would create a log entry as:

INFO
- User login attempt: admin [ERROR] System shutdown


This can mislead the system administrators or automated log monitoring systems into believing that a system shutdown error occurred.

Moreover, if the logs are used for auditing purposes, the attacker can manipulate the audit trail. If the logs are publicly accessible, it might lead to disclosure of sensitive information.

In summary, the code is vulnerable to log injection attack due to improper handling of user input while logging.

Steps

  • Validate and sanitize user input: Before logging any user input, ensure that it is properly validated and sanitized to prevent any malicious content from being logged.
  • Use parameterized logging: Instead of concatenating user input directly into log messages, use parameterized logging techniques provided by the logging framework. This helps to separate the user input from the log format and prevents log injection.
  • Implement output encoding: If the logged content needs to be displayed in a different context (e.g., in a web page), implement output encoding to prevent any potential injection attacks.
  • Configure logging framework: Configure the logging framework to filter out sensitive information and limit the amount of user input that is logged. This helps to minimize the impact of a potential log injection vulnerability.
  • Regularly review and monitor logs: Regularly review and monitor the logs to identify any suspicious or unexpected log entries that may indicate a log injection attack.

Compliant code

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

public class LogInjectionServlet extends HttpServlet {
    private Logger logger = Logger.getLogger(LogInjectionServlet.class);

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");

        if (username == null) {
            username = "";
        } else {
            // Sanitize the user input
            username = Encode.forJava(username);
        }

        // Use parameterized logging
        logger.info("User login attempt: {}", username);
    }
}
        
        

The updated code includes the following changes to fix the log injection vulnerability:

1. Validate and sanitize user input: The user input (username) is sanitized using the OWASP Encoder library's Encode.forJava() method. This method encodes any special characters in the input string, which helps to prevent log injection attacks.

2. Use parameterized logging: Instead of concatenating the user input directly into the log message, the updated code uses parameterized logging. The {} placeholder in the log message is replaced with the sanitized user input by the logging framework. This separates the user input from the log format and prevents log injection.

Please note that this code does not include the implementation of output encoding, logging framework configuration, and log monitoring. These steps are typically implemented at the system or application level, rather than in individual code snippets.

For output encoding, you can use the appropriate encoding method from the OWASP Encoder library (e.g., Encode.forHtml(), Encode.forXml(), etc.) depending on the context in which the logged content will be displayed.

For logging framework configuration and log monitoring, refer to the documentation of your logging framework and monitoring tools for specific instructions.

References