Skip to content

Security Issue: Allow changing of binding options to decrease attack vectors #907

Open
@mitchcapper

Description

@mitchcapper

Operating System Info

Other

Other OS

No response

OBS Studio Version

Other

OBS Studio Version (Other)

No response

obs-websocket Version

Git

OBS Studio Log URL

n/a

OBS Studio Crash Log URL

No response

Expected Behavior

n/a

Current Behavior

n/a

Steps to Reproduce

/na

Anything else we should know?

Before the details I figured start with why this matters, what is the attack surface this plugin exposes and what is at risk if a malicious user (you below) can successfully execute commands:

  • You can create new scenes/captures of the users entire desktop for example, and then start a remote stream or save the recording remotely.
  • You can write files to the local disk at arbitrary paths you specify (save screenshot for example)
  • You can remotely listen to any audio input (microphone) or output on the users pc
  • Trigger absolutely any OBS hot key the user has setup
  • Read the users configuration for scenes/sources/profiles/stream services/etc (not sure if this could have sensitive information embedded but it looks like it could contain keys)
  • Read images/videos from anywhere on the users computer. You do not need to know the name of the image/video you want to see just using the slideshow functionality you can read entire directories of images/videos. For example trying common paths for storage/sync services like google drive, dropbox, onedrive, or just the users Pictures and Videos folder in their private account.
  • Read other files from the computer, I have no idea on OBS's full capabilities but I at least see a "Text Source" option which I believe can easily access any UTF-8 encoded file.
  • I don't see an obvious 'execute random OS command or application' but OBS supports such a massive source of inputs and outputs I might be missing the easy method of doing this.
  • OBS does not run in a lower security context, a sandbox, or drop the user's credential tokens (I believe) so likely anything the user has network access to is also fair game (ie a user on a corporate network having all file share access available).
  • The fact: All code contains bugs, some bugs can lead to remote code execution / full system access, unmanaged languages like C/C++ (what this plugin is written in) are more likely to be subject to corruption/off by one exploits. You have rolled your own security / web socket authentication method (sadly a downside of there not being a standard), meaning less eyes are probably on that code than more standardized code. You have to allow the user to connect and issue certain commands before you get to authentication, so there is already more potential vulnerability (and parsing of arbitrary json or MsgPack binary data that the client sends) than say a TLS client cert auth stack.

The above could also contain errors (or miss other things), as I am not really an obs user and just briefly looked at the remote API as part of something else. Some of the above may be possible to enable and disable before the user only noticed. For continuous monitoring the only way a user may notice is the red dot in the OBS systray icon (which windows hides by default) or randomly checking the OBS window. I did notice the 5x plugin added a windows toast option on initial connect (and client list, but rarely would someone look at the client list). It looks like toast is off by default (although even with it unchecked on my new install I still get the toasts so not sure).

You are about to become embedded in every OBS install by default (although I assume/hope off by default). This by no means is about removing the above functionality but hopefully reducing the attack surface for these things may be available through.

Now for the details of the ticket:

Sorry I don't actually use OBS but from some quick googling I didn't see another avenue for reporting security issues. I was casually looking at another project that uses this plugin and noticed the global binding by default. I also saw @bdrung in #778 made a simple enough request, allow binding the web socket to localhost. @tt2468 shot this down saying they didn't see much use for this, there is password auth and websites can abuse even local only sockets with their own code. Something else that might have helped was #54 which was deemed unneeded as password by default was added (although that feature served another purpose). Ironically @notr1ch in #424 (comment) pointed out some of the very real security issues that exist with obs (when this plugin is enabled).

