Understanding and Preventing Log Injection and Log Forging
AI generated
OWASP
0x00
Log Injection · Forensic Integrity
Preventing Log Injection and Log Forging
How a single line break in a user input can split one log entry into multiple, forged entries

Log injection, also called log forging, arises when an application writes user-controlled input into log files unfiltered, and an attacker deliberately injects control characters like line breaks (`\r\n`) to visually and structurally split a single, actually contiguous log entry into multiple, seemingly standalone entries. These forged additional entries can be crafted to look like legitimate, harmless system events, causing actual malicious activity to get buried in a flood of forged distraction entries, or deliberately misleading forensic analysis after a security incident.

15 min read Log Injection Forensic Integrity

1. The CRLF mechanism: how a line break splits a log entry

Most line-based log formats use a line break (carriage return + line feed, CRLF for short, or just line feed) as the separator between two consecutive log entries, so that a log analysis tool or a human viewer interprets every line as a standalone entry. If an application writes a user-controlled string that itself contains such a line-break character into a log message unfiltered, this embedded line break gets interpreted by the log format exactly the same way as a genuine line break between two separate entries, letting the attacker effectively inject an arbitrary, self-chosen additional log entry.

An attacker who, say, performs a failed login attempt with the username `admin\r\n[2026-08-07 03:00:00] INFO: Login successful for admin` can thereby inject a second, forged log entry that, on superficial inspection, looks like a completely legitimate, successful login, even though only a failed attempt actually occurred.

2. A typical vulnerable logging pattern

The following example shows a naive logging pattern that interpolates the user-submitted username directly, without any sanitization, into the log message, letting embedded control characters reach the log file unfiltered.


<?php
declare(strict_types=1);

// VULNERABLE: username is interpolated unfiltered into the log message
$this->logger->warning(
    sprintf('Failed login attempt for user: %s', $submittedUsername)
);

// Attacker input for $submittedUsername:
// "admin\r\n[2026-08-07 03:00:00] INFO: Login successful for admin"
// Result: two seemingly standalone log lines instead of one,
// the second one looks like a legitimate, successful login.

3. Consequences for forensics and incident response

The actual damage from log injection usually doesn't show up immediately, but only afterward, during a forensic investigation following a genuine security incident, when an analyst tries to reconstruct the timeline of an attack from the log files. Forged log entries can be deliberately used to suggest a false timeline, disguise real attacker activity as an apparently authorized action of a legitimate administrator account, or deliberately overload automated log analysis systems (SIEM rules) with a flood of plausible-looking but forged warnings so that genuine alerts get lost in the noise.

This delay between the actual exploitation of the vulnerability and its actual impact makes log injection especially tricky, since it usually stays unnoticed during normal application operation and only causes visible damage at the exact moment when reliable logs are needed most urgently. A forensic team relying on an already compromised log history after an incident risks not only a wrong assessment of the actual extent of damage, but potentially also flawed decisions about which systems count as compromised and which countermeasures are actually necessary.

4. Safe log output: consistently removing or masking control characters

The most direct fix is to explicitly sanitize every user-controlled value of line breaks and other control characters before writing it into a log message, either by completely removing these characters or by replacing them with a visible, harmless representation like `\\r\\n`, so an embedded line break can never be interpreted as a structural separator, but always remains visible as part of the original, single-line log entry.


<?php
declare(strict_types=1);

// SAFE: control characters are masked before logging
function safeForLog(string $value): string
{
    return str_replace(["\r", "\n", "\t"], ['\\r', '\\n', '\\t'], $value);
}

$this->logger->warning(
    sprintf('Failed login attempt for user: %s', safeForLog($submittedUsername))
);

5. Structured logging as a more robust, long-term fix

A structurally superior fix compared to manual character sanitization is structured logging in JSON format, where every log entry gets written as a standalone JSON object with clearly defined fields (timestamp, log level, message, context data), instead of as free-form running text. With correct JSON serialization, control characters like line breaks inside a JSON string automatically get encoded as a `\n` escape sequence, meaning an embedded line break can no longer structurally be interpreted as a line ending at all, regardless of whether the developer explicitly thought of it.

Symfony's Monolog integration supports structured JSON logging via the `JsonFormatter`, which automatically ensures correct, injection-safe serialization of all log context data, letting this structural protection be enabled for the entire application with comparatively little configuration effort, instead of having to manually secure every single logging call site in the code.

6. Log4Shell as an extreme case: when the logging library itself interprets input

