obsproject / obs-websocket

Remote-control of OBS Studio through WebSocket
GNU General Public License v2.0
3.92k stars 708 forks source link

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

Open mitchcapper opened 2 years ago

mitchcapper commented 2 years ago

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:

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 https://github.com/obsproject/obs-websocket/issues/424#issuecomment-763240944 pointed out some of the very real security issues that exist with obs (when this plugin is enabled).

There are several relevant points:

Suggestions:

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.

tt2468 commented 2 years ago

Reopening this as we decided to revert the previously committed solution out of caution for user experience.

The going idea right now is to implement a token system for clients, where new clients can optionally (default) be required to be manually approved by the user before they can be allowed. obs-websocket would provide a token upon successful authentication, which the client would save, then pass it to obs-websocket along with correct authentication details to avoid popups in the future.

Basically, a default-enabled feature that warns the user when an unrecognized client connects, but not after subsequent connects. Changing the WebSocket server password would invalidate all tokens.

root-goblin commented 2 years ago

Would it be reasonable keep both the default as open to external connections, and also retain the option to close external connections (serve over localhost only). This would prevent breakage for users that depend on the existing behavior, but also keep open an upgrade path for the ecosystem to slowly move toward secure-by-default.

Edit: this has already been pointed out as a solution in the original issue

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.

mitchcapper commented 2 years ago

OBS can act as massive spyware for anyone who can remote control it. Breaking insecure remote connections to warn the user probably is a more reasonable solution (at a minimum users without a password set). Keep in mind that is also only remote connections which I would have a hard time figuring is more than a very small fraction of the user base. Without local bind by default most users are far more exposed than they likely know.

JorianWoltjer commented 2 months ago

This issue still seems to be an active problem. I found this same vulnerability independently and also failed to find a security contact until I came across this GitHub issue. I would like to add that it is possible to reliably get Remote Code Execution on a victim who visits a malicious public site (eg. attacker.com) all in the background. This is a big risk for the small percentage of people using the 'No authentication' setting.

I am happy to disclose the full code execution method privately but won't post it here publicly yet. I think the research is useful to others so I will publicize it later, hopefully after OBS has fixed the issue.

mitchcapper commented 2 months ago

This issue still seems to be an active problem.

Yes they were going to partially fix this but, as often the case, security lost to convenience.

I would like to add that it is possible to reliably get Remote Code Execution

Yes as well, OBS is crazy powerful in terms of the myriad of ways you can get output/input interact with other processes (including using triggers), and spy on the user all before you even consider 3rd party plugins.

They should have sucked it up and said in version X we are going to require tokens (either through an updated token system or even older apps have been given tokens through the password interface). Then for that version a welcome on first launch saying hey you have remote access enabled we are going to restrict it to the localhost interface by default and non-updated apps will need to manually have a token password input into them and updated apps you will just have to hit approve on.

It is a pain but the web socket is part of the official OBS now and has massive holes that allow for some crazy user abuse.

It is going to be those spam emails come true, I have been watching the sites you visit and have you on camera using your own software, and their tip at the end will be 'enable a password and local only bind in OBS for the future' hahaha.

mitchcapper commented 2 months ago

Also, the chrome changes that would have helped prevent some of the exploit vectors if we set the right headers got pushed way back. What was going to be in shortly in 2022, is still not a thing in 2024: https://wicg.github.io/private-network-access/

chromes latest update (some things happened in the 130 just released but still quite rolled back): https://developer.chrome.com/blog/private-network-access-update-2024-03

FlyingFathead commented 1 week ago

I just stumbled upon OBS's WebSocket server and am genuinely baffled that binding to 127.0.0.1 (local loopback) by default hasn't been implemented yet.

This is an egregious oversight and a significant security risk. By default, the WebSocket server should only listen on the local loopback (127.0.0.1), with options to change this for other use cases.

Like others have noted, allowing it to bind to all interfaces (0.0.0.0) by default is reckless and exposes users to unnecessary risks, especially given how powerful OBS is as a potential attack vector.

The fact that there is no way to change the bind address natively (short of duct-taping a solution with iptables, nginx, etc.) is unacceptable.

This needs to be patched as a priority.

What were the developers thinking when this decision was made?

mitchcapper commented 1 week ago

The fact that there is no way to change the bind address natively

I don't use OBS but my understanding was that you should be able to change the bind address just not defaulted to localhost.

What were the developers thinking when this decision was made?

The same thing everywhere always, convenience trumps security.

What is sad is that when I filed this ticket V5 was going to be a breaking release and would have been the perfect time to enable additional security. At a minimum they could have enabled token based approval for new installs.