[OpenAFS] The Illusion of Security

Rodney M Dyer rmdyer@uncc.edu
Sun, 17 Aug 2003 17:59:55 -0400


Subtitled "My Gripe with Pipe"

Hi everyone,

I've just been in an interesting short debate via personal email with one 
of the developers of MIT's Kerberos toolset.  I will keep their name 
private out of professional courtesy.  The debate centers around the 
reasoning behind preventing plaintext passwords to be passed to certain 
applications that require them.  In this instance, kinit, ssh, etc.  This 
polite exchange expanded into bigger issues of security.  I'm emailing this 
list to get some commentary from a larger community that deals with these 
issues every day.  I'd be interested in what the global concensus might be.

Originally the email centered around the simple question of why the MIT 
Kerberos for Windows "kinit" client will not allow passwords to be provided 
through stdin.  See...

	http://www.coe.uncc.edu/~rmdyer/krblogon.htm
	Section:  Very Important Notes
	SubSection:  "Bug in MIT's version of KINIT.EXE prevents reading passwords 
from stdin"

The standard answer from MIT is...it's not a bug, it was intentional.

Apparently there is some rational for not allowing plaintext passwords to 
be passed around between processes via pipes.  The following points merit 
that rational...

1.  STDIN is a pipe.  The operating system may create a temporary file for 
transfering the plaintext through the pipe.  Someone may figure out the 
file name and grab the password.  If the pipe has been redirected over a 
network, it's likely not through a secured channel like SSL.

2.  Since pipes are essentially FIFO's the recieving application may not be 
written well, so it might be buffer overflowed.

3.  Using the stdin method allows dumb users to do stupid things like...

	kinit < file

	or,

	echo "password_1234" | kinit

4.  Processes that request passwords from users should have their own 
direct user input channels that can't be overridden.

5.  If you absoulutely need to pass a plaintext password to another process 
like "kinit", you should instead create your own application that calls the 
libraries that the other application uses.

6.  What if the auth process needs more than a password, as with a hardware 
or bio crypto system?

7.  SSH doesn't allow stdin.  Why should kinit?


At this point if anyone has any other reasons I'd love to hear them.  I 
suppose these are all perfectly valid reasons for intentionally coding 
"kinit" so that it can't allow stdin to be used.


But...


I'm what might be termed as a practical, or practitioning systems 
programmer.  That means that for solving the given problem of the day I may 
not always be capable of pursuing idealistic solutions.

Case in point, for the problem of gluing together three differing systems 
of AFS, Windows, and Kerberos 5 I had to put together something that I had 
hoped would be easy to understand, require little code, be easily 
scriptable, use off-the-shelf components that people are already familiar 
with, and above all else be secure.  I had put together the method of using 
the AFSLogonShell, kinit, and aklog, to solve a number of niggling little 
problems with storing user accounts in AFS while authenticating my users to 
Kerberos 5.  This all seemed to be very rational to me.

Then, one day recently I get this email from a developer at MIT saying that 
what I've done is really bad mojo.  I shouldn't be sending the user 
passwords to kinit via stdin and I shouldn't allow it.  Well now, this is a 
wake-up call.  He gladly retorted some of the above reasons.


My response to him was to be sympathic to his reasons, but at the same 
time, stand in the devils advocates shoes.  I understand ideology and 
political correctness, but many times those reasons don't play well with 
getting things done, and making things supportable.

My responses are...


1.  Even though the OS may create a temporary file for the pipe, the 
contents of that file should be off-limits to unpriviledged users.  That 
is, assuming you could figure out the file name in the first 
place.  Moreover, as an experience systems admin/programmer working at the 
level of password authentication, not one of us is likely to redirect the 
pipe over a network.  Give us some credit please!

2.  Most passwords are rather limited in scope.  The characters used, and 
the length of the string would extremely limit the probablity of a buffer 
overflow, especially if we pre-validate it first.

3.  Users can be stupid.  It isn't my job as admin to limit what they do in 
their sandbox.  My job is to create a safe sandbox for them to work 
in.  You will never be able to write code that manages dumb users.  And, if 
if matters so much to prevent ordinary users from doing this, then do 
something smart like make "kinit" find out what level of secuity they 
have.  Require both a "-pipe" option on the command line as well as 
internal code that checks to see if you are running as root, or in the case 
of Windows, user "SYSTEM".  But, even this won't pevent the user from being 
a smartass.  See Bigger Issues below.

4.  Since the process runs in the users context anyway isn't it up to the 
user to decide what channels the password takes for authentication?  This 
is related to the Bigger Issues below.

5.  In our IT group we try to limit the number of special "in-house" apps 
we have to write, while at the same time use common "well-known" apps with 
well defined interfaces.  This minimizes the knowledge base that our IT 
people have to deal with.  People "know" kinit, they "know" aklog, they 
"know" pipes and scripting.  They've never heard of some special app that 
I've written just for our site.

