Have you Patched the Apache Log4j vulnerability CVE-2021-44228?

Updated on Aug 30, 2022

Apache Log4j vulnerability CVE-2021-44228 is a critical zero-day code execution vulnerability with a CVSS base score of 10. On December 9, 2021, the Internet was set on fire when an exploit was posted publicly for Apache Log4J – a well-known logging utility in the Java programming language. 

The implications of Log4j are going to have a very long tail! Leaders need to continue to verify which of their systems are impacted and continuously check for updates to make sure they are completely patched. Continuous scanning has been the most effective method that we’ve seen success with.

-Aaron Sandeen, CEO of CSW

Recent Developments

APT Lazarus Association: On May 23, 2022, Lazarus, a group associated with North Korea, exploits Log4J’s RCE vulnerability (CVE-2021-44228) to gain access to VMware Horizon servers. As part of the attack chain, a PowerShell command is executed on VMware Horizon’s ws_tomcatservice.exe process in order to exploit the Log4j vulnerability. This PowerShell command installs the NukeSped backdoor on the vulnerable server. Users are recommended to check for firmware updates for Log4Shell vulnerabilities and apply the patches. 

Fire Chili Malware: On April 01, 2022, a Chinese hacker group Deep Panda is deploying a new rootkit malware named Fire Chili on VMware Horizon servers using the Log4Shell exploit. Researchers uncovered several overlaps between the Deep Panda campaign and Winnti, another notorious Chinese hacker group known for using digitally signed certificates.  On February 18, 2022, researchers observed that Iran-linked APT group TunnelVision was actively exploiting the Log4j vulnerability to deliver ransomware to unpatched VMware Horizon servers. 

Ubiquiti Network Targeted: It is found that Ubiquiti network appliances running the UniFi operating system are being attacked and taken over by threat actors using a customized public exploit for the Log4Shell vulnerability, on February 04, 2022. 

Night Sky Ransomware: The Night Sky ransomware gang has begun to attack the major CVE-2021-44228 vulnerability in the Log4j logging library to get access to VMware Horizon computers. Night Sky ransomware targets organization networks and has encrypted the data of many victims and demanded $800,000 in ransom from one of them.

On January 10, 2022, Microsoft has issued a warning on a new campaign by a China-based attacker known as DEV-0401 that aims to exploit the Log4Shell vulnerability on publicly accessible VMware Horizon servers and install the Night Sky ransomware.

US Federal Trade Commission Warning: On January 05, 2022, the US Federal Trade Commission warned that it will take action against any US company not protecting its customers’ information from ongoing Log4J attacks. It’s vital that firms and their vendors who use Log4j act quickly to decrease the risk of consumer harm and prevent FTC legal action.

After noticing state-sponsored and cyber-criminal attackers investigating systems for the LogShell weakness in December, Microsoft has issued a warning to Windows and Azure customers users to be careful.

ONUS Falls Victim: ONUS, a crypto trading platform, suffered a cyberattack on its payment system, which was running a vulnerable Log4j version. Threat actors put roughly 2 million ONUS customers’ data up for sale on dark forums after the firm refused to pay the ransom of $5 million.  According to researchers, ONUS’s Cyclos server was exploited by threat actors between December 11th and 13th, and backdoors were planted to allow sustained access. We recommend users upgrade to the newest version of Log4j 2.17.1. 

According to CrowdStrike researchers, a Chinese hacker group known as AQUATIC PANDA famous for industrial espionage and intelligence collection exploited a Log4j vulnerability to target a significant academic institution.

Log4shell Fifth Vulnerability: On December 29, 2021, Apache discovered its fifth vulnerability in Log4j 2.17.0 – an RCE flaw assigned a CVE Identifier as CVE-2021-44832, for which a patch is now available. Two different weaknesses in code can be exploited using this vulnerability, classified under CWE-74 (Improper Neutralization of Special Elements in Output Used by a Downstream Component ) and CWE-20 (Improper Input Validation). 

