Bugtraq mailing list archives
Re: Sudo: local root compromise with krb5 enabled
From: Ken Raeburn <raeburn () MIT EDU>
Date: Mon, 11 Jun 2007 18:52:11 -0400
Thor Lancelot Simon writes:
Widely distributed software using Kerberos for password authentication (e.g. the original Merit RADIUS server code, as I disclosed in the mid1990s) has had a long and ugly history of failing to perform the second step, usually because its authors didn't understand that it was necessary.
Yes, this is the standard KDC spoofing attack, known since I think the early 90s at least, maybe late 80s.
But sudo has a curious bug: it *tries* to do the second step,but if that step fails because no local service keys are known, it lets the user become root anyway, because the (potentially fake) Kerberos serversaid so. For example, on a host without a "keytab" file:
In some MIT applications there was a conscious choice to that effect. The MIT library's interface for verifying credentials has a flag that can be set to indicate whether it should return success or failure for this specific case. (Though personally, I think the default should be the more paranoid one, it would be an incompatible break from previous versions.)
Needless to say, this should be fixed. Simply adding local keytabs with service keys for every host that has a kerberos-enabled sudo looks, from a cursory inspection of the code in auth/kerb5.c in the latest sudo distribution (1.6.8pl12) like it will suffice: the other errors appear to be correctly handled. But woe betide any system administrator who accidentally puts a Kerberos-enabled sudo on a host that's configured as a Kerberos client only!
There is the argument that you should have keytabs on any host with resources you want to protect, and conversely, if there's no keytab, it doesn't matter if you grant root access. For some environments, that's actually reasonably accurate, but not all environments by any means.
On a system without a keytab, Kerberos by itself -- any implementation -- cannot verify much of anything at all.
Actually, if you link sudo to MIT krb5 (rather than Heimdal) it's worsethan that, I think: users can override the system keytab setting andcause sudo to *think* there's no keytab when there actually is one, andthen have it ask their fake Kerberos servers, and make them root.
Only because the sudo code is buggy.
The MIT library provides several different flavors of krb5_init_context
I count two, unless you're looking at internal functions.
and only one of them (krb5_init_secure_context()) actually sets the profile_secure flag. But sudo uses the standard krb5_init_context() which does *not* set profile_secure
Like I said, sudo has a bug. Any program or module that needs the Kerberos code to not trust the environment must use krb5_init_secure_context, or clean out the environment. You wouldn't call execvp (or system without an absolute path) from a privileged part of a setuid program with $PATH supplied by the untrusted user, would you?
and also doesn't call the obsolete(and, I think, never documented) old krb5_secure_config_files() function,which is the only other thing in the MIT library that would set profile_secure and avoid this root compromise.
That was the original way of dealing with this, until I pointed out back around 1999 that krb5_init_context used $KRB5_CONFIG to read the config file, and even reading some files that might be root-only could have bad effects, like device files (rewind a tape drive while the sysadmin is in between writing dump files to the current tape), or in subtler cases, expose information only root should be privy to. (For example, does file X exist in that directory that I can't read? A missing config file produces different results from a file found but not in krb5.conf format.) So by the time you could call krb5_secure_config_files, you might have already lost.
The function still exists, and will set the "secure" flag, and throw away the original config data and re-read just the files at compiled- in pathnames, but now it also returns an error code saying it's obsolete.
So the hole is worse than I thought. It is probably simplest and best to remove the current krb5 password validating code from sudo, and use Heimdal's krb5_verify_user() instead, and make sudo thus no longer work with MIT krb5, which is a terrible security accident just waiting to happen.
You might consider talking with the MIT Kerberos team about the issue.
Evidently modern MIT krb5 has krb5_verify_user too and though it pokes around in the library internals it doesn't set profile_secure in the context.
Not in my source tree it doesn't. Maybe you're looking at krb5_verify_init_creds?
As I described above, at this point in the process, if you've created a normal context in a setuid process, you may have already had some exposure. Indeed, in future versions it's possible that creating a normal context and calling get_init_creds could potentially load some plugin modules indicated by the user's config file. Calling verify_init_creds after that and expecting the user to be unable to subvert it is pointless.
It might be a useful enhancement to have krb5_init_context create a "secure" context when invoked with uid!=euid (and likewise check for setgid, oh and check saved set-user-ID too). But I think it would be sloppy to rely on that for security.
For that, with MIT krb5, one has to call krb5_init_context_secure() instead of the standard krb5_init_context().
Right. We do want to be able to run servers in secure environments with information passed in through environment variables. Since setuid programs are much more the exception than the rule, our defaults are oriented towards programs running in environments that can be trusted, and krb5_init_secure_context is for handling the other cases. (Not just programs when running with different real and effective uids, but any such programs that have since set both ids the same, or programs spawned from such processes without purging the environment, etc.)
the initial patchto sudo I posted won't protect against it (since one can override the keytab and krb5.conf locations and just force a bogus keytab to be checked againsta bogus server).
You should just make it call krb5_init_secure_context.People concerned about proper use of Kerberos in applications are welcome to send mail to the kerberos () mit edu list for discussion; we'd be glad to help, and there are a lot of people besides the MIT team on the list.
Ken
Current thread:
- Sudo: local root compromise with krb5 enabled Thor Lancelot Simon (Jun 07)
- Re: Sudo: local root compromise with krb5 enabled Thor Lancelot Simon (Jun 07)
- MIT krb5: makes sudo authentication issue MUCH worse. Thor Lancelot Simon (Jun 07)
- Re: Sudo: local root compromise with krb5 enabled James Downs (Jun 07)
- Re: Sudo: local root compromise with krb5 enabled Mark Senior (Jun 07)
- Re: Sudo: local root compromise with krb5 enabled Todd C. Miller (Jun 07)
- Re: Sudo: local root compromise with krb5 enabled Mark Senior (Jun 07)
- <Possible follow-ups>
- Re: Sudo: local root compromise with krb5 enabled Ken Raeburn (Jun 12)
- Re: Sudo: local root compromise with krb5 enabled Kyle Wheeler (Jun 14)
- Re: Sudo: local root compromise with krb5 enabled Ken Raeburn (Jun 15)
- Re: Sudo: local root compromise with krb5 enabled Kyle Wheeler (Jun 14)
- Re: Sudo: local root compromise with krb5 enabled Thor Lancelot Simon (Jun 07)