6.  I don't really have a response here.  The question of what we do in 
this circumstance depends largely on whether we need such 
flexability.  Some do, others don't.  When processes like "kinit" and "ssh" 
request that kind of input, please let me know.  It's my job as systems 
programmer to determine yet another solution to the problem.

7.  The Solaris "kinit" allows stdin "out-of-the-box".  Why not the Windows 
version?


Bigger issues...

Installing open-source software on unmanaged Windows machines is a risky 
business in the first place.  If you don't find some way of protecting the 
very files that you are using to authenticate your users, then they can be 
changed...by the users, or by someone else.

For example, installing OpenAFS, Kerberos, and Kerberos for Windows on any 
ordinary unmanaged user box is not secure.  Since any hacker can download 
the source code, they can potentially sneak into one of your user boxes a 
socket based password grabber in the form of "afslogon.dll", "kinit", or 
"Leash32".  You would never know unless you performed a checksum of some 
kind like MD5.

Microsoft itself passes the plaintext password to all the logon 
authenticators in the form of an environment variable.  All that needs to 
be done is to make a change to "afslogon.dll" to send the password to some 
site.  The source is readily available.

The AFSLogonShell is simply a glue that allows you to pass the password 
(provided by Microsoft) to "kinit" which gets a tgt.  The reason I can do 
this is because I've modified (hacked) "prompter.c" to allow "kinit" to 
accept input from stdin.  However I don't like adding in my prompter hack 
with every new version of "kinit".  I'd rather have that functionality 
"out-of-the-box".  I believe this should be allowed.

The cultural history of Windows is that users have complete control, or 
root level priviledge on their boxes.  This is slowly beginning to 
change.  Our group has managed a "closed" network of NT/2000/XP machines 
since '97.  The users don't have the ability to change local system files 
and settings beyond their own environments.  The local file system and 
processes are protected by ACLs.  We've managed our boxes with rather 
unorthodox (in the windows world) UNIX-like techniques.  In a sense they 
are very much like our Sun Solaris machines.

Based on this environment, the entire authentication chain, including the 
AFSLogonShell is protected.  No user is going to be able to grab the 
plaintext password, change a system file, or modify the process.  No user 
is going to be able to grab the information passed through stdin to 
"kinit".  It is "secured", and it works.


MIT Rebuttle...

What I've done is just wrong.  Instead of piping to "kinit", I should write 
my own application that is coded against the Leash libraries.  According to 
them, I can take my environment variable password and pass it directly to 
the LeashAPI.  I thought about this for a bit, then it hit me...how is this 
any different?  I've just changed this...

	c:\>envout env_password_var | kinit

to this...

	set env_password_var=Password_1234
	mykinit.exe

Nothing has changed here.  This won't help.


My further rebuttle...


The simple issue is this...OpenAFS, Leash, MIT Kerberos, AFSLogonShell, are 
"add-on" applications that don't link into the "real" kernel.  No add-on 
application, especially an open-source one will make your environment 
secure, no matter how smart you think you've coded the password input.  If 
your box is unmanaged, or can be "owned" by a hacker, then "all bets are 
off".  The justification for not allowing stdin to be used for password 
entry is flimsy at best, and leads to a false sense of security at 
worst.  It also prevents me, a practical systems programmer from 
implementing a rather simple yet effective technique to provide an interim 
solution for a rather long term problem.


This is not a rant, or flamefest against my MIT friend.  I respect their 
opinion and value their input.  I do not however believe it is in the best 
interest of the community as a whole to "decide for us" on how we should 
implement our solutions to complex problems.  This smells of the "we know 
better than you" syndrome.  In fact, it actually costs MIT some code to 
prevent us from performing the pipe.


I'm ready to take the slings and arrows of the OpenAFS community at 
large.  I also value your opinion too.  Please let me know how you feel on 
this issue.  I'm open to suggestions and ready to consider another 
solution.  Do any of you use "kinit" authentication via a pipe of some kind?


A Cleaner Way

Speaking of which, does anyone know how to modify ms2mit.exe so that it 
will work in the AFSLogonShell?  The problem here is that the AFSLogonShell 
doesn't run in the user's process space at logon, it runs as user SYSTEM, 
in the WinLogon process space.  This is why it has so much appeal, it 
actually runs before the user's process space is init'ed, before the 
profile downloads, and before folders are redirected.  I simply need a way 
to grab the user's Windows Krb5 logon credential as user SYSTEM.  This 
would be the best fix for my problem, but I'm not sure how to accomplish 
this.  That way I would have no need for the password, even though...don't 
forget, it would still be provided to me by WinLogon.

I would essentially be changing this...

	envout env_password_var | kinit
	aklog

	to this...

	ms2mit -special_logon_option?
	aklog


Anybody got a clue?


Thanks for listening,

Rodney

Rodney M. Dyer
Windows Systems Programmer
Mosaic Computing Group
The William States Lee College of Engineering
University of North Carolina at Charlotte
Email rmdyer@uncc.edu
Phone (704)687-3518
Help Desk Line (704)687-3150
FAX (704)687-2352
Office  267 Smith Building