PoC Released: On December 25, 2021, CSW Researchers have developed a Proof-of-Concept exploit for CVE-2021-44228 Log4j vulnerability. 

Note: This is not a “point and click” exploit. The initial trigger payload will be generated; however, the user will be responsible for injecting it into the appropriate location (i.e., HTTP header/chat/etc.).

CISA, NSA & FBI: The Cybersecurity and Infrastructure Security Agency (CISA), the Federal Bureau of Investigation (FBI), the National Security Agency (NSA), and other cybersecurity agencies from Australia, New Zealand, and the United Kingdom, on December 24, 2021, have issued a joint Cybersecurity Advisory (CSA) to provide mitigating measures to address.

Additionally, CISA has launched a scanner utility to discover systems that are vulnerable to the Log4J Shell vulnerability, comparable to the CERT Coordination Center (CERT/CC) tool. 

Belgian Defense Ministry Targeted: On December 22, 2021, the Belgian defense ministry experienced a breach on its computer networks as a result of unpatched log4j servers, which clearly demonstrates the lack of cyber hygiene. In spite of knowing of the security hole and the significant risk posed to corporate networks around the world, organizations continue to fail to heed the warnings that can eventually lead to major cyberattacks. We, therefore, urge users to patch their Apache servers immediately.

LogShell’s Fourth Vector 

{Updated on December 21}: Unsurprisingly, here comes another new RCE vulnerability (CVE-2021-4104) that affects Log4j v1.2 instances using the JMSAppender, which will not be fixed because the 1.x branch has reached end-of-life. CVE-2021-4104 has a severity of  8.1 (high) on the CVSS v3 scale and is classified as CWE-502 vulnerable to deserialization of untrusted data. 

Multiple threat actors are now taking advantage of the Apache Log4j vulnerabilities to infect affected Windows devices, with the latest attacks using the Dridex banking malware or Meterpreter. Dridex infections have also been connected to ransomware attacks carried out by the Evil Corp hacking gang activity. 

The US government cybersecurity agency issued an Emergency Directive 22-02, urging other federal agencies to identify susceptible Log4j systems and deploy the necessary patches and mitigations by 5 p.m. on December 23, 2021. 

LogShell’s DoS Vector Patched

{Updated on December 18}: Apache pushed another fix for the DoS vector of the second log4j flaw, which is now tracked as CVE-2021-45105. This CVE carries a CVSS score of 7.5 (high) that impacts all versions from 2.0-beta9 to 2.16.0. We urge Apache users to apply the latest patch release of 2.17.0.

Earlier, Conti Ransomware was found to be venturing laterally on vulnerable VMware vCenter servers, revealing the first major gang known to weaponize the log4j vulnerability. 

In addition, researchers in China discovered an old inactive ransomware family named TellYouThePass being used in attacks against Windows and Linux computers to exploit the severe remote code execution flaw in the Apache Log4j modules.

The never-ending, incomplete fix pattern for the LogShell vulnerabilities continues to discover newer loopholes. We will now have to wait and watch how the latest release holds up.

{Updated on December 17}: Praetorian researchers warned of a third independent flaw in Log4j version 2.15.0 that might allow sensitive data to be exfiltrated in certain instances. To avoid future exploitation, more technical details about the vulnerability have been concealed; however, it’s unclear whether this has already been resolved in version 2.16.0.

The second Log4j vulnerability (CVE-2021-45046) that was initially rated CVSS v3 score of 3.7 (medium) has been bumped up to 9.0 (critical). Since researchers have developed exploits that could lead to Information leaks, Remote Code Execution, and Local Privilege Escalation. Therefore, Apache has labelled the CVE to Remote Code Execution from Denial of Service attacks.

Considering Khonsari ransomware and threat groups such as Nemesis Kitten, Hafnium, and Phosphorus are looking for an opportunity to make the most of the critical vulnerability, we urge organizations to employ mitigations and patch the vulnerable systems on priority to reduce the impact of Log4j vulnerability on their systems.

