Opened 8 years ago

Closed 8 years ago

#7098 closed defect (fixed)

Add safe-cookie authentication to Extended ORPort and TransportControlPort

Reported by: asn Owned by:
Priority: Medium Milestone: Tor: 0.2.4.x-final
Component: Core Tor/Tor Version:
Severity: Keywords: tor-bridge
Cc: rransom, dcf@… Actual Points:
Parent ID: #4773 Points:
Reviewer: Sponsor:

Description

Safe-cookie authentication makes sure that the control port is only
accessed by clients that are aware of a secret cookie.

We should also protect the Extended ORPort and the
TransportControlPort in the same way, to make sure that only legit
pluggable transport proxies can access these ports.

Looking at control-spec.txt, it seems that the safe-cookie
authentication protocol follows the protocol format of the control
port protocol. Also, control.c:handle_control_authchallenge() is
designed specifically for control-port connections and cannot be used
in other parts of the codebase as it is.

This leaves us with (at least) three options:

1) Abstract handle_control_authchallenge() a bit, so that it's usable
by other parts of the codebase too. Modify the code as little as we
can, and leave it using the control-spec protocol format.

Pros:
+ We get to use safe-cookie auth in the transport ports, and maybe
in other ports in the future.
+ Refactoring handle_control_authchallenge() will be as easy and
painless as we can.

Cons:
+ The safe-cookie authentication protocol will have the format of
the control port, which will make it look funny when used in
front of other ports.

2) Abstract handle_control_authchallenge() so that it can be used as a
generic local-system authentication mechanism for Tor. This
involves removing all the control-port stuff from the protocol
(including the '250' return codes), simplifying the HMAC-SHA256
static strings, and making a beautiful API for the authentication.

Pros:
+ We get to use safe-cookie authentication in the transport ports.
+ We get a flexible local-system authentication mechanism that can
also be used nicely in the future when Tor's architecture becomes
modular.

Cons:
+ It will require some aesthetic refactoring of the safe-cookie
authentication protocol, and writing some spec files.
+ The implementation will be more troublesome than 1).
+ We will need to provide backwards compatibility for the current
safe-cookie authentication protocol.

3) Make a new variant of safe-cookie authentication protocol for the
transport ports. The protocol of the new variant will resemble the
protocol of the Extended ORPort and the TransportControlPort.

Next time we need a local-system authentication mechanism, we will
have to make yet another variant of the safe-cookie authencation
protocol.

Pros:
+ We don't get to abstract anything, and we simply copy/paste and
edit code. We also get to use safe-cookie authenication in
transport ports.

Cons:
+ Next time we need a local-system authentication system we will
need to redo this.


I haven't looked at the safe-cookie code enough to decide how easy it
is to be abstracted, but I'm drifting towards 1) or 2).

