This is not a bug, but some notes about the new Steam "Open in Desktop" button. I am going to show how to look for bugs in these kinds of browser-to-desktop interactions.
When you go to a game's Steam page in the browser, you get this button.
Clicking on it, will open the game page in the Steam desktop app.
Every time you see a web to app transition without any user notification, a security control has been circumvented. Whether this is good or bad is not the objective here.
Summary: How does it Work?
- WebSocket connection from the web page to the Steam desktop app at
localhost:27060
. - Web page passes a message like this to the desktop app.
{ "message": "OpenSteamURL", "url": "steam://openurl/https://store.steampowered.com/app/1517290/Battlefield_2042/?utm_bid=3546095213808494257", // removed }
- Steam desktop opens the page URL.
How Can I Also See It?
There are only a few ways to bypass those browser security controls and it's almost always a WebSocket.
- Go to the BF 2042 page at https://store.steampowered.com/app/1517290/Battlefield_2042/.
F12
to open Developer Tools (I assume you're using a Chromium based browser).- Edge annoyingly asks if you actually want to open DevTools. Check the box so it doesn't ask again.
- Switch to the
Network
tab. ctrl + F5
to refresh the page.- Click on
Open in Desktop
. Switch back to Dev Tools. - There will be a bunch of junk here that we have to sift through.
- Optionally, you could use Burp and filter these in
HTTP Proxy
.
- Optionally, you could use Burp and filter these in
- Click on the
Status
column to sort by the response status code. - See this
101
on top? That's what we want.
It's even conveniently named openindesktopclient.js
. Click on it to see the
header, request, response, and messages.
101 is the response code for switching protocols. While the Protocol upgrade mechanism is technically protocol agnostic, I have only seen it in WebSocket connections. Upon further searching, it looks like it can also be used to upgrade an HTTP/1.1 connection to HTTP/2.
I Wanna See the WebSocket Messages
You can click on the Message
tab in the previous image or go the Network
tab
of DevTools Click WS
. You can even filter messages by connection (which is
supposedly useful if you have multiple ones in the same page which I've never
seen).
The 3rd message is the one that opens the page.
{
"message": "OpenSteamURL",
"url": "steam://openurl/https://store.steampowered.com/app/1517290/Battlefield_2042/?utm_bid=3546095213808494257",
"universe": 1,
"accountid": 0,
"sequenceid": 2
}
If you want to see which process is doing this, run netstat -anb
in an admin
prompt and look for who is listening on 127.0.0.1:27060
. It's steam.exe
.
Protocol Handlers
This is actually the Steam protocol handler. And that can also lead to a bunch of RCEs.
- Close Steam. As in right-click on the taskbar icon and select
Exit Steam
. - Run Process Monitor.
- Press
F12
to open DevTools for this page and select theConsole
tab. - Click on this link. Hover you mouse over it to see the actual link matches the caption.
- See the browser pop-up that asks if you want to open Steam.
- If you click on
Open Steam
, Steam desktop will open and navigate the BF 2042 page.
You can see the protocol handler in the Console
tab of DevTools.
Steam is actually executed with this protocol handler as the parameter. Switch
to Procmon and press ctrl + t
or Tools (menu) > Process Tree
. Procmon is
cutting off the complete parameter in the screenshot.
This blog is just trying to show where to look for these things. If you want to learn more please start with the following links:
- Eric Lawrence's (he also wrote Fiddler) excellent blog: Web-to-App Communication: App Protocols.
- a Attack Surface Analysis - Part 2 - Custom Protocol Handlers.
Why Use a WebSocket?
A WebSocket is the most common way to bypass the annoying protocol handler dialog because it's not bound by the Same Origin Policy.
It's not always a WebSocket server. Here's a bug by Jonathan Leitschuh where it turns out Zoom was using a local web server (that even remained on the machine after removing Zoom) to do "seamless transition."
So How do I Find Bugs Here?
The moment you see a local web server or WebSocket server, you need to open Burp
and change the Origin
header.
- Go to the website in Burp.
- Select the WebSocket handshake request (the one with the
101
response header). - Send to Repeater. Hint:
ctrl + r
thanks to Agarri's Burp course. - Switch to Repeater. Hint:
ctrl + shift + r
. - Change the
Origin
header to something else likehttps://example.net
. - ???
- Click send.
If this goes through then you have a bug. You can connect to the local WebSocket server from any website and send requests.
But in this case, we cannot. Fiddle with the Origin
header and see what is
accepted. It's only https://store.steampowered.com
and not even other subdomains.
This means it's not vulnerable (at least from this attack surface). This issue is so common that is even has its own specific CWE: CWE-1385: Missing Origin Validation in WebSockets.
Note the browser sets the Origin
header and it cannot be modified by
JavaScript because it's a Forbidden Header.
But what if I have a malicious local app? If you're running a local app that
wants to spoof the Origin
header then you have bigger problems.
But muh persistence tradecraft! lol, shut up!
There are other way to do web-to-app communication apart from protocol handlers and WebSockets. See Browser Architecture: Web-to-App Communication Overview
How about You Show Us Some Actual Bugs!
Here are a bunch of references:
- Websites Can Run Arbitrary Code on Machines Running the ‘PlayStation Now’ Application.
- The images were not disclosed the report, but the H1 report starts from scratch and shows how to find an RCE in a local WebSocket server.
- CVE-2021-43907 - Remote Code Execution in Visual Studio Code's Remote WSL Extension
- This is basically the same bug as before.
- See me and a bunch of people from HackerNews complain about MSRC.
- localghost: Escaping the Browser Sandbox Without 0-Days
- Tavis Ormandy found a similar issue in Logitech Options
- Full Steam Ahead: Remotely Executing Code in Modern Desktop Application Architectures by Thomas Shadwell in Infiltrate 2019.
Obviously, there's more, but I am le tired. Thanks for reading and you know where to find me.