A New Ransomware: On December 15, 2021, a new ransomware family specifically targeting Windows Servers, dubbed as Khonsari, has been observed exploiting the vulnerability CVE-2021-44228. The most troubling aspect is its direct deployment of ransomware using the Log4jShell (CVE-2021-44228) vulnerability. Another Iran-based state-sponsored threat actor, Nemesis Kitten, was also seen leveraging the vulnerability in an attack.

Check out CSW’s Ransomware Spotlight Reports for more information on Ransomware

Furthermore, Advanced Persistent Threat groups from China, Iran, North Korea, and Turkey, including Hafnium and Phosphorus, have stepped into the battle to operationalize the vulnerability and find and exploit as many vulnerable systems as possible.

{December 15}: A second vulnerability involving Apache Log4j was discovered and is tracked as CVE-2021-45046, rated 3.7/10 (low) on the CVSS scale. This vulnerability emerges from the incomplete patch to the CVE-2021-44228 that leads attackers to craft malicious input data using a JNDI Lookup pattern resulting in a denial of service (DOS) attack. 

CVE 2021-45046 is categorized under the weakness enumeration CWE-502 (Deserialization of Untrusted Data). Though it has a low severity, the CWE assigned to it is listed in the Top 15 most dangerous software weaknesses published by MITRE.

Apache has already released an updated version of Log4j 2.16.0 for this issue and urges users to apply the necessary patches.

Apache Log4J Vulnerability

CVE-2021-44228 is a critical java-based zero-day vulnerability that exists in the Java logging framework of Apache Software Foundation. This unauthenticated RCE vulnerability allows the attacker full control of the affected server if the user-controlled string is logged.

This zero-day vulnerability came to light on December 9, 2021, when a security researcher shared an exploit for this unknown bug on Twitter. Since then, a CVE number has been assigned to it and the vulnerability is trending in the wild with many exploits being posted. The exploit enables remote code execution of this vulnerability facilitating a complete take over of the server.

Our Analysis

  • CVE-2021-44228 is a Remote Code Execution vulnerability in the Apache Log4j with over 400,000 downloads from its GitHub project.
  • This CVE is classified under the weaknesses enumerations of CWE – 502, CWE-400, and CWE-20, that fall under the 2021 Top 30 dangerous software weaknesses listed by MITRE.
  • The first alert was released by CERT New Zealand, followed by those from CISA and the National Cyber Security Centre of the United Kingdom.
  • According to researchers, botnets such as Mirai and Muhstik (aka Tsunami) are targeting vulnerable systems to deploy cryptocurrency miners and setting up backdoors to Linux systems, leading to DDoS attacks.
  • Popular scanners such as Qualys, Nessus, and Nexpose were able to detect the CVE-2021-44228 vulnerability and have been assigned with the following plugin IDs.


Vulnerable Products {Updated on April 7, 2022}

This vulnerability affects everything from enterprise software to web applications and popular consumer products. In a nutshell, if an organization is using the Apache Log4j framework (including Apache Struts2, Apache Solr, Apache Druid, Apache Flink, etc.) then they are vulnerable to CVE-2021-44228. 

In our initial analysis of Log4j vulnerable products, we found only 273 impacted products which have now grown to 1888. Our CSW analysts are keeping up-to-date on the affected products and updating the following list on a daily basis. 

Exposure Analysis

CSW experts did an exposure analysis by geography and product and here are the results. 



How to Detect CVE-2021-44228?

CSW researchers have come up with a script to help organizations detect exploitation of Apache Log4j vulnerabilities. We urge organizations to use this script to check if attackers are targeting their environment.

Log4j Vulnerabilities: Script to detect exploitation attempts of CVE-2021-44228, CVE-2021-45046, and CVE-2021-45015.

NOTE: Teams must enable saving log information as files for the scan to be conducted.

#!/usr/bin/env python3

import os
import sys
import copy
import gzip
import urllib.parse
import argparse
from datetime import datetime, timedelta
from collections import defaultdict
import traceback
import base64
import time
import subprocess

