Subject: Re: [kitten] BrowserID GSS mechanism

From: Jeffrey Hutzelman <[email-masked]>
Date: Fri, 04 Jan 2013 14:07:18 -0500

On Fri, 2013-01-04 at 21:44 +1100, Luke Howard wrote:
> I made some notes on a putative BrowserID GSS mechanism here:
> 
> 
> http://www.padl.com/~lukeh/gss-browserid.html (or .md)
> 
> 
> I intend to write it up as an Internet Draft at some point. Comments
> welcome.

I've so far only skimmed this, but it looks so far like it probably has
the makings of a good mechanism.  I would ask that if you're going to
use a DH exchange to obtain keying material for PRF and per-message
tokens, that you write that portion of the document such that it can be
reused by reference in other mechanisms.  Nico would probably say it
should actually be done as a stackable mechanism, but I won't insist on
that.

-- Jeff

---

From: Nico Williams <[email-masked]>
Date: Fri, 4 Jan 2013 15:41:22 -0600

> should actually be done as a stackable mechanism, but I won't insist on

I'd like that, but nah.

The more interesting thing is that this is the first mech we have that can
authenticate the initiator but not the acceptor yet prevents MITM attacks.
(Active attackers can impersonate the acceptor to the initiator but not
vice versa; they cannot steal or reuse the initiator's credentials.)  By
not authenticating the acceptor this mech can't be used with SASL/GS2, but
the security properties of this mech make it safe to use with SASL/GS2
nonetheless.  We should update SASL/GS2 to relax the requirement for
GSS_C_NT_HOSTBASED_SERVICE support!

Nico
--

---

From: Luke Howard <[email-masked]>
Date: Sat, 5 Jan 2013 08:51:27 +1100

> The more interesting thing is that this is the first mech we have that can authenticate the initiator but not the acceptor yet prevents MITM attacks.  (Active attackers can impersonate the acceptor to the initiator but not vice versa; they cannot steal or reuse the initiator's credentials.)  By not authenticating the acceptor this mech can't be used with SASL/GS2, but the security properties of this mech make it safe to use with SASL/GS2 nonetheless.  We should update SASL/GS2 to relax the requirement for GSS_C_NT_HOSTBASED_SERVICE support.
> 
You mean GSS_C_MUTUAL_FLAG? :-)

The mech does support GSS_C_NT_HOSTBASED_SERVICE (the acceptor can verify the initiator's idea of its name).

-- Luke

---

From: Jeffrey Hutzelman <[email-masked]>
Date: Fri, 04 Jan 2013 17:00:06 -0500

On Fri, 2013-01-04 at 15:41 -0600, Nico Williams wrote:

> The more interesting thing is that this is the first mech we have that
> can authenticate the initiator but not the acceptor yet prevents MITM
> attacks.  (Active attackers can impersonate the acceptor to the
> initiator but not vice versa; they cannot steal or reuse the
> initiator's credentials.)  By not authenticating the acceptor this
> mech can't be used with SASL/GS2, but the security properties of this
> mech make it safe to use with SASL/GS2 nonetheless.  We should update
> SASL/GS2 to relax the requirement for GSS_C_NT_HOSTBASED_SERVICE
> support!

In theory, the OpenID, OAuth, and SAML mechs all cannot be used with
GS2, for that reason.  In practice, they lie and claim to perform mutual
auth even though they actually don't, which is a serious problem for the
security of GSS applications everywhere and should be fixed presently.
Probably that means we need to define new versions of these mechs that
don't lie, and invent a new extended-mech-inquiry property to identify
which mechanisms lie in this way, so that GSS-API applications have a
prayer of being able to rely on the mutual_state flag again.

In the meantime, there is actually no reason GS2 cannot be used with GSS
mechanisms that don't provide mutual authentication, as long as it is
understood that the resulting SASL mech _also_ doesn't provide mutual
authentication, and that clients may not rely on channel binding results
from such mechs.  Unfortunately, we've never done a really good job of
explaining that SASL and GSS clients cannot rely on channel bindings if
the mech does not do mutual authentication.  I also don't think we've
done a good job of making it clear that mechanisms must be designed so
that clients _can_ rely on channel bindings if mutual auth succeeds.
The Kerberos mechanism gets this right, but I'm not sure about any
others.

And actually, I don't think this is the first mech to have these
properties.  It may be the first mech with a published spec that has
these properties and doesn't lie about them.

-- Jeff

---

From: Luke Howard <[email-masked]>
Date: Sat, 5 Jan 2013 09:16:07 +1100

> prayer of being able to rely on the mutual_state flag again.

Exactly. I was surprised when GS2 failed with the BrowserID mechanism (because it doesn't lie about GSS_C_MUTUAL_FLAG), and then I read RFC 5801 again, and the code, and realised that it was just implementing the spec.

Cyrus SASL already checks if the mechanisms supports mutual authentication and sets a SASL flag to indicate this (which presumably the application can check):

    if (MA_PRESENT(GSS_C_MA_AUTH_TARG))
        *security_flags |= SASL_SEC_MUTUAL_AUTH;

So maybe it's safe to relax that check.

> The Kerberos mechanism gets this right, but I'm not sure about any

I need to get my head around this still. Does not using CB to bind the context to a channel in which the client has authenticated the server provide the moral equivalent of mutual authentication? I'm thinking of the typical case where the client verifies a server's TLS certificate. (OK, maybe there are lots of clients that don't even bother to do that properly!)

-- Luke

---

From: Luke Howard <[email-masked]>
Date: Sat, 5 Jan 2013 09:16:51 +1100

> So maybe it's safe to relax that check.

By "that check" I mean only advertising mechanisms that support GSS_C_MA_AUTH_TARG.

-- Luke

---

From: Nico Williams <[email-masked]>
Date: Fri, 4 Jan 2013 16:23:25 -0600

On Jan 4, 2013 4:51 PM, "Luke Howard" <[email-masked]> wrote:
>>
>> [...]  We should update SASL/GS2 to relax the requirement for
GSS_C_NT_HOSTBASED_SERVICE support.
> You mean GSS_C_MUTUAL_FLAG? :-)

No.  That flag refers to key confirmation, not to authentication of each
party to the other.

> The mech does support GSS_C_NT_HOSTBASED_SERVICE (the acceptor can verify
the initiator's idea of its name).

Oh.  Then we probably need to think a bit more about how to distinguish the
two meanings of "mutual authentication".

---

From: Luke Howard <[email-masked]>
Date: Sat, 5 Jan 2013 09:29:08 +1100

> No.  That flag refers to key confirmation, not to authentication of each party to the other.
> 

Do you have a reference? Skimming RFC2743 the most direct I could find was "mutual_state == TRUE ... target authenticated to initiator".

-- Luke

---

From: Jeffrey Hutzelman <[email-masked]>
Date: Fri, 04 Jan 2013 17:34:22 -0500

On Fri, 2013-01-04 at 16:23 -0600, Nico Williams wrote:
> > The mech does support GSS_C_NT_HOSTBASED_SERVICE (the acceptor can
> verify the initiator's idea of its name).
> 
> Oh.  Then we probably need to think a bit more about how to
> distinguish the two meanings of "mutual authentication".
> 
Hm?  "mutual authentication" here means that the mechanism has proven
the acceptor's identity to the initiator.  It should go without saying
that any further services provided by the mechanism, such as CB, PRF,
and per-message tokens, are provided using keys known only to the
initiator and the actual acceptor, whether or not mutual_flag is set.

---

From: Nico Williams <[email-masked]>
Date: Fri, 4 Jan 2013 16:35:28 -0600

party to the other.
>
> Oh.  Then we probably need to think a bit more about how to distinguish
the two meanings of "mutual authentication".

Or, the method you have of authenticating the acceptor, though weak, is
close enough to mutual auth.  We may simply need to add a mech attr that
says the mech prevents impersonation of the server, and then we can say
something about when this mech attr should be required by the app.

Nico
--

---

From: Nico Williams <[email-masked]>
Date: Fri, 4 Jan 2013 16:52:38 -0600

> initiator and the actual acceptor, whether or not mutual_flag is set.

In the Kerberos mech the mutual auth flag refers to the full round trip
exchange,  (as opposed to the half-round trip exchange).  Oh, ok, I think
that confused me.  So, yes, i think we want to relax the mutual auth req in
SASL/GS2, with some carefully written text.

---

From: Luke Howard <[email-masked]>
Date: Sat, 5 Jan 2013 13:47:37 +1100

> initiator and the actual acceptor, whether or not mutual_flag is set.

Right, that was always my understanding too.

-- Luke

---

From: Jeffrey Hutzelman <[email-masked]>
Date: Thu, 10 Jan 2013 14:00:58 -0500

On Thu, 2013-01-10 at 10:40 -0800, Ozten wrote:

> I have to admit that I am ignorant of GSS, so please forgive me if this
> is not possible, but I would try to do something "out of band". Instead
> of altering the format of a backed assertion, what about a GSS specific
> payload that includes the assertion?

And how would that payload be authenticated?

> If the system being logged into isn't a web addressable audience,
> perhaps you can create a synthetic mapping. Example: An audience value
> of urn:x-gss:ldap/example.com could be mapped to
> https://ldap.example.com.

No; that conflates two completely unrelated services -- the LDAP server
running on example.com and the HTTP server running on ldap.example.com.
Those may be completely unrelated services run by different people, and
I don't want to hand one credentials that would allow it to log in as me
to the other.

Why constrain an audience to particular URI schemes at all?  You're not
connecting to that resource; it's just an identifier, so wny not allow
any URI?

---

From: Luke Howard <[email-masked]>
Date: Fri, 11 Jan 2013 09:59:04 +1100

Hi Austin,

> Is it possible to use BrowserID for authentication to bootstrap a secure
> communication channel, to fulfill the GSS protocol?

Yes, we do a signed Diffie-Hellman exchange. More information in the protocol specification here:

	http://www.padl.com/~lukeh/gss-browserid.html

If this is not signed (i.e. included in the assertion), the client is unauthenticated, and it is not a secure communication channel.

> I realize that the overall GSS payload, without any verification
> mechanisms, could be tampered with.
> 
> As an analogy, in a web context, BrowserID can bootstrap a session which
> can be communicated over https. Additional security can be layered in using nonces and other web security best practices.
> 
> Are there any existing protocols or building blocks available to GSS for
> securing communication after an entity has been authenticated using vanilla
> BrowserID?

No. I mean, we could build a TLS GSS mechanism, but even then that channel would still need to be cryptographically bound to the BrowserID authentication to avoid a MITM attack. (See RFC 5056.) Nico can probably explain this better.

> An experimental feature "key wrapping" might be a means of signing the GSS
> payload, but this isn't really available today.

A signed DH exchange is fine.

> I agree that the audience is just an identifier. That is why I don't see
> potentially re-using an identifier across two services as that horrible of
> an option. I agree two different people might run
> https://example.comversus ldap://
> example.com, but at the end of the day they are probably two people in the
> same organization. JR Random cannot casually operate an example.com service.
> 
> I am not trying to defend either of these suggestions, they are forged in
> ignorance. But the core suggestion I will stand by - which is strive to
> make GSS composable with the BrowserID protocol.
> 
> I'm not saying we won't open up the URI schemes or allow for arbitrary
> fields eventually, but these are changes to the protocol, which will take
> time to evaluate. Composability unblocks you (and has other beneficial
> engineering properties).

In the GSS BrowserID protocol, the RP verifies that the audience name. Even though there is no mutual authentication in the current protocol, it strikes me as undesirable to have a lossy transformation from GSS service name to an arbitrary URL.

Particularly given we have an implementation that works, I'm going to advocate strongly for doing things "the right way" (which of course is my subjective opinion!). :-)

-- Luke

---

From: Luke Howard <[email-masked]>
Date: Fri, 11 Jan 2013 10:06:44 +1100

Hi Austin,

Thanks for the feedback!

> Great work so far on a BrowserID GSS-API/SASL mechanism.
> 
> On the topics of changing 
> * the valid types of URLs of an audience from http/https to allow urn:x-gss
> * BrowserID.internal.get() should allow application-defined claims
> 
> I would work towards a design that layers on top of the BrowserID protocol, without altering it's design or forking any implementations.

I agree that this is desirable and should be our starting point. However, I think that if a layered implementation leads to "hacks" (in the specific case above, this might mean encoding the GSS service name/claims somehow inside the existing audience URL), it's worth considering how much pain the "right" solution will cause. (Of course, "right" is subjective. I'm going to argue my case from the GSS perspective.)

> I have to admit that I am ignorant of GSS, so please forgive me if this is not possible, but I would try to do something "out of band". Instead of altering the format of a backed assertion, what about a GSS specific payload that includes the assertion?

It needs to be "in band" so that it is signed with the user's private key, in order to authenticate the DH exchange used to establish a session key and/or to provide channel bindings.

The less aesthetically pleasing way to do "in band" is to base32 encode the GSS claims in the audience URL. The more pleasing way, which our current implementation does (by some JavaScript swizzling), is to insert these claims directly in the assertion.

-- Luke

---

From: Luke Howard <[email-masked]>
Date: Sat, 12 Jan 2013 02:10:32 +1100

I updated the spec notes here:

with some notes about providing mutual authentication. This is useful for protocols that {do,can}not use TLS.

Changes from the previous version:

* The acceptor now sends the initiator a backed assertion rather than a JWT. This is for future extensibility (mutual authentication using native JSON rather than X.509 certificates). That said, I felt that using X.509 server certificates for now is more amenable to existing keying infrastructures. (JSON Web Signatures provides for embedding X.509 certificates in a JWT.)

* If the initiator desired mutual authentication, it sends a nonce to the acceptor. If the acceptor is keyed, it echoes the nonce and signs the response using its private key rather than a session subkey (which would have been derived from the Diffie-Hellman exchange). The server's certificate is embedded in the response.

* The initiator verifies the echoed nonce, response assertion, certificate and certificate chain. If it succeeds, it can return GSS_C_MUTUAL_FLAG.

If the client cannot verify the response assertion certificate, then it's a hard error; there's no easy way to fallback as the acceptor has already returned completion.

Someone more security-aware than I can indicate whether a nonce is sufficient to bind the request and response assertions. Nico suggested the response signature being over the entire conversation, but that would break the JWS abstraction (the signature is over the payload only). I know using a nonce might be a bit old-fashioned.

-- Luke

---

From: Luke Howard <[email-masked]>
Date: Sat, 12 Jan 2013 02:23:45 +1100

On 11/01/2013, at 6:43 AM, Austin King <[email-masked]> wrote:

> can be communicated over https. Additional security can be layered in using
> nonces and other web security best practices.

One thing I should add: from the GSS mechanism's perspective, we don't know whether there is an outer channel using TLS or similar. (Channel bindings provide a way to bind the two, but their contents are opaque.) Moreover, many applications that support GSS do not use TLS, for example NFS, CIFS, DCE RPC (think Outlook, Exchange).

I'd like the mechanism to provide some security beyond bearer tokens (which aren't too much better than passwords).  i.e. channel binding, a session key and possibly mutual authentication (see separate mail).

Nico/Jeff are going to be able to explain this much better than I.

-- Luke

---

From: [email-masked] (Martin Rex)
Date: Fri, 11 Jan 2013 20:28:00 +0100 (CET)

On my first quick read of that page I didn't really understand
the protocol architecture yet (I blame myself--too busy and
lack of sleep),  so just a quick comment on

  GSS_C_MUTUAL_FLAG

The name of this flag is actually a misnomer.
This flag is *ONLY*  about authentication of acceptor to initiator.

In the original GSS-API architecture, authentication of initiator
to acceptor was implied (unconditional), and requesting MUTUAL
would add acceptor to initiator authentication to the existing,
unconditional initiator to acceptor authentication.

In GSS-API v2 the "ANON" flag was added to "get rid" of the previously
unconditional initiator to acceptor authentication.

The flags to obtain the common SSL/TLS authentication scheme,
server authenticates to client, client is anonymous (no client cert)
would use the flags (GSS_C_ANON_FLAG|GSS_C_MUTUAL_FLAG), although
this may look slightly weird at first encounter.

-Martin

---

From: Luke Howard <[email-masked]>
Date: Sat, 12 Jan 2013 14:10:26 +1100

Hi Martin,

Thanks for the comments.

> This flag is *ONLY*  about authentication of acceptor to initiator.

Noted.

> this may look slightly weird at first encounter.

The BrowserID mechanism doesn't support this case; the initiator is always authenticated.

GSS_C_MUTUAL_FLAG is optionally supported if the acceptor (the relying party, in BrowserID-speak) is keyed with an private key, and the initiator (user agent) can verify its certificate.

-- Luke