Detecting Log4Shell with Wazuh

| by Awwal Ishiaku
Post icon

The Apache Log4J is one of the most common logging libraries in Java, mainly used for error messages. It is part of several high valued applications including iCloud, Twitter, and Minecraft amongst others.

Recently, a zero-day vulnerability dubbed Log4Shell with CVE CVE-2021-44228 was detected in Apache’s Log4J 2 that allows malicious actors to launch Remote Code Execution (RCE) attacks. This means that an assailant can remotely send commands to a server running vulnerable applications.

The affected Apache Log4j 2 versions are 2.0-beta9 to 2.15.

As a matter of fact, version 2.15.0 which was the initial fix for the vulnerability was later discovered to still be vulnerable. So it is recommended to update to version 2.16.0 which disables JNDI and completely removes %m{lookups}.

There are several ways to defend your system against this vulnerability and potential attacks:

  • Running scans to detect when a vulnerable version of Apache Log4j 2 exists on your system.
  • Patching the vulnerability by updating to Apache Log4j 2 version 2.16.0 or disabling JNDI.
  • Creating detection rules that monitor connection and web access logs to detect exploitation attempts.

The key to combating the current wave of attacks is early detection of the vulnerability for immediate patching, and constant monitoring of all assets to identify when there is an attempt to exploit this vulnerability.

We will be looking at how Wazuh can help with the monitoring and detection of this vulnerability in the following sections.

Scanning vulnerable versions of Apache Log4j 2

We will utilize a Wazuh SCA (Security Configuration Assessment) policy for this. SCA policies are written in YAML format and they are used to run checks for system hardening; in many cases detecting vulnerable software also falls under this category.

Unless otherwise stated, all of the following configurations were done on the Wazuh server side. There is usually no need to edit the local configuration of the agents being monitored.

First, we create a new policy file at /var/ossec/etc/shared/default/log4j_check.yml:

policy:
  id: "log4j_check"
  file: "log4j_check.yml"
  name: "Log4j dependency check"
  description: "This document provides prescriptive guidance for identifying Log4j RCE vulnerability"
  references:
    - https://nvd.nist.gov/vuln/detail/CVE-2021-44228
    - https://www.cisa.gov/uscert/apache-log4j-vulnerability-guidance
requirements:
  title: "Check if Java is present on the machine"
  description: "Requirements for running the SCA scan against machines with Java on them."
  condition: all
  rules:
    - 'c:sh -c "ps aux | grep java | grep -v grep" -> r:java'
checks:
  - id: 10000
    title: "Ensure Log4j is not on the system or under 2.16"
    description: "The Log4j library is vulnerable to RCE on versions between 2.10 and 2.15."
    remediation: "Update the log4j library to version 2.16 or set log4j2.formatMsgNoLookups to true if possible."
    condition: none
    rules:
      - 'c:find / -regex ".*log4j.*.jar" -type f -exec sh -c "unzip -p {} META-INF/MANIFEST.MF | grep Implementation-Version" \; -> r: 2.10.| 2.11.| 2.12.| 2.13.| 2.14.| 2.15.'
  - id: 10001
    title: "Ensure Java is not running or is properly configured"
    description: "The Log4j library is vulnerable to RCE on versions between 2.10 and 2.15."
    remediation: "Update the log4j library to version 2.16 or set log4j2.formatMsgNoLookups to true if possible."
    condition: any
    rules:
      - 'c:sh -c "ps aux | grep java | grep -v grep" -> r:java && r:Dlog4j2.formatMsgNoLookups=true'

We do this so that the SCA policy gets shared with a group of agents, which are the ones that will run the checks. In our case, we are sharing the policy with the default group, hence the default directory.

Note: Please be aware that, depending on the monitored system, the find command used to detect vulnerable applications can be CPU intensive.

Additionally, once the SCA policy file is created, the owner and group are modified so it can be used by Wazuh:

chown ossec:ossec /var/ossec/etc/shared/default/log4j_check.yml

Next, we added the SCA block to /var/ossec/etc/shared/default/agent.conf to enable the new policy on the Wazuh agents that belong to the default group:

<agent_config>
  <sca>
    <enabled>yes</enabled>
    <scan_on_start>yes</scan_on_start>
    <interval>24h</interval>
    <skip_nfs>yes</skip_nfs>    
    <policies> 
      <policy>/var/ossec/etc/shared/log4j_check.yml</policy>  
    </policies>
  </sca>
</agent_config>

Below we edited a local setting on the Wazuh agent configuration file. This is done directly on the systems that are being monitored, as there is no way to push this setting from the Wazuh server. The purpose of this modification is to enable the execution of commands in the SCA policies that are received from the Wazuh server. This is not necessary when those SCA policies are local to the agent.

echo "sca.remote_commands=1" >> /var/ossec/etc/local_internal_options.conf

For the new setting to take effect we restarted the Wazuh agent. The server also pushed the new SCA policy file automatically.

We can see under SCA events that the system currently has a vulnerable Log4J 2 version on it.

Log4Shell SCA

Detecting Log4Shell Exploit Attempts

To add another layer of security, we created rules that will detect Log4Shell exploitation attempts.

For this particular case, we monitored web access logs and looked for specific patterns that are known to be used for this exploit.

We added the following rule to our Wazuh server in the /var/ossec/etc/rules/local_rules.xml file:

<group name="log4j, attack,">
  <rule id="110002" level="7">
    <if_group>web|accesslog|attack</if_group>
    <regex type="pcre2">(?i)(((\$|24)\S*)((\{|7B)\S*)((\S*j\S*n\S*d\S*i))|JHtqbmRp)</regex>
    <description>Possible Log4j RCE attack attempt detected.</description>
    <mitre>
      <id>T1190</id>
      <id>T1210</id>
      <id>T1211</id>
    </mitre>
  </rule>

  <rule id="110003" level="12">
    <if_sid>110002</if_sid>
    <regex type="pcre2">ldap[s]?|rmi|dns|nis|iiop|corba|nds|http|lower|upper|(\$\{\S*\w\}\S*)+</regex>
    <description>Log4j RCE attack attempt detected.</description>
    <mitre>
      <id>T1190</id>
      <id>T1210</id>
      <id>T1211</id>
    </mitre>
  </rule>
</group>

We also restarted the Wazuh manager to apply this rule:

systemctl restart wazuh-manager

Our agent system is running an Apache web server.

In some cases, Wazuh might not already be monitoring the web log files. We enabled log data collection by modifying the configuration group on the Wazuh server side. For this, we appended the following block to /var/ossec/etc/shared/default/agent.conf:

<localfile>
  <log_format>syslog</log_format>
  <location>/var/log/apache2/access.log</location>
</localfile>

To test this rule, we send a web request with known Log4Shell patterns to the monitored system. The request can be sent from any device that has network connectivity with the endpoint:

http://your_system_ip_address/?x=${jndi:ldap://${localhost}.{{test}}/a}

We immediately got it logged under security events.

Log4Shell injection

Conclusion

In summary, we have been able to detect the presence of the Log4Shell vulnerability by utilizing an SCA policy. We also created a rule that monitors the web access log to detect when a known exploit pattern exists in the web request.

This is useful for those who want to stay proactive by implementing measures that will alert when there is an indication of the Log4Shell vulnerability.