Bug 14557 (CVE-2020-25721) - CVE-2020-25721 [SECURITY] KDC canonicalisation and mapping rules: challenges and hardening
Summary: CVE-2020-25721 [SECURITY] KDC canonicalisation and mapping rules: challenges ...
Status: ASSIGNED
Alias: CVE-2020-25721
Product: Samba 4.1 and newer
Classification: Unclassified
Component: AD: LDB/DSDB/SAMDB (show other bugs)
Version: 4.13.0
Hardware: All All
: P5 normal (vote)
Target Milestone: ---
Assignee: Andrew Bartlett
QA Contact: Samba QA Contact
URL:
Keywords:
Depends on: 14835
Blocks: 14725
  Show dependency treegraph
 
Reported: 2020-10-29 08:27 UTC by Andrew Bartlett
Modified: 2021-12-10 18:29 UTC (History)
10 users (show)

See Also:


Attachments
A Kerberos bind against LDAP (255 bytes, application/vnd.tcpdump.pcap)
2020-11-17 01:32 UTC, Andrew Bartlett
no flags Details
keytab to decrypt (827 bytes, application/octet-stream)
2020-11-17 01:33 UTC, Andrew Bartlett
no flags Details
the cleartext decode of the LDAP bind with Kerberos (3.56 KB, text/plain)
2020-11-17 01:34 UTC, Andrew Bartlett
no flags Details
the 'wire' encrypted LDAP bind (2.71 KB, text/plain)
2020-11-17 01:35 UTC, Andrew Bartlett
no flags Details
Possible letter to Microsoft for comment. (2.83 KB, text/plain)
2020-11-17 02:05 UTC, Andrew Bartlett
no flags Details
New possible mail to Microsoft (probably via the protocols team) (5.02 KB, text/plain)
2020-12-01 04:53 UTC, Andrew Bartlett
no flags Details
advisory text (v01) (3.07 KB, text/plain)
2021-11-03 08:48 UTC, Andrew Bartlett
metze: review+
Details
advisory text (v02) (4.20 KB, text/plain)
2021-11-03 17:49 UTC, Andrew Bartlett
abartlet: review? (metze)
ab: review+
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Andrew Bartlett 2020-10-29 08:27:58 UTC
Ever since writing the infamous krb5.kdc.canon test I've always hated the way this is handled and I think there is scope for abuse there but I've not figured what exactly yet. 

We should find a way to return to a target server (even if not the client) only the samAccountName@REALM principal name, as this is what is most often seen and kerberos-only applications like the popular mod_auth_kerb assume this mapping. 

Because these applications can't read the PAC they need a more reliable way to get user info from just the principal string.

