Bugtraq mailing list archives

Re: FreeBSD 2.2.5 Security problem


From: eivind () YES NO (Eivind Eklund)
Date: Mon, 4 Jan 1999 00:42:37 +0100


On Sat, Jan 02, 1999 at 04:14:22PM -0600, Missouri FreeNet Administration wrote:
Greetings, how is everyone after the 30 day pig-out? ;-0

We originally posted this problem to the FreeBSD GNATS system on
December 20th, and still haven't heard so much as an acknowledgement
of the report (GNATS#: i386/9141).  I figured with the holidays, they
were all busy, and would [eventually] get to it, but today I checked
and saw that several GNATS reports on either side of this one (some
as recent as today) have been looked at, processed, and even closed!
So...

The PR was misfiled; it was filed as a i386 PR (meaning a bug
in the i386-specific code of FreeBSD).

Apart from this, the PR system is not an effective way of reporting
security problems.  The right way to report a security problem is to
mail security-officer () FreeBSD ORG.

FreeBSD 2.2.5-R (other rev's not tested) fail to log penetration attempts
on quiescent systems properly when using syslog (to any target).  Failed
login attempts (*any* number of them) will not be reported until a user name
which is *different* from the failed name is entered.  For example, I can
attempt to penetrate the root password *all day long* without getting a
syslog report, provided a name other than root is not entered.  The reson
for this is that there is an attempt to de-verbosify syslog reporting in
FBSD which accumulates a counter for events, and then reports a cumulative
total.  In this attempt to save verbiage, they are tallying all the failed
attempts, *rather* than *reporting* them!

Your "*any* number" is incorrect.  The correct answer is "10", unless
you've changed the default for your login class in /etc/login.conf.
After 10 attempted logins, the problem will be logged by the part of
login that check for attacks.

This is (obviously) not going to be an issue on a busy system, as
*someone* other than the target account is likely to log in and flush the
counter report, but on a selected system, such as a name server, this
could be a devastating flaw...

The limit is on a per-login-execution basis.  As long as the attacker
has the tty for that execution of login, it will not matter if
somebody else log in.

However, looking carefully at the code, I do notice that there is a
bug whereby a 'silent attack' could be done (though not at all like
you've stated above).  I think I fixed this problem in rev 1.44 of
login.c:

Index: login.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/login/login.c,v
retrieving revision 1.43
diff -u -r1.43 -r1.44 login.c
--- login.c     1998/11/21 02:22:14     1.43
+++ login.c     1999/01/03 23:22:05
@@ -111,6 +111,9 @@
  */
 u_int  timeout = 300;

+/* Buffer for signal handling of timeout */
+jmp_buf timeout_buf;
+
 struct passwd *pwd;
 int    failures;
 char   *term, *envinit[1], *hostname, *username, *tty;
@@ -132,15 +135,23 @@
        time_t warntime;
        uid_t uid, euid;
        char *domain, *p, *ttyn;
-       char tbuf[MAXPATHLEN + 2], tname[sizeof(_PATH_TTY) + 10];
+       char tbuf[MAXPATHLEN + 2];
+       char tname[sizeof(_PATH_TTY) + 10];
        char localhost[MAXHOSTNAMELEN];
        char *shell = NULL;
        login_cap_t *lc = NULL;

-       (void)signal(SIGALRM, timedout);
-       (void)alarm(timeout);
        (void)signal(SIGQUIT, SIG_IGN);
        (void)signal(SIGINT, SIG_IGN);
+       if (setjmp(timeout_buf)) {
+               if (failures)
+                       badlogin(tbuf);
+               (void)fprintf(stderr,
+                             "Login timed out after %d seconds\n", timeout);
+               exit(0);
+       }
+       (void)signal(SIGALRM, timedout);
+       (void)alarm(timeout);
        (void)setpriority(PRIO_PROCESS, 0, 0);

        openlog("login", LOG_ODELAY, LOG_AUTH);
@@ -250,7 +261,6 @@
                if (failures && strcmp(tbuf, username)) {
                        if (failures > (pwd ? 0 : 1))
                                badlogin(tbuf);
-                       failures = 0;
                }
                (void)strncpy(tbuf, username, sizeof tbuf-1);
                tbuf[sizeof tbuf-1] = '\0';
@@ -769,8 +779,7 @@
 timedout(signo)
        int signo;
 {
-       (void)fprintf(stderr, "Login timed out after %d seconds\n", timeout);
-       exit(0);
+       longjmp(timeout_buf, signo);
 }


@@ -829,6 +838,7 @@
                    "%d LOGIN FAILURE%s ON %s, %s",
                    failures, failures > 1 ? "S" : "", tty, name);
        }
+       failures = 0;
 }

 #undef UNKNOWN


Eivind.



Current thread: