Nick Mathewson:
> Hi!
> 
> As you may know, the Tor control port assumes that if you can
> authenticate to it, you are completely trusted with respect to the Tor
> instance you have authenticated to.  But there are a few programs and
> tools that filter access to the Tor control port, in an attempt to
> provide more restricted access.
> 
> When I've been asked to think about including such a feature in Tor in
> the past, I've pointed out that while filtering commands is fairly
> easy, defining a safe subset of the Tor control protocol is not.  The
> problem is that many subsets of the control port protocol are
> sufficient for a hostile application to deanonymize users in
> surprising ways.
> 
> But I could be wrong!  Maybe there are subsets that are safer than others.
> 
> Let me try to illustrate. I'll be looking at a few filter sets for example.
[...]
> Filters from 
> https://git-tails.immerda.ch/tails/tree/config/chroot_local-includes/etc/tor-controlport-filter.d

Small note: we've renamed tor-controlport-filter to onion-grater, to not 
infringe on the Tor trademark. :) 

> 1. onioncircuits.yml
> 
> See onioncircuits.json above; it allows the same GETINFO stuff.

The whole point of onioncircuits is to present all Tor circuit/stream state to 
the users since they (IIRC) feel that Tor is too opaque without this (and I'm 
sure the Tor Browser added its per-tab circuit view for similar reasons). In 
other words, the point of onioncircuits *is* to expose this information. Hence 
I guess this all boils down balancing the security consequences of this (e.g. 
user compromise => full Tor state leak) vs the desired transparency.

As for Tails, my impression of our current threat model here is that we don't 
protect against the main user being compromised, so we certainly won't 
sacrifice the transparency desired by our users to block this leak -- there are 
probably equally bad leaks around already so that sacrifice would be pointless. 
But we are incrementally working towards this by limiting information leaks 
(e.g. control port filtering) and sandboxing applications to protect full user 
compromise so we *do* care about these things. At the point where we feel we 
can start caring about this for real we'll have to revisit this point.

> 2. onionshare.yml
> 
> As above, appears to allow HS_DESC events.

Explanation: modern (ADD_ONION instead of SETCONF HiddenService{Dir,Port}) 
onionshare uses stem's create_ephemeral_hidden_service() with 
`await_publication = True`, which means waiting for the corresponding HS_DESC 
event. I believe the roflcoptor filter was written for the "old" onionshare 
only. 

> It allows "GETINFO
> onions/current", which can expose a list of every onion service
> locally hosted, even those not launched through onionshare.

I think this can be disallowed; in fact, when looking at the onionshare and 
stem sources I don't see why this would ever be used by onionshare.

> 3. tor-browser.yml
> 
> As "tbb.json" above.

Not quite! As intrigeri pointed out, this filter sets `restrict-stream-events: 
true` which gives what meejah called a "limited view" of the STREAM events, 
namely only those "belonging" to the client/controller (implementation: for 
each event look up which PID that has opened the socket with the event's source 
address/port, then match PIDs to determine whether it should be suppressed or 
not).

So, how bad is "GETINFO circuit-status" with only the "limited" STREAM view)? 
Well, by knowing all circuits' exit nodes an attacker that also observes the 
traffic of these exit nodes knows a bit more than what we are comfortable with. 
:/

I guess treating "GETINFO circuit-status" specially with a 
`restrict-circuit-status` option that, when set, suppresses circuits that 
doesn't have any stream belonging to the client. But the same goes for CIRC 
events and "GETINFO stream-status", so, in fact, what about these options:

* restrict-circuit-view: when enabled:
  - "GETINFO circuit-status" will only show circuits that has some stream 
attached that belongs to the controller.
  - CIRC events are dropped unless some stream attached to the circuit in 
question belongs to the controller.
* restrict-stream-view (replacing the current `restrict-stream-events`):
  - "GETINFO stream-status" will only show streams belonging to the controller.
  - STREAM events are dropped unless they belong to the controller.

Does this make sense? What other bits of sensitive internal Tor state 
accessible for controllers have I missed?

BTW, I guess a `restrict-onion-view` would also make sense for HS_DESC events 
and "GETINFO onions/current", but I see no general way to learn what 
application an onion "belongs" to. The filter could keep track of it, but such 
tracking would be lost if restarted (and not tracked at all if the onion was 
added before the filter started). A general solution would depend on little-t 
tor tracking this information, e.g. the PID of the controller that asked for an 
onion to be added. That seems ugly, though.

> 4. tor-launcher.yml
> 
> Allows setconf of bridges, which allows the app to pick a hostile
> bridge on purpose.  Similar issues with Socks*Proxy.  The app can also
> use ReachableAddresses to restrict guards on the .

