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.
localhost:27060
. {
"message": "OpenSteamURL",
"url": "steam://openurl/https://store.steampowered.com/app/1517290/Battlefield_2042/?utm_bid=3546095213808494257",
// removed
}
There are only a few ways to bypass those browser security controls and it's almost always a WebSocket.
F12
to open Developer Tools (I assume you're using a Chromium based browser).Network
tab.ctrl + F5
to refresh the page.Open in Desktop
. Switch back to Dev Tools.HTTP Proxy
.Status
column to sort by the response status code.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.
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
.
This is actually the Steam protocol handler. And that can also lead to a bunch of RCEs.
Exit Steam
.F12
to open DevTools for this page and select the Console
tab.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:
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."
The moment you see a local web server or WebSocket server, you need to open Burp
and change the Origin
header.
101
response header).ctrl + r
thanks to Agarri's Burp course.ctrl + shift + r
.Origin
header to something else like https://example.net
.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
Here are a bunch of references:
Obviously, there's more, but I am le tired. Thanks for reading and you know where to find me.