Log4shell: Detecting Potential Abuse with EDR Products

Digital Forensics and Incident Response Team


Digital Forensics and Incident Response Team

December 15, 2021 at 17:00


Note: This blog post has now been updated for the last time. 

Updated querys: 20 Dec, 18:00 EET

As the Log4shell situation is running rampant in the world, we at Nixu, among all the others, are developing ways to detect malicious activity within our environments. Endpoint Detection and Response agents are able to detect potentially malicious activity after the Java process has been instructed to do the bidding of the malicious attacker. Of course, it is very hard to detect all possible actions carried out by the attacker and potentially even close to impossible if the attacker were an exceptionally skilled one.

However, our defensive development team is doing its best to provide our customers the ability to detect Log4shell exploitation attempts. In the example presented in this blog post, we are running the exploit code on a vulnerable Minecraft server.  We are using a very basic example of the exploit and are only spawning powershell.exe, which, of course, is relatively easy to detect with an EDR tool. No additional details are given of the actual exploit, as the internet is already full of Proof-of-Concept implementations.

First things first, we need to run the code on a Minecraft client by writing the exploit code into the chat:

View of the Minecraft game and exploit code

















After running the code, the Minecraft server will spawn a cmd.exe process, which in turn launches the powershell.exe process. This exact behavior is specific to the exploit used in this occasion. In reality, the Java process can launch any other process – or even refrain from launching anything else, which can make detection much harder. As there is not much to show on the Minecraft server itself, let's look at different EDR solutions.

Crowdstrike Falcon

Crowdstrike can be used to observe malicious processes with multiple views. The easiest and most visual is likely the process tree view:

Crowdstrike process image

 As Crowdstrike is running with the Splunk backend, the full power of SPL (Search Processing Language) can be used to query and modify the output. In this example, we are looking for process creations events with the Grand Parent process name starting with java*cmd.exe as a parent and powershell.exe as the launched process filename:

Crowdstrike GrandParent screenshot




Microsoft Defender for Endpoint

Defender for Endpoint offers two ways to view the data, either from the device timeline or from the Advanced Hunt.

From the Device Timeline view, we can see, for example, the following:

Microsoft Defender for Endpoint screenshot

 Now, the output can be heavily specified when looking at the same event in Advanced Hunt. Advanced Hunt is also an excellent tool for hunting anomalies within the Java processes. We could, for example, view only the following information:Now, the output can be heavily specified when looking at the same event in Advanced Hunt. Advanced Hunt is also an excellent tool for hunting anomalies within the Java processes. We could, for example, view only the following information:

MDE Advanced Hunt screenshot

Carbon Black Enterprise EDR

Carbon Black Enterprise EDR (known earlier as Carbon Black Response) is a very visual EDR tool. The visualization can show the activity in a very nice format.

Carbon Black Enterprise EDR



All three EDR products seen here are capable of detecting the malicious activity that could be launched using the Log4shell exploit. They might not be able to see everything that the attackers could do; however, they can still detect it at least partly. The assumption, of course, is that an EDR agent is installed on the vulnerable system, which sometimes is not possible.

However, as we have been developing some threat hunting queries and potential detection rules, we would like to share them with the community.

Finding malicious processes with EDR products

These queries are provided as-is and can hopefully help someone detect potentially malicious Log4shell-related activity. These queries will not detect all possible Log4shell attacks, but hopefully they can still help.


Unfortunately, because of time limitations, we haven't been able to create elaborate rules for Crowdstrike Falcon. However, the following simple query looks for command interpreters as child process of Java and makes a table of these.  Anomalies found from the data can be analyzed further. There are much more elaborate queries that can be created – SPL language provides great options for finding potential anomalies within the Java process.

(ParentBaseFileName="cmd.exe" OR ParentBaseFileName="powershell.exe" OR ParentBaseFileName="bash" OR ParentBaseFileName="dash" OR ParentBaseFileName="sh") AND GrandParentBaseFileName="java*" | table GrandParentBaseFileName, ParentBaseFileName, FileName, CommandLine, ComputerName


Defender for Endpoint

This is very simple, it only looks for connections to remote addresses which ends with ".class". Although simple, this can produce results at least in some occasions.

DeviceNetworkEvents | where RemoteUrl endswith ".class"


This query counts the remote ports to which Java process connects to and removes the ports that go over a certain count. The Log2shell vulnerability has to connect to an external server for the exploit to succeed, so this query can potentially find anomalies.

The RemoteUrl might be one thing that reveals malicious activity. Look for something like this: IP:PORT/ExecTemplateJDK7.class. This data could also be joined with other data like process data to reveal child processes.


// Author: Jouni Mikkola, Nixu DFIR
// This query counts the remote ports to which java process connects to and removes the ports that go over a certain count
// As the log2shell vulnerability has to connect to external server for the exploit to succeed so this query can potentially find anomalies.
// This could be joined to process data to find any child processes for example, if needed.
// The RemoteUrl might be one thing that reveals malicious activity look for something like this: IP:PORT/ExecTemplateJDK7.class