Being able to set these options arbitrarily is Tor Launcher's purpose, so I'm 
fine with all this. We treat it as a "trusted" application in Tails, and I'm 
having difficulties imaging how it could be any different.

> Allows SAVECONF, which lets the application make the above changes
> permanent (for as long as the torrc file is persisted)

Indeed! In general, Tails users have control of exactly what should persist, so 
it depends on their own threat model here. At the moment Tails itself does 
nothing to support making torrc persistent, but if we could make only the part 
of torrc that Tor Launcher sets persistent I'm sure we would (preferably on a 
per-network basis).

> So above, I see a few common patterns:
[...]
>   * Many restrictive filters block SETCONF and SAVECONF.  These two
> changes together should be enough to make sure that a hostile
> application can only deanonymize _current_ traffic, not future Tor
> traffic. Is that the threat model?  It's coherent, at least.

FWIW, Tails has this threat model in general.

>   * The NEWNYM-based side-channel above is a little scary.

Agreed! NEWNYM is too broad when multiple clients use the same tor instance -- 
right now a compromised Tor Browser would be able to influence all other 
torified applications. I'd be great if instead of NEWNYM the "New identity" 
feature would use the same mechanism as for "New Tor Circuit for this Site" for 
all tabs' domains before clearing the browser session; this way, if any of the 
domains are revisited, it would be with a new circuit, so it is as if we had 
issued a NEWNYM scoped only for the Tor Browsers circuits, so other 
applications are unaffected.

> And where do we go forward from here?
> 
> The filters above seem to have been created by granting the
> applications only the commands that they actually need, and by
> filtering all the other commands. But if we'd like filters that
> actually provide some security against hostile applications using the
> control port, we'll need to take a different tactic: we'll need to
> define the threat models that we're trying to work within, and see
> what we can safely expose under those models.
>
> Here are a few _possible_ models we could think about, but I'd like to
> hear from app developers and filter authors and distributors more
> about what they think:
> 
>  A. Completely trusted controller.  (What we have now)

It can be argued that Tor Launcher (and similar) could be in this category 
since the capabilities it must have in order to do its job are so severe that 
preventing other capabilities won't make much difference. OTOH, if there are 
mechanisms for limiting this, why not use them? And we do need such mechanisms 
to support the other relevant use cases.

>  B. Controller is untrusted, but is blocked from exfiltrating information.
>     B.1. Controller can't connect to the network at all.
>     B.2. Controller can't connect to the network except over tor.

In Tails, B.2 is strongly enforced for all network usage, not just controllers, 
but B.1 less so; for instance, onioncircuits runs as the normal user, but any 
application under that user is allowed to connect to the Internet through Tor, 
so if that user is compromised the information onionshare has access to can 
leak out on the network (but through Tor).

B.1 seems really desirable for Tor state visualisation applications like 
onioncircuits, but I fear only heavily compartmentalized systems like Qubes and 
Whonix can go in this direction. B.2 seems like something that only can be 
achieved in systems where Tor is enforced for all connections on at least the 
OS-level, like in Tails and Whonix, but that threat model already strictly 
includes this one, so it seems irrelevant.

>  D. Controller is trusted wrt a fraction of the requests that the
> clients are handling. (For example, all requests going over a single
> SOCKSPort, or all ADD_ONION requests that it makes itself.)

I feel work in this direction is highly necessary for many threat models and 
applications, not least Tor Browser itself vs. Tor's stream state. As I 
mentioned above, Tails' control port filter allows a controller to only see its 
own Tor stream state, and that should be expanded to circuits and onions too. 
It would be even nicer if tor internally tracked usage of both SocksPort and 
ControlPort on an application-level, and controller commands would be scoped 
accordingly: controllers would only be able to see stream/circuit/hidden 
service/etc state belonging to them. Just to give you an idea, the tracking 
could be by PID (which is pretty weak).

Imagine that ControlPort can take a "RestrictedView" flag. When set, 
controllers will get a view of Tor's state (streams, circuits, onions etc) 
restricted to what "belongs" to them, e.g. it only sees streams for connections 
itself made via the SocksPort. Tor would then have to internally track who 
these things belong to, which could be done by PID, which is pretty weak, but I 
bet there are more convincing ways. A crappy idea would be that the cookie used 
for authenticating to the ControlPort would be unique for the application and 
also used for the SocksPort (via SOCKS authentication), so that when the 
"RestrictedView" flag is set, controllers only see things originating from the 
ControlPort and SocksPorts that have used the same cookie.

Other interesting ideas?

Cheers!
_______________________________________________
tor-dev mailing list
tor-dev@lists.torproject.org
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-dev

Reply via email to