Weakness reference
CWE-117

Improper Output Neutralization for Logs

Log injection occurs when user-controlled data is written directly to application logs without sanitization, allowing an attacker to forge log entries or…

01Summary

Log injection occurs when user-controlled data is written directly to application logs without sanitization, allowing an attacker to forge log entries or inject malicious content. This weakness can lead to log tampering, obfuscation of attack evidence, false incident reports, and misinterpretation of security events by automated monitoring tools.

02How It Happens

Applications often log user actions, errors, and system events for auditing and debugging. When input from users, HTTP requests, or external sources is concatenated directly into log messages without neutralization, an attacker can inject special characters—particularly newlines—to create fake log entries that appear legitimate. Log viewers and automated parsers may then misinterpret these forged entries as genuine events, masking real attacks or triggering false alarms. The vulnerability is especially dangerous when logs are parsed by scripts or SIEM systems that rely on consistent formatting.

03Real-World Impact

An attacker exploiting log injection can hide their tracks by injecting entries that make malicious activity appear normal, or create false entries that frame legitimate users. Security teams relying on logs for incident detection may miss real breaches or waste resources investigating fabricated events. In compliance contexts, tampered logs can invalidate audit trails and create legal liability. Automated alerting systems may be tricked into suppressing genuine security warnings or triggering denial-of-service conditions through log flooding.

04Vulnerable & Fixed Patterns

Vulnerable pattern
import logging

logger = logging.getLogger(__name__)

def process_login(username, password):
    # User input logged directly without sanitization
    logger.info(f"Login attempt for user: {username}")
    
    if authenticate(username, password):
        logger.info(f"User {username} logged in successfully")
    else:
        logger.warning(f"Failed login for user: {username}")

Why it's vulnerable:
If username contains newline characters (e.g., admin\nLogged in successfully), the attacker can forge log entries that appear to show successful authentication when it actually failed.

Fixed pattern
import logging

logger = logging.getLogger(__name__)

def process_login(username, password):
    # Sanitize input by replacing newlines and other control characters
    safe_username = username.replace('\n', ' ').replace('\r', ' ')
    
    logger.info(f"Login attempt for user: {safe_username}")
    
    if authenticate(username, password):
        logger.info(f"User {safe_username} logged in successfully")
    else:
        logger.warning(f"Failed login for user: {safe_username}")
Vulnerable pattern
<?php
$username = $_POST['username'];
$ip = $_SERVER['REMOTE_ADDR'];

// User input written directly to log file
error_log("Login attempt from IP: $ip for user: $username");

if (authenticate($username, $password)) {
    error_log("User $username authenticated successfully");
} else {
    error_log("Authentication failed for user: $username");
}
?>

Why it's vulnerable:
An attacker can submit a username containing %0A (URL-encoded newline) or literal newlines to inject fake log entries that appear to show successful logins or other forged events.

Fixed pattern
<?php
$username = $_POST['username'];
$ip = $_SERVER['REMOTE_ADDR'];

// Sanitize by removing newlines and carriage returns
$safe_username = str_replace(["\n", "\r"], ' ', $username);
$safe_ip = str_replace(["\n", "\r"], ' ', $ip);

error_log("Login attempt from IP: $safe_ip for user: $safe_username");

if (authenticate($username, $password)) {
    error_log("User $safe_username authenticated successfully");
} else {
    error_log("Authentication failed for user: $safe_username");
}
?>

05Prevention Checklist

Sanitize all user input before logging:
Remove or replace newline (\n), carriage return (\r), and other control characters that could break log formatting.
Use structured logging:
Employ JSON or key-value logging formats that separate fields programmatically, making injection harder and parsing safer.
Validate log output format:
Ensure log entries conform to a strict, parseable schema; reject or sanitize entries that deviate.
Restrict log file permissions:
Limit write access to log files so only the application can modify them; prevent attackers from directly editing logs.
Monitor log integrity:
Use log aggregation and SIEM tools that detect anomalies in log structure or unexpected entry patterns.
Avoid logging sensitive data:
Never log passwords, tokens, or PII; this reduces both injection risk and the impact of log tampering.

06Signs You May Already Be Affected

Review your application logs for entries with unusual formatting, unexpected newlines within a single log line, or entries that appear out of sequence with surrounding events. Check for log entries that claim successful authentication or administrative actions you did not perform, or entries with timestamps that don't match the surrounding context. If your logs are parsed by automated tools, look for alerts that seem inconsistent with actual user behavior or system state.

07Related Recent Vulnerabilities