let PortCountThreshold = 20; // Set the threshold for the port count. Anything over this number will be dropped.
let rareports =
| where InitiatingProcessFileName contains "java"
| where ActionType == "ConnectionSuccess"
| where RemoteIPType == "Public"
| summarize count() by RemotePort
| where count_ < PortCountThreshold;
| where InitiatingProcessFileName contains "java"
| where ActionType == "ConnectionSuccess"
| where RemoteIPType == "Public"
| where RemotePort in (rareports)
| project-reorder Timestamp, DeviceName, RemoteIP, RemotePort, RemoteUrl


Carbon Black Enterprise EDR

This query looks for network connections by the Java process. The private ranges and ports 80 and 443 have been removed from the results. Depending on the environment this can cause huge amount of noise, unfortunately.

process_name:java* AND netconn_count:[1 TO *] AND -ipport:443 AND -ipport:80 AND (-ipaddr:[ TO] OR -ipaddr:[ TO] OR -ipaddr:[ TO] OR -ipaddr:[ TO] OR -ipv6addr:::1)

This query looks for the Java process with network connections to non-ephemeral ports which spawns powershell.exe or cmd.exe. It can be developed further by whitelisting common applications that are not vulnerable or ports such as 80 and 443.

(process_name:java.exe OR process_name:javaw.exe) (netconn_count:[1 TO *] AND ipport:[* TO 47823] -ipaddr: -ipaddr: -ipaddr: -ipaddr: -ipv6addr:::1) AND (childproc_name:powershell.exe OR childproc_name:cmd.exe)

We have also created a query, which monitors especially XMRig-related download processes. Recent threat intelligence reports around the world have revealed that vulnerable servers have been exploited with the Log4j vulnerability and XMRig cryptocurrency miner has been dropped onto the host. This type of behavior was observed earlier in 2021 when WebLogic had a similar RCE vulnerability. The query searches for cmd prompts spawned from Java, that ultimately reach out to an external host, and PowerShell is then launched.

(parent_name:java.exe OR parent_name:javaw.exe) process_name:cmd.exe cmdline:http* (childproc_name:powershell.exe OR childproc_name:pwsh.exe OR childproc_name:powershell_ise.exe)


Carbon Black Enterprise EDR has the live query feature in Beta. This is basically OsQuery. This can be a VERY powerful tool and can be used to look for signs of vulnerable software versions or indicators of compromise.

In this example, we are using a Yara rule developed by Florian Roth – available here: https://github.com/Neo23x0/signature-base/blob/master/yara/expl_log4j_cve_2021_44228.yar.

Yara rules can be run with the following command. Remember to escape the double quotes. The PATH values need to be checked as well. Currently, it seems that this will timeout if it will be attempted against c:\%% which is unfortunate.

FROM yara
WHERE PATH LIKE 'c:\program files\%%'
OR PATH LIKE 'c:\program files (x86)\%%'
AND sigrule ='rule EXPL_Log4j_CallBackDomain_IOCs_Dec21_1
description = \"Detects IOCs found in Log4Shell incidents that indicate exploitation attempts of CVE-2021-44228\"
author = \"Florian Roth\"
reference = \"https://gist.github.com/superducktoes/9b742f7b44c71b4a0d19790228ce85d8\"
date = \"2021-12-12\"
score = 60
$x01 = /\b(ldap|rmi):\/\/([a-z0-9\.]{1,16}\.bingsearchlib\.com|[a-z0-9\.]{1,40}\.interact\.sh|[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}):[0-9]{2,5}\/([aZ]|ua|Exploit|callback|[0-9]{10}|http443useragent|http80useragent)\b/
1 of them


Update 1: 16 Dec, 18:00 EET

Further queries to be used with Carbon Black EDR

The following query looks for Java processes with Log4j in the command line. This does not limit the results to only vulnerable versions, it targets all Java processes where Log4j is part of the command line and then looks for unusual child processes. The child processes contain typically seen scripting interfaces and command prompts, which malware typically utilizes.

The child processes added here are often seen within security incidents used by an attacker for malicious activity.

(process_name:java.exe OR process_name:javaw.exe OR process_name:java) cmdline:log4j AND (childproc_name:cmd.exe OR childproc_name:powershell.exe OR childproc_name:bash OR childproc_name:sh OR childproc_name:wscript.exe OR childproc_name:cscript.exe OR childproc_name:wmic.exe OR childproc_name:net.exe OR childproc_name:nltest.exe OR childproc_name:whoami.exe OR childproc_name:netstat.exe OR childproc_name:nslookup.exe OR childproc_name:rundll32.exe OR childproc_name:regsvr32.exe)