We need to work with Microsoft on a behaviour change here.
Comment 1 Isaac Boukris 2020-10-29 10:27:18 UTC
(In reply to Andrew Bartlett from comment #0)

Since then, name canonicalization has been standardized in rfc6806, which describes almost accurately Windows behaviour in this regard, which is:

- Both client and server names get canonicalized in AS-REP *if* the canonicalize flag is set.
- Neither client or server names get canonicalized in TGS-REP (including S4U2Self!).
- The realm component of the names always gets canonicalized, except for none-enterprise S4U2Self request with netbios realm (that's the only way to end up with a ticket where cname is user@nbrealm).

So to get the client name always canonicalized, we should just make sure to always set the canonicalize flag in AS-REQ, like Windows clients do but S4U2Self client name will remain uncanonicalized (IMO the latter should be canonicalized as S4U2Self is more like an initial request, and it should be fine security wise, especially with PA_FOR_X509_USER as the returned client name is protected with a checksum).
Comment 2 Isaac Boukris 2020-10-29 11:01:46 UTC
Another approach could be to provide PAC decoding facilities in the krb5 libraries, making it available more natively.

I started some wip for MIT a while ago, but manual NDR decoding has proven quite hard..
Comment 3 Andrew Bartlett 2020-10-29 18:42:49 UTC
(In reply to Isaac Boukris from comment #1)
The issue is that the client (the attacker in this case) can choose not to set the canonicalise bit in the AD-REQ and so pass the original principal name all the way to the target server.
Comment 4 Andrew Bartlett 2020-11-11 08:37:52 UTC
(In reply to Andrew Bartlett from comment #3)

I notice here that MIT Kerberos (wisely) does not allow authentication with an alias without setting canonicalise.

I wonder how we might transition to that in samba?  It will be difficult as the default linux krb5.conf configurations mean that kinit does not use canonicalise.

Could we put force a canonicalised username into the encrypted ticket while leaving the original other one outside?  What would that break?
Comment 5 Isaac Boukris 2020-11-11 11:04:33 UTC
(In reply to Andrew Bartlett from comment #4)

> I notice here that MIT Kerberos (wisely) does not allow authentication with an alias without setting canonicalise.

You mean MIT kdc? I "fixed" it in MIT and if you try v1.18 this won't be the case and enterprise-name aren't implicitly flag with the canon flag in MIT kdc (i did it in order to match Windowd and Heimdal behaviour so we can eventually pass the canonicalization tests, see upstream MR 1018).

That's not a real problem though, as we can always force canonicalization of enterprise clients in the KDB module by checking the name type (the client and core kdc code would still allow it, for enterprise names).

The main problem as you pointed out, is that unless we get MS on our side, we can only solve it for samba-dc, while domain member in windows env would still be an issue, and i suspect they'd be reluctant to change it given heir servers are fine as they use the PAC.

Another problem is none-enterprise aliases, like using the LHS of the UPN without using enterprise name type, we can force canonicalization here too but that would require a patch in the core kdc code (otherwise the kdc just ignores what we set in the KDB module and sets the requested name in the reply).

> I wonder how we might transition to that in samba?  It will be difficult as the default linux krb5.conf configurations mean that kinit does not use canonicalise.

For enterprise name it would be fine, but none enterprise aliases would fail on client side if the get canonicalized name (not necessarily that bad).

btw, do you have a clear attack in mind? in my tests i mostly worried that it might cause conflicts when the admin changes or adds names, but not a clear attack.

> Could we put force a canonicalised username into the encrypted ticket while leaving the original other one outside?  What would that break?

That would break gss_accept() call on the server side.
Comment 6 Andrew Bartlett 2020-11-12 02:25:15 UTC
(In reply to Isaac Boukris from comment #5)
Like you I couldn't for the longest time come up with a clear attack, but you can see the other bugs for details of what I've been able to exploit.  

Some of them don't require that username move around!

My MIT comment comes from 
https://www.freeipa.org/page/V4/Kerberos_principal_aliases

My general concerns are well written up here:
https://k5wiki.kerberos.org/wiki/Projects/Aliases

That is that it can "break name-based authorization."  I guess this means we can consider that this problem space is already publicly described. 

Can you explain how gss_accept() would fail on the server-side if the KDC always put the canonical name in the service ticket?

Thanks!

Andrew Bartlett
Comment 7 Isaac Boukris 2020-11-12 06:52:51 UTC
(In reply to Andrew Bartlett from comment #6)

> Can you explain how gss_accept() would fail on the server-side if the KDC always put the canonical name in the service ticket?

That's not exactly how you've phrased the question, it is missing a key part "while leaving the original other one outside"; when the client makes an AP request it uses the unencrypted name (it can't read the one in the ticket), and if the server finds that the client name in the AP authenticator and the one in the ticket aren't the same, it will fail the request.
Comment 8 Isaac Boukris 2020-11-12 23:31:17 UTC
(In reply to Isaac Boukris from comment #7)

To be more accurate, in normal AS flow (as opposed to kinit -S, or S4U2Self), this failure will occur earlier than gss_accept(), when the client will do a TGS request (which is basically an AP request to the TGS server).

Quote from RFC 6806 section 13. Security Considerations:
   If only the negotiation mechanism is used, then the request from the
   client to the KDC is protected, but not all of the response is
   protected.  In particular, the client name is not protected; the
   ticket is also not protected.  An attacker can potentially modify
   these fields.  Modification of the client name will result in a
   denial of service.  When the client attempts to authenticate to a
   service (including the TGS), it constructs an AP-REQ message.  This
   message includes a client name that MUST match the client name in the
   ticket according to RFC 4120.  Thus, if the client name is changed,
   the resulting ticket will fail when used.
Comment 9 Andrew Bartlett 2020-11-12 23:50:32 UTC
(In reply to Isaac Boukris from comment #8)
OK, that makes more sense.

We would have to know the target server was not a TGS server and force canonicalisation only then.

Would that work?
Comment 10 Isaac Boukris 2020-11-13 18:01:30 UTC
(In reply to Andrew Bartlett from comment #9)

Then it will fail at gss_accept(), in other words the outer name must match the name in the ticket, which is what protects in retrospect.

Note that in TGS request the KDC may not even know to the canonical client name, i.e. in case of cross-forest trust.

I think the most sensible way would be to force client canonicalization in AS-REP (and S4U2Self initial reply) for both enterprise and none-enterprise names (the latter would be more susceptible to break it for current clients), ideally in accordance with MS.
Comment 11 Andrew Bartlett 2020-11-17 01:32:35 UTC
Created attachment 16339 [details]
A Kerberos bind against LDAP
Comment 12 Andrew Bartlett 2020-11-17 01:33:26 UTC
Created attachment 16340 [details]
keytab to decrypt
Comment 13 Andrew Bartlett 2020-11-17 01:34:12 UTC
Created attachment 16341 [details]
the cleartext decode of the LDAP bind with Kerberos
Comment 14 Andrew Bartlett 2020-11-17 01:35:55 UTC
Created attachment 16342 [details]
the 'wire' encrypted LDAP bind

This shows that the client's principal name is only, when presented to the target server (the kerberos acceptor) in the encrypted ticket.

--- /tmp/foo.txt	2020-11-17 14:17:11.429560530 +1300
+++ /tmp/foo-encrypted.txt	2020-11-17 14:18:07.815695134 +1300
@@ -39,16 +40,4 @@
                                                 authenticator
                                                     etype: eTYPE-AES256-CTS-HMAC-SHA1-96 (18)
                                                     cipher: 18f7fa3cfc8348ab12401d6641a479ae7a75d06e34e8ad3eā€¦
-                                                        authenticator
-                                                            authenticator-vno: 5
-                                                            crealm: ADDOM.SAMBA.EXAMPLE.COM
-                                                            cname
-                                                                name-type: kRB5-NT-PRINCIPAL (1)
-                                                                cname-string: 1 item
-                                                            cksum
-                                                            cusec: 600302
-                                                            ctime: 2020-11-17 01:12:35 (UTC)
-                                                            subkey
-                                                            seq-number: 131126817
-                                                            authorization-data: 1 item
         [Response In: 205]
Comment 15 Andrew Bartlett 2020-11-17 01:36:58 UTC
(In reply to Isaac Boukris from comment #10)
I'm still lost as to why that would happen.  Couldn't the KDC only canonicalise what is put into the service ticket, and not otherwise change things?  Wouldn't that essentially eliminate this flaw without breaking existing clients?
Comment 16 Andrew Bartlett 2020-11-17 02:05:27 UTC
Created attachment 16343 [details]
Possible letter to Microsoft for comment.
Comment 17 Andrew Bartlett 2020-11-17 02:14:58 UTC
I've added Luke Howard and Jeffrey Altman.

Folks,

I'm adding you to this bug to try and get some advise as to if we should try and have a broader industry (potentially coordinated) fix for my concerns around mixing principal aliases and (not setting) Kerberos canonicalisation.

Samba has, probably late to the party, realised quite how dangerous name-based authorization can be in AD.  Fixing Samba is easy(ish) as we can double-down on requiring the PAC, but it occurs to me that there are many, many other Kerberos targets out there accepting tickets and it would be better to harden the KDC. 

I'm hoping you might be able to give me some suggestions on if this is a worthwhile thing to attempt, generally provide some more experienced advice.

Please let me know other folks who we should add to the ticket.

The problematic alias lookups are described in MS-KILE here:

https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-kile/6435d3fb-8cf6-4df5-a156-1277690ed59c

Finally, to the extent that this is not public already (and the issues with Samba specifically are not) please do keep this confidential.

Thanks,

Andrew Bartlett
Comment 18 Luke Howard 2020-11-17 02:18:27 UTC
Could be worth adding Nicolas Williams <nico@cryptonector.com> too.
Comment 19 Luke Howard 2020-11-17 02:29:54 UTC
(In reply to Andrew Bartlett from comment #15)

In Heimdal see krb5_verify_ap_req2(); the client name in the ticket and the authenticator (which the client gets from the TGS-REP) have to match.
Comment 20 Andrew Bartlett 2020-11-17 02:42:03 UTC
(In reply to Luke Howard from comment #19)
I was thinking perhaps to only force-canonicalise the ticket given to the target service, not krbtgt/ tickets.  Would that be a way around this check?  As I see it the target service has no other knowledge of the real principal.
Comment 21 nico 2020-11-17 05:53:52 UTC
Re: comment #3

Apps that don't know how to extract SIDs/whatever from the PAC will generally depend on name-based authorization.  Those will generally use case-sensitive string comparisons.  What happens then is that if I have ACLs that grant nico@CRYPTONECTOR.COM and somewhere I kinit w/o canon as NiCo@Cryptonector.COM then I'll get a credential for NiCo@CRYPTONECTOR.COM and that won't match what's in the ACL, in which case the failure is safe as long as there's not also a different user named NiCo@CRYPTONECTOR.COM, which is on the realm admins to make sure is so.

AD uses case-insensitive matching for samAccountName, so you can't have a `nico` and a `NiCo` in the same domain.  There's replication latency to worry about, but if there's a race to create those two at different DCs then one will end up getting renamed.

Regarding other comments...  Kerberos IV made some dumb mistakes that Kerberos V replaced with other dumb mistakes.  One of those dumb mistakes was to require that the Authenticator state the client's name and that the Ticket match it -- dumb!  Another dumb mistake was to require that the AP-REP enc part be encrypted in the Ticket's session key (argh).  Lots of dumb mistakes.

The mistake about the Authenticator could be fixed by adding an payload-less authz-data element that says "the cname in the Authenticator is garbage, please ignore it and just use the one from the Ticket".  I've wanted to do that before for this very problem.  We could get one assigned by Greg and then just always set it in Heimdal and MIT in all Authenticators, wrapped in an AD-IF-RELEVANT.  And then we could publish an I-D and let MSFT implement some day.
Comment 22 nico 2020-11-17 05:55:44 UTC
The AP-REP mistake can also be fixed with an authz-data element in the Authenticator.
Comment 23 nico 2020-11-17 05:56:34 UTC
I suggest inviting Greg Hudson too.
Comment 24 nico 2020-11-17 06:01:03 UTC
I don't quite understand why this issue is marked as a security issue.  As I noted, name-based ACLs tend to be case-sensitive, so they'll generally fail safe, and case-insensitive ones should be safe too when all the realms implement case-insensitive principal naming (specifically disallowing existence of two principals differing only in case).

My comment about AP-REP enc part, however, is probably best embargoed.  Ironic.  (Sorry.  Feel free to edit and redact those bits.)
Comment 25 Luke Howard 2020-11-17 06:17:36 UTC
Nico, have a look at comment #16, I think Andrew sees some issues with computer names (which can be chosen by the user and are aliased to the name without the trailing $ sign). I'm not across this entirely yet.
Comment 26 nico 2020-11-17 06:26:55 UTC
Oh, I didn't know about the '$' thing.  Well, that's sad.

The 'root' example is not too terrifying to me: no one really has or should have principals named 'root' let alone authorize them in name-based ACLs.

But treating 'foo' as an alias of 'foo$' while *also* allowing a different 'foo' in the same realm is clearly a disaster.

Does AD allow that?  Does Samba?  (I don't believe Heimdal or MIT do, FWIW.)
Comment 28 Luke Howard 2020-11-17 06:31:38 UTC
So if you have foo and foo$, then foo will always be found first. I suppose it's just a general case of the fact that names can be recycled, whereas SIDs can't (well, unless you roll back a backup I suppose).
Comment 29 nico 2020-11-17 06:35:40 UTC
Reusing names is not a good practice.  We certainly don't allow it at $work.

Using SIDs would require more than just parsing the PAC and exposing them in an API (which we kinda have in GSS via name attributes).  It would require new ACL technology wherever name-based ACLs are being used now.  For things like NFS/filesystems it requires mapping to the filesystem's native ID form, or else switching wholesale to SIDs.  (ZFS supports both.)

Name-based ACLs are hard to avoid, so avoiding name reuse is essential.  This means not deleting user accounts but tombstoning them.
Comment 30 nico 2020-11-17 06:39:55 UTC
Luke, the MS-KILE doc you linked allows 'foo' and 'foo$' to be distinct in the directory, which is a problem, but doesn't prevent the directory from disallowing 'foo' and 'foo$' from existing concurrently in the same domain/realm (module multi-master replication and conflict resolution).

Given the rules MSFT implemented and documented, the directory simply must not allow 'foo' and 'foo$' to exist in the same domain/realm.  If AD doesn't, that needs to be fixed.  If Samba doesn't, that needs to be fixed.

The case equivalence issues is, I think, is a non-issue.
Comment 31 Jeffrey Altman 2020-11-17 06:54:18 UTC
[I have not read this issue in depth yet.]  

As a reminder, there are applications such as AFS and AuriStorFS, that implement case-insensitive name-based authorization.  I'm quite sure there are many other services that Kerberos authentication was added to which perform case folding.

It would be useful to add to Heimdal / MIT a configuration mode that prevents case only principal name conflicts.
Comment 32 nico 2020-11-17 06:57:43 UTC
Oh, Luke, right, since 'foo' is matched before 'foo$', knowing the machine account password for 'foo$' doesn't let you impersonate 'foo' if 'foo' also exists.  So maybe the only issue is a race condition: if you have 'foo$' and know 'foo' will soon exist separately, then you can acquire a credential for 'foo' before it exists and use it to impersonate 'foo' when 'foo' is created.
Comment 33 nico 2020-11-17 06:58:50 UTC
Jeff, that's good to know.  Yes, given what you say I agree that Heimdal and MIT should have a case-insensitive HDB/KDB mode.
Comment 34 Jeffrey Altman 2020-11-17 07:47:48 UTC
What are the conditions under which Samba is matching against samAccountName?  

I believe that KILE is written with the assumption that 'canonicalize' is requested by the client because Windows clients always request 'canonicalize'.  Is samAccountName matching performed when 'canonicalize' is unset?

The general problem with samAccountName matching as I see it is that the selection of a domain joined computer's samAccountName name and the ability to alter it, is left up to the owner/administrator of the computer.

If the KDB is not actively checking for and preventing the assignment of samAccountName to ensure that it cannot match a principal name (perhaps even a case-insensitive match) I can see that being problematic.

The root$ -> root@REALM case can be generally problematic if samAccountName can be set to "NiCo" when a client principal "nico" exists.  Such that 

   NiCo$ -> NiCo@REALM

For AFS/AuriStorFS and other systems that use case-insensitive authorization name matching this would be a disaster.
Comment 35 Jeffrey Altman 2020-11-17 07:58:38 UTC
Samba, Heimdal and MIT might want to automatically create "root" and other well-known names as disabled principals with random expired keys in order to ensure that samAccountName aliases cannot be used.
Comment 36 Andrew Bartlett 2020-11-17 08:17:30 UTC
(In reply to Jeffrey Altman from comment #34)
Thanks everyone for their input.

Indeed in AD it is quite possible to have a root$ and root user, but this isn't the problem, because a kinit for root@REALM will just match on the root user (this matches first).  

But if the root$ user exists and root does not, and canonicalise is NOT requested, the ticket will be issued!

Then when the unix-centric service being contacted uses 'user exists in nsswitch getpwname()' as the authorization logic (rather than a pure 'exists in AD'), we get an issue.

Samba, which should know better, certainly does, which is bug #14556 (one of a number I've filed on different aspects of the issue).  I'll CC you all to that shortly so you get the context properly.

(I also agree that mixed cases as alias could be used to defeat deny ACLs, or create multiple accounts in simple web apps.  Enterprise principals could be even more fun!). 

That (because all this is intertwined) is why this is embargoed, because one leads to the other, once you start thinking about it.

There are also issues with races between aliases and newly created accounts with the alias as a samAccountName (bug #14561), but that is probably less serious or exploitable.

We also have the samba-only bug 14563 where we match a userPrincipalName first, rather than samAccountName first, but that is 'just a bug'. 

Fun times!
Comment 37 Andrew Bartlett 2020-11-17 08:22:52 UTC
(In reply to Jeffrey Altman from comment #34)
> What are the conditions under which Samba is matching against samAccountName?  

Samba matches against the principal when the PAC is not supplied.

The main fix for Samba will be to just require the PAC in an AD domain, but this won't help (eg) NFS, OpenSSH which looks like a worry to me in some common example configurations.
Comment 38 Jeffrey Altman 2020-11-17 08:31:03 UTC
Its worth noting that even Microsoft permits user accounts (mapped to SPNs) to be flagged such that tickets will be issued for the SPN without a PAC.  Accounts used for AFS/AuriStorFS SPNs recommend that PACs be disabled.  One of the primary motivations is to ensure that the resulting ticket is small enough to fit in an unfragmented UDP packet.
Comment 39 Jeffrey Altman 2020-11-17 08:34:56 UTC
(In reply to Andrew Bartlett from comment #36)
> Indeed in AD it is quite possible to have a root$ and root user, but this isn't the problem, because a kinit for root@REALM will just match on the root user (this matches first).  

> But if the root$ user exists and root does not, and canonicalise is NOT requested, the ticket will be issued!

My question is: what breaks if the matching of samAccountName is restricted to when the canonicalize flag is set in the request?
Comment 40 Andrew Bartlett 2020-11-17 08:46:30 UTC
(In reply to Jeffrey Altman from comment #39)
This is one obvious fix, to only permit an alias (of any kind, be it case-wise or the extra $ or a userPrincipalName) if canonicalise is set.  This is like 

https://www.freeipa.org/page/V4/Kerberos_principal_aliases#Design

What would break would be default unix clients.  The default krb5.conf on Ubuntu (at least) has canonicalise disabled, and administrators accustomed to windows being case-insensitive would have to (eg) 'kinit Administrator' not 'kinit administrator'. 

Also, many organisations set a userPrincipalName, and often still use the same domain name.  This works, with a UPN of fred.nurk@samba.example.com being able to obtain a ticket with 'kinit fred.nurk@SAMBA.EXAMPLE.COM', even if the samAccountName (and so canonicalised principal name) would be fnurk / fnurk@SAMBA.EXAMPLE.COM.  (With patched Samba Heimdal you can even use the lowercase realm). 

So even if we allowed case-wise aliasing, I think the answer is 'more would break than we can do in a security release'.  :-(
Comment 41 Isaac Boukris 2020-11-17 09:04:25 UTC
(In reply to Andrew Bartlett from comment #14)

This is not the ticket, it's the AP-REQ authenticator encrypted by the client (not the kdc), so it will only have the name that the client is aware of, which must match the one in the ticket (encrypted by the kdc).
Comment 42 Isaac Boukris 2020-11-17 09:06:24 UTC
(In reply to Andrew Bartlett from comment #15)

If the kdc canonicalizes the name in the service ticket, then the client idea of the name would differ from the one in the ticket, causing gss_accept() to eventually fail on the server side.
Comment 43 Jeffrey Altman 2020-11-17 13:47:54 UTC
Having slept a little bit, the underlying problem here is one of namespaces.   Although it might appear as though there are separate namespaces for client principal, samAccountName, UPN and aliases.  In reality, each of these name forms results in a principal name in a common namespace.  It is the KDC's responsibility to ensure that two or more entities cannot authenticate as the same name.   Hence, it is critical that the KDC block registration of any name form that would produce a conflict or otherwise reserve the any nameform that can resolve to a common name.

In the case of samAccountName "root" + "$" -> root@REALM, it is the obligation of the KDC to not only ensure that client principal "root@REALM" does not exist, but to prevent its creation in the future.

Likewise, when name based authorization might be used, best practice says that names should never be reused.   Therefore, even if the samAccountName "root" is changed to "banana", the client principal name "root@REALM" must still be off limits.

That is necessary to prevent client principal "kangaroo@REALM" from assigning a samAccountName of "root", acquiring a TGT for "root@REALM" and then changing the samAccountName to "pineapple".  Thereby opening the door for "root@REALM" client principal to be created.

The same is true for any UPN or alias.

I haven't thought through how to represent this namespace management in the KDB but I believe this is the underlying problem that needs to be addressed.
Comment 44 nico 2020-11-17 16:19:00 UTC
People who rely on DENY ACL entries should expect to get what they deserve.
Comment 45 nico 2020-11-17 18:24:13 UTC
> Indeed in AD it is quite possible to have a root$ and root user, but this isn't the problem, because a kinit for root@REALM will just match on the root user (this matches first).  
> 
> But if the root$ user exists and root does not, and canonicalise is NOT requested, the ticket will be issued!
> 
> Then when the unix-centric service being contacted uses 'user exists in nsswitch getpwname()' as the authorization logic (rather than a pure 'exists in AD'), we get an issue.

Again, for root I'm not terribly concerned, and for human users or what we call "role accounts" there should be a principal of the same name in the appropriate realm(s).  So I'm of the mind that this is a minor issue.
Comment 46 nico 2020-11-17 22:16:08 UTC
So I don't think this is a big deal, but for anyone who does, the obvious thing to do is to create disabled AD user accounts (with randomized password/keys for extra safety) for every Unix account resolvable with `getpasswdbyname()`.  This is advice that can be given to Windows domain admins in general, and MSFT maybe could help by doing this for new domains or something.
Comment 47 Andrew Bartlett 2020-11-18 01:28:31 UTC
(In reply to nico from comment #46)
Would you be more concerned if I told you that by default in AD, all accounts in the domain (even machine accounts themselves!) can create up to 10 new machine accounts, of any name (as long as they end in $). 

(I reported and they fixed the recursive part of this a few years back, you could exhaust the domain of SIDs!).

It is also fairly common to allow lower-privileged users to add new 'unprivileged' accounts to specific OUs or via onboarding tools.
Comment 48 Luke Howard 2020-11-18 01:32:44 UTC
It would make sense (to me) for Samba to adopt a more secure policy by default even if it is stricter than AD.
Comment 49 Jeffrey Altman 2020-11-18 02:03:25 UTC
Under what circumstances does AD issue a computer account principal as

  computer@DOMAIN

?   I ask because what I see from my Window's machine's SYSTEM account principal is

  Identities seen by fileserver for path '\\afs\yfs\':
    jaltman@YOUR-FILE-SYSTEM.COM
    FROGSLEAP$@AD.SECURE-ENDPOINTS.COM

The machine's name is frogsleap.ad.secure-endpoints.com.  Are we sure the samAccountName lookup doesn't return a client principal with a terminating '$'?
Comment 50 Andrew Bartlett 2020-11-18 02:12:41 UTC
(In reply to Jeffrey Altman from comment #49)
This happens if you don't set canonicalise in the AS-REQ.

This is the heart of the problem, as the normal case behaves 'sensibly' developers and administrators assume that the realm obtained from (eg) gss_display_name() is sAMAccountName@REALM, but it can be any-alias@REALM, being the userPrincipalName or the machine-name-without-$.
Comment 51 Jeffrey Altman 2020-11-18 02:39:33 UTC
Then I think we need to proceed with an intervention.

I think Samba should behave sanely.  I wonder if non-canonicalized queries that require the samAccountName or UPN should fail with a new canonicalization required error, KRB5KDC_CANON_REQUIRED.   Upon receipt the client can either fail or retry with the canonicalization flag set.
Comment 52 nico 2020-11-18 02:47:54 UTC
> Would you be more concerned if I told you that by default in AD, all accounts in the domain (even machine accounts themselves!) can create up to 10 new machine accounts, of any name (as long as they end in $). 

MSFT should change that default, and in the meantime users should.

What we can do is an extension to stop using the cname from the Authenticator.  But we'd need MSFT to implement it too.  Short of that and documentation and advice to users, and getting MSFT to make some minimal changes here, I don't see what we can do.
Comment 53 Andrew Bartlett 2020-11-18 03:30:33 UTC
(In reply to nico from comment #52)
It's trickier than that, real-world workflows and applications rely on the behaviour.  See https://lists.samba.org/archive/samba/2020-November/233232.html from today.

So I think the key to getting a fix that helps us (as owners and developers of the Kerberos target service) is to figure out something that is of the absolute minimum disruption, so we can convince MS to also implement it (soon or eventually).

If we can't do a neat trick like you suggest (so the ticket is always canonicalised, not matter what), then (probably with the exception for case-wise equality) what Jeffrey Altman says in from comment #51 might be the best option.
Comment 54 nico 2020-11-18 17:43:24 UTC
The ball will have to be in MSFT's court.  They have options like:

 - document the issue, provide advice to users

 - disable machine account creation by default for non-domain admins

 - disable the 'foo' -> 'foo$' match by default (what would this break? something will, no doubt, but maybe altSecIDs can be used to un-break those things)

 - pre-create disabled accounts for all typical system accounts on Unix/Linux

 - work with us on an extension to always send the canonical name in the Ticket

What else?

Of these I think the third one is a must, especially since one can undo it for specific cases one needs to continue working as before.

How good is AD at checking for collisions among attributes that share a unique namespace?  E.g., samAccountName and altSecID contribute to the namespace of principals.  With UPNs they allow collisions, IIRC, and I forget what happens when you do have a collision.
Comment 55 nico 2020-11-18 19:39:46 UTC
From #krbdev on IRC (freenode):

11:33 < nico103> ghudson: what would break if krb5_rd_req*() start ignoring the cname/crealm from Authenticator enc-part and just use the cname/crealm from the
                 Ticket, unilaterlally, no extension needed to enable this?
11:33 < nico103> I'm thinking: "nothing"
11:34 < nico103> it wouldn't enable anything new right away, but down the line it would
12:52 < ghudson> I guess the authenticator is already bound to the ticket by the session key.
13:32 < nico103> right
13:32 < nico103> so I think we should just do it
13:36 < nico103> we could reduce the size of AP-REQs by just sending a zero-component cname with empty crealm :)

I'm quite certain we could safely just ignore the cname/crealm from the Authenticator and use only the cname/crealm from the Ticket.  This would improve interoperability.
Comment 56 Luke Howard 2020-11-18 22:14:36 UTC
(In reply to nico from comment #55)

How does the client know it's safe to omit the cname in the authenticator? Are any of these changes less intrusive than just configuring the client to request canonicalise?
Comment 57 nico 2020-11-18 22:22:48 UTC
> How does the client know it's safe to omit the cname in the authenticator? Are any of these changes less intrusive than just configuring the client to request canonicalise?

Today it wouldn't.
Comment 58 nico 2020-11-18 22:40:59 UTC
@Luke, currently the KDC can negotiate one thing about the acceptor's capabilities: its enctypes.  In principle it could also know whether the acceptor handles other things.  Anyways, for now the best thing to do is write MSFT a bunch of suggestions, and Samba could implement some of them.
Comment 59 Andrew Bartlett 2020-12-01 04:53:47 UTC
Created attachment 16351 [details]
New possible mail to Microsoft (probably via the protocols team)
Comment 60 Andrew Bartlett 2020-12-04 02:19:37 UTC
I've finally mailed Microsoft with my concerns and I'll update here if I get any useful resolution.
Comment 61 Andrew Bartlett 2020-12-08 21:41:36 UTC
Had a call with MS today.  Microsoft is thinking about what to do here.  The next call in the week Feb 8th due to holidays for various folks.
Comment 62 Andrew Bartlett 2020-12-09 02:56:32 UTC
If we can't just put the canonical principal name in the ticket (for reasons of upgrade) could we solve this by having the KDC always send the PAC, and having the client lib know to override the returned principal with the samAccountName from the PAC?

It would mean parsing the NDR, but asking Microsoft to essentially always ignore the client request for no-pac would be a much, much smaller ask.

It would mean upgrading all target servers, but at least not upgrading all clients (to set canonicalise).

It would however automatically fix CVE-2020-25717 and CVE-2020-25719 for Samba, which would be cool.
Comment 63 Luke Howard 2020-12-09 03:02:13 UTC
(In reply to Andrew Bartlett from comment #62)

That's not a bad idea. I don't even think you need an NDR library because you could use PAC_CLIENT_INFO and/or UPN_DNS_INFO which have a straightforward encoding.
Comment 64 Andrew Bartlett 2020-12-09 04:01:09 UTC
(In reply to Luke Howard from comment #63)
Sadly LOGON_NAME must (to prevent PAC swapping) be the ticket name, so isn't any help.

The UPN name however would at least be stable and match what many Kerberos targets want, which is a email address like thing to look up in single LDAP attribute (eg a Drupal installation matching with mod_auth_kerb under Apache). 

However, for a simple low-impact (to users) fix the one that matches the canonicalized name is the samAccountName, deep in the main PAC_TYPE_LOGON_INFO.  

This is really what we want to require.
Comment 65 Luke Howard 2020-12-09 04:12:29 UTC
(In reply to Andrew Bartlett from comment #64)

Ah, OK. I don't know of any BSD licensed NDR libraries except for the OSF one, which has some pretty gnarly threading dependencies. What about the DNS domain name, are there any canonicalisation issues there? That's not in the logon info form memory.
Comment 66 Andrew Bartlett 2020-12-09 04:44:41 UTC
(In reply to Luke Howard from comment #65)
As far as I can tell (from the tests we have which check for specifically this) the realm is always issued correctly, even if you use lowercase or a netbios domain.
Comment 67 nico 2020-12-09 16:36:46 UTC
> Had a call with MS today.  Microsoft is thinking about what to do here.  The next call in the week Feb 8th due to holidays for various folks.

Thanks for doing this!
Comment 68 Andrew Bartlett 2021-02-17 21:52:07 UTC
I've reported this to Microsoft as VULN-042738 however MSRC has declined to service this as a security issue so we are unlikely to get KDC-side protection on an urgent basis.

I'll continue to work with Microsoft to secure the KDC long-term but we will need to work with other 'Kerberos in AD' projects as best as we can and just protect the kerberos targets.
Comment 69 Andrew Bartlett 2021-02-17 22:04:17 UTC
I've been thinking about how we could protect Kerberos acceptors from dangerous aliases in the absence of canonicalisation.

However, the only approach I can come up with requires that the PAC be sent, which is a detail under the control of the client.

That said, if we could assert that we are in a Active Directory realm, and any client that does not send the PAC should not be provided access, we could without changing the interfaces to (say) mod_auth_kerberos do this:

* Parse the PAC in the krb5 libs
* Extract the UPN from the UPN and DNS info
* Extract the samAccountName (account_name) from the LOGON_INFO

Insist that there be a case-insenstitive match between one of these names and the name in the LOGON_NAME (which is in turn matched to the principal in the ticket).

If there is a mismatch, then the user is playing games and the ticket should be rejected.

A stronger test is that the name in the LOGON_NAME must match the samAccountName (account_name in LOGON_INFO) bytewise, but this would break using a UPN or a case variation on a unix client without canonicalisation set (the default). 

The main challenge is that this would remain opt-in, unless we can otherwise tell this is an AD ticket.
Comment 70 Andrew Bartlett 2021-02-17 22:32:40 UTC
The kerberos library could of course also return the samAccountName@REALM as the principal via the PAC, essentially doing the canonicalisation on the kerberos target server.  

But again we have to know we can rely on the PAC being present, or convince the KDC to always send it.
Comment 71 Isaac Boukris 2021-02-18 09:51:30 UTC
(In reply to Andrew Bartlett from comment #69)

Note that as discussed elsewhere, NDR decoding in the krb5 libs is tricky.

I think the simplest approach would still be to just force canonicalization, perhaps via a kdc flag, thus allowing the use of plain ACLs for environment where it is being used, while others not using the flag would need to rely on the PAC. Then perhaps suggest MS to implement the same via a registry flag, which should be simple enough.
Comment 72 Andrew Bartlett 2021-02-18 10:17:25 UTC
(In reply to Isaac Boukris from comment #71)
I know NDR is tricky, but this would not need to be a full NDR parse, we just need the 4th string at a fixed offset, so this shouldn't be quite as hard.

But I would say this.  We need a client-side solution, we can't it seems rely on help from the KDC.  Even if we get an improvement from MS, I don't expect it to be anything more than an improvement in future releases, and there are a lot of domains out there currently.

Opt-in Registry flags almost never get set, so this won't help.
Comment 73 Isaac Boukris 2021-02-18 15:15:44 UTC
(In reply to Andrew Bartlett from comment #72)

If we can't rely on help from the kdc then we can't expect it to always force a PAC, so we'd still need a krb5.conf per-realm acceptor flag to tell it to require a PAC for this realm.  Then perhaps the same flag will also indicate the krb5 lib to return the samAccountName@REALM from the PAC, the samAccountName from LOGON_INFO and the canonical realm from the DNS_UPN_INFO (i think), and do the canonicalization on the target server side as you've suggested.
Comment 74 Alexander Bokovoy 2021-06-03 14:18:35 UTC
Adding Robbie to be able to discuss MIT changes for Samba AD.
Comment 75 Andrew Bartlett 2021-11-03 08:48:59 UTC
Created attachment 16925 [details]
advisory text (v01)

This advisory is deliberately a bit vague, it will go public before this bug does, and we want to talk with impacted external libraries (eg libkrb5 etc) once patches are published about any way they might use this new feature.

For now, this bug is not opened to vendors.
Comment 76 Alexander Bokovoy 2021-11-03 09:04:29 UTC
Comment on attachment 16925 [details]
advisory text (v01)

Please change

..  which use Samba under the hood like FreeIPA decode this.

to 

.. which use Samba components under the hood like FreeIPA and SSSD decode PAC.

I would suggest to rewrite

The CVE is for the protocol deployement weakness as seen in AD, that
meant most Linux and Unix applications were for practical reasons only
able to rely on the Kerberos "client name" from the ticket.

as the following:

The protocol deployment weakness, as demonstrated with the CVE-2020-25717 in Active Directory, leaves most Linux and UNIX applications only to rely on the "client name" from the Kerberos ticket. When the "client name" as seen by the KDC is under an attacker control across multiple Kerberos requests, such applications need an additional information to correlate the client name across those requests.
Comment 77 Andrew Bartlett 2021-11-03 17:49:27 UTC
Created attachment 16940 [details]
advisory text (v02)
Comment 78 Andrew Bartlett 2021-12-10 18:29:03 UTC
Removing embargo, we need to be able to discuss these issues in public forums.