Full Report
The author of this post had recently found an RCE in a VPN client called SuperShy. After finding this bug, they were curious about other services that exposed WebSockets locally on their system. They noticed that CurseForge was doing this, a widely used video game modding platform. To actually find the websocket, they used something like Wireshark to see what was going on. Every time CurseForge was launched, they would see a payload for a typical launch message. Notably, it had AdditionalJavaArguments inside of it, a type and a Name that looked like Java functions. Websockets are not bound to the Same Origin Policy (SOP) as HTTP requests are. As long as the server allows requests from any origin, it's allowed. The message contained no origin check, no authorization mechanism, or anything else. So, they tried connecting from a Websocket with a bogus origin header, and it worked. This means the application can be accessed from any website the user visits. Neat! There were several actions but a single one stood out: minecraftTaskLaunchInstance. It contains a parameter for arbitrary additional Java arguments that is used to start the game. Another interesting one is createModpack. This is creating a modpack on the user's system. This is required because we need a valid modpack to call minecraftTaskLaunchInstance with. The author used a clever trick to trigger arbitrary code. First, they pass -XX:MaxMetaspaceSize=16m; this limits the JVM's memory space. Since the JVM crashes, it will call an out-of-memory handler, which can be anything. The second flag is -XX:OnOutOfMemoryError="cmd.exe /c calc", that gets triggered on crash. The CurseAgent doesn't bind its WebSocket server to a fixed port. It listens to a randomly assigned local port whenever the launcher starts. So they wrote a JavaScript scanner that scans 16K ports to find this. Good write-up! To fix the bug, CurseForge no longer exposes the WebSocket server; I don't know what they use for this functionality instead.
Analysis Summary
# Vulnerability: Remote Code Execution via Unauthenticated Local WebSocket in CurseForge
## CVE Details
- **CVE ID**: Not specified (Assigned/tracked internally by CurseForge)
- **CVSS Score**: Estimated 8.8 (High) - [CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H]
- **CWE**: CWE-346 (Origin Validation Error), CWE-94 (Improper Control of Generation of Code)
## Affected Systems
- **Products**: CurseForge Desktop Launcher
- **Versions**: Versions prior to 1.289.3
- **Configurations**: Default installations where `CurseAgent.exe` exposes a local WebSocket server.
## Vulnerability Description
The CurseForge launcher utilizes a background process, `CurseAgent.exe`, which opens a WebSocket server on a random local port. This server failed to implement any **Origin validation** or **Authorization mechanisms**.
Because WebSockets are not restricted by the Same-Origin Policy (SOP) in the same way as standard HTTP requests, any website visited by a user could initiate a connection to the local WebSocket server. Attackers could then invoke sensitive methods, specifically `minecraftTaskLaunchInstance`, which accepted an `AdditionalJavaArguments` parameter. This allowed for the injection of arbitrary JVM flags.
## Exploitation
- **Status**: PoC available (Publicly disclosed by researcher)
- **Complexity**: Medium (Requires a port-scanning script to identify the dynamic WebSocket port)
- **Attack Vector**: Network (Via a malicious or compromised website visited by the user)
Technique used:
1. **Discovery**: A JavaScript-based scanner probes ~16,000 local ports to find the active WebSocket.
2. **Modpack Creation**: Connection to `createModpack` to obtain a valid GUID.
3. **Execution**: Using `-XX:MaxMetaspaceSize=16m` to force a crash and `-XX:OnOutOfMemoryError="cmd.exe /c calc"` to execute OS commands upon that crash.
## Impact
- **Confidentiality**: High (Attacker can execute commands to steal local files)
- **Integrity**: High (Attacker can modify system files or install malware)
- **Availability**: High (Attacker can crash the application or the system)
## Remediation
### Patches
- **CurseForge App Version 1.289.3**: This version and subsequent updates contain a fix that adds origin checking and/or removes the exposed WebSocket functionality.
### Workarounds
- Ensure the CurseForge launcher is closed when browsing untrusted websites.
- Use browsers with strict private network access controls (though the port-scanning technique often bypasses basic filters).
## Detection
- **Indicators of Compromise**: Unexpected `calc.exe` or `cmd.exe` processes spawned as children of the Minecraft/Java process.
- **Detection Methods**: Monitor local loopback traffic (127.0.0.1) for unauthorized WebSocket handshakes with non-standard origin headers.
## References
- **Researcher Write-up**: hxxps://elliott[.]diy/blog/curseforge-rce/
- **Vendor Release Notes**: hxxps://blog[.]curseforge[.]com/app-release-notes-1-289-3/
- **PoC Source**: hxxps://github[.]com/elliott-diy/curseforge