Patching Log4j stops future exploitation, but it does not answer the question every incident responder asks first: was I already hit? Because Log4Shell rode in on ordinary logged data, the evidence usually sits in logs you already collect. This article is a defender's guide to finding that evidence. It explains which fields attackers abused, the JNDI patterns to search for, the network clues that confirm a successful attempt, and how to triage results without drowning in false positives. There are no attack instructions here, only detection.

If you have not confirmed which systems are even vulnerable yet, run the Log4Shell scanner first so you know where to focus your hunt.

Where the Malicious Data Lands

The defining feature of Log4Shell is that the trigger is logged user input. So the first step is to think about every field your application records. Attackers sprayed the JNDI token into anything that tends to be logged, including:

  • HTTP headers such as User-Agent, Referer, X-Forwarded-For, and custom headers.
  • URL paths and query strings that get written to access logs.
  • Form fields and JSON bodies such as usernames, search terms, and free-text comments.
  • Authentication fields, because failed logins are frequently logged verbatim.
  • Application-specific channels like chat messages, device names, or API parameters.

Because the entry point is so broad, your search has to span web server access logs, application logs, and any centralised logging platform you operate. A useful exercise is to enumerate, for each application, exactly which inbound fields end up in a log line, because that list defines the realistic attack surface you must search and where future detections should focus.

The Patterns to Search For

The core indicator is the JNDI lookup syntax. In its plainest form it is a ${...} token referencing a remote scheme such as ldap, ldaps, rmi, or dns. A simple first-pass search is to grep for the string jndi: across your logs. That will catch unobfuscated attempts immediately.

However, attackers rapidly adopted obfuscation to evade keyword filters, so a single literal search misses a lot. You also need to look for the building blocks of evasion, such as nested lookups like ${lower:...}, ${upper:...}, and the default-value form ${::-...} used to reassemble letters. Our article on obfuscated JNDI payloads explains each technique so you can write resilient regular expressions rather than brittle string matches.

A Layered Search Strategy

Rather than one perfect regex, use several overlapping searches and review the union of their hits:

  1. Literal token search. Look for jndi: and the ${ opening sequence across all log sources to catch the obvious attempts.
  2. Scheme search. Search for ldap, rmi, and dns appearing inside ${...} wrappers, which is uncommon in legitimate traffic.
  3. Obfuscation marker search. Flag occurrences of nested lookup keywords such as lower, upper, env, and the :- default-value separator inside log fields.
  4. Decode and re-scan. URL-decode and unescape suspect entries, then run the searches again, because payloads were frequently percent-encoded.

Network Evidence: The Confirming Signal

Seeing a JNDI token in a log proves someone tried, not that they succeeded. The exploitation worked by causing the server to reach out to an attacker-controlled host. So the strongest confirmation of a successful or near-successful attempt is an outbound connection from your application server to an unfamiliar destination shortly after a suspicious log entry.

Pivot to your network and DNS telemetry and look for outbound LDAP, RMI, or DNS lookups originating from servers that have no business making them. A web server suddenly resolving a strange hostname or opening an LDAP connection to the internet, correlated in time with a JNDI log entry, is a high-confidence indicator that warrants immediate incident response.

Reducing False Positives

Once you start searching, you will get noise. Internet-wide scanning means almost any internet-facing service logged Log4Shell probe traffic, most of it harmless attempts that hit non-vulnerable systems. To keep triage manageable:

  • Correlate with vulnerability. Prioritise hits on hosts the scanner and the version checker confirm were actually running a vulnerable Log4j build.
  • Require an outbound pivot. Treat a log hit plus a matching outbound connection as far more serious than a log hit alone.
  • Whitelist known scanners. Recognise benign security-research and bug-bounty probe sources to cut volume.
  • Check the callback host. Internal canary or test traffic from your own security team should be excluded.

How Far Back to Look

Mass exploitation began in December 2021, but probing continued for a long time afterward, and some intrusions used Log4Shell as an initial foothold months later. If you retain logs from that period, search the full window. If a host was vulnerable and exposed, assume it was probed and look hard for evidence of follow-on activity such as new processes, unexpected scheduled tasks, or unusual outbound traffic, not just the initial log entry. In practice the strongest evidence often comes from joining two data sets that teams keep separately: the application log that captured the inbound token and the network or DNS log that recorded any resulting outbound activity. Correlating those by host and timestamp turns a noisy pile of probe attempts into a short list of genuinely concerning events.

From Detection to Triage

When a search returns a credible hit, move into structured triage:

  1. Confirm vulnerability. Verify the target host actually ran an affected Log4j version using the version checker.
  2. Look for the callback. Check network and DNS logs for an outbound connection from that host around the same timestamp.
  3. Assess impact. If a callback occurred, treat the host as potentially compromised and begin host forensics.
  4. Contain. Isolate the host and preserve volatile evidence before remediation.
  5. Remediate the root cause. Patch per the patching guide so the same path cannot be used again.

Our companion article on triaging Log4Shell with a scanner goes deeper on prioritising findings across a large estate.

Building Lasting Detections

Beyond the immediate hunt, convert what you learned into standing detections. Create alerts that fire when JNDI lookup syntax appears in any logged field, and pair them with network rules that flag outbound LDAP, RMI, or unexpected DNS from server tiers. These detections remain valuable because variants of the technique reappear whenever a similar lookup or deserialization flaw surfaces in other software. A defender who can quickly grep for callback patterns and correlate them with outbound connections is well prepared for the next event, not just this one.

From Hunt to Standing Detection

A one-off hunt answers whether you were hit, but the real payoff comes from converting what you learned into permanent detections. Codify the searches that found credible hits into alerts that fire whenever JNDI lookup syntax appears in a logged field, and pair them with network rules that flag unexpected outbound LDAP, RMI, or DNS from server tiers. Tune them against the false-positive sources you identified during the hunt so they stay actionable rather than noisy. These standing detections keep paying off because the underlying technique reappears whenever a similar lookup or deserialization flaw surfaces in other software, and a team that can already correlate inbound payloads with outbound callbacks is far better prepared for the next incident than one starting from scratch.

Conclusion

Detecting Log4Shell in your logs comes down to searching every logged field for JNDI lookup syntax and its obfuscated variants, then confirming with outbound network evidence and correlating against genuinely vulnerable hosts. Start by mapping where you are exposed with the Log4Shell scanner at log4shell.tools, then hunt your logs with confidence.