Russ Allbery wrote:
> My impression is that the broader Kerberos community is increasingly
> leaning towards not doing DNS canonicalization. That Kerberos libraries
> have been canonicalizing hostnames using DNS for quite some time is
> certainly true, but it's considered an unfortunate bug that needs to be
> supported for backward compatibility but that is clearly not the right way
> to do things. This is the reason why Kerberos implementations are
> increasingly adding options to disable DNS canonicalization.
>
> (1) is a vulnerability that Kerberos can protect against if you use it
> properly. It's called the Zanarotti attack, and the way that you defend
> against it is by obtaining a service ticket for a principal in a local
> keytab after initial authentication and verifying that the service ticket
> matches. This uses your shared secret with the KDC to verify that you're
> talking to the right KDC.
Leaving aside your followup which clarified this clause: the obvious point is
that a Kerberos client needs to have trusted *local* data to protect against
this attack. Delegating the trust to the KDC obviously doesn't solve this
problem. (Not to mention that again, a KDC is by definition a trusted 3rd
party. If you can't trust it, then the entire Kerberos framework is compromised.)
> Your analysis of (2) assumes that every ldap principal in your KDC is
> created by someone you trust not to spoof any other ldap principal in your
> KDC.
Yes, again, that is implicit in the fact that the KDC is a trusted 3rd party.
> That's a high bar to meet and many sites are not going to meet that
> bar, nor want to given a competing desire for distributed administration.
Delegating administration authority still implies that you trust whoever you
delegated it to. Again, if you can't trust everyone then your administrative
procedures are broken and your framework has already been compromised.
> For example, Stanford allows students to run Kerberized services on their
> personal computers if they wish, and therefore allows them to download
> keytabs (and hence create ldap principals) for those computers. If they
> can use DNS hijacking to return a CNAME for an LDAP server pointing to
> their computer instead, they can obtain a legitimate keytab for the ldap
> principal for that computer, and can successfully trick a client that
> trusts DNS canonicalization.
Trust within a realm is all-or-nothing. And of course, Kerberos trust is
transitive... But the right way to handle regions under different
administrative control is to place them in separate realms. For your example
of students creating their own principals, independently from the centrally
administered realm, you should be using a separate realm (and setup a
cross-realm trust if that's appropriate.) That at least gives you consistent
accountability, and you can uniformly limit the privileges granted to tickets
from non-default realms.
> Another, possibly more obvious case where (2) doesn't hold is in the
> presence of cross-realm trust. If I can use DNS spoofing to return a
> CNAME of ldap.stanford.edu to dorm-machine.mit.edu, and stanford.edu and
> ATHENA.MIT.EDU have cross-realm trust, I can perform the same attack. So
> you not only have to trust everyone who can create ldap principals in your
> local realm, but everyone who can create ldap principals in any realm with
> which you have cross-realm trust.
Yes, and again, that is basic to the definition of Kerberos. If you don't
actually trust everyone, then you should not be adding them into your KDC,
because their presence in the KDC is a declaration of trust.
Garbage-in-garbage-out applies here.
> There are a lot of nasty things that you can do with DNS spoofing, and
> this almost certainly isn't the most likely attack, but it is a potential
> vulnerability that's been widely discussed within the Kerberos community,
> including transition plans for how to get away from always doing
> canonicalization. You can, for example, see part of the opinion of the
> MIT developers in the comments around the relevant segment of code:
>
> if (maybe_use_reverse_dns(context, DEFAULT_RDNS_LOOKUP)) {
> /*
> * Do a reverse resolution to get the full name, just in
> * case there's some funny business going on. If there
> * isn't an in-addr record, give up.
> */
> /* XXX: This is *so* bogus. There are several cases where
> this won't get us the canonical name of the host, but
> this is what we've trained people to expect. We'll
> probably fix it at some point, but let's try to
> preserve the current behavior and only shake things up
> once when it comes time to fix this lossage. */
>
> This is the reason why there's an rdns option in krb5.conf to disable this
> code. There has been other discussion of it on krbdev and
> kerberos(a)mit.edu in the past.
>
> I would agree that there's no way that you can change the default; too
> much stuff would break. That's also why the Kerberos libraries continue
> to do this by default. But I think the original bug reporter isn't
> unreasonable for wanting a way to disable canonicalization if they know
> that their code and environment will handle that appropriately.
You've already proven that the option being discussed here is *not
appropriate* because a non-local KDC cannot be trusted. So once again, solve
the real problem. What's been proposed here is not a solution.
--
-- Howard Chu
CTO, Symas Corp. http://www.symas.com
Director, Highland Sun http://highlandsun.com/hyc/
Chief Architect, OpenLDAP http://www.openldap.org/project/
rra(a)stanford.edu writes:
> (1) is a vulnerability that Kerberos can protect against if you use it
> properly. It's called the Zanarotti attack, and the way that you defend
> against it is by obtaining a service ticket for a principal in a local
> keytab after initial authentication and verifying that the service
> ticket matches.
I'm sorry -- this is wrong. I overthought this. The scenario discussed
here is not the Zanarotti attack. The Zanarotti attack involves spoofing
the KDC so that you don't have to know the correct key for a principal;
you instead use a key that you know and fool the system into talking to a
KDC that uses the same key. It's an attack on login or a screen saver to
allow someone to use a bogus password to authenticate.
The protection against the scenario (1) listed here is integral into the
Kerberos protocol. The Kerberos authentication process involves
requesting a TGT from the KDC that's encrypted in your private key and
then decrypting the return with your private key. You cannot spoof
Kerberos initial authentication from a keytab or a correct password by
using DNS to redirect the authentication to a bogus KDC because the bogus
KDC won't know your correct private key and hence won't be able to return
a TGT that you can decrypt. Similarly, you can't successfully redirect a
TGS_REQ to a bogus KDC because that KDC doesn't have the private key and
can't complete the protocol exchange.
This is why kinit doesn't bother to protect against the Zanarotti attack;
there's no need, since kinit doesn't provide increased local privileges
and the Zanarotti attack is an attack only on the local system, not
against a network service.
--
Russ Allbery (rra(a)stanford.edu) <http://www.eyrie.org/~eagle/>
hyc(a)symas.com writes:
> In the meantime, the arguments about secure DNS are pure red herrings:
> 1. if your DNS has been hijacked, it's most likely that you'll be
> directed to a rogue KDC first, so the question of which service you're
> talking to is moot.
> 2. there's nothing to gain from directing you to a rogue service, since if
> you managed to contact the legitimate KDC, you're going to have a service
> ticket that can only be decoded by the legitimate service principal.
> On the other hand, if the rogue service is actually a valid principal in
> your trusted KDC's database, then you clearly have an administrative problem
> in your KDC.
>
> This patch attempts to provide a band-aid without actually solving the
> real problem. It merely masks the problem temporarily, until it gets
> even worse.
My impression is that the broader Kerberos community is increasingly
leaning towards not doing DNS canonicalization. That Kerberos libraries
have been canonicalizing hostnames using DNS for quite some time is
certainly true, but it's considered an unfortunate bug that needs to be
supported for backward compatibility but that is clearly not the right way
to do things. This is the reason why Kerberos implementations are
increasingly adding options to disable DNS canonicalization.
(1) is a vulnerability that Kerberos can protect against if you use it
properly. It's called the Zanarotti attack, and the way that you defend
against it is by obtaining a service ticket for a principal in a local
keytab after initial authentication and verifying that the service ticket
matches. This uses your shared secret with the KDC to verify that you're
talking to the right KDC. Software such as PAM modules that do Kerberos
authentications do this check as a matter of course. Once you've done
that, further communication with the KDC is done using the session keys in
your TGT, and a hijacked KDC won't be able to complete the protocol
exchange because it can't decrypt the TGT. kinit and similar programs
currently don't do this check by default, but there's no reason why they
couldn't if an appropriate keytab is available.
Your analysis of (2) assumes that every ldap principal in your KDC is
created by someone you trust not to spoof any other ldap principal in your
KDC. That's a high bar to meet and many sites are not going to meet that
bar, nor want to given a competing desire for distributed administration.
For example, Stanford allows students to run Kerberized services on their
personal computers if they wish, and therefore allows them to download
keytabs (and hence create ldap principals) for those computers. If they
can use DNS hijacking to return a CNAME for an LDAP server pointing to
their computer instead, they can obtain a legitimate keytab for the ldap
principal for that computer, and can successfully trick a client that
trusts DNS canonicalization.
Another, possibly more obvious case where (2) doesn't hold is in the
presence of cross-realm trust. If I can use DNS spoofing to return a
CNAME of ldap.stanford.edu to dorm-machine.mit.edu, and stanford.edu and
ATHENA.MIT.EDU have cross-realm trust, I can perform the same attack. So
you not only have to trust everyone who can create ldap principals in your
local realm, but everyone who can create ldap principals in any realm with
which you have cross-realm trust.
There are a lot of nasty things that you can do with DNS spoofing, and
this almost certainly isn't the most likely attack, but it is a potential
vulnerability that's been widely discussed within the Kerberos community,
including transition plans for how to get away from always doing
canonicalization. You can, for example, see part of the opinion of the
MIT developers in the comments around the relevant segment of code:
if (maybe_use_reverse_dns(context, DEFAULT_RDNS_LOOKUP)) {
/*
* Do a reverse resolution to get the full name, just in
* case there's some funny business going on. If there
* isn't an in-addr record, give up.
*/
/* XXX: This is *so* bogus. There are several cases where
this won't get us the canonical name of the host, but
this is what we've trained people to expect. We'll
probably fix it at some point, but let's try to
preserve the current behavior and only shake things up
once when it comes time to fix this lossage. */
This is the reason why there's an rdns option in krb5.conf to disable this
code. There has been other discussion of it on krbdev and
kerberos(a)mit.edu in the past.
I would agree that there's no way that you can change the default; too
much stuff would break. That's also why the Kerberos libraries continue
to do this by default. But I think the original bug reporter isn't
unreasonable for wanting a way to disable canonicalization if they know
that their code and environment will handle that appropriately.
--
Russ Allbery (rra(a)stanford.edu) <http://www.eyrie.org/~eagle/>
There exists no OpenLDAP 2.1 b102. There exists a 2.1 branch, which was
obsoleted few years ago. Even if there existed one, you don't provide
enough info that could help debugging your issue.
Please see <http://www.openldap.org/faq/data/cache/56.html> for details
about how to report an issue.
p.
Ing. Pierangelo Masarati
OpenLDAP Core Team
SysNet s.r.l.
via Dossi, 8 - 27100 Pavia - ITALIA
http://www.sys-net.it
-----------------------------------
Office: +39 02 23998309
Mobile: +39 333 4963172
Fax: +39 0382 476497
Email: ando(a)sys-net.it
-----------------------------------
Full_Name: Eduardo Garcia
Version: slapd 2.1 b102
OS: solaris 5.9
URL: ftp://ftp.openldap.org/incoming/traza_mala
Submission from: (NULL) (194.113.59.80)
Hello,
We are using a customized version of the slapd v2.1 b102. The problem that we
are seeing in the last days is that the slapd process goes into a sleeping mode,
and none ldap request is answered. This problems seems to happend in an
intervals of 72 hours more or less.
The process slapd is alive, but it seems to be stuck.
Last time this problem arised, I run a truss command to get more clues about it.
Above these lines, you can find the ooutput of truss and also a snoop of the
port 389 in the slapd machine.
Could you please look into this problem? Any further info you need , please tell
me.
Thanks a lot in advance
Eduardo
PS: we have implemented a local script to verify if the slapd process is up and
answering and we could see that in the moment when this problem happens, the
slapd did not answer to this local ldap request either. It kept sleeping and
running
This was the output of the truss command:
/1: lwp_wait(2, 0xFFBFFCC4) (sleeping...)
/4: lwp_park(0x00000000, 0) (sleeping...)
/5: lwp_park(0x00000000, 0) (sleeping...)
/7: lwp_park(0x00000000, 0) (sleeping...)
/11: lwp_park(0x00000000, 0) (sleeping...)
/8: lwp_park(0x00000000, 0) (sleeping...)
/12: lwp_park(0x00000000, 0) (sleeping...)
/13: lwp_park(0x00000000, 0) (sleeping...)
/10: read(15, 0x002E6476, 2064) (sleeping...)
/18: lwp_park(0x00000000, 0) (sleeping...)
/17: lwp_park(0x00000000, 0) (sleeping...)
/16: lwp_park(0x00000000, 0) (sleeping...)
/3: lwp_park(0x00000000, 0) (sleeping...)
/15: lwp_park(0x00000000, 0) (sleeping...)
/9: lwp_park(0x00000000, 0) (sleeping...)
/2: poll(0xFE3FD418, 3, -1) (sleeping...)
/6: lwp_park(0x00000000, 0) (sleeping...)
/14: lwp_park(0x00000000, 0) (sleeping...)
I also get a snoop trace in the slapd machine to see which was the messages
received and sent from our machine ---> traza_mala file at
ftp://ftp.openldap.org/incoming/
Full_Name: Kostas Kalevras
Version: 2.4.12
OS: FreeBSD
URL: ftp://ftp.openldap.org/incoming/
Submission from: (NULL) (147.102.247.100)
In the manpage for slapd.conf (slapd.conf.5) in the limits directive description
the value for the size.unchecked pattern should be disabled and not disable
according to limits.c