[comp.protocols.kerberos] Verifying passwords without getting new tickets

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.