Skip to content

Add Peyara Remote Mouse RCE Module#21491

Open
capture0x wants to merge 1 commit into
rapid7:masterfrom
capture0x:peyara-remote-mouse-rce
Open

Add Peyara Remote Mouse RCE Module#21491
capture0x wants to merge 1 commit into
rapid7:masterfrom
capture0x:peyara-remote-mouse-rce

Conversation

@capture0x
Copy link
Copy Markdown

This adds an exploit module for Peyara Remote Mouse v1.0.1 unauthenticated RCE.

The module connects to the Socket.IO WebSocket service on TCP port 1313 and sends unauthenticated keyboard events to open cmd.exe and execute a Windows command payload.

References:

Verification:

  • ruby -c modules/exploits/windows/misc/peyara_remote_mouse_rce.rb
  • Loaded successfully in msfconsole with loadpath
  • info/show options verified

@capture0x capture0x changed the title Peyara Remote Mouse RCE module Mouse RCE module Add Peyara Remote Mouse RCE module Mouse RCE module May 22, 2026
@capture0x capture0x changed the title Add Peyara Remote Mouse RCE module Mouse RCE module Add Peyara Remote Mouse RCE module May 22, 2026
@capture0x capture0x changed the title Add Peyara Remote Mouse RCE module Add Peyara Remote Mouse RCE Module May 22, 2026
require 'http/cookie'

class MetasploitModule < Msf::Exploit::Remote
Rank = NormalRanking
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why only NormalRanking?

end

def socketio_uri
"#{normalize_uri(target_uri.path, 'socket.io/')}?EIO=4&transport=websocket"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This should be probably inlined.

end

def socketio_uri
"#{normalize_uri(target_uri.path, 'socket.io/')}?EIO=4&transport=websocket"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The GET parameters should be passed with vars_get.


safe_wsclose(wsock)

return CheckCode::Appears('Socket.IO service on the Peyara Remote Mouse port returned an Engine.IO open frame') if open_frame&.start_with?('0')
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Does this mean that the application is definitely vulnerable? Is there a way to detect a version?

Comment on lines +106 to +109
unless open_frame&.start_with?('0')
safe_wsclose(wsock)
fail_with(Failure::UnexpectedReply, 'The service did not return a Socket.IO open frame')
end
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is already checked in check, no need to check it here as well.

Comment on lines +126 to +128
def socketio_event(event, data)
"42#{JSON.generate([event, data])}"
end
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You can inline this

Comment on lines +68 to +69
OptFloat.new('KEY_DELAY', [true, 'Delay between keyboard events in seconds', 0.2]),
OptFloat.new('WINDOW_DELAY', [true, 'Delay after opening the command prompt in seconds', 1.0]),
Copy link
Copy Markdown
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 parameters needs to be stored as datastore, you can use fixed delay probably

Comment on lines +79 to +83
def safe_wsclose(wsock)
wsock&.wsclose
rescue StandardError
nil
end
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why not inline this?

nil
end

def recv_wstext(wsock, timeout = datastore['WS_TIMEOUT'])
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why do you need to pass WS_TIMEOUT as parameter rather than use it directly?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

3 participants