Ticket #1384 (new defect)

Opened 7 years ago

Last modified 4 years ago

Disable DNS canonicalization for Kerberos

Reported by: geofft Owned by:
Priority: normal Milestone: The Distant Future
Component: -- Keywords:
Cc: Fixed in version:
Upstream bug:

Description (last modified by andersk) (diff)

Use of Kerberos in the Athena environment currently involves using DNS for canonicalization, an insecure practice called out in RFC 4120 (the krb5 RFC):

one should not rely on an unprotected DNS record to map a host alias to the primary name of a server, accepting the primary name as the party that one intends to contact, since an attacker can modify the mapping and impersonate the party.

Athena basically uses Kerberos DNS canonicalization (forward and reverse lookup) as a user experience measure: users expect to be able to do things like ssh athena.dialup, remctl xvm-remote help, etc. without providing the long name. In particular, the .mit.edu suffix needs to be appended, and names like linux.mit.edu need to be expanded to canonical names like linerva.mit.edu (or, in the case of athena.dialup.mit.edu, one of several possible canonical names), before the name becomes something suitable to turn into the name portion of a Kerberos service key.

But since DNS is completely insecure, an attacker can spoof the DNS response and canonicalize, say, linux to some-random-server.mit.edu, which they might legitimately own a keytab for, and the login would succeed. Deployment of DNSSEC would basically solve this issue, but as far as I'm aware there are no real plans to deploy DNSSEC at MIT.

Turning off canonicalization is mostly straightforward, but doing so right now would break the UX mentioned earlier. So this ticket is primarily about software changes needed to make the UX work as well, without trusting DNS.

Here are a couple of approaches. For merely fully-qualifying a domain name:

  • Active Directory solves this in a straightforward manner by issuing a domain-joined server a host/machine@EXAMPLE.COM key as well as a host/machine.example.com@EXAMPLE.COM one. We could do that: I don't see a security issue in creating host/linerva@ATHENA.MIT.EDU etc. keytabs, but maybe I'm not thinking hard enough. This requires no client changes.
  • We can also have the Kerberos libraries process /etc/resolv.conf, which would let them know how unqualified names should be fully-qualified.

For resolving aliases:

  • We could just have servers carry keys for all their aliases (that people log in through). This would mean that athena.dialup's keytab would need a key for each athena.dialup alias (x.dialup, etc.) and each servers' own aliases (ant, cvp, etc.), which would be slightly awkward but certainly manageable.
  • The KDC has support for  aliases, which seem to be ways for the server and KDC to agree that a certain name is an alias for an existing principal, and that the same key should be used. I'm not sure what needs to be done on the server side to configure aliases on a key in a keytab.
  • There's a  project on the krb5 wiki talking about doing DNS resolution on the KDC, which should be significantly more trustworthy than doing it on the client. It looks like the implementation is that you'll ask the TGS for a service ticket for host/linux, and get a service ticket for host/linerva.mit.edu back.
  • You could also imagine combining the above two approaches: keeping aliases in the KDC database (and not trusting DNS anywhere), but returning the canonical name to the client.

I think that, in addition to rdns = false in krb5.conf, this also requires GSSAPITrustDns No in ssh_config. Also note that the Kerberos libraries in Ubuntu have a bug (fixed in in krb5 1.10.2) that seems to effectively make rdns = true unconditionally set, so we'll need to get a security update through for that.

In terms of deployment strategy, it'd be nice to find a solution that doesn't break existing clients or servers, but allows clients to opt in to be more secure without breaking their functionality. I think all of the above solutions allow unmodified clients, that continue to canonicalize hostnames in DNS, to still work. Some of the above solutions don't involve coordinating with server maintainers; some involve adding more keys to the keytab, or configuring aliases server-side.

(Like #529, this is not entirely a Debathena bug, but this is the most convenient place to keep track of it, especially as it interacts with our security policy re GSSAPIDelegateCredentials, GSSAPIKeyExchange, and friends.)

Change History

comment:1 Changed 7 years ago by ghudson

A few corrections:

  • Disabling all canonicalization is not straightforward as things stand. All we have right now is "rdns=false", which disables reverse resolution but not forward resolution. An attacker can fake a cname record and make forward resolution give whatever result the want, so rdns=false carries no security advantage. We may implement a flag in 1.12 which disables all canonicalization, since Red Hat has asked for one.
  • The way service name aliases work is that the KDC returns a ticket which looks like whatever the client asked for, but uses the encryption key for the real principal entry. This is not expected to change. The changes we do anticipate making are (1) adding more ways for the KDC to do service name aliases, such as trusting its local DNS setup, and (2) extending the protocol so that the KDC can tell the client to turn off local service canonicalization because the KDC expects to do it.
  • The bug preventing rdns=false from working is actually a libc bug; krb5 1.10.2 has a workaround for it. The libc bug is fixed in Fedora, but I believe not in upstream or anything Debian-based.  #15218 has more details.

comment:2 Changed 7 years ago by andersk

Just to clarify that none of the currently proposed mitigations (rdns=false, GSSAPITrustDNS=no, GSSAPIServerIdentity) are effective:

$ head -n3 /etc/krb5.conf
[libdefaults]
	default_realm = ATHENA.MIT.EDU
	rdns = false
$ grep not-slowlaris ~/.ssh/known_hosts
$ ssh -o GSSAPIKeyExchange=yes -o GSSAPITrustDNS=no -o GSSAPIServerIdentity=not-slowlaris.mit.edu andersk@not-slowlaris.mit.edu

Welcome to Linerva, the SIPB Linux dialup for MIT.
…
andersk@dr-wily:~$ 

rdns=false only means that Kerberos doesn’t do reverse DNS lookups, GSSAPITrustDNS only means that ssh doesn’t do reverse DNS lookups, and GSSAPIServerIdentity is still forward-resolved.

comment:3 follow-up: ↓ 6 Changed 7 years ago by geofft

Having thought a bit harder about the possible options, I'm more of a fan of giving folks keys (or principal aliases) for the unqualified name, i.e, giving Linerva a host/linerva@ATHENA.MIT.EDU key instead of having the client resolve linerva to linerva.mit.edu via /etc/resolv.conf. While that file is significantly more trusted than DNS, it's still vaguely untrusted if you're using DHCP. You can imagine a scenario where you get a search domain of xvm.mit.edu or something via DHCP, and it'd be nice for ssh linerva to not be silently willing to talk to whichever machine happens to have a host/linerva.xvm.mit.edu@ATHENA.MIT.EDU key, which may have no relation to the "real" linerva.

Is there a reason to deny giving those keys or key aliases? I guess they're probably denied by policy right now, but I'm curious if that would be safe to change. The fact that AD makes a practice of handing out these keys makes me think it's safe.

Obviously the aliases should just involve stripping .mit.edu, no more and no less.

comment:4 Changed 6 years ago by andersk

Kerberos 1.12 in trusty implements dns_canonicalize_hostname = false.

Having played with it for two minutes, I observe that there isn’t yet a keytab for host/athena.dialup.mit.edu itself, let alone its aliases.

comment:5 Changed 6 years ago by andersk

  • Description modified (diff)

comment:6 in reply to: ↑ 3 Changed 4 years ago by adehnert

Replying to geofft:

Is there a reason to deny giving those keys or key aliases? I guess they're probably denied by policy right now, but I'm curious if that would be safe to change.

FWIW, so far as I can tell, these (probably) aren't denied by policy right now -- I successfully got daemon/chiron (though didn't try for host/chiron) a couple years ago. (I'm vaguely guessing nobody's actually working on this, though.)

Note: See TracTickets for help on using tickets.