If we agree that safe-cookie authentication is a reasonable protocol
to protect any future Tor ports (we will have more of them as Tor
becomes more modular, won't we?), then maybe we should do 2) and
future-proof ourselves.

What do you say?

Child Tickets

Change History (25)

comment:1 Changed 8 years ago by asn

Cc: rransom added
Component: - Select a componentTor
Keywords: tor-bridge added
Milestone: Tor: 0.2.4.x-final

comment:2 Changed 8 years ago by rransom

The ‘safe cookie authentication’ protocol was limited to using the same cookie file format (32 uniform random bytes; no headers) as the old cookie authentication protocol, mostly because I didn't want to have to add code to write another cookie file to Tor. The reason for the new protocol was that 32-byte files could also be used to store secret key material for other systems, and I did not want Tor controllers to disclose the contents of such files to an attacker. Thus, I had two main design goals for the safe cookie authentication protocol:

  • Use the cookie data in a manner as unlike any sane cryptographic protocol as reasonably possible, so that any protocol which would be vulnerable to a ‘cross-protocol attack’ involving safe cookie authentication would be blatantly asking for it.
  • Prove to the client that the server knows the contents of the cookie file (or that someone else is using it in a way that is clearly intended to conflict with safe cookie authentication) before the client discloses any information about the cookie.

If you can use e.g. a 64-byte file with a 32-byte constant header for your protocols, you can use something a little simpler and nicer (perhaps using the 32-byte secret from the file as the HMAC key, and putting the protocol-identifying and ‘client-to-server’-versus-‘server-to-client’ static string(s) in the HMAC message).

But even if you don't want to improve the cryptographic protocol, I strongly recommend that you not use anything that looks like Tor's current control-port protocol anywhere else. Send fixed-length binary byte strings around, and skip the hex-encoding and text parsing.

comment:3 in reply to:  2 ; Changed 8 years ago by rransom

Replying to rransom:

If you can use e.g. a 64-byte file with a 32-byte constant header for your protocols, you can use something a little simpler and nicer (perhaps using the 32-byte secret from the file as the HMAC key, and putting the protocol-identifying and ‘client-to-server’-versus-‘server-to-client’ static string(s) in the HMAC message).

On actual thought, if you put a header in your cookie file, you can just use it as a plain client-to-server password. You wouldn't have to worry about breaking other systems that happen to use 32-byte secret keys, and the ‘safe cookie’ protocol doesn't defend against MITMs anyway.

Someone should figure out and specify what security properties these protocols actually need.

comment:4 in reply to:  3 ; Changed 8 years ago by asn

Replying to rransom:

Replying to rransom:

If you can use e.g. a 64-byte file with a 32-byte constant header for your protocols, you can use something a little simpler and nicer (perhaps using the 32-byte secret from the file as the HMAC key, and putting the protocol-identifying and ‘client-to-server’-versus-‘server-to-client’ static string(s) in the HMAC message).

On actual thought, if you put a header in your cookie file, you can just use it as a plain client-to-server password. You wouldn't have to worry about breaking other systems that happen to use 32-byte secret keys, and the ‘safe cookie’ protocol doesn't defend against MITMs anyway.

Someone should figure out and specify what security properties these protocols actually need.

If we are to create a new protocol, maybe we should keep the security properties of the safe-cookie protocol. That is:

+ authenticate client and server based on the contents of a file on the local filesystem
+ don't leak file contents to potential attackers
+ be resistant to cross-protocol attacks

Similarly, we should probably not try to solve the integrity/confidentiality problem and instead let an SSL layer handle it, if there is a need.

If we add a header to the cookie file, what do you imagine having in that header? Maybe the type of cookie; what else?

Also, is there a reason for the cookie to be of a specific size, or can it be the rest of the cookie file after the header? We are going to send it hashed on the wire anyway.

As for the protocol we might want to keep the safe-cookie protocol, but change it aesthetically and make it easier to parse. The safe-cookie design seems solid and resembles the HTTP digest authentication.

comment:5 in reply to:  4 Changed 8 years ago by rransom

Replying to asn:

If we are to create a new protocol, maybe we should keep the security properties of the safe-cookie protocol. That is:

+ authenticate client and server based on the contents of a file on the local filesystem

This is important, but can be done easily by using a secret string stored in the file as a password.

+ don't leak file contents to potential attackers
+ be resistant to cross-protocol attacks

These features were only important in the control-port safe cookie protocol because (a) controller implementers had already implemented ‘send the contents of an arbitrary file over a socket’ bugs, and (b) cookie files were headerless, and thus could be confused with real secret keys (e.g. Curve25519 or ChaCha or HMAC-SHA-256 keys).

If you put headers on your cookie files, you don't have to use such an ugly protocol to resist cross-protocol attacks.

Similarly, we should probably not try to solve the integrity/confidentiality problem and instead let an SSL layer handle it, if there is a need.

If we add a header to the cookie file, what do you imagine having in that header? Maybe the type of cookie; what else?

Include the socket address(es) which a client should consider sending the cookie to, and possibly an integrity-check field (plain SHA-256 of the rest of the file? HMAC of the rest of the file with some fixed constant string?).

Also, is there a reason for the cookie to be of a specific size, or can it be the rest of the cookie file after the header? We are going to send it hashed on the wire anyway.

The reason that the original cookie authentication protocol required the cookie to be of a specific size (starting sometime late last year) is that I freaked out at the thought of Vidalia sending someone's secret keys to whatever socket it connects to, and I didn't think anyone would use 32-byte keys to store real secrets at the time. The reason that the safe cookie authentication protocol requires the cookie (and the server nonce) to be of a specific size is so that the HMACed ‘message’ strings would be uniquely parsable as cookie..client_nonce..server_nonce without having to add length fields (and specify e.g. byte order).

If you still want your protocol to involve an HMAC, you can use the cookie as the HMAC key instead of including it in the message; in that case, if you really want to teach clients to read a variable-length cookie (and presumably a length indication) (while resisting timing attacks on the parsing gunk) rather than a fixed-length fixed-offset field, you can indeed use a variable-length cookie.

As for the protocol we might want to keep the safe-cookie protocol, but change it aesthetically and make it easier to parse. The safe-cookie design seems solid and resembles the HTTP digest authentication.

I thought HTTP digest authentication could (optionally?) be bound to (i.e. authenticate) requests too.

comment:6 Changed 8 years ago by asn

OK. I guess we have two options then:


Protocol A:

A very simple protocol that uses the cookie as a client-to-server password. The cookie is extracted from a cookie-file with a header, so as to avoid sending passwords of other systems on the wire.

Note that this protocol does not make sure that the server knows the password. Do we even care about weird setups were a local attacker binds on localhost pretending to be a Tor port, and then fires up a controller to get the cookie?

Protocol B:

A protocol that uses challenge-response and the cookie as a secret, so as to not reveal the cookie to servers that don't know it already.

We can use Robert's scheme, or look further into zero-knowledge proofs. Maybe the Socialist Millionaire Protocol can also do the trick.


Sounds like Protocol B will be harder to design, prove and implement. Does our threat model include the attacks that it protects against? If not, we should probably do Protocol A.

Some further questions:
+ Should it be a text-based or binary-based protocol?
+ Should the protocol be versioned?
+ Should we let the cookie be of arbitrary size? I'm leaning towards 'no'. 32 secret bytes hold enough entropy.

comment:7 in reply to:  6 ; Changed 8 years ago by nickm

Replying to asn:

[...]

Sounds like Protocol B will be harder to design, prove and implement. Does our threat model include the attacks that it protects against? If not, we should probably do Protocol A.

There are a couple of pieces of the protocols left off here. To wit: how does the proxy learn where to look for the secret file? I'd lean towards "Specify the location of the file in its environment when it's launched."

In the managed proxy case, since you're getting both the cookie file location and the extended ORPort from Tor when it launches the proxy, there's not too much risk of connecting to something that isn't really a Tor process, and not much risk of reading something that isn't really a cookie file. If you add a header to the file (which seems like an obviously correct choice), there's zero risk of reading a non-cookie file. So we probably _could_ get away with just a password system for that case.

In the external proxy case, are we worried about somebody setting up the external proxy to point at the wrong extended ORPort for Tor, or at the wrong cookie file, or what?

That said, I am fine with doing an HMAC-based challenge/response thing here, on the theory that the assumptions above might turn out to be less robust than we thought.

Some further questions:
+ Should it be a text-based or binary-based protocol?

The rest of the extended ORPort protocol is binary.

+ Should the protocol be versioned?

Yes.

+ Should we let the cookie be of arbitrary size? I'm leaning towards 'no'. 32 secret bytes hold enough entropy.

Yes.

comment:8 in reply to:  7 Changed 8 years ago by asn

Replying to nickm:

Replying to asn:

[...]

Sounds like Protocol B will be harder to design, prove and implement. Does our threat model include the attacks that it protects against? If not, we should probably do Protocol A.

There are a couple of pieces of the protocols left off here. To wit: how does the proxy learn where to look for the secret file? I'd lean towards "Specify the location of the file in its environment when it's launched."

Sounds reasonable.

How do you think this should be done in the protocol?
Should we increase the managed-proxy protocol version and add a new mandatory env var (TOR_PT_AUTH_COOKIE), or should we add an optional env var on the current protocol version, or should we add the path to the already existing TOR_PT_EXTENDED_SERVER_PORT env. var?

I'm leaning towards adding an optional new env var. What do you think?

In the managed proxy case, since you're getting both the cookie file location and the extended ORPort from Tor when it launches the proxy, there's not too much risk of connecting to something that isn't really a Tor process, and not much risk of reading something that isn't really a cookie file. If you add a header to the file (which seems like an obviously correct choice), there's zero risk of reading a non-cookie file. So we probably _could_ get away with just a password system for that case.

In the external proxy case, are we worried about somebody setting up the external proxy to point at the wrong extended ORPort for Tor, or at the wrong cookie file, or what?

Yes, something like that. I don't really think these are realistic adversarial attacks.

That said, I am fine with doing an HMAC-based challenge/response thing here, on the theory that the assumptions above might turn out to be less robust than we thought.

I think I'm going to go with the HMAC-based challenge/response protocol too. I will also make the protocol flexible enough to support other authentication types.

comment:9 Changed 8 years ago by asn

See branch bug7098_draft in https://git.torproject.org/user/asn/torspec.git for an early-draft of the proposal. Do you like the general direction of the protocol?

comment:10 in reply to:  9 ; Changed 8 years ago by nickm

Status: newneeds_review

Replying to asn:

See branch bug7098_draft in https://git.torproject.org/user/asn/torspec.git for an early-draft of the proposal. Do you like the general direction of the protocol?

I don't think the version negotiation works. What is the client supposed to do if it sees a version it doesn't recognize, or an authentication means that it doesn't support? What if the server supports multiple versions/authenticators? Other than that, looks sane. Also, it should specify how the client finds out the cookie; that was a world of trouble in the earlier control protocol things.

"Tor Port Guardian" is a bit silly as a name. We already have "Guards"; let's not confuse people. How about just "Tor Extended ORPort Authentication" ?

The cookie file should have have 32 fixed bytes to start with, and then a fixed-length cookie.

I really do want to know how the parent protocol specifies the file location.

TOR_AUTH_PT_COOKIE should be TOR_AUTH_PT_COOKIE_FILE imo.

comment:11 in reply to:  10 Changed 8 years ago by asn

Replying to nickm:

Replying to asn:

See branch bug7098_draft in https://git.torproject.org/user/asn/torspec.git for an early-draft of the proposal. Do you like the general direction of the protocol?

I don't think the version negotiation works. What is the client supposed to do if it sees a version it doesn't recognize, or an authentication means that it doesn't support? What if the server supports multiple versions/authenticators? Other than that, looks sane. Also, it should specify how the client finds out the cookie; that was a world of trouble in the earlier control protocol things.

OK. Would you prefer something like this:
S->C: <list of supported handshake versions>
C->S: <picks a handshake version>
handshake version 1:
S->C: <list of types of authentication>
C->S: <picks a type of authentication>
...auth-specific messages...
?
Or something with less round trips and less flexibility?

"Tor Port Guardian" is a bit silly as a name. We already have "Guards"; let's not confuse people. How about just "Tor Extended ORPort Authentication" ?

OK.

The cookie file should have have 32 fixed bytes to start with, and then a fixed-length cookie.

Sure. I misinterpreted the end of comment:7 to mean that you wanted a variable-sized cookie.

I really do want to know how the parent protocol specifies the file location.

TOR_AUTH_PT_COOKIE should be TOR_AUTH_PT_COOKIE_FILE imo.

Sure.

comment:12 Changed 8 years ago by asn

Also, we will need to keep connection state (like the nonce). Should we keep this in or_connection_t (#4773 also keeps ext_or_conn_id in or_connection_t)?

comment:13 Changed 8 years ago by nickm

That sounds ok. WRT the setup handshake, I am okay with just having the version and the authentication negotiated as a single thing. Do we foresee a problem with that?

comment:14 Changed 8 years ago by asn

Hi Nick. How does branch bug7098_draft2 look like to you?

comment:15 Changed 8 years ago by asn

Hm, I'm considering replacing:

  + ClientHash is computed as:
      HMAC-SHA256("ExtORPort authentication safe cookie client-to-server hash",
                  CookieString | ClientNonce | ServerNonce)

with:

  + ClientHash is computed as:
      HMAC-SHA256(SHA256(CookieString | ClientNonce | ServerNonce),
                  "ExtORPort authentication safe cookie client-to-server hash")

and the same for ServerHash. This allows us to use the HMAC construction correctly (secret used as the HMAC key).

comment:16 Changed 8 years ago by rransom

Why not HMAC-SHA256(CookieString, "ExtORPort authentication safe cookie client-to-server hash" || ClientNonce || ServerNonce)? Putting a header on the cookie file solves the ‘it might be my Ed25519 secret key’ problem.

comment:17 in reply to:  16 Changed 8 years ago by asn

Replying to rransom:

Why not HMAC-SHA256(CookieString, "ExtORPort authentication safe cookie client-to-server hash" || ClientNonce || ServerNonce)?

Yes, or that.

I'll use your variant. It does a SHA256() less, and it separates secret from non-secret correctly.

comment:18 Changed 8 years ago by asn

Updated bug7098_draft2 with Robert's suggestion.

comment:19 Changed 8 years ago by asn

Nick, in pt-spec.txt do you like TOR_AUTH_PT_COOKIE_FILE being optional? Or would you prefer to start a new Extended ORPort protocol version just for it?

comment:20 Changed 8 years ago by dcf

Cc: dcf@… added

comment:21 in reply to:  18 ; Changed 8 years ago by nickm

Replying to asn:

Updated bug7098_draft2 with Robert's suggestion.

Looks okay to me.

Also, we will need to keep connection state (like the nonce). Should we keep this in or_connection_t (#4773 also keeps ext_or_conn_id in or_connection_t)?

That seems okay. It's only 64 bytes per or_connection_t.

Nick, in pt-spec.txt do you like TOR_AUTH_PT_COOKIE_FILE being optional? Or would you prefer to start a new Extended ORPort protocol version just for it?

Having it be optional but strongly recommended is IMO OK. Or we could just make it required in the Extended ORPort protocol. After all, there aren't any current extended ORPort users that we'd be breaking, right?

comment:22 in reply to:  21 ; Changed 8 years ago by nickm

Replying to nickm:

Replying to asn:

Updated bug7098_draft2 with Robert's suggestion.

Looks okay to me.

Except that it needs a different number, since 213 is taken. Let me know if you want to call it a proposal, and I can assign it a number, merge it, and send it to tor-dev. Or send it to tor-dev without a number and I'll assign one.

comment:23 in reply to:  22 Changed 8 years ago by asn

Replying to nickm:

Replying to nickm:

Replying to asn:

Updated bug7098_draft2 with Robert's suggestion.

Looks okay to me.

Except that it needs a different number, since 213 is taken. Let me know if you want to call it a proposal, and I can assign it a number, merge it, and send it to tor-dev. Or send it to tor-dev without a number and I'll assign one.

There you go:
https://lists.torproject.org/pipermail/tor-dev/2012-November/004184.html

Before sending it to tor-dev, I changed the date to today, and the 'Target' to 0.2.5.x.

comment:24 Changed 8 years ago by asn

Please see branch bug7098_draft3 in https://git.torproject.org/user/asn/torspec.git for some changes related to the Extended ORPort in other proposals.

Do you think it would make sense to consider this ticket as spec-only, and use #4773 as the implementation ticket? If yes, let's close this after merging bug7098_draft3.

comment:25 Changed 8 years ago by nickm

Resolution: fixed
Status: needs_reviewclosed

Okay, merged it.

(Does the existence of pt-spec.txt mean that proposal 180 should be called "closed" rather than "finished"? IOW, is there anything left in 180 that should go into pt-spec.txt or not ?)

Note: See TracTickets for help on using tickets.