CapOne-Zeek-Docker/capitalone/detect/log4j/CVE_2021_44228_java_GET.zeek
Patrick Kelley 04da5c1250 Inital
2025-05-28 14:31:31 -04:00

75 lines
3.4 KiB
Plaintext

module CVE_2021_44228;
# Refer to the following for a description of the method used in script.
# https://corelight.com/blog/detecting-log4j-exploits-via-zeek-when-java-downloads-java
redef enum Notice::Type += {
LOG4J_JAVA_CLASS_DOWNLOAD,
};
redef record HTTP::Info += {
CVE_2021_44228_content_type: string &optional;
CVE_2021_44228_detected: bool &default = F;
};
# Anchoring Java at ^, as have only seen sample attacks with this.
global java_UA_pattern : pattern = /^Java\//;
# Adding java-serialized-object out of caution. Unsure if it can be used, but have not seen legit use except with POST method
global java_mime_pattern_header: pattern = /java-vm|java-serialized-object/i;
global java_mime_pattern_sniffed: pattern = /java-applet/;
# The first check uses the Server's HTTP Content-Type header
event http_header(c: connection, is_orig: bool, name: string, value: string)
{
if (!c$http?$method || (c$http?$method && c$http$method!="GET"))
return;
if (is_orig)
return;
if (c$http?$CVE_2021_44228_content_type)
return;
if (name == "CONTENT-TYPE" && java_mime_pattern_header in value)
{
c$http$CVE_2021_44228_content_type = value;
if (c$http?$user_agent && java_UA_pattern in c$http$user_agent)
{
c$http$CVE_2021_44228_detected = T;
add c$http$tags[LOG4J_RCE];
NOTICE([$note=LOG4J_JAVA_CLASS_DOWNLOAD,
$conn=c,
$identifier=cat(c$id$orig_h,c$id$orig_p,c$id$resp_h,c$id$resp_p),
# $suppress_for=3600sec,
$msg=fmt("Possible Log4j CVE-2021-44228 exploit, Java has downloaded a Java class over HTTP indicating a potential second stage, after the primary LDAP request. Refer to sub field for user_agent and mime-type"),
$sub=fmt("user_agent='%s', CONTENT-TYPE='%s', host='%s'", c$http$user_agent, c$http$CVE_2021_44228_content_type, split_string1(c$http$host, /:/)[0])]);
}
}
}
# The second check uses the sniffed resp_mime_types, which can differ from the Server header.
event http_message_done (c: connection, is_orig: bool, stat: http_message_stat)
{
if (c$http$trans_depth > 1)
return;
if (is_orig)
return;
if (!c$http?$resp_mime_types)
return;
# If we've already raised the notice via the Server's Content-Type header check, return
if (c$http$CVE_2021_44228_detected)
return;
if (c$http?$user_agent && java_UA_pattern !in c$http$user_agent)
return;
local resp_mime_types_string = join_string_vec(c$http$resp_mime_types, ",");
if (java_mime_pattern_sniffed in resp_mime_types_string)
{
local user_agent: string = "";
if (c$http?$user_agent)
user_agent = c$http$user_agent;
add c$http$tags[LOG4J_RCE];
NOTICE([$note=LOG4J_JAVA_CLASS_DOWNLOAD,
$conn=c,
$identifier=cat(c$id$orig_h,c$id$orig_p,c$id$resp_h,c$id$resp_p),
# $suppress_for=3600sec,
$msg=fmt("Possible Log4j CVE-2021-44228 exploit, Java has downloaded a Java class over HTTP indicating a potential second stage, after the primary LDAP request. Refer to sub field for user_agent and resp_mime_types"),
$sub=fmt("user_agent='%s', resp_mime_types='%s'", user_agent, resp_mime_types_string)]);
}
}