XSS in steam react chat client

 Resolved (Closed)
DisclosedJanuary 8, 2019 4:00am +0800
Reported ToValve



WeaknessCross-site Scripting (XSS) - Stored
SeverityCritical (9.3)
  • Disclosed (Full)


Summary by zemnmez

1. Background

The Steam Chat client is a particularly interesting system to attack because it's built using a modern set of technologies with strong security characteristics.

It's built on React, which has some of the strongest security characteristics of any modern Javascript application framework, and avoids use of the unsafe dangerously family of functions well.

Content Security Policy is deployed, although with unsafe-inline. This is a minor inconvenience but an interesting step forward.

The Chat client, unlike most desktop applications using web technologies runs in a custom, highly locked down build of Chrome Embedded Framework. In most Electron-like systems, privileged access is granted to the Javascript VM via the window object. The chat client takes the interesting and potentially much more secure approach of running at, in essence the privilege of a regular webpage allowing privileged actions only through PostMessage and a loopback WebSocket that communicates with the parent process.

The WebSocket carries a custom binary protocol that is very difficult to dissect over the wire and it's leveraged such that through some common bug I have yet to find root cause on Chrome Dev Tools crashes if breakpoints fire as the page loads (I think it's some kind of race that happens when WebWorkers are active and the Javascript assets are heavy).

The trend toward DOM heavy applications is interesting to me, as many in the security industry still rely heavily on HTTP proxies that aren't able to accurately reflect application state in these cases.

2. Techniques

2a. React Security Gotchas

Since the Steam Chat client is built on React, there's far fewer ways XSS is possible. There are a few ways I look for particularly:

  • React does not special-case encode the attributes of any tags. Attributes with DOM manipulation properties are dangerous.

    It's very common to see <a href> attributes generated from user input where javascript: input URIs, when clicked will result in XSS. Hand-rolled countermeasures to javascript: URIs are still poor, and often employ URL parsers that are not intended to be used defensively.

    It's not uncommon to see style tags generated by string concatenation that include user input where an image, for example as a background URL can be injected to IP address information and tokens from the URL via Referer header. CSS sanitization isn't really a thing, even in the best contextually-aware XSS libraries. CSS-based attacks on the DOM that use selector[value=string] or that define fonts that make HTTP requests for each character to conditionally load resources and exfiltrate data are almost entirely unknown outside infosec circles.

  • React doesn't attempt to provide hardened versions of other unsafe Javacript functionality, or disable them. It's common to see React applications use document.location = xxx to change the location of the browser which is also vulnerable to Javascript URI injection.

    In the same vein, requests to HTT…

Show more


zemnmez submitted a report to Valve.

Sep 15th (4 months ago)

The Steam chat client both sends and receives bbcode format chat messages. These map to HTML elements, and notably the [url] bbcode tag is supported for arbitrary URLs. React has strong XSS mitigations but does not mitigate javascript: URI based XSS.

This is rather difficult to exploit as the client transmits sanitised messages and receives over a binary WebSocket. I've attached a video of executing this XSS, which is persistent.


I strongly believe an attacker could get remote code execution in Steam via this method. The Steam chat client uses the same codebase as the steam web chat client, and, I imagine does so using electron or some other webview system. These systems all expose functions which allow arbitrary calls to system to allow them to be competitive with e.g. windows forms.

bgilmore posted a comment.

Sep 15th (4 months ago)

Hi @zemnmez

Thanks for your submission. We are currently reviewing your report and will get back to you once we have additional information to share.

zemnmez posted a comment.

Sep 15th (4 months ago)

OK. so there's a trivial way to reach RCE using this bug. From my tests, because the Steam Chat Client is run inside the Steam CEF context, any steam:// commands it issues (through uri syntax) are immediately evaluated and trusted (whereas if they're issued from a browser there's a confirmation window) as though they were issued from e.g. the game listing inside the steam client.

You can issue, therefore steam://run/[GAMEID] and it will run any installed game, without confirmation, and with command line parameters

bgilmore posted a comment.

Sep 18th (4 months ago)

Thanks for the additional details — we will consider the additional impact of steam:// URLs when determining final report severity. However, I do want to note that launching an installed app isn't enough to qualify as generalized RCE unless you can demonstrate a way to use that functionality to run arbitrary code.

Thanks again for your report. We should have more information soon.

zemnmez posted a comment.

Updated Sep 18th (4 months ago)

I believe you can use the XSS to accept a game invite via ackguestpass, use remoteactions to remotely install it, then issue a steam:// url to run it

zemnmez posted a comment.

Sep 23rd (4 months ago)

as per my research in https://hackerone.com/reports/411329#activity-3375819 you can use the openexternalforpid protocol i.e. steam://openexternalforpid/10400/file:///C:/Windows/cmd.exe to remotely initiate process calls on the victim's PC. I can provide another PoC video of this if needed, but the TL;DR is you can use the previously mentioned bug to send [url=steam://openexternalforpid/10400/file:///C:/Windows/cmd.exe]click me[/url] and you win :)

afarnsworth updated the severity from Critical to Critical (9.6).

Oct 2nd (4 months ago)

afarnsworth posted a comment.

Oct 2nd (4 months ago)

We have removed the ability to send [url] tags for anything but http links, however we are still working on a fix for steam://openexternalforpid in general to prevent that to be abused.

jonp updated the severity from Critical (9.6) to Medium (6.3).

Oct 2nd (4 months ago)

jonp updated the severity from Medium (6.3) to High (7.6).

Oct 2nd (4 months ago)

afarnsworth updated the severity from High (7.6) to Critical (9.3).

Oct 2nd (4 months ago)

jonp closed the report and changed the status to Resolved.

Oct 6th (4 months ago)

Thanks for the report! We have deployed a fix to the Steam Client Beta. Please let us know if you are still able to reproduce the issue.

Valve rewarded zemnmez with a $7,500 bounty.

Oct 6th (4 months ago)

zemnmez requested to disclose this report.

Jan 3rd (21 days ago)

bgilmore agreed to disclose this report.

Jan 8th (16 days ago)

This report has been disclosed.

Jan 8th (16 days ago)




2020-2-13 22:10:34



2020-2-13 22:10:59

0 条回复 A文章作者 M管理员
有新私信 私信列表
有新消息 消息中心