The second query is monitoring active network connections to external networks from Java processes. The connections are limited to ports 1099, 1389 and 8180 to match the behaviour of a known JNDI-Inject-Exploit tool, that was published by security researchers. This query would then find instances of the tool running in the network.

(process_name:java*) (netconn_count:[1 TO *] -ipaddr: -ipaddr: -ipaddr: -ipaddr: -ipv6addr:::1) AND (ipport:1099 OR ipport:1389 OR ipport:8180)

The Live Query feature has also been explored further, but unfortunately, we haven't been able to launch the Yara rules reliably with the product, so that the whole disk could be targeted.

However, Mika Kontio created a Yara rule that looks for jndiclass from the jar files. Here is the rule, shown with the way how you would launch it with Live query (or osquery on which the live query is based).

FROM yara
WHERE PATH LIKE 'c:\users\%%'
OR PATH LIKE 'c:\program files\%%'
OR PATH LIKE 'c:\program files (x86)\%%'
AND sigrule = 'rule Vuln_JndiLookup_Dec21
description = \"Detects Jar-files that contain a possibly vulnerable JndiLookup.class\"
author = \"Mika Kontio\"
reference = \" \"
date = \"2021-12-15\"
score = 60
$class1 = /\b(JndiLookup)\b/
1 of them


Update 2: 20 Dec, 18:00 EET

A few more MDE queries

This one looks for Java process connecting to the default ports used by some of the publicly available exploit kits.

// Author: Jouni Mikkola, Nixu DFIR
// Looks for java process connecting to the public IP addresses and publicly known jndi exploitkit ports
| where InitiatingProcessFileName contains "java"
| where RemoteIPType == "Public"
| where RemotePort == 1099 or RemotePort == 1389 or RemotePort == 8180


Successful exploitation of Log4Shell will lead to the attacker being able to execute commands on the target. To do this, they will need an interpreter to achieve the code execution. Java-based processes will launch abnormal child processes in case of a successful exploit. Likely, fine-tuning needs to be done by removing some false-positive command lines to clean up the results, depending on the environment.

// Author: Juuso Myllylä, Nixu SOC
// Looks for Java processes spawning command line interpreters or other abnormal processes, communicating with external domains.
let _cmdscripts = dynamic(["cmd.exe", "powershell.exe", "pwsh.exe", "powershell_ise.exe", "cscript.exe", "wscript.exe", "mshta.exe", "rundll32.exe", "regsvr32.exe"]);
let _javaprocess = dynamic(["java.exe", "javaw.exe", "java"]);
| where InitiatingProcessFileName in~(_javaprocess)
| where FileName in~ (_cmdscripts)
| where ProcessCommandLine contains "http"
| project DeviceName, FileName, FolderPath, ProcessCommandLine, InitiatingProcessParentFileName, InitiatingProcessCommandLine
| summarize count() by ProcessCommandLine


This query joins incoming requests accepted by Java to outbound requests to public IP addresses by the same Java process in the next 5 minutes. Not the prettiest of queries and can potentially be improved to be much more efficient. However, it seems to work. Also, it does not provide a huge amount of results, so it can be used as a detection rule. So far no false positives seen by us.

// Author: Jouni Mikkola, Nixu DFIR
// This query looks for inbound connections accepted by Java process and then joins it to outbound process to the same IP within the next 5 minutes.
// The lookup window is from MS example: https://docs.microsoft.com/en-us/azure/data-explorer/kusto/query/join-timewindow
let lookupWindow = 10min; // set the lookup window.
let lookupBin = lookupWindow / 2.0; // Half of the lookup window
| where InitiatingProcessFileName contains "java"
| where ActionType == 'InboundConnectionAccepted'
| where LocalIP != RemoteIP
| where RemoteIPType == "Public"
| extend Start = Timestamp
| extend InboundTimestamp = Timestamp
| extend TimeKey = bin(Timestamp, lookupBin)
| join (
| where InitiatingProcessFileName contains "java"
| where ActionType == 'ConnectionSuccess'
| where LocalIP != RemoteIP
| where RemoteIPType == "Public"
| extend End = Timestamp
| extend OutboundTimestamp = Timestamp
| extend OutboundRemotePort = RemotePort
| extend TimeKey = range(bin(Timestamp-lookupWindow, lookupBin), bin(Timestamp, lookupBin), lookupBin)
| mv-expand TimeKey to typeof(datetime)
) on DeviceName, InitiatingProcessId, TimeKey
| where End > Start // In this case we only want results where the outbound connection is initiated afte the inbound one
| project-reorder InboundTimestamp, OutboundTimestamp, InitiatingProcessFileName, RemoteIP, OutboundRemotePort



  • Jouni Mikkola, Senior Security Consultant, DFIR
  • Antti Ollila, Senior Security Analyst, SOC
  • Teemu Kantola, Security Analyst, SOC
  • Juuso Myllylä, Security Analyst, SOC