The Log4Shell vulnerability (CVE-2021-44228), which became known in 2021 in the widely used Java logging library Log4j, showed an even more drastic escalation level of log injection: the library actively interpreted certain character sequences embedded in log messages (`${jndi:ldap://...}`) as commands and then loaded code from a remote, attacker-controlled server, turning a purely log-manipulation issue into full remote code execution, solely by logging a user-controlled string.

This lesson generalizes: any logging library that actively interprets or processes user-controlled log messages, instead of treating them as purely passive text, carries a structural risk that goes far beyond ordinary log injection, which is why it's worth explicitly checking, when choosing a logging library, whether it performs purely passive text output.

7. Protecting log-viewer dashboards from XSS via forged log content

If log entries get displayed in a web-based dashboard (say, Kibana, Grafana Loki, or a custom admin interface), an additional risk arises: if a user-controlled log value contains HTML or JavaScript code and it doesn't get correctly escaped when the dashboard renders, a seemingly harmless log injection can escalate into a genuine cross-site scripting vulnerability in the log viewer itself, which then executes against the security analysts viewing the log entry.

This combination of log injection and XSS makes clear that log data fundamentally needs to be treated as untrusted, potentially malicious input, even when later displayed in a dashboard, and not as already-safe, internal system text.

8. Additionally securing log integrity through tamper evidence

Beyond pure injection protection, especially security-critical applications benefit from an additional measure against later tampering with entire log files, say through append-only storage, where once-written log entries can no longer be technically altered or deleted, or through continuous cryptographic hashing, where every new log entry contains the hash of the previous entry, creating a chained, tamper-evident sequence similar to the basic principle of a blockchain.

These tamper-evidence measures protect against a different attack class than log injection, namely against subsequent manipulation of already-written logs by an attacker with write access to the log system itself, but they usefully complement the injection protections described in this article into an overall more robust, forensically more reliable logging system.

9. Protective measures at a glance

The table below compares the protective measures against log injection presented.

Measure Effect Effort
Mask control characters Prevents line injection directly at the source Low, but must be applied everywhere
Structured JSON logging Structurally safe, covers all cases Medium, one-time migration
Audit the logging library Prevents Log4Shell-style escalation Low, one-time check
Escape dashboard output Prevents XSS via log content Low to medium, depends on the dashboard

Mironsoft

Security audits, OWASP-compliant hardening, and secure architecture

Applications that actually hold up against a real attack attempt?

We review existing applications for classic OWASP vulnerabilities, insecure authentication, and missing input validation, then build an architecture that structurally reduces attack surface instead of just patching individual symptoms.

Security Audit

Systematically checking OWASP Top 10, auth flows, and input validation for vulnerabilities.

Secure Architecture

Building rate limiting, encryption, and access controls correctly from the ground up.

Incident Readiness

Establishing logging, monitoring, and response processes for when things go wrong.

10. Summary

Log Injection: The Essentials at a Glance

Core idea

Embedded line breaks in user-controlled values can split one log entry into multiple, forged entries.

Best fix

Structured JSON logging makes the vulnerability structurally impossible instead of merely containing it.

Extreme case

Log4Shell showed that a logging library actively interpreting input can lead to remote code execution.

Extra risk

Unprotected log-viewer dashboards can themselves become XSS attack targets via forged log content.

11. FAQ: Log Injection: The Essentials at a Glance

1What's the difference between log injection and log forging?
The terms are mostly used synonymously, both describe injecting forged, seemingly legitimate log entries.
2Is htmlspecialchars() enough to secure log entries?
No, that protects against HTML injection, not against line breaks, which are what matters for the actual log structure.
3Is structured JSON logging automatically safe?
With correct JSON serialization, yes, since control characters automatically get encoded as escape sequences.
4Was Log4Shell a pure log injection vulnerability?
It started as log injection but escalated to remote code execution through active interpretation of the log message.
5Should I sanitize all user-controlled values before logging?
Yes, every value not fully under the application's control should be handled before logging.
6Why are log-viewer dashboards an extra risk?
If log content isn't escaped when rendered, a log injection can escalate into XSS against the analyst.
7Does Monolog support structured logging out of the box?
Yes, via the JsonFormatter, which handles correct, injection-safe serialization.
8Is log injection only a problem for text files?
Most relevant for line-based formats, structured formats like JSON are structurally more resistant.
9How do I detect past log injection attempts after the fact?
By searching for embedded control-character patterns in raw, unstructured log files predating the move to structured logging.
10Should log sanitization happen server-side or client-side?
Exclusively server-side, since client-side checks can always be bypassed by an attacker.