New issue
Advanced search Search tips
Starred by 2 users

Issue metadata

Status: Fixed
Owner:
Closed: Jan 11
Cc:



Sign in to add a comment

transmission: rpc session-id mechanism design flaw

Project Member Reported by taviso@google.com, Nov 30 2017

Issue description

The transmission bittorrent client uses a client/server architecture, the user interface is the client and a daemon runs in the background managing the downloading, seeding, etc.

Clients interact with the daemon using JSON RPC requests to a web server listening on port 9091. By default, the daemon will only accept requests from localhost.

A sample RPC session looks like this:

$ curl -H 'X-Transmission-Session-Id: foo'  -sI '{}' http://localhost:9091/transmission/rpc
HTTP/1.1 409 Conflict
Server: Transmission
X-Transmission-Session-Id: JL641xTn2h53UsN6bVa0kJjRBLA6oX1Ayl06AJwuhHvSgE6H
Date: Wed, 29 Nov 2017 21:37:41 GMT

$ curl -H 'X-Transmission-Session-Id: JL641xTn2h53UsN6bVa0kJjRBLA6oX1Ayl06AJwuhHvSgE6H'  -d '{"method":"session-set","arguments":{"download-dir":"/home/user"}}' -si http://localhost:9091/transmission/rpc
HTTP/1.1 200 OK
Server: Transmission
Content-Type: application/json; charset=UTF-8
Date: Wed, 29 Nov 2017 21:38:57 GMT
Content-Length: 36

{"arguments":{},"result":"success"}

As with all HTTP RPC schemes like this, any website can send requests to the daemon with XMLHttpRequest, but the theory is they will be ignored because requests must read and request a specific header, X-Transmission-Session-Id. Unfortunately, this design doesn't work because of an attack called "dns rebinding". Any website can simply create a dns name that they are authorized to communicate with, and then make it resolve to localhost.

The attack works like this:

1. A user visits http://attacker.com.
2. attacker.com has an <iframe> to attack.attacker.com, and have configured their DNS server to respond alternately with 127.0.0.1 and 123.123.123.123 (an address they control) with a very low TTL.
3. When the browser resolves to 123.123.123.123, they serve HTML that waits for the DNS entry to expire, then they XMLHttpRequest to attack.attacker.com and have permission to read and set headers.

You can test this attack like this, I have a domain I use for testing called rbndr.us, you can use this page to generate hostnames:

https://lock.cmpxchg8b.com/rebinder.html

Here I want to alternate between 127.0.0.1 and 199.241.29.227, so I use 7f000001.c7f11de3.rbndr.us:

$ host 7f000001.c7f11de3.rbndr.us
7f000001.c7f11de3.rbndr.us has address 127.0.0.1
$ host 7f000001.c7f11de3.rbndr.us
7f000001.c7f11de3.rbndr.us has address 199.241.29.227
$ host 7f000001.c7f11de3.rbndr.us
7f000001.c7f11de3.rbndr.us has address 127.0.0.1

Here you can see the resolution alternates between the two addresses I want (note that depending on caching it might take a while to switch, the TTL is set to minimum but some servers round up).

I just wait for the cached response to expire, and then POST commands to the server.

Exploitation is simple, you could set script-torrent-done-enabled and run any command, or set download-dir to /home/user/ and then upload a torrent for ".bashrc". 

Here is my (simple) demo:

http://lock.cmpxchg8b.com/Asoquu3e.html

See screenshots for how it's supposed to work, I've only tested it on fedora with `yum install transmission-daemon` and all default settings, but this should work on any platform that transmission supports.


This bug is subject to a 90 day disclosure deadline. After 90 days elapse
or a patch has been made broadly available, the bug report will become
visible to the public.

 
Fedora 64-bit-2017-11-29-16-25-19.png
70.4 KB View Download
Fedora 64-bit-2017-11-29-16-25-27.png
86.8 KB View Download
Fedora 64-bit-2017-11-29-16-25-48.png
223 KB View Download
Fedora 64-bit-2017-11-29-16-30-12.png
226 KB View Download
Fedora 64-bit-2017-11-29-16-30-26.png
68.6 KB View Download

