[PATCH] Fix SPNEGO interoperability with servers implementing RFC2478

classic Classic list List threaded Threaded
21 messages Options
12
Reply | Threaded
Open this post in threaded view
|

[PATCH] Fix SPNEGO interoperability with servers implementing RFC2478

David Woodhouse-7
From: David Woodhouse <[hidden email]>

Servers running Windows 2003 and earlier do not send a negState of
request-mic in their initial reply when the first mechanism is
declined. That's because they implement (roughly) RFC2478, which
predates the addition of the request-mic state.

A server conforming to RFC4178 MUST send request-mic there, but it
is equally clear that on the client side, we should deal with its
absence. For example, the language in §5 (c) is as follows:
    "if the negState was request-mic in the first reply from the
     target, a mechlistMIC token MUST be included; otherwise..."

In the MIT implementation as it stands, there is no "otherwise".
Because we already overzealously aborted the negotiation.

Other language in RFC4178 which supports this interpretation includes
the whole of Appendix C, which explains the changes since RFC2478.

Looking at that, in fact it seems that the addition of request-mic on
the wire was done specifically to allow interoperability with older
implementations which don't set it. If not for that consideration,
and if we were only ever communicating between RFC4178-compliant
implementations, we could always have just behaved as if request-mic
were set — and there would be no need to *say* so on the wire.
---

On a practical note, the potential vulnerability which is permitted
by failing to use a MIC is described in §7, and exists anyway when
the selected mechanism doesn't support integrity protection:

   "In order to produce the MIC token for the mechanism list, the
   mechanism must provide integrity protection.  When the selected
   mechanism does not support integrity protection, the negotiation is
   vulnerable: an active attacker can force it to use a security
   mechanism that is not mutually preferred but is acceptable to the
   target."

So the vulnerability is that a hypothetical attacker can trick us into
selecting a mechanism that both client and server were prepared to use
anyway, and which the server *would* have accepted if we'd happened to
try it first.

In practice, the viable fallback mechanism is almost always going to be
NTLMSSP. And in the case of HTTP and many other protocols, our
hypothetical attacker would have a much easier way of making the client
use NTLM — just mangle the 'WWW-Authenticate: Negotiate' in the 401
response so that my client only sees the 'WWW-Authenticate: NTLM', and
no need to screw around with SPNEGO packets at all.

