snapcast icon indicating copy to clipboard operation
snapcast copied to clipboard

Improve JSON-RPC security

Open AsbjornOlling opened this issue 3 years ago • 2 comments

Is your feature request related to a problem? Please describe. Any client with access to the JSONRPC API can execute arbitrary code on the host. This is a security problem.

I wrote a quick proof-of-concept, and it was astonishingly easy to get a reverse shell through snapcast. I can share it if you want, but I'm sure you can figure out roughly how it works. :wink:

In most installations, this means that anyone who can reach the host can execute code on it. I assume that most installations are only accessible on LAN, limiting the scope - but someone might want to set up snapcast over the internet, which would be a security nightmare right now.

It can be mitigated somewhat by limiting access to the host. One could set up a reverse proxy with HTTP Auth, or one could limit snapcast to being accessible over a VPN, as was suggested in issue #801. This can give the admin more control over who can access snapserver, but not without some inconveniences: running it over a VPN adds complexity to the whole setup, and makes it significantly harder to add clients ad-hoc. Limiting the server to HTTP/WS and adding HTTP Basic Auth makes it incompatible with many existing clients - including the android client.

And still: any client with audio streaming powers has code execution powers.

Describe the solution you'd like As far as I can tell, security isn't mentioned at all in the documentation. As long as it is insecure by default, it would be nice to inform users about this. The Mopidy docs have a nice warning for this exact situation. I think this would be a huge step forward in helping people make secure setups.

In terms of improving security at the protocol level, there are of course a number of ways to do it:

  • The configuration might include a field named something like read_only_rpc, which disables all the effectful RPC methods, like: SetVolume, SetLatency, SetName, SetMute, SetStream, etc. While this removes a bunch of features, it could be a quick-and-dirty way of locking down the server. I assume snapcast could still work without these RPC methods?
  • A snapcast-native password mechanism. If the snapserver were able to authenticate different users, it could also permit different functionality for different clients. I imagine a world where my speaker-attached clients can adjust their own volume, my laptop can do anything, and unauthenticated clients can do nothing.
  • Maybe just an option disable to the JSON-RPC alltogether?

Any of these likely represent a lot of implementation work, and I realize that I'm just pointing out issues without doing much of the solving :sweat_smile: But security is important, and I'm afraid that there are a lot of blatantly vulnerable snapcast installations out there.

Alternate Solutions I considered maybe making a service that intercepts JSON-RPC messages and enforces some authorization rules. It would also solve similar problems for Mopidy (and any other auth-less JSON-RPC services). I'm not sure I'll make it, or if I'll even get around to making it - but I think it's interesting.

Additional Context I want to use snapcast over the internet. It seems like snapcast is the the best streaming option for using Mopidy on-the-go. I love how easy it is to switch between listening devices when I'm out.

AsbjornOlling avatar Apr 22 '21 15:04 AsbjornOlling

I wrote a quick proof-of-concept, and it was astonishingly easy to get a reverse shell through snapcast. I can share it if you want, but I'm sure you can figure out roughly how it works. 😉

Are you referring to the RPC command Stream.AddStream?

badaix avatar Mar 26 '24 08:03 badaix

I started adding SSL support in the tls branch, which currently only allows HTTPS, WSS connections, next step is to re-enable plain HTTP/WS functionality.

Some ideas:

  • add HTTP Basic Auth for SSL connections
  • Continue supporting plain HTTP/WS RPC and streaming, but make RPC read-only per default config
  • have some user management, where certain RPC calls can be enabled/disabled per user (for SSL connections only)
  • Maybe deprecate RPC over plain TCP => Snapdroid must switch to HTTP(S)
    • at lease disable in the default config
  • Leave plain TCP streaming connections for the moment, as they are read-only

Not everything will be done at once, I think the next release will just add support for HTTPS/WSS. This is a prerequisite for things like auth and user management. Some careful transition path must be chosen to stay as backward-compatible as possible.

badaix avatar May 08 '24 13:05 badaix