Comment 1 Deleted

Project Member

Comment 2 by taviso@google.com, Nov 30 2017

I discussed this with a jannh, I think a good solution would work like this:

* If a connection is over the loopback interface, the hostname must match "localhost", "localhost.", "127.0.0.1", or "[::1]". This is the same list CUPS uses: https://github.com/apple/cups/blob/master/scheduler/client.c#L3752
* If a connection is not over loopback, allow any hostname iff auth is enabled.
* If a connection is not over loopback and auth is not enabled, require the user to create a whitelist of acceptable hostnames (They can specify * if they really really don't want security).

I'll propose it to the transmission developers.
Project Member

Comment 3 by taviso@google.com, Jan 7

I sent the attached patch to transmission developers on 1-Dec-17, they seemed willing to apply it, but explained they were too busy to review it until January.

I hadn't received any update, so pinged them again on 7-Jan-18.
0001-mitigate-dns-rebinding-attacks.patch
10.1 KB Download
Project Member

Comment 4 by taviso@google.com, Jan 9

I'm finding it frustrating that the transmission developers are not responding on their private security list, I suggested moving this into the open so that distributions can apply the patch independently. I suspect they won't reply, but let's see.

I've never had an opensource project take this long to fix a vulnerability before, so I usually don't even mention the 90 day limit if the vulnerability is in an open source project. I would say the average response time is measured in hours rather months if we're talking about open source.

Because it looks like we might hit the 90 day limit here, which would be the first time in Project Zero history for an open source project, I corrected that and informed them about the limit.

----
As there is a patch available and downstream distributions (Debian, Fedora, etc.) can prepare updates independently from upstream, I think transferring this discussion into the open so that I can ping package maintainers to prepare updates would be a good idea. That way, we can make sure users are protected while we work on this. As I mentioned before, happy to to do anything I can to help get this patch or another solution landed.

I'm sorry to bring this up, but Project Zero has a 90 day disclosure limit, and I usually include this notice in bug reports:

This bug is subject to a 90 day disclosure deadline. After 90 days elapse or a patch has been made broadly available, the bug report will become visible to the public.

I didn't mention it in my original report because opensource projects typically patch so quickly, it's the proprietary vendors that demand months or years unless we force their hands. We're only up to 41 days though, so if you have strong feelings about keeping this issue private, I won't press the issue for another month. For comparison, the major opensource private disclosure list has a strict limit of 14 days before users must be informed.

Just so we we're clear, this is a remote code execution vulnerability that is relatively low complexity, which is why I'm eager to make sure everyone is patched. I think getting downstream packages safe while we continue to work on getting a solution ready that you guys find acceptable is a nice compromise, what do you think?
----

Project Member

Comment 5 by taviso@google.com, Jan 10

Transmission developers did respond, and have reviewed the patch I sent them, it looks like we will get this fixed this month and we won't have to worry about deadlines.

We're discussing if the patch should be committed now, or if they should sit on it until the next release.

I said that my preference is that the patch is available to users as quickly as possible, but the choice is theirs.
Project Member

Comment 6 by taviso@google.com, Jan 11

I tested my proof of concept on Chrome and Firefox on Windows/Linux, it works fine on all platforms and browsers.
Project Member

Comment 7 by taviso@google.com, Jan 11

OK, we're going to convert this patch into a public PR on github today, and I'll notify distributions via oss-security.

The transmission developers said they'll merge the PR, but I don't know how long that will take them. I'm guessing it will take a while.

I think I've done all I can here to speed the process up,

- I sent a detailed report.
- Built a working testcase so they can reproduce the problem.
- Proposed a solution and wrote a patch.
- Volunteered to take care of notifying downstream distributions.

(That took about 48 hours, the other 6 weeks we were just waiting for a response)

All that's left for them to do is click "merge" on github.
Project Member

Comment 8 by taviso@google.com, Jan 11

Labels: -Restrict-View-Commit
Status: Fixed (was: New)
This is now public: 
https://github.com/transmission/transmission/pull/468


Comment 9 Deleted

Sign in to add a comment