DEFAULT_PATHS = [‘/var/log’, ‘/storage/log/vmware’, ‘/var/atlassian/application-data/jira/log’, ‘/home/logs’]
LINUX_PATH_SKIPS_START = set([“/proc”, “/dev”, “/sys/kernel/debug”, “/sys/kernel/slab”, “/sys/devices”, “/usr/src/linux”])

class log4j2_detect(object):

    EXPLOIT_STRINGS = [‘${jndi:ldap:’, ‘${jndi:rmi:/’, ‘${jndi:ldaps:/’, ‘${jndi:dns:/’, ‘${jndi:nis:/’, ‘${jndi:nds:/’, ‘${jndi:corba:/’, ‘${jndi:iiop:/’, ‘$%7Bjndi:ldap://’, ‘%2524%257Bjndi:ldap:/’, ‘%2F%252524%25257Bjndi%3Aldap%3A%2F’, ‘%2F%252524%25257Bjndi%3Aldaps%3A%2F’, ‘%2F%252524%25257Bjndi%3Adns%3A%2F’
    ‘%2F%252524%25257Bjndi%3Armi%3A%2F’, ‘${jndi:ldap:’, ‘${jndi:rmi:’, ‘${jndi:ldaps:’, ‘${jndi:dns:’, ‘${jndi:nis:’, ‘${jndi:nds:’, ‘${jndi:corba:’, ‘${jndi:iiop:’, ‘${ctx:’]
    INSTALL_PATHS = [‘/usr/local’]
        “”: [
            ” header with value of BadAttributeValueException: “
        “”: [
            “at java.naming/com.sun.jndi.url.ldap.ldapURLContext.lookup(“,
        “”: [
        “”: [
            ‘Reference Class Name: foo’

    def __init__(self, maximum_distance, debug, fast):
        self.debug = debug = fast
        self.number_of_detections = 0
        self.affected_files = []

    def decode_line(self, line):
        while “%” in line:
            line_before = line
            line = urllib.parse.unquote(line)
            if line == line_before:
        return line

    def evaluate_log_paths(self):
        paths = []
        print(“Automatically evaluating the folders to which Applications write logsn”)
        command = “lsof 2>/dev/null | grep ‘\.log’ | sed ‘s/.* \//\//g’ | sort | uniq”
        path_eval = subprocess.Popen(command,shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
        output = path_eval.communicate()[0].splitlines()
        for o in output:
            path = os.path.dirname(o)
            if isinstance(path, bytes):
                path = path.decode(“utf-8”)

            # Some filters
            skip_append = False
            # If already in list – skip
            if path in paths:
                skip_append = True
            # If in exclude list – skip
            for exclude in LINUX_PATH_SKIPS_START:
                if path.startswith(exclude):
                    skip_append = True
            if skip_append:

            # Append the found path
            print(“Adding PATH: %s” % path)

        return paths

    def log4j_detect(self):
        Detect the version of log4j instance
        in the default install paths
        checker_commands = [
        “ps aux | egrep ‘[l]og4j'”,
        “find / -iname “log4j*””,
        “lsof | grep log4j”,
        “grep -r –include *.[wj]ar “JndiLookup.class” / 2>&1 | grep matches”,
        for checker_command in checker_commands:
            if len(subprocess.Popen(checker_command,shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT).communicate()[0].splitlines()) > 0:
                return True
        return False

    def base64_decode(self, log):
        payload = “”
        if “Base64” in log:
            payload = base64.decodebytes(log.split(“Base64/”)[1].split(“}”)[0].encode()).decode()
        return payload

    def check_line(self, line):
        Check line and identify presence of
        a character present in exploit string.
        Look for the next consecutive character
        within the maximum distance
        :param line:    single line from a log file
        :type  line:    str
        :param detection_pad:    dictionary created from attack string
        :type  detection_pad:    dict
        :return:    detection string if found
        :rtype:     str

        decoded_line = self.decode_line(line)

        for ref, strings in self.PLAIN_STRINGS.items():
            for s in strings:
                if s in line or s in decoded_line:
                    return s

        decoded_line = decoded_line.lower()
        linechars = list(decoded_line)
        # temporary detection pad
        dp = copy.deepcopy(self.detection_pad)
        # Walk over characters
        for c in linechars:
            for exploit_string in dp:
                # If the character in the line matches the character in the detection
                if c == dp[exploit_string][“chars”][dp[exploit_string][“level”]]:
                    dp[exploit_string][“level”] += 1
                    dp[exploit_string][“current_distance”] = 0
                # If level > 0 count distance to the last char
                if dp[exploit_string][“level”] > 0:
                    dp[exploit_string][“current_distance”] += 1
                    # If distance is too big, reset level to zero
                    if dp[exploit_string][“current_distance”] > dp[exploit_string][“maximum_distance”]:
                       dp[exploit_string][“current_distance”] = 0
                       dp[exploit_string][“level”] = 0
                # Is the pad completely empty?
                if len(dp[exploit_string][“chars”]) == dp[exploit_string][“level”]:
                    return exploit_string

    def scan_file(self, file_path):
        Give a path, scan all files to check if
        an exploit string is written/obfuscated
        in it via detection pads
        :param file_path:    single file in the path
        :type  file_path:    str
        :return:    matches in file
        :rtype:     dict
        matches_in_file = []
            # Gzipped logs
            if “log.” in file_path and file_path.endswith(“.gz”):
                with, ‘rt’) as gzlog:
                    c = 0
                    for line in gzlog:
                        c += 1
                        # Quick mode – timestamp check
                        if and not “2021” in line and not “2022” in line:
                        # Analyze the line
                        result = self.check_line(line)
                        if “${ctx:” in str(result):
                            print(“Possible DOS/RCE exploitation for new CVEsn”)
                        if result:
                            payload = self.base64_decode(line.rstrip())
                            matches_dict = {
                                “line_number”: c,
                                “match_string”: result,
                                “line”: line.rstrip()
                            print(“nWarning: Exploitation attempt detected FILE: %s LINE_NUMBER: %d LINE: %s DEOBFUSCATED_STRING: %s DECODED_PAYLOAD: %s” %
                            (file_path, matches_dict[‘line_number’], matches_dict[‘line’], result, payload))
            # Plain Text
                with open(file_path, ‘r’) as logfile:
                    c = 0
                    for line in logfile:
                        c += 1
                        # Quick mode – timestamp check
                        if and not “2021” in line and not “2022” in line:
                        # Analyze the line
                        result = self.check_line(line)
                        if “${ctx:” in str(result):
                            print(“Possible DOS/RCE exploitation for new CVEsn”)
                        if result:
                            payload = self.base64_decode(line.rstrip())
                            matches_dict = {
                                “line_number”: c,
                                “match_string”: result,
                                “line”: line.rstrip()
                            print(“nWarning: Exploitation attempt detected FILE: %s LINE_NUMBER: %d LINE: %s DEOBFUSCATED_STRING: %s DECODED_PAYLOAD: %s” %
                            (file_path, matches_dict[‘line_number’], matches_dict[‘line’], result, payload))

        except UnicodeDecodeError as e:
            if self.debug:
                print(“nUnable to process FILE: %s REASON: most likely not an ASCII based log file” % file_path)
        except Exception as e:
            print(“nUnable to process FILE: %s REASON: %s” % (file_path, traceback.print_exc()))

        return matches_in_file

    def scan_path(self, path):
        Give a path, scan all files to check if
        an exploit string is written/obfuscated
        in it via detection pads
        :param path:    single line from a log file
        :type  path:    str
        :return:    number of detections
        :rtype:     int
        affected_files = self.affected_files
        detections = defaultdict(lambda: defaultdict())
        # Loop over files
        for root, directories, files in os.walk(path, followlinks=False):
            for filename in files:
                file_path = os.path.join(root, filename)
                print(“Processing file : %s” % file_path)
                if self.debug:
                    print(“Processing file :  %s” % file_path)

                evidences_in_file = self.scan_file(file_path)

                    for evidence in evidences_in_file:
                        detections[file_path][evidence[‘line_number’]] = [evidence[‘line’], evidence[‘match_string’]]

        count_affected_files = len(detections.keys())
        number_of_detections = self.number_of_detections

        if number_of_detections > 0:
            print(“nWarning: %d exploitation attempts detected in PATH: %s” % (number_of_detections, path))
            print(“nNo Log4Shell exploitation attempts detected in path PATH: %s” % path)

        self.write_out_summary(path, affected_files)

        return number_of_detections

    def prepare_detections(self, maximum_distance):
        Deconstruct exploit string
        to form detection pads
        :param dist:    maximum distance
        :type  dist:    int
        :return:    detection pads
        :rtype:     dict
        self.detection_pad = {}
        for ex in self.EXPLOIT_STRINGS:
            self.detection_pad[ex] = {}
            self.detection_pad[ex] = {
                “chars”: list(ex),
                “maximum_distance”: maximum_distance,
                “current_distance”: 0,
                “level”: 0

    def write_out_summary(self, path, affected_files):
        filename = “infected_files_”+str(time.time())+”.txt”
        with open(filename, ‘w’) as f:
            f.writelines(“Affected Files in path : “+path)
            for file in affected_files:

if __name__ == ‘__main__’:

    parser = argparse.ArgumentParser(description=’Log4Shell Exploitation Detection’)
    parser.add_argument(‘-p’, nargs=’+’, help=’Path to scan’, metavar=’path’, default=”)
    parser.add_argument(‘-d’, help=’Maximum distance between each character, Default=30′, metavar=’distance’, default=30)
    parser.add_argument(‘–fast’, action=’store_true’, default=False, help=”Skip log lines that don’t contain a 2021 or 2022 time stamp”)
    parser.add_argument(‘–defaultpaths’, action=’store_true’, default=False, help=’Scan a set of default paths known to contain relevant log files.’)
    parser.add_argument(‘–debug’, action=’store_true’, default=False, help=’Debug output’)

    args = parser.parse_args()

    detective = log4j2_detect(maximum_distance=args.d, debug=args.debug,

    if not args.p and not args.defaultpaths:
        print(“Must specify at least one folder to scan with -p target-folder or use –defaultpaths”)

    date_scan_start =
    print(“Scan initiated at DATE: %s” % date_scan_start)
    check = detective.log4j_detect()

    # Prepare the detection pads
    #detection_pad = prepare_detections(int(args.d))

    # Counter
    all_detections = 0

    # Scan paths
    paths = args.p
    if args.defaultpaths:
        paths = detective.evaluate_log_paths()
    for path in paths:
        if not os.path.isdir(path):
            print(“Path %s doesn’t exist” % path)
            if not args.defaultpaths:
                print(“Path %s doesn’t exist” % path)
        print(“Scanning FOLDER: %s …” % path)
        detections = detective.scan_path(path)
        all_detections += detections

    # Finish
    if all_detections > 0:
        print(“nWarning: %d exploitation attempts detected in the complete scan” % all_detections)
        print(“nNo exploitation attempts detected in the scan”)
    date_scan_end =
    print(“Scan completed DATE: %s” % date_scan_end)


Indicators of Compromise {Updated on Jan 13, 2022}

CSW researchers have compiled a list of IOCs that includes malicious IP addresses, domains, and hashes.

Commenting on this critical development, Aaron Sandeen, CSW’s CEO said, “Our vulnerability & threat intelligence shows that the Log4j vulnerability is not only critical but the threat actor chatter about it is extremely high!  We see quite a few foreign actors talking about this and it will soon turn into the next solar winds. If this is not remediated immediately it will be turned into an attack vector for nation-states and used to compromise critical systems.


Organizations are urged to take quick action against this vulnerability and mitigate them immediately.

Note: Our team is constantly working on this story and we will update the blog as and when we get new information. Stay tuned!

Cyber Security Predictions | Our Services | Case Study

Share This Post On