There are several relevant points:

  • Security is about layers and you largely relying on a single one, a password
  • If a security feature can narrow an attack surface even if not completely eliminating it, it should be considered. With notice to potential false senses of security (oh I bind to the local IP so no password access is just fine).
  • Browsers do pose a very real security risk to internal web servers this is why more security restrictions are coming: https://developer.chrome.com/blog/private-network-access-update/ / https://wicg.github.io/private-network-access/ still if this is the only likely vulnerable path that is still a massive footprint reduction from anyone with network access
  • Password required, was NOT the default until a year ago. In addition from the notes on the 5 beta it seems it may not have always been set to non-empty when this change happened. If some of these other features were used, users may have been far less vulnerable (or still are if they have not upgraded or potentially are not running the beta)
  • Given the list of 3rd party apps that you post planning to work with 5.0 I can only imagine a whole lot more use this product. Some of them may encourage or require users to use this plugin without a password. While you cannot stop users (or 3rd party apps) potentially from requiring stupid things you can still reduce that attack footprint.
  • In Please support running websocket on localhost #778 they said hey, just block it at a firewall level. Fair enough, but this is very advanced and 99% of your users won't know how to do this. Default windows users normally have one chance to obviously do this, that is on first startup with this plugin enabled, however almost all users will click allow access here without understanding what they are allowing. For one, as Windows Defender doesn't know what the required access is for, the user has virtually no information to make an informed decision even if they tried. It just says "Windows defender firewall has blocked some features of OBS Studio on public and private networks" do you want to allow?. Given OBS is often used for streaming I highly doubt most users would ever say no to that.

Suggestions:

  • For browsers give an option if users want to allow them. With the upcoming changes which will require " Access-Control-Allow-Private-Network" when network boundaries are crossed: https://developer.chrome.com/blog/private-network-access-preflight/#what-is-private-network-access / https://web.dev/cors-rfc1918-feedback/ sadly the first chrome restrictions will not completely cutoff local access according to the specs above, but it is in theory coming. In the mean time X-XSS-Protection block, and reject WS requests with Origin headers that are not a localhost alias are decent methods to block browsers. I think blocking browsers would need to be an option not a always, as I believe some of the apps that use the web socket are browser hosted, but the local origin requirements likely work.

  • For the love of god allow users to bind to localhost only, it is a simple checkbox you need to add (or better default to on) and massively reduces the attack surface. Otherwise a user on a random public wifi network (or god forbid a publicly routed computer) are instant targets. It also likely satisfies a large portion of your users needs without restricting them.

  • Randomize the port for the socket when the password is randomized. You are going to use the QR code or have to remotely configure your apps at that point anyway, might as well enter port number then too. While this is more obfuscation, it greatly increases the time to scan large amounts of IP's for OBS instances.

  • There are near 0 conditions I can imagine this websocket should ever be accessed through a router. It is not a secure web socket, there is no certificate options, if you are using a proxy infront of it that does not count as routed through a router (in most normal setups). Please take advantage of boost::asio::socket_base::do_not_route option(true); if you really have a use case to have routed packets give the user a checkbox for allowing public routed access to the web socket but again, probably a bad idea as users don't often know what they are doing.

  • There are a slew of more complicated additions of any large footprint API system like allowing scoped api access (I may need my phone to be able to change to existing scenes remotely but not create entirely new scenes or save random things to my hard drive). Per client approval on initial connect, suggested in one of the bug reports above (you don't need to fingerprint the client just issue them back a secret token to identify themselves on future connections, this also gives the user an opportunity to name that connection at initial creation). For browser based clients another option here is to force the web socket connect request to include a ticket/token that it first obtains with a normal HTTP request to the server. This has the great benefit of allowing all the standard cross site scripting header/request prevention mechanisms to work that don't work over the web socket.

  • Consider requiring a startup parameter for really insecure setups, just like you don't allow the debug command to be stuck on, show a message box on every startup of users who do something like an unauthenticated web socket with public routing enabled unless a command line arg is passed (--web-socket-allow-complete-unathed-access-to-my-files anyone;)). Might be helpful to let users know that anyone with web socket abilities can read/write their files and likely capture them remotely (also might be a nice warning when the user is setting the socket password). Another security improvement is requiring passwords (or change the terminology to say an API key) and only allow it to be randomly generated (with a regenerate button). Users are bad at picking passwords.

  • Given how vulnerable old versions might be and now being an in-house plugin, a warning on detected old insecure versions may be a good idea.

Some of these suggestions are breaking changes, and users clients would potentially stop working (ie for randomized port if retroactively applied). The great news is you are coming up on V5 that is ALREADY going to break things, so take advantage. IE Rather than require the use of port 4455 randomize it at upgrade.

Clearly do what you like with this information / suggestions I am no expert here, just offering some incite that might be useful.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions