Skip to main content

Log injection

Need

Implementation of proper input validation, sanitization, and escaping for system logs

Context

  • Usage of Scala for building scalable and high-performance applications
  • Usage of play.api.Logger for logging in a Play Framework application

Description

Non compliant code

import play.api.Logger

def logUserActivity(user: User, activity: String): Unit = {
val logMessage = s"User ${user.name} performed activity: $activity"
Logger.info(logMessage)
}

In the above Scala code, we have a function logUserActivity which logs a message about a user's activity. The function takes two parameters: user and activity. The user parameter is an instance of a User class, and activity is a string that describes what the user did.

The problem lies in the logMessage line. Here, the code directly includes the activity string in the log message without any sanitization or validation. If an attacker has control over the activity string, they could inject malicious content into the system logs.

For example, an attacker could use control characters or special sequences recognized by the log viewer to obfuscate the logs or to insert false entries. This is known as log injection, and it can lead to a variety of security issues, including information disclosure, data tampering, and denial of service.

Steps

  • Validate and sanitize user input before logging it
  • Use parameterized logging to prevent log injection
  • Implement proper logging configuration and filtering

Compliant code

import play.api.Logger
import org.owasp.encoder.Encode

def logUserActivity(user: User, activity: String): Unit = {
val sanitizedUserName = Encode.forJava(user.name)
val sanitizedActivity = Encode.forJava(activity)
val logMessage = s"User $sanitizedUserName performed activity: $sanitizedActivity"
Logger.info(logMessage)
}

The original code was vulnerable to log injection attacks because it directly used user input in log entries without any validation or sanitization. This could allow an attacker to inject malicious content into the logs, which could lead to various security issues such as data leakage, denial of service, or even remote code execution.

The fixed code mitigates this vulnerability by sanitizing the user input before using it in the log entries. This is done using the Encode.forJava method from the OWASP Java Encoder library, which is designed to prevent various types of injection attacks, including log injection. This method encodes special characters in the input string that could be used to perform an injection attack.

In addition to sanitizing the input, the fixed code also uses parameterized logging. This is a good practice that can further help to prevent log injection attacks. In parameterized logging, the log message is a format string, and the user input is passed as separate arguments that are inserted into the format string. This ensures that the user input is always treated as data, not as part of the log message format.

Finally, it's important to note that proper logging configuration and filtering should also be implemented as part of the overall logging strategy. This can help to prevent sensitive information from being logged, and can also help to detect and respond to potential security incidents.

References