What should the password/security/userinfo/login system include?

Robert J. Reschly Jr. reschly at BRL.MIL
Wed Dec 20 02:57:06 AEST 1989


      Michael,

   Yes, what and when to log has been an interesting topic of discussion
here as well.  We have been working with some of the software likely to
be in 4.4BSD; login and friends in particular.  The code for login as it
comes from Berkeley is a bit forgiving for our tastes.  Comments in the
code imply it is supposed to allow a user to make one mistake (if the
mistake is not a valid username) without generating a log entry.
Reading between the lines leads us to conclude this code is there to
reduce the chance of accidentally catching a password in the logs --
something which happens more frequently than we would like in our
experience.  We protect our authorization failure logs, and shred old
console printouts because of this, by the way.  The code as received
also allows 10 login attempts before aborting, delaying the next
"login:" prompt by 5 additional seconds for each new prompt after the
third failed attempt -- or so the comments indicate.

   In actuality, both code segments are flawed.  First, the prompting
delays do not kick in until after the fourth failed attempt -- a classic
"off by one" bug.  And the log suppression code is flawed in that it
will allow any number (up to 10) of different attempts to be made
without logging any of them as long as each of the failing attempts does
not match any username or the (yes 'the', not 'any') previous attempt.
If the final attempt is successful and the failing attempts meet the
above restrictions, login will not generate any log entry at all.

   Before discussing our modifications, it is also worth noting that
getty will hand login a username longer than login is willing to accept
when it prompts for a username itself.  I don't recall whether the stock
login protects itself from overrun, but even if it does, I don't think
allowing this mismatch is good practice (we found this one by just
mashing a handful of keys while testing our mods :-)).

   After batting various options around for a while, we settled on having
the login process store each failed attempt (reasonable since this is
bounded by both username length and number of attempts) and calling
badlogin() on each exit path -- including timeouts and hangups.  Badlogin()
itself expects to be handed a string.  If this string is non-null, the
string is the username associated with a successful login.  If there were
any failures badlogin() generates a syslog message listing each of the
failures, and if there was ultimately a successful login, that username
is included in parentheses at the end.  Log entries now look like this:

Dec  4 20:23:25 sem login: 4 FAILED from spark: this is a test (reschly)

   Note that this entry keeps all attempts from a session on a single
line, giving a count of the number of failures, listing them ('this',
'is', 'a', and 'test') and finally listing the successuful login attempt
in parentheses.  Absent is the terminal information for network
connections (this one came from host "spark" -- who cares if it came
from ttyp0 or ttyp1?), and the amount of SHOUTING in the logfile has
been reduced.  The count of failures is included as a check on the list
of failures -- since failures may contain any character including space,
we just printed what we captured space separated and did not worry about
it too much.

   The rationale for logging the successful login along with the
failures is to allow us to catch someone "escaping" in a suspicious
manner. For example, on many systems there are one or more "safe"
passwordless accounts (e.g. a "sync" account which runs /bin/sync).
It is easy to envision someone trying one or two usernames followed by
"sync".  If the unmodified login is run, no log entry will be made if
the username is invalid; and the failed attempt count will not get high
enough to trip the delays.

   Our changes do have their disadvantages as well.  In the current
implentation, all attempts are buffered up until login exits.  This
means we have no indication of an ongoing attempt.  Since this seems
like it may be useful information, but it is not normally needed in
our environment, we will probably add code to syslog attempts at some
lower level as they occur (auth.debug is the current favorite).

   In addition, we can now match passwords with a vengeance, since
failures are all nicely lined up in a single log entry (and the log
entry may even include the successful attempt).  Given the contortions
in the code as shipped aimed at avoiding logging passwords, we will give
Berkeley back code to deal with this.  Since the successful login
proceeded by failures is the case we are concerned about, our current
thinking involves running crypt over the failures and comparing the
result against the successful login.  If there is a match, badlogin()
would not list that attempt in the log entry.  In the event of a match,
the log entry will probably still give an indication of how many matches
occurred (or said another way, how many failed attempts were not
listed).

   Finally -- and I mention these only for completness -- we also made
minor modifications to some of the user messages.  Army regulations do
not permit us to return responses which would allow a user to determine
the reason access was denied.  This means that we have to return the
same "Login incorrect" message for expired passwords or accounts, and
for things like attempts to log in as "root" on non-secure terminals and
invalid shells.  We then added syslog's indicating the true reason for
failure to preserve the system administrator's sanity.

				Later,
				    Bob 
   --------
Arpa:   reschly at BRL.MIL (or BRL.ARMY.MIL)  Phone: (301)278-6808  AV: 298
UUCP:   ...!{{cmcl2,nlm-mcs,husc6}!adm,smoke}!reschly
Postal: Robert J. Reschly Jr.
        U.S. Army Ballistic Research Laboratory
        Systems Engineering and Concepts Analysis Division
        Networking and Systems Development Team
        ATTN: SLCBR-SE-A  (Reschly)
        APG, MD  21005-5066             (Hey, *I* don't make 'em up!)

****  For a good time, call: (303) 499-7111.   Seriously!  ****



More information about the Comp.unix.wizards mailing list