(Note: If I could just disable IAKERB, or install the GSS-NTLMSSP plugin
with a sufficiently high priority that it's the first thing we offer to
this server, that would also suffice for me to avoid this problem. As
long as I offer GSS-NTLMSSP first and not IAKERB (which never works in
my environment and only serves to exacerbate other issues such as this
one), I'd be OK.)

---
 src/lib/gssapi/spnego/spnego_mech.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/lib/gssapi/spnego/spnego_mech.c b/src/lib/gssapi/spnego/spnego_mech.c
index 2aa6810..9721cad 100644
--- a/src/lib/gssapi/spnego/spnego_mech.c
+++ b/src/lib/gssapi/spnego/spnego_mech.c
@@ -831,17 +831,17 @@ init_ctx_reselect(OM_uint32 *minor_status, spnego_gss_ctx_id_t sc,
  sc->internal_mech = &sc->mech_set->elements[i];
 
  /*
- * Windows 2003 and earlier don't correctly send a
- * negState of request-mic when counter-proposing a
- * mechanism.  They probably don't handle mechListMICs
- * properly either.
+ * A server conforming to RFC4178 MUST set REQUEST_MIC here
+ * but Windows 2003 and earlier implement (roughly) RFC2478
+ * instead, and send ACCEPT_INCOMPLETE.
  */
- if (acc_negState != REQUEST_MIC)
+ if (acc_negState != REQUEST_MIC &&
+    acc_negState != ACCEPT_INCOMPLETE)
  return GSS_S_DEFECTIVE_TOKEN;
 
  sc->mech_complete = 0;
  sc->mic_reqd = 1;
- *negState = REQUEST_MIC;
+ *negState = acc_negState;
  *tokflag = CONT_TOKEN_SEND;
  return GSS_S_CONTINUE_NEEDED;
 }
--
1.9.3



--
David Woodhouse                            Open Source Technology Centre
[hidden email]                              Intel Corporation

_______________________________________________
krbdev mailing list             [hidden email]
https://mailman.mit.edu/mailman/listinfo/krbdev

smime.p7s (7K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Fix SPNEGO interoperability with servers implementing RFC2478

Greg Hudson
On 07/25/2014 06:42 AM, David Woodhouse wrote:
> A server conforming to RFC4178 MUST send request-mic there, but it
> is equally clear that on the client side, we should deal with its
> absence. For example, the language in §5 (c) is as follows:
>     "if the negState was request-mic in the first reply from the
>      target, a mechlistMIC token MUST be included; otherwise..."

This is followed by "(Note that the MIC token exchange is required
if a mechanism other than the initiator's first choice is chosen.)"  A
mechanism may require multiple hops to complete, so there can be
multiple SPNEGO exchanges even when the client's preferred mechanism was
selected.

> Other language in RFC4178 which supports this interpretation includes
> the whole of Appendix C, which explains the changes since RFC2478.

It is not clear to me that appendix C promises compatibility with Server
2003 in any case but when the preferred mechanism is negotiated.

> So the vulnerability is that a hypothetical attacker can trick us into
> selecting a mechanism that both client and server were prepared to use
> anyway, and which the server *would* have accepted if we'd happened to
> try it first.

It may seem like a marginal gain in security, but RFC 4178 went to
considerable effort to prevent this kind of downgrade attack, and I
don't think we want to just throw that out the window.  Nor do I think
our SPNEGO implementation should assume that one of the fallback
mechanisms is too weak to reliably provide MIC protection, or that
SPNEGO is taking place within a higher-level negotiation which is
subject to downgrade.

Heimdal has a complicated but acceptable compromise, which is to query
the negotiated security context for whether the peer ought to have
updated SPNEGO, and only insist on a downgrade MIC exchange if the
mechanism says yes.  I think we would accept a good implementation of
that facility (where "good" includes not making any overly long
functions significantly longer).  We should probably use the same query
OID as Heimdal, although I really wish that OID were fail-closed instead
of fail-open.

I have opened https://krbdev.mit.edu/rt/Ticket/Display.html?id=7975
about this negotiation scenario.  Although I am not in favor of the
simple solution, I do agree that it is important to solve the
interoperability problem in some way.
_______________________________________________
krbdev mailing list             [hidden email]
https://mailman.mit.edu/mailman/listinfo/krbdev
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Fix SPNEGO interoperability with servers implementing RFC2478

David Woodhouse-7
On Fri, 2014-07-25 at 11:44 -0400, Greg Hudson wrote:
> On 07/25/2014 06:42 AM, David Woodhouse wrote:
> > Other language in RFC4178 which supports this interpretation includes
> > the whole of Appendix C, which explains the changes since RFC2478.
>
> It is not clear to me that appendix C promises compatibility with Server
> 2003 in any case but when the preferred mechanism is negotiated.

If that isn't the intention, the I wonder why the request-mic state was
added at all. If servers required to send it and clients were expected
to abort the connection when they didn't see it, surely there's no
point? They could have just continued to use accept-incomplete as in
RFC2478, and always behave as if it were sent — basically making the MIC
mandatory where the underlying mechanism supports it.

Then there wouldn't be any need for them to explain what the client
should do when request-mic *isn't* sent, as they did.

> > So the vulnerability is that a hypothetical attacker can trick us into
> > selecting a mechanism that both client and server were prepared to use
> > anyway, and which the server *would* have accepted if we'd happened to
> > try it first.
>
> It may seem like a marginal gain in security, but RFC 4178 went to
> considerable effort to prevent this kind of downgrade attack, and I
> don't think we want to just throw that out the window.

Perhaps I'm missing something, but I don't think the patch just throws
that protection out of the window, does it?

A server compliant with RFC4178 will not only send request-mic, but it
will also expect us to actually *send* a MIC. If a hypothetical attacker
downgrades 'request-mic' in the reply to 'accept-incomplete', the server
isn't actually going to accept our authentication, surely? So my patch
doesn't seem to open us up to a viable downgrade attack there unless
I've misunderstood something.

My patch is only about interoperability with Windows RFC2478ish servers,
which don't send request-mic and won't check for or generate a MIC. And
it's a straight choice of whether we want to interoperate with those or
not, surely? Yes, *if* we talk to such a server then there's a downgrade
attack. We can be downgraded to a mechanism that is configured to be
acceptable, but just isn't preferred.

> Heimdal has a complicated but acceptable compromise, which is to query
> the negotiated security context for whether the peer ought to have
> updated SPNEGO, and only insist on a downgrade MIC exchange if the
> mechanism says yes.

So we'd ask the NTLMSSP mechanism, after it's succeeded in establishing
a security context, what version of Windows it thinks it was talking to
and thus whether it's reasonable for us to have seen accept-incomplete
where we wanted request-mic?

That could work, I suppose, but I'm not 100% convinced that it isn't
spoofable too by our hypothetical attacker by tampering with the NTLMSSP
exchange — which would render the whole thing just a pointless piece of
complexity. I'd have to check (or ask Simo ☺).

> I have opened https://krbdev.mit.edu/rt/Ticket/Display.html?id=7975
> about this negotiation scenario.  Although I am not in favor of the
> simple solution, I do agree that it is important to solve the
> interoperability problem in some way.

As I said, just disabling IAKERB or preferably being able to install
GSS-NTLMSSP at a higher priority would help. But there *are* cases where
we actually try krb5, with the *wrong* SPN, and then have to fall back
to NTLMSSP. So fixing the "real" problem would be good, from more than
just an engineering purity point of view.

--
dwmw2

_______________________________________________
krbdev mailing list             [hidden email]
https://mailman.mit.edu/mailman/listinfo/krbdev

smime.p7s (7K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Fix SPNEGO interoperability with servers implementing RFC2478

David Woodhouse-7
In reply to this post by Greg Hudson
FWIW here's an updated version of the patch which sets sc->mic_reqd
according to whether we see request-mic or not. My previous version
still unconditionally set it to 1.

It didn't make any difference in practice. It meant that we *sent* a MIC
to the server, which hadn't asked for it and duly ignored it. And if
Firefox or Curl had actually been feeding the final SPNEGO token back
into the GSS context after receiving it in a successful HTTP 200
response, it might then have been rejected. But what web client is going
to bother doing that when the authentication has already *succeeded*? :)

diff --git a/src/lib/gssapi/spnego/spnego_mech.c b/src/lib/gssapi/spnego/spnego_mech.c
index 2aa6810..542a78b 100644
--- a/src/lib/gssapi/spnego/spnego_mech.c
+++ b/src/lib/gssapi/spnego/spnego_mech.c
@@ -831,17 +831,17 @@ init_ctx_reselect(OM_uint32 *minor_status, spnego_gss_ctx_id_t sc,
  sc->internal_mech = &sc->mech_set->elements[i];
 
  /*
- * Windows 2003 and earlier don't correctly send a
- * negState of request-mic when counter-proposing a
- * mechanism.  They probably don't handle mechListMICs
- * properly either.
+ * A server conforming to RFC4178 MUST set REQUEST_MIC here
+ * but Windows 2003 and earlier implement (roughly) RFC2478
+ * instead, and send ACCEPT_INCOMPLETE.
  */
- if (acc_negState != REQUEST_MIC)
+ if (acc_negState != REQUEST_MIC &&
+    acc_negState != ACCEPT_INCOMPLETE)
  return GSS_S_DEFECTIVE_TOKEN;
 
  sc->mech_complete = 0;
- sc->mic_reqd = 1;
- *negState = REQUEST_MIC;
+ sc->mic_reqd = (acc_negState == REQUEST_MIC);
+ *negState = acc_negState;
  *tokflag = CONT_TOKEN_SEND;
  return GSS_S_CONTINUE_NEEDED;
 }
--
1.9.3


--
dwmw2

_______________________________________________
krbdev mailing list             [hidden email]
https://mailman.mit.edu/mailman/listinfo/krbdev

smime.p7s (7K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Fix SPNEGO interoperability with servers implementing RFC2478

Greg Hudson
In reply to this post by David Woodhouse-7
On 07/25/2014 03:45 PM, David Woodhouse wrote:
> If that isn't the intention, the I wonder why the request-mic state was
> added at all.

I'm not sure.  It wouldn't be the first time that a protocol used
explicit state where implicit state would serve.

> A server compliant with RFC4178 will not only send request-mic, but it
> will also expect us to actually *send* a MIC. If a hypothetical attacker
> downgrades 'request-mic' in the reply to 'accept-incomplete', the server
> isn't actually going to accept our authentication, surely?

I think the server will wind up returning accept-incomplete because it
hasn't yet received a mic from the client.  But the client won't
necessarily see that; the attacker could alter the final message from
the server to have accept-complete state.

> My patch is only about interoperability with Windows RFC2478ish servers,
> which don't send request-mic and won't check for or generate a MIC. And
> it's a straight choice of whether we want to interoperate with those or
> not, surely?

Yes, we have to tolerate a downgrade attack in order to interoperate
with these servers; but if we have a reason to believe we aren't talking
to an old SPNEGO implementation, we don't need to tolerate downgrade
attacks.

> That could work, I suppose, but I'm not 100% convinced that it isn't
> spoofable too by our hypothetical attacker by tampering with the NTLMSSP
> exchange — which would render the whole thing just a pointless piece of
> complexity.

(In IRC, David indicated that he believed NTLM is subject to downgrading
the relevant bit without knowing the shared secret, but I can't confirm
that.)

It would in the case where NTLM is one of the fallback mechanisms, but
not in all negotiation scenarios.  If the negotiated mechanism is not
implemented in Server 2003, then we don't have to tolerate a downgrade
without MIC.  Likewise if the negotiated mechanism is krb5 and used RFC
4121.
_______________________________________________
krbdev mailing list             [hidden email]
https://mailman.mit.edu/mailman/listinfo/krbdev
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Fix SPNEGO interoperability with servers implementing RFC2478

David Woodhouse-7
On Fri, 2014-07-25 at 18:57 -0400, Greg Hudson wrote:

>
> > A server compliant with RFC4178 will not only send request-mic, but it
> > will also expect us to actually *send* a MIC. If a hypothetical attacker
> > downgrades 'request-mic' in the reply to 'accept-incomplete', the server
> > isn't actually going to accept our authentication, surely?
>
> I think the server will wind up returning accept-incomplete because it
> hasn't yet received a mic from the client.  But the client won't
> necessarily see that; the attacker could alter the final message from
> the server to have accept-complete state.
Looking at handle_mic(), I think our implementation will return
GSS_S_DEFECTIVE_TOKEN if it sees a final mechanism token without the MIC
attached. It doesn't return GSS_S_CONTINUE_NEEDED and hope for the MIC
to come in later on its own. I don't think that's even possible.

--
dwmw2

_______________________________________________
krbdev mailing list             [hidden email]
https://mailman.mit.edu/mailman/listinfo/krbdev

smime.p7s (7K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Fix SPNEGO interoperability with servers implementing RFC2478

Greg Hudson
On 07/25/2014 07:26 PM, David Woodhouse wrote:
> Looking at handle_mic(), I think our implementation will return
> GSS_S_DEFECTIVE_TOKEN if it sees a final mechanism token without the MIC
> attached. It doesn't return GSS_S_CONTINUE_NEEDED and hope for the MIC
> to come in later on its own. I don't think that's even possible.

The server appears to do so if it sends the final mech token.  It has
to; the client can't necessarily produce a MIC until the context is
established.

(My reasoning, with line numbers from current master: handle_mic decides
to reject at line 528 if no token is to be sent, but continues on if a
token is to be sent.  At line 559, it decides to respond with
ACCEPT_INCOMPLETE if a MIC is required.)
_______________________________________________
krbdev mailing list             [hidden email]
https://mailman.mit.edu/mailman/listinfo/krbdev
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Fix SPNEGO interoperability with servers implementing RFC2478

David Woodhouse-7
On Fri, 2014-07-25 at 20:01 -0400, Greg Hudson wrote:

> On 07/25/2014 07:26 PM, David Woodhouse wrote:
> > Looking at handle_mic(), I think our implementation will return
> > GSS_S_DEFECTIVE_TOKEN if it sees a final mechanism token without the MIC
> > attached. It doesn't return GSS_S_CONTINUE_NEEDED and hope for the MIC
> > to come in later on its own. I don't think that's even possible.
>
> The server appears to do so if it sends the final mech token.  It has
> to; the client can't necessarily produce a MIC until the context is
> established.
>
> (My reasoning, with line numbers from current master: handle_mic decides
> to reject at line 528 if no token is to be sent, but continues on if a
> token is to be sent.  At line 559, it decides to respond with
> ACCEPT_INCOMPLETE if a MIC is required.)
Ah, right. In the case where our server sends the final mech token,
although the underlying mechanism is complete, the SPNEGO negotiation
isn't. So the overall authentication isn't done yet;
spnego_gss_init_sec_context() will end up returning
GSS_S_CONTINUE_NEEDED to its caller and, for example, the HTTP server
will return the token in another 401 'Unauthorized' response to the
client.

If the underlying mechanism has completed and established a security
context, but the overall authentication has not succeeded, is that
materially different from the proposed solution that allows the
underlying security context to be established and then queries it to see
if the fallback without MIC was 'believable'?

--
dwmw2

_______________________________________________
krbdev mailing list             [hidden email]
https://mailman.mit.edu/mailman/listinfo/krbdev

smime.p7s (7K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Fix SPNEGO interoperability with servers implementing RFC2478

David Woodhouse-7
In reply to this post by Greg Hudson
On Fri, 2014-07-25 at 18:57 -0400, Greg Hudson wrote:
> On 07/25/2014 03:45 PM, David Woodhouse wrote:
> > If that isn't the intention, the I wonder why the request-mic state was
> > added at all.
>
> I'm not sure.  It wouldn't be the first time that a protocol used
> explicit state where implicit state would serve.

No, it's much more than that.

You are quite right that it's not unheard-of for protocols to use
explicit state where implicit state would serve. (And sometimes that
makes sense, for forward compatibility. You might explicitly know the
state *today* but in future new possibilities might be added.)

But this additional state was *added* to an existing protocol.

If the intention was that new servers and clients must *always* require
MIC processing without regard to backward compatibility, there was
absolutely no need for that change. Just send and check/require the MIC
unconditionally (when the underlying mechanism supports it), and that's
all there is to it.

The only way that the addition of the REQUEST-MIC state makes sense, is
for clients to be able to tell the difference between RFC4178-compliant
and older servers.

Furthermore, in your interpretation it's not just redundant state on the
wire. There's also verbiage in the RFC which would be entirely
redundant, where it *explicitly* sets out how a client should behave
when a server doesn't send the REQUEST-MIC state in its reply.

Seriously, the *only* logic that makes sense for the change is that it
allows clients to interoperate with older servers.

FWIW I tested on Windows 7, with a fake server. My client (using SSPI)
sends a Kerberos token, and the server sends back:
     Proxy-Authenticate: Negotiate oRUwE6ADCgEBoQwGCisGAQQBgjcCAgo=
That is, a SPNEGO "no, try GSS-NTLMSSP" with ACCEPT-INCOMPLETE. At which
point Windows happily falls back to GSS-NTLMSSP as requested.

This behaviour matches my reading of the specification, and I'm fairly
certain that it *is* what they intended.

Now, that doesn't mean we *have* to do what they intended, of course.
But it's a fairly strong hint in that direction.

> > A server compliant with RFC4178 will not only send request-mic, but it
> > will also expect us to actually *send* a MIC. If a hypothetical attacker
> > downgrades 'request-mic' in the reply to 'accept-incomplete', the server
> > isn't actually going to accept our authentication, surely?
>
> I think the server will wind up returning accept-incomplete because it
> hasn't yet received a mic from the client.  But the client won't
> necessarily see that; the attacker could alter the final message from
> the server to have accept-complete state.

If it's the client that sends the last token, as is the case in NTLMSSP,
there's no downgrade attack here. Either we send our final packet
without a MIC, or perhaps we'd send it with an unsolicited MIC of the
tampered packets, and either way the server is doing to reject that.

If it's the server that sends the last token, then still we're never
going to be able to authenticate to that server because it'll be waiting
for a MIC. But you are correct that the attacker could alter the final
message to have ACCEPT-COMPLETE state, and fool us into thinking that we
succeeded. Although we'd be left with a GSSAPI context which isn't
actually *useful* for anything, because the server will hate us.

Maybe I'm missing a reason why we'd really care about that, given that
an attacker could have bypassed the whole exchange and just made it look
like the server didn't require authentication in the first place.

But I'm not going to lose sleep over that. Given the limited
circumstances in which the fallback is necessary, it would be perfectly
acceptable to accept fallback without REQUEST-MIC *only* if the
mechanism being requested is one where the client sends the final token.
Or indeed, *only* if the mechanism is NTLMSSP.

Like this, for example...

From ec9988362314819963e025aee5b0deca28a98eb6 Mon Sep 17 00:00:00 2001
From: David Woodhouse <[hidden email]>
Date: Fri, 25 Jul 2014 11:10:01 +0100
Subject: [PATCH] Fix SPNEGO interoperability with servers implementing RFC2478
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Servers running Windows 2003 and earlier do not send a negState of
request-mic in their initial reply when the first mechanism is
declined. That's because they implement (roughly) RFC2478, which
predates the addition of the request-mic state.

A server conforming to RFC4178 MUST send request-mic there, but it
is equally clear that on the client side, we should deal with its
absence. For example, the language in §5 (c) is as follows:
    "if the negState was request-mic in the first reply from the
     target, a mechlistMIC token MUST be included; otherwise..."

In the MIT implementation as it stands, there is no "otherwise".
Because we already overzealously aborted the negotiation.

Other language in RFC4178 which supports this interpretation includes
the whole of Appendix C, which explains the changes since RFC2478.

Looking at that, in fact it seems that the addition of request-mic on
the wire was done specifically to allow interoperability with older
implementations which don't set it. If not for that consideration,
and if we were only ever communicating between RFC4178-compliant
implementations, we could always have just behaved as if request-mic
were set — and there would be no need to *say* so on the wire.

Testing on Windows 7 shows that the Windows client *will* continue in
this situation without using a MIC, as requested by the server.

This change does NOT make us vulnerable to a downgrade attack where an
attacker changes request-mic in a server's response to accept-incomplete.

The server in any such situation is still going to be looking for the
MIC that it asked for. And when we fail to send one (or if we send one
but we've hashed the tampered packets), the server is going to reject
our authentication.

In the case where the final mechanism token is sent from client to
server, the server will reject our authentication attempt outright.
This is, in fact, the case we see in practice because it is NTLMSSP
that the affected servers will be asking us to fall back to.

In the case where the final mechanism token is sent from server to
client, the server will send its final token with accept-incomplete
state indicating that it is waiting for the MIC. A hypothetical
attacker could change that to accept-complete, thus tricking us into
thinking that the authentication succeeded. It's not entirely clear
what practical purpose this could serve in any situation, since
the context *isn't* established and the server *hasn't* authenticated
us. But we don't need to lose sleep over that. We *only* need to allow
NTLMSSP for this fallback anyway, so just disallow it for any other
mechanisms.
---
 src/lib/gssapi/spnego/spnego_mech.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/src/lib/gssapi/spnego/spnego_mech.c b/src/lib/gssapi/spnego/spnego_mech.c
index 2aa6810..0abe175 100644
--- a/src/lib/gssapi/spnego/spnego_mech.c
+++ b/src/lib/gssapi/spnego/spnego_mech.c
@@ -806,6 +806,9 @@ init_ctx_nego(OM_uint32 *minor_status, spnego_gss_ctx_id_t sc,
  return ret;
 }
 
+static const gss_OID_desc gss_mech_ntlmssp_oid =
+        { 10, "\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a" };
+
 /*
  * Handle acceptor's counter-proposal of an alternative mechanism.
  */
@@ -831,17 +834,20 @@ init_ctx_reselect(OM_uint32 *minor_status, spnego_gss_ctx_id_t sc,
  sc->internal_mech = &sc->mech_set->elements[i];
 
  /*
- * Windows 2003 and earlier don't correctly send a
- * negState of request-mic when counter-proposing a
- * mechanism.  They probably don't handle mechListMICs
- * properly either.
+ * A server conforming to RFC4178 MUST set REQUEST_MIC here
+ * but Windows 2003 and earlier implement (roughly) RFC2478
+ * instead, and send ACCEPT_INCOMPLETE. Tolerate that *only*
+ * if they are asking us to fall back to NTLMSSP.
  */
- if (acc_negState != REQUEST_MIC)
+ if (acc_negState == ACCEPT_INCOMPLETE) {
+ if (!g_OID_equal(supportedMech, &gss_mech_ntlmssp_oid))
+ return GSS_S_DEFECTIVE_TOKEN;
+ } else if (acc_negState != REQUEST_MIC)
  return GSS_S_DEFECTIVE_TOKEN;
 
  sc->mech_complete = 0;
- sc->mic_reqd = 1;
- *negState = REQUEST_MIC;
+ sc->mic_reqd = (acc_negState == REQUEST_MIC);
+ *negState = acc_negState;
  *tokflag = CONT_TOKEN_SEND;
  return GSS_S_CONTINUE_NEEDED;
 }
--
1.9.3




--
dwmw2

_______________________________________________
krbdev mailing list             [hidden email]
https://mailman.mit.edu/mailman/listinfo/krbdev

smime.p7s (7K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Fix SPNEGO interoperability with servers implementing RFC2478

Greg Hudson
On 08/04/2014 10:10 AM, David Woodhouse wrote:
> If the intention was that new servers and clients must *always* require
> MIC processing without regard to backward compatibility, there was
> absolutely no need for that change. Just send and check/require the MIC
> unconditionally (when the underlying mechanism supports it), and that's
> all there is to it.

"Always" is oversimplifying.  The MIC is not required when the
optimistic mech is negotiated, or when the negotiated mech does not
support integrity protection.  (We do not currently check the latter
condition.  That may give us a path forward since NTLM as negotiated
with an old Windows server won't support integrity protection, and we
can check this after the internal context is established.)

The client can still deduce the MIC requirement without the benefit of
the requires-mic flag, of course.

> The only way that the addition of the REQUEST-MIC state makes sense, is
> for clients to be able to tell the difference between RFC4178-compliant
> and older servers.

Section 5 flatly states: "In all other cases, MIC tokens MUST be
exchanged after the mechanism context is fully established."  I cannot
reconcile your interpretation with that statement.  Appendix C also
states, "If at least one of the two peers implements the updated pseudo
mechanism in this document, the negotiation is protected."

It is conceivable that the bit was added for interoperablity, and then
the interoperability constraints were tightened for security, to the
point where the bit is no longer actually needed.  I was hoping to find
support for this hypothesis in the history of the RFC 4178 drafts, but
even the -00 version of the draft contains all of the elements we're
talking about (the presence of the request-mic flag, the verbiage on how
to react to it, and the flat requirement of exchanging MICs).  So this
is complete speculation.

> FWIW I tested on Windows 7, with a fake server. My client (using SSPI)
> sends a Kerberos token, and the server sends back:
>      Proxy-Authenticate: Negotiate oRUwE6ADCgEBoQwGCisGAQQBgjcCAgo=
> That is, a SPNEGO "no, try GSS-NTLMSSP" with ACCEPT-INCOMPLETE. At which
> point Windows happily falls back to GSS-NTLMSSP as requested.

However, note that a current Windows server requires a MIC exchange if
NTLMSSP with integrity protection is selected (even if it is the
optimistic mechanism).  See
https://github.com/krb5/krb5/commit/bff6bbf52401f9464df365d76f0987fbf8101c5e

I am not sure if Windows has the same restriction on the client.

> If it's the client that sends the last token, as is the case in NTLMSSP,
> there's no downgrade attack here. Either we send our final packet
> without a MIC, or perhaps we'd send it with an unsolicited MIC of the
> tampered packets, and either way the server is doing to reject that.

A downgrade attack against the client does not necessarily involve the
real server's participation after authentication.  Perhaps the attacker
wants to collect early ciphertext from the client which can be more
easily cryptoanalyzed, for instance.

In the context of HTTP this is meaningless, because the mechanism isn't
used to protect the data stream.  But the SPNEGO implementation does not
make this assumption.
_______________________________________________
krbdev mailing list             [hidden email]
https://mailman.mit.edu/mailman/listinfo/krbdev
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Fix SPNEGO interoperability with servers implementing RFC2478

David Woodhouse-7
On Mon, 2014-08-04 at 13:36 -0400, Greg Hudson wrote:
>  That may give us a path forward since NTLM as negotiated
> with an old Windows server won't support integrity protection, and we
> can check this after the internal context is established.)

... as negotiated with an old Windows server, or with an attacker
sitting in the middle clearing the interesting bits in the feature
flags :)

There's no point in that check. You might as well reduce it to "if
NTLMSSP". Which I already did :)

> The client can still deduce the MIC requirement without the benefit of
> the requires-mic flag, of course.

In practice I'm happy for the client to still produce and "require" the
MIC. My first patch did precisely that, in fact, and *only* avoided the
GSS_S_DEFECTIVE_TOKEN return, leaving sc->mic_reqd=1. That works because
when we produce a MIC it's ignored by the server anyway — and although
we "require" one, fairly much no clients actually feed the final token
back into gss_init_sec_context() after a successful authentication
anyway. Many protocols like IMAP don't even have a *way* for that to
happen, and web clients just don't bother. If they get a 200 successful
response, they're done.

>  I was hoping to find
> support for this hypothesis in the history of the RFC 4178 drafts, but
> even the -00 version of the draft contains all of the elements we're
> talking about (the presence of the request-mic flag, the verbiage on how
> to react to it, and the flat requirement of exchanging MICs).  So this
> is complete speculation.

Are any of the authors still available to ask? If their implementation
in Windows isn't considered to be sufficient evidence of their intent,
that is...

--
dwmw2

_______________________________________________
krbdev mailing list             [hidden email]
https://mailman.mit.edu/mailman/listinfo/krbdev

smime.p7s (7K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Fix SPNEGO interoperability with servers implementing RFC2478

Nico Williams
On Mon, Aug 04, 2014 at 07:29:06PM +0100, David Woodhouse wrote:

> >  I was hoping to find
> > support for this hypothesis in the history of the RFC 4178 drafts, but
> > even the -00 version of the draft contains all of the elements we're
> > talking about (the presence of the request-mic flag, the verbiage on how
> > to react to it, and the flat requirement of exchanging MICs).  So this
> > is complete speculation.
>
> Are any of the authors still available to ask? If their implementation
> in Windows isn't considered to be sufficient evidence of their intent,
> that is...

The mailing list archives should have plenty of content.  IIRC SPNEGO
was ambiguous as specified and subject to a downgrade attack as
implemented by one major implementor.  We thought we'd not be able to
fix this without a flag day untill Larry Zhu came up with a fix that
worked for all the cases we cared about, and this led to RFC4178.

I was an active participant, though I don't recall the details but I
could swap it all back in if need be.  All authors and participants
should still be reachable, but you're likely to find the mail archives
degrade less badly than human memory does!

Nico
--
_______________________________________________
krbdev mailing list             [hidden email]
https://mailman.mit.edu/mailman/listinfo/krbdev
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Fix SPNEGO interoperability with servers implementing RFC2478

Nico Williams
In reply to this post by David Woodhouse-7
On Fri, Jul 25, 2014 at 11:42:30AM +0100, David Woodhouse wrote:
> So the vulnerability is that a hypothetical attacker can trick us into
> selecting a mechanism that both client and server were prepared to use
> anyway, and which the server *would* have accepted if we'd happened to
> try it first.

Yes.

> In practice, the viable fallback mechanism is almost always going to be
> NTLMSSP. And in the case of HTTP and many other protocols, our
> hypothetical attacker would have a much easier way of making the client
> use NTLM — just mangle the 'WWW-Authenticate: Negotiate' in the 401
> response so that my client only sees the 'WWW-Authenticate: NTLM', and
> no need to screw around with SPNEGO packets at all.

Today, yes.  It's not clear that this will always be so.

> (Note: If I could just disable IAKERB, or install the GSS-NTLMSSP plugin
> with a sufficiently high priority that it's the first thing we offer to
> this server, that would also suffice for me to avoid this problem. As
> long as I offer GSS-NTLMSSP first and not IAKERB (which never works in
> my environment and only serves to exacerbate other issues such as this
> one), I'd be OK.)

You should be able to gss_set_neg_mechs() to disable offering mechanisms
you can't / don't want to use.

Nico
--

_______________________________________________
krbdev mailing list             [hidden email]
https://mailman.mit.edu/mailman/listinfo/krbdev
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Fix SPNEGO interoperability with servers implementing RFC2478

David Woodhouse-7
On Mon, 2014-08-04 at 14:01 -0500, Nico Williams wrote:
> You should be able to


... patch every application in the system, including third party apps
like Google Chrome, to ...

> gss_set_neg_mechs() to disable offering mechanisms you can't / don't
> want to use.

:(

--
dwmw2

_______________________________________________
krbdev mailing list             [hidden email]
https://mailman.mit.edu/mailman/listinfo/krbdev

smime.p7s (7K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Fix SPNEGO interoperability with servers implementing RFC2478

Nico Williams
On Mon, Aug 04, 2014 at 08:20:08PM +0100, David Woodhouse wrote:

> On Mon, 2014-08-04 at 14:01 -0500, Nico Williams wrote:
> > You should be able to
>
> ... patch every application in the system, including third party apps
> like Google Chrome, to ...
>
> > gss_set_neg_mechs() to disable offering mechanisms you can't / don't
> > want to use.
>
> :(

Yeah, we have a problem :(

One option might be to require calling gss_set_neg_mechs() to enable
offering mechanisms other than Kerberos and NTLM.  Greg?

Nico
--
_______________________________________________
krbdev mailing list             [hidden email]
https://mailman.mit.edu/mailman/listinfo/krbdev
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Fix SPNEGO interoperability with servers implementing RFC2478

David Woodhouse-7
On Mon, 2014-08-04 at 14:27 -0500, Nico Williams wrote:

> On Mon, Aug 04, 2014 at 08:20:08PM +0100, David Woodhouse wrote:
> > On Mon, 2014-08-04 at 14:01 -0500, Nico Williams wrote:
> > > You should be able to
> >
> > ... patch every application in the system, including third party apps
> > like Google Chrome, to ...
> >
> > > gss_set_neg_mechs() to disable offering mechanisms you can't / don't
> > > want to use.
> >
> > :(
>
> Yeah, we have a problem :(
>
> One option might be to require calling gss_set_neg_mechs() to enable
> offering mechanisms other than Kerberos and NTLM.  Greg?
Perhaps. But it's still a workaround. And I do have cases where I
actually need to fall back from Kerberos to NTLM. Thus still leaving me
with the *real* problem that SPNEGO isn't interoperating properly...

--
dwmw2

_______________________________________________
krbdev mailing list             [hidden email]
https://mailman.mit.edu/mailman/listinfo/krbdev

smime.p7s (7K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Fix SPNEGO interoperability with servers implementing RFC2478

Nico Williams
On Mon, Aug 04, 2014 at 08:30:46PM +0100, David Woodhouse wrote:

> On Mon, 2014-08-04 at 14:27 -0500, Nico Williams wrote:
> > On Mon, Aug 04, 2014 at 08:20:08PM +0100, David Woodhouse wrote:
> > > On Mon, 2014-08-04 at 14:01 -0500, Nico Williams wrote:
> > > > You should be able to
> > >
> > > ... patch every application in the system, including third party apps
> > > like Google Chrome, to ...
> > >
> > > > gss_set_neg_mechs() to disable offering mechanisms you can't / don't
> > > > want to use.
> > >
> > > :(
> >
> > Yeah, we have a problem :(
> >
> > One option might be to require calling gss_set_neg_mechs() to enable
> > offering mechanisms other than Kerberos and NTLM.  Greg?
>
> Perhaps. But it's still a workaround. And I do have cases where I
> actually need to fall back from Kerberos to NTLM. Thus still leaving me
> with the *real* problem that SPNEGO isn't interoperating properly...

To help any further I'd have to swap in the RFC4178 background.

I thought these issues had been addressed in the RFC.  Without swapping
all that state back in I'd suspect that MIT doesn't implement it
correctly.
_______________________________________________
krbdev mailing list             [hidden email]
https://mailman.mit.edu/mailman/listinfo/krbdev
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Fix SPNEGO interoperability with servers implementing RFC2478

Stefan Metzmacher
In reply to this post by Greg Hudson
Hi Greg, hi David,

> On 08/04/2014 10:10 AM, David Woodhouse wrote:
>> If the intention was that new servers and clients must *always* require
>> MIC processing without regard to backward compatibility, there was
>> absolutely no need for that change. Just send and check/require the MIC
>> unconditionally (when the underlying mechanism supports it), and that's
>> all there is to it.
>
> "Always" is oversimplifying.  The MIC is not required when the
> optimistic mech is negotiated, or when the negotiated mech does not
> support integrity protection.  (We do not currently check the latter
> condition.  That may give us a path forward since NTLM as negotiated
> with an old Windows server won't support integrity protection, and we
> can check this after the internal context is established.)
> The client can still deduce the MIC requirement without the benefit of
> the requires-mic flag, of course.
NTLMSSP in windows 2000 and 2003 supports integrity and privacy protection.

>> The only way that the addition of the REQUEST-MIC state makes sense, is
>> for clients to be able to tell the difference between RFC4178-compliant
>> and older servers.
>
> Section 5 flatly states: "In all other cases, MIC tokens MUST be
> exchanged after the mechanism context is fully established."  I cannot
> reconcile your interpretation with that statement.  Appendix C also
> states, "If at least one of the two peers implements the updated pseudo
> mechanism in this document, the negotiation is protected."
>
> It is conceivable that the bit was added for interoperablity, and then
> the interoperability constraints were tightened for security, to the
> point where the bit is no longer actually needed.  I was hoping to find
> support for this hypothesis in the history of the RFC 4178 drafts, but
> even the -00 version of the draft contains all of the elements we're
> talking about (the presence of the request-mic flag, the verbiage on how
> to react to it, and the flat requirement of exchanging MICs).  So this
> is complete speculation.
>
>> FWIW I tested on Windows 7, with a fake server. My client (using SSPI)
>> sends a Kerberos token, and the server sends back:
>>      Proxy-Authenticate: Negotiate oRUwE6ADCgEBoQwGCisGAQQBgjcCAgo=
>> That is, a SPNEGO "no, try GSS-NTLMSSP" with ACCEPT-INCOMPLETE. At which
>> point Windows happily falls back to GSS-NTLMSSP as requested.
>
> However, note that a current Windows server requires a MIC exchange if
> NTLMSSP with integrity protection is selected (even if it is the
> optimistic mechanism).  See
> https://github.com/krb5/krb5/commit/bff6bbf52401f9464df365d76f0987fbf8101c5e
>
> I am not sure if Windows has the same restriction on the client.
This is the ntlmssp code:
https://git.samba.org/?p=idra/gss-ntlmssp.git;a=summary
https://git.samba.org/?p=idra/gss-ntlmssp.git;a=commitdiff;h=bdb7be8468140550b59d1ec6694130f51ba9a799

New versions of NTLMSSP indicate their knowledge about RFC4178 to the
SPNEGO layer,
which gives the SPNEGO layer a chance to decide if the peer expects a
MechListMic
or not.

There're also strange tricks where windows tries to workaround the situation
where the client generated a MechListMic, but the server ignores it.

See http://msdn.microsoft.com/en-us/library/gg465664.aspx
[MS-SPNG] 3.3.5.1 NTLM RC4 Key State for MechListMIC and First Signed
Message
I think this doesn't work as intended as they forgot to also reuse the
same sequence number...

So this is tricky to get right and needs a lot of testing.

metze


_______________________________________________
krbdev mailing list             [hidden email]
https://mailman.mit.edu/mailman/listinfo/krbdev

signature.asc (254 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Fix SPNEGO interoperability with servers implementing RFC2478

David Woodhouse-7
On Tue, 2014-08-05 at 00:09 +0200, Stefan (metze) Metzmacher wrote:

> > However, note that a current Windows server requires a MIC exchange if
> > NTLMSSP with integrity protection is selected (even if it is the
> > optimistic mechanism).  See
> > https://github.com/krb5/krb5/commit/bff6bbf52401f9464df365d76f0987fbf8101c5e
> >
> > I am not sure if Windows has the same restriction on the client.
>
> This is the ntlmssp code:
> https://git.samba.org/?p=idra/gss-ntlmssp.git;a=summary
> https://git.samba.org/?p=idra/gss-ntlmssp.git;a=commitdiff;h=bdb7be8468140550b59d1ec6694130f51ba9a799
>
> New versions of NTLMSSP indicate their knowledge about RFC4178 to the
> SPNEGO layer, which gives the SPNEGO layer a chance to decide if the
> peer expects a MechListMic or not.
That's an orthogonal (and solved) issue, surely?

It's one thing to say "NTLMSSP did negotiate a MIC, therefore we know
that Windows SPNEGO will require mechlistMIC even if NTLMSSP was the
optimistic mechanism and SPNEGO wouldn't normally require it." That's
fairly clear-cut.

It's not clear that there's *any* way a client can safely infer from the
NTLMSSP exchange that a server really *is* one of the RFC2478ish Windows
versions. Any feature we use to detect a 'newer' server can be disabled
by the attacker¹, AFAICT. I can't see a better option than just to allow
fallback without REQUEST-MIC but *only* to NTLMSSP. And perhaps only if
enabled by a krb5.conf option? Either abusing allow_weak_crypto or
adding something more appropriate...


--
dwmw2

¹ I've been vaguely hacking gss-ntlmssp to mangle its own feature flags
  as if there were such an attacker and prove this hypothesis. So far
  I haven't succeeded but I'm blaming that mostly on my stupidity today.

_______________________________________________
krbdev mailing list             [hidden email]
https://mailman.mit.edu/mailman/listinfo/krbdev

smime.p7s (7K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Fix SPNEGO interoperability with servers implementing RFC2478

Nico Williams
On Mon, Aug 4, 2014 at 5:53 PM, David Woodhouse <[hidden email]> wrote:
> It's not clear that there's *any* way a client can safely infer from the
> NTLMSSP exchange that a server really *is* one of the RFC2478ish Windows
> versions. Any feature we use to detect a 'newer' server can be disabled
> by the attacker¹, AFAICT. I can't see a better option than just to allow
> fallback without REQUEST-MIC but *only* to NTLMSSP. And perhaps only if
> enabled by a krb5.conf option? Either abusing allow_weak_crypto or
> adding something more appropriate...

That seems reasonable to me, yes.

If you're willing to fallback on a mechanism that can't do integrity
protection then you can't have downgrade detection.

Of course, if you have credentials for a mechanism like Kerberos that
can tell you a priori that you stand a good chance of succeeding, and
it does tell you that, then you shouldn't offer any other mechanisms
weaker than Kerberos.  (This is a common idiom in SSHv2 GSS key
exchange clients: call gss_init_sec_context() first, and if that
doesn't fail, offer the mechanism, else don't.)

Nico
--

_______________________________________________
krbdev mailing list             [hidden email]
https://mailman.mit.edu/mailman/listinfo/krbdev
12