kctreima@eos.ncsu.edu (Kenneth C. Treimann) (05/17/91)
Hello, I'm new to this newsgroup, so be patient with me. Is there a way to verify a userid and password without getting a new ticket-granting-ticket? All I want to do is pass a name to a function, make sure that Kerberos knows the principal, prompt for the password, verify it, and return a yes or no type answer (or k_errno). I do NOT want to use krb_get_pw_in_tkt, because it replaces the existing tickets, and then I have to do another call to krb_get_pw_in_tkt to get a new ticket-granting-ticket for the user who was already logged in (unfortunately, this is what my program does now). I asked one of the systems programmers here and he said he didn't know, but would be very interested in such a thing. Any ideas? -- Kenneth C. Treimann (The Bean) Obligatory quote: "F*** you, a******." - The Terminator Meaningless song lyrics: I'm so bad I should be in detention. - Anthrax (Stolen from the film Easy Money) Optional disclaimer: See obligatory quote above.
bjaspan@ATHENA.MIT.EDU ("Barr3y Jaspan") (05/17/91)
From: kctreima@eos.ncsu.edu (Kenneth C. Treimann)
Reply-To: kctreima@eos.ncsu.edu (Kenneth C. Treimann)
Is there a way to verify a userid and password without getting a
new ticket-granting-ticket?
By definition, no. "Verifying a userid and a password" under Kerberos
is defined as asking the Kerberos server for a tgt and having it
successfully decrypted by the kinit/login program, using the password
provided by the user. The Kerberos server neither knows nor cares
whether the request is valid.
All I want to do is pass a name to a function, make sure that
Kerberos knows the principal, prompt for the password, verify it,
and return a yes or no type answer (or k_errno). I do NOT want to
use krb_get_pw_in_tkt, because it replaces the existing tickets,
Well, that is a different question. :-) What you want to do is get a
tgt and not store it in the ticket file (aka credential cache).
krb_get_pw_in_tkt (in lib/krb/get_in_tkt.c) is mostly a wrapper for
the real workhorse function, krb_get_in_tkt (in krb_get_in_tkt.c).
The body of that function actually acquires the ticket, decrypts it,
checks it out, et cetera, and at the VERY END contains the following
code:
/* initialize ticket cache */
if (in_tkt(user,instance) != KSUCCESS)
return(INTK_ERR);
/* stash ticket, session key, etc. for future use */
if (kerror = save_credentials(s_name, s_instance, rlm, ses,
lifetime, kvno, tkt,
t_local.tv_sec))
return(kerror);
return(INTK_OK);
}
It would appear that if you really want to get a ticket WITHOUT
stashing it in the cache, you could just copy all the code from
krb_get_in_tkt into a new function (say, krb_get_in_tkt_nosave) that
does *not* call in_tkt or save_credentials, and call the new function
instead.
DISCLAIMER: I haven't tried this, I just glanced at the source code.
This, of course, is a DIGUSTING KLUDGE but appears to be all you can
do within Kerberos V4. The API for Kerberos V5 (which will be in beta
test soon, see previous message on this list) is considerably more
versatile and (presumably) does not have this problem.
I hope this helps.
Barr3y Jaspan, bjaspan@mit.edu
MIT Student Information Processing Board
Watchmaker Computing (bjaspan@watch.com)
tytso@ATHENA.MIT.EDU (Theodore Ts'o) (05/17/91)
Date: 16 May 91 21:34:33 GMT From: kctreima@eos.ncsu.edu (Kenneth C. Treimann) Organization: North Carolina State University Sender: owner-comp-protocols-kerberos@shelby.Stanford.EDU Reply-To: kctreima@eos.ncsu.edu (Kenneth C. Treimann) Hello, I'm new to this newsgroup, so be patient with me. Is there a way to verify a userid and password without getting a new ticket-granting-ticket? All I want to do is pass a name to a function, make sure that Kerberos knows the principal, prompt for the password, verify it, and return a yes or no type answer (or k_errno). I do NOT want to use krb_get_pw_in_tkt, because it replaces the existing tickets, and then I have to do another call to krb_get_pw_in_tkt to get a new ticket-granting-ticket for the user who was already logged in (unfortunately, this is what my program does now). DANGER WILL ROBINSON!!!!! If your site is relying on Kerberos to check passwords as you've described, your site has a huge large security hole. What you're doing is *NOT* sufficient for verifying a userid and password, even if you get a new ticket-granting-ticket. So the short answer is no --- getting a ticket-granting-ticket isn't even sufficient by itself. Consider the following scenario: you write a "ksu" program which prompts for a username and password and tries to get a ticket-granting-ticket to verify the password. Then if that username is in an access control list, it gives you a root shell. This program is vulnerable to attack in the following method: the attacker runs the ksu program, and enters a username which he knows is in the access control list. He then floods the port that ksu is using with faked-up replies which appear to come from the KDC, but which are really a fake set of credentials encrypted in a password of the attcker's choosing. The attacker then types the password which he choose, and the ksu program (having gotten one of the fake replies from the KDC) decrypts the reply using the password and gets something which looks like valid credentials, and so the ksu program will give the attack a root shell. This security "hole" comes from the misuse and misunderstanding of what it means to be able to successfully obtain a ticket granting ticket. Obviously, as the above scenario shows, merely obtaining a ticket granting ticket does not prove anything about the user's authenticity. You can only say something about the user's authenticity if you can successfully use those tickets to obtain service from a server. You see, in the above scenario, the fake "tickets" are useless because the attacker does not have any of the secrets known by the KDC. Thus, the first time anyone tried to use those tickets, they would be known to be fakes. The problem with the "ksu" program as designed above is that it never tried to use the ticket-granting-ticket. It merely assumed that possession of something which looked like a ticket-granting-ticket was good enough give someone a root shell. Kerberos was not designed to verify passwords; it was designed to authenticate clients to servers across a network. Anyone trying to use Kerberos for the first purpose has really voided their warranty..... There is one safe way of using Kerberos to verify passwords, but it requires that the program have access to a service key. (For example, the rcmd.hostname service key in /etc/srvtab.) The way to check if a password is valid is as follows: 1) request ticket-granting-tickets. 2) try to decrypt the ticket-granting tickets with the user's password. If it fails, error out. 3) Using the ticket-granting-tickets obtained in step 2, obtain credentials for rcmd.hostname. 4) Using the key for rcmd.hostname found in /etc/srvtab, verify that the session key stored in the rcmd.hostname ticket matches the session key in the credentials. If and only if all four steps are successful can you assume that the password is valid. - Ted
cjr@SIMPACT.COM (Chris Riddick) (05/17/91)
You asked if there was a way for Kerberos to be used to authenticate a principal without geeting a new TGT. First, I'm not sure why you want to do that. The purpose of Kerberos is to provide that authentication for you. If you are asking the principal to authenticate himself, then you really need to go through the TGT protocol again. Second, the point of the TGT is that it is to be used for future service ticket requests instead of having to reauthenticate with your password each time you want another ticket. The benefits are twofold: exposure of your password is minimized and the user only need login to the kerberos server once during the lifetime of the TGT. If what you are really trying to do is to provide a periodic verification of the identity of the user at the workstation, then you really should limit the lifetime of the TGT to that of the authentication period and force the user to get a new TGT. The password is an integral part of the Kerberos authentication protocol. It is used to decrypt the packet with the TGT returned by the Kerberos server. The protocol is set up to remove the need to send the password over the wire. Not even an encrypted password goes over the wire. Rather, a complete encrypted message is sent. This removes the threat of dictionary attacks against the password itself. Chris Riddick Chris Riddick UUNET: uunet!nss1!cjr Internet: nss1!cjr@UUNET.UU.NET USSnail: Simpact Associates, Inc. 12007 Sunrise Valley Drive Reston, Virginia 22091 Phone: 703-758-0190 x2156 FAX: 703-758-0941
jon@MIT.EDU (Jon A. Rochlis) (05/17/91)
Is there a way to verify a userid and password without getting a new ticket-granting-ticket? By definition, no. "Verifying a userid and a password" under Kerberos is defined as asking the Kerberos server for a tgt and having it successfully decrypted by the kinit/login program, using the password provided by the user. This is not true. Think about it. If you ask Kerberos for a initial ticket (it need not be a TGT) and decrypt it, you have only made use of *one* secret (the user's password). Kerberos is based upon shared secrets. To identify a principle you need to have *two* secrets. This is an example of the old ksu bug, where spoofing the KDC actually buys you something. (I.e. I want to fool you into thinking I'm George.Bush@WhiteHouse.GOV, so I tell you that's my name. You request a TGT (or whatever) from Kerberos, but before Kerberos can respond with a real ticket, I reply with a well formed ticket encrypted in the password "millie", which I type in when your program asks. It will decrypt just fine and dandy. If you tried to actually use the ticket, the service you're trying to fool would reject it.) This is pretty easy to do and has been demonstrated. To be safe you must ask Kerberos for a ticket and then *use* it by sending it to a service with it's own secret (service key) registered with kerberos. Check out the sources for ksu. In order to be secure you need to have a srvtab with rcmd.hostname for ksu to use (since ksu is setuid it can keep the service key secret). This is perhaps subtle, but very important. There is at least one commercial implementation of Kerberos which is vulnerable to this attack. -- Jon
marc@ATHENA.MIT.EDU (Marc Horowitz) (05/18/91)
>> The password is an integral part of the Kerberos authentication protocol. >> It is used to decrypt the packet with the TGT returned by the Kerberos >> server. The protocol is set up to remove the need to send the password over >> the wire. Not even an encrypted password goes over the wire. Rather, a >> complete encrypted message is sent. This removes the threat of dictionary >> attacks against the password itself. It is true that the password is never sent over the wire. However, this does not prevent dictionary attacks. I can request from your kerberos server a TGT for you, and then attack it in the privacy of my own host in whatever way I want. Once I can decrypt your TGT, I effectively have your password, except I can't use kinit, since stringtokey is irreversible. And in this whole process, only one TGT request will be logged. There have been discussions on this list about how to prevent this type of attack, but I don't know what was adopted for krb5, if anything. Marc
mdl@B.GP.CS.CMU.EDU (Mark Lillibridge) (05/21/91)
> It is true that the password is never sent over the wire. However, > this does not prevent dictionary attacks. I can request from your > kerberos server a TGT for you, and then attack it in the privacy of my > own host in whatever way I want. Once I can decrypt your TGT, I > effectively have your password, except I can't use kinit, since > stringtokey is irreversible. And in this whole process, only one TGT > request will be logged. There have been discussions on this list > about how to prevent this type of attack, but I don't know what was > adopted for krb5, if anything. > > Marc It is impossible to protect against this kind of attack without radically altering kerberos. (i.e., adding random #'s at both ends or using public-key methods) Note that it is not even necessary ask for a TGT for X to do a dictionary attack against X. All you need to do is eavesdrop on X logging in once. - Mark Lillibridge
cjr@SIMPACT.COM (Chris Riddick) (05/21/91)
There is a way to render the dictionary attack ineffective. That is the use of one-time passwords. With a onetime password, even a TGT that was stolen simply by eavesdropping during login would not be useful. The password that was extracted via the dictionary attack (other other cryptanalysis) was only good for that login (i.e., TGT). The next time the user logs in, a different password will be required. Granted, Mark was right in saying that the Kerberos protocol would have to be altered. However, only the TGT protocol would be modified. All service ticket requests would continue to be done as they are now. By the way, in V5, the confounder was created to make cryptanalysis more difficult by adding random padding to the front of the protocol packet. Chris Riddick
jon@MIT.EDU (Jon A. Rochlis) (05/21/91)
All you need to do is eavesdrop on X logging in once. That is *much* harder than simply asking for a ticket in somebody else's name and therefore even though it's only a partial solution, it add significant value. Security is a world of tradeoffs. -- Jon
mdl@B.GP.CS.CMU.EDU (Mark Lillibridge) (05/21/91)
> From: Chris Riddick <cjr@simpact.COM> > > There is a way to render the dictionary attack ineffective. That is the use > of one-time passwords. With a onetime password, even a TGT that was stolen > simply by eavesdropping during login would not be useful. The password that > was extracted via the dictionary attack (other other cryptanalysis) was only > good for that login (i.e., TGT). The next time the user logs in, a > different password will be required. No. "One-time passwords" (this is really the wrong term for this, but I know what you mean from the previous time you explained yourself), do NOT by themselves render the dictionary attack ineffective. If the user chooses his/her own master password, the fact that one-time passwords are generated from it will not make the attack impossible. [The details of how to alter the attack to deal with this are left to the reader.] However, forcing the user to use a randomly generated password will render the dictionary attack useless. Granted, this is particularly easy to do when the user already has to carry a one-time password generator device around with him/her. > From: "Jon A. Rochlis" <jon@MIT.EDU> > > All you need to do is eavesdrop on X logging in once. > >That is *much* harder than simply asking for a ticket in somebody >else's name and therefore even though it's only a partial solution, it >add significant value. Security is a world of tradeoffs. > > -- Jon Jon's point above is important, however. Just because you can't protect against the attack, doesn't mean you can't make it harder. I don't remember off hand if krb5 actually prevents you from doing a dictionary attack without eavesdropping or setting off alarms. - Mark Lillibridge
kctreima@eos.ncsu.edu (Kenneth C. Treimann) (05/21/91)
Thanks once again to all those who responded to my question. I suppose my real concern about getting tickets for one user was that in doing so, the tickets for another user were destroyed. This meant I had to type in a password to verify one user, then type in another password to get the original user's tickets back. But thanks to the miracle of KRBTKFILE (and some helpful people from MIT and elsewhere), this is no longer a problem. My program now only asks for one password and leaves the original user's tickets alone. I can always tell when a problem has a simple if not obvious solution. It's just finding it is the hard part... -- Kenneth C. Treimann (The Bean) Obligatory quote: "F*** you, a******." - The Terminator Meaningless song lyrics: I'm so bad I should be in detention. - Anthrax (Stolen from the film Easy Money) Optional disclaimer: See obligatory quote above.