8785839 2002-07-29 10:51 -0400  /261 rader/ Michal Zalewski <lcamtuf@coredump.cx>
Sänt av: joel@lysator.liu.se
Importerad: 2002-07-29  18:13  av Brevbäraren
Extern mottagare: bugtraq@securityfocus.com
Extern mottagare: vulnwatch@vulnwatch.org
Mottagare: Bugtraq (import) <23320>
Ärende: RAZOR advisory: Linux util-linux chfn local root vulnerability
------------------------------------------------------------
From: Michal Zalewski <lcamtuf@coredump.cx>
To: bugtraq@securityfocus.com, <vulnwatch@vulnwatch.org>
Message-ID: <Pine.LNX.4.42.0207291048140.4453-100000@nimue.bos.bindview.com>


Linux util-linux chfn local root vulnerability

   Issue Date: July 29, 2002
   Contact: Michal Zalewski
   CVE: CAN-2002-0638
   CERT vulnerability note: http://www.kb.cert.org/vuls/id/405955
   (the URL should be accessible soon)

Topic:

   A locally exploitable vulnerability is present in the util-linux
   package shipped with Red Hat Linux and numerous other Linux
   distributions.

Affected Systems:

   Red Hat Linux 7.3 and previous; potentially many other
   distributions up to date that use util-linux to provide chfn and
   chsh utilities.  Please refer to the CERT vulnerability note for
   more information.

   Systems that ship chfn within the shadow-utils package (for example
   SuSE) are not vulnerable.

Details:

   The vulnerability is present within the shared code of the
   util-linux package. For the purpose of this discussion, we use the
   setuid application 'chfn' as an attack vector. We used the
   "Fenris" utility, available at
   http://razor.bindview.com/tools/fenris, to analyze the issue.

   The purpose of the 'chfn' utility is to allow users to modify
   personal information stored within the system-wide password file,
   /etc/passwd.  In order to modify this file, this application must
   be installed setuid root. It is a part of the base installation of
   most Linux systems.

   Under certain commonly met conditions (see "Mitigating Factors"), a
   carefully crafted attack sequence can be performed to exploit a
   complex file locking and modification race present in this utility,
   and, as a result, alter /etc/passwd to escalate privileges in the
   system.

   Password file locking and modification code can be found in
   util-linux within the login-utils/setpwnam.c file. The general
   logic used for this process is as follows:

    1. /etc/ptmptmp file is opened with O_WRONLY|O_CREAT, 0644 perms
    2. the file is linked to /etc/ptmp, exit on failure
    3. /etc/ptmptmp is removed

   Later, the descriptor obtained in step 1 is used for writing to
   construct the new /etc/passwd contents. This is done line by line,
   by calling the fputs() routine. When the new file is ready, three
   more steps are taken:

    4. /etc/passwd.OLD is removed
    5. /etc/passwd is linked to /etc/passwd.OLD
    6. /etc/ptmp is renamed to /etc/passwd

   At first sight, this logic is not flawed. There is no O_EXCL in
   step 1, but step 2 works as an accurate exclusive locking
   mechanism, and prevents other instances of this application from
   making any writes until the procedure is completed (step 6). Also,
   step 3 ensures that no process will work on the hardlink of
   /etc/passwd after the procedure is completed. This, while is not a
   standard way of handling file locking on Linux, is an adequate
   protection against race conditions. The only concern is that if
   chfn, chsh, or any other process that uses /etc/ptmp is terminated
   abnormally (e.g. never exits because of a system crash or is
   killed with SIGKILL), the lock has to be removed manually in order
   for applications that rely on this signaling method to work
   properly. This includes utilities such as chsh, chfn, useradd,
   userdel, adduser, vipw and other software. Most of seasoned Linux
   administrators have had to remove this lock file at least once,
   and many utilities offer help troubleshooting this issue - for
   example, adduser refuses to run when /etc/ptmp is present and
   terminates with the following message:

   # adduser
   vipw lockfile (/etc/ptmp) is present!

   This is exactly what causes the problem. Because this dangling
   lock file makes it impossible to perform regular user management
   tasks, it is trivial to force the administrator to remove it. This
   is a risk if chfn is stopped (by SIGSTOP) between steps 2 and 3 -
   which can be done. There is a very small window of opportunity
   here, but it is possible to fit into it. Later, the application
   can be resumed with SIGCONT.

   Note that there is no easy way to diagnose who created /etc/ptmp
   and for what reason they created it. The file is owned by root and
   has no additional information whatsoever. The attack relies on
   small windows of opportunity, making one-shot attempts not
   feasible on certain systems, it is reasonable to expect that if
   the attacker repeatedly runs chfn or chsh just to create dangling
   lock files several times a day - and to make user management and
   maintenance tasks repeatedly fail because of this lockfile - the
   administrator will most likely add "rm -f /etc/ptmp" or equivalent
   to his crontab, instead of putting much more effort into tracing
   the problem that cannot be easily diagnosed using standard Linux
   tools - there is no log entry associated with successful
   authentication for chfn service, ownership of the file is set to
   root, the file is empty.

   As soon as this or a similar counter-measure is deployed,
   trial-and-error attacks become much simpler. None of the above
   administrative tasks is to be viewed as requiring social
   engineering.  Such tasks are a part of standard system maintenance
   and operations, and it is safe to assume that almost all system
   administrators will follow this or a similar procedure to address
   the problem.

   Once the attacker has a stopped chfn process in between steps 2
   and 3, and the /etc/ptmp file has been removed, he can easily
   execute another instance of chfn. It will open the already
   existing /etc/ptmptmp (this file is not considered a lock by any
   software, and most likely won't be deleted). The second instance
   runs and step 2 succeeds because there is no lock file
   present. The file is then written. As soon as /etc/ptmp has the
   projected size (or /etc/passwd.OLD appears), the instance should
   be killed to avoid renaming to /etc/passwd (this is a timing
   concern for this attack, and we will address it later).

   The First instance of chfn is still holding an open descriptor to
   /etc/ptmptmp, which later became /etc/ptmp - and, if we send
   SIGCONT to this process, will be renamed to /etc/passwd. Step 3
   will fall through because there is no error checking, and new
   information will be written into a descriptor that will de facto
   become /etc/passwd.

   Copying the file should go smoothly up to the point where attacker
   account information is stored. Let's analyze what is going to
   happen past this point if the second instance of chfn was called
   with significantly longer GECOS parameters than first (minimum
   GECOS length set by chfn is zero, maximum is 260 characters). Keep
   in mind that there is no call to ftruncate() before fclose(), so
   the new file would have a "tail" consisting of the last characters
   of the longer version of /etc/passwd. If 'Write 1' is the first
   write to file, or the write made by the second instance of chfn,
   'Write 1 is the second write (first instance), and '|' represents
   a record separator (newline), then:

   Write 1: user 1 | user 2 | ATTACKER LONG | user 3 | user 4 |
   Write 2: user 1 | user 2 | ATTACKER | user 3 | user 4 |
   ------------------------------------------------------------
   Result:  user 1 | user 2 | ATTACKER | user 3 | user 4 |r 4 |

   As a result, /etc/passwd has now a new line at the end, a
   "leftover" part from last username. This, itself, can be
   considered an annoyance, but is hardly a full-blown security
   issue. There is, however, something that makes this problem more
   serious - that is, GNU libc.

   As we mentioned earlier, records are being written to wannabe
   /etc/passwd line by line, using fputs(). It is important to
   realize that the text-file functions such as fputs() are buffered
   - that is, lines are being actually written to disk in chunks,
   when internal cache is full. Until this point, the OS's idea of
   the file and the process's idea of the file are not
   synchronized. Cache block size, by default, is four
   kilobytes. This means that if the password file has more than four
   kilobytes (which is very often true on systems where local attacks
   are performed, see "Mitigating Factors"), and the attacker's
   account is not in the last cached that is going to be written
   before fclose(), it should be possible to "cut" the file on four
   kilobytes boundary by killing the first chfn process as soon as
   /etc/passwd has the desired contents:

                   <--- attacker's account           4 kB boundary
                                                       |
   Write 1: ...ser1:x:640:640:Foo Bar:/bin/bash\nuser2:x:641:641:Foo...
   Write 2: ...user1:x:640:640:Foo Bar:/bin/bash\nuser2: ***CUT***
   --------------------------------------------------------------------
   Result:                                   ...\nuser2::641:641:Foo...

   Note that both the data written in "Write 1" and in "Write 2" can
   be padded within a 260 byte range, which is typically much more
   than a typical /etc/passwd line length, so it is possible to pad
   the record exactly in the way described above - which happens to
   erase the password for user2. All it takes is to determine the
   appropriate initial padding, then invoke the first chfn with one
   more character in GECOS than in the second chfn.

   It is also possible to create root accounts or other privileged
   access accounts that effectively lead to privilege escalation
   (kmem, mail, etc). A root account with no password can be
   generated in two steps, first truncate the UID ending with '0' to
   the last digit, and the second step is to remove the password as
   described above. Note that even if there is no account with UID 0
   anywhere close to the 4 kB boundary, data can be moved over much
   longer distance by several subsequent attack cycles where the
   first instance is called with the maximum length GECOS field, and
   the second with minimum.

   The question of timing required for trimming is essential in
   evaluating the feasibility of this attack - but, fortunately for
   the attacker, timing is on his side. First of all, the copying
   procedure is essentially pretty slow, being done in a
   read-compare-write cycle.  Then, the results are cached so the
   output appears in larger chunks, but less frequently, giving the
   attacker plenty of CPU cycles.  Finally, the passwd file is
   world-readable, which gives the attacker a tremendous advantage -
   it can be easily monitored e.g. by mapping a single byte at the
   boundary to the memory space of the exploit.  Additionally, for
   files that consist of more than one segment past the attacker's
   account, the problem of careful timing needed to avoid renaming
   /etc/ptmp to /etc/passwd becomes less of an issue, because the
   process can be killed before reaching the end of the file, just
   after the desired boundary is modified.

Mitigating factors:

   In order to successfully exploit the vulnerability and perform
   privilege escalation, the following additional requirements have
   to be met:

    1. There is a need for a minimal administrator interaction that falls
       into the category of standard system maintenance and operations.

    2. The password file, /etc/passwd, must be over 4 kilobytes. This
       requirement is typically satisfied on systems with approximately
       50 accounts or more - that is, on a vast majority of systems that
       where unprivileged accounts are being compromised / used by
       malicious attackers.

    3. Assume that /etc/passwd is divided into 4 kB chunks. The
       attacker's account record in this file must NOT be located in the
       last chunk. That is, if /etc/passwd has 9 kB and we have three
       chunks, 4 kB, 4 kB and 1 kB, and attacker's account must be
       located within the first or second chunk and cannot be located
       further than 8th kilobyte of the file.

   Other mitigating factors are similar to ones for other local
   vulnerabilities in setuid binaries.

Workaround / fix:

   The fast workaround is to remove setuid flags from /usr/bin/chfn
   and /usr/bin/chsh. A more appropriate fix is to patch the sources
   as follows:

--- util-linux-2.11n-old/login-utils/setpwnam.c Mon Jul 31 08:50:39
2000
+++ util-linux-2.11n/login-utils/setpwnam.c     Wed Jun 12 21:37:12 2002
@@ -98,7 +98,8 @@
     /* sanity check */
     for (x = 0; x < 3; x++) {
        if (x > 0) sleep(1);
-       fd = open(PTMPTMP_FILE, O_WRONLY|O_CREAT, 0644);
+        // Never share the temporary file.
+       fd = open(PTMPTMP_FILE, O_WRONLY|O_CREAT|O_EXCL, 0644);
        if (fd == -1) {
            umask(oldumask);
            return -1;

Vendor Response:

   Please refer to CERT VU#405955 for more information.

Additional credits:

   Thanks to Chris Coffin and Mark Loveless for their contributions
   to this advisory.
(8785839) /Michal Zalewski <lcamtuf@coredump.cx>/(Ombruten)
Kommentar i text 8791696 av Andrew Pimlott <andrew@pimlott.net>
Kommentar i text 8792686 av Szemkel <eliandir@poczta.wp.pl>
8791696 2002-07-30 01:35 -0400  /57 rader/ Andrew Pimlott <andrew@pimlott.net>
Sänt av: joel@lysator.liu.se
Importerad: 2002-07-30  21:22  av Brevbäraren
Extern mottagare: Michal Zalewski <lcamtuf@coredump.cx>
Extern kopiemottagare: bugtraq@securityfocus.com
Mottagare: Bugtraq (import) <23364>
Kommentar till text 8785839 av Michal Zalewski <lcamtuf@coredump.cx>
Ärende: Re: RAZOR advisory: Linux util-linux chfn local root vulnerability
------------------------------------------------------------
From: Andrew Pimlott <andrew@pimlott.net>
To: Michal Zalewski <lcamtuf@coredump.cx>
Cc: bugtraq@securityfocus.com
Message-ID: <20020730053536.GF1593@pimlott.net>

On Mon, Jul 29, 2002 at 10:51:50AM -0400, Michal Zalewski wrote:
>    the administrator will most likely add "rm -f /etc/ptmp" or
>    equivalent to his crontab

If he is smart, he will check whether the file is open (eg with
fuser) before removing it.  So your attack does require an
administrator mistake.

However!  There appears to be an attack that does not require any
administrator action.

>     1. /etc/ptmptmp file is opened with O_WRONLY|O_CREAT, 0644 perms  
>     2. the file is linked to /etc/ptmp, exit on failure
>     3. /etc/ptmptmp is removed
> 
>    Later, the descriptor obtained in step 1 is used for writing to     
>    construct the new /etc/passwd contents. This is done line by line, by
>    calling the fputs() routine. When the new file is ready, three more
>    steps are taken:
> 
>     4. /etc/passwd.OLD is removed
>     5. /etc/passwd is linked to /etc/passwd.OLD
>     6. /etc/ptmp is renamed to /etc/passwd

    chfn 1              chfn 2              chfn 3

    open /etc/ptmptmp   open /etc/ptmptmp
    link -> /etc/ptmp
    rm /etc/ptmptmp
    fputs() ...
    mv -> /etc/passwd

At this point, chfn 2 has a fd open to /etc/passwd.

                                            open /etc/ptmptmp
                        ln -> /etc/ptmp
                        rm /etc/ptmptmp
                        fputs() ...

chfn 2 is now scribbling over /etc/passwd, and may at some point
create an "improved" password entry.

This is based on what Michal wrote; I haven't tested it.

>    step 3 ensures that no process will work on the hardlink of
>    /etc/passwd after the procedure is completed.

If what Michal wrote is complete, it does not.

Andrew
(8791696) /Andrew Pimlott <andrew@pimlott.net>/-----
Kommentar i text 8792214 av Michal Zalewski <lcamtuf@bos.bindview.com>
8792214 2002-07-30 09:59 -0400  /31 rader/ Michal Zalewski <lcamtuf@bos.bindview.com>
Sänt av: joel@lysator.liu.se
Importerad: 2002-07-30  23:59  av Brevbäraren
Extern mottagare: Andrew Pimlott <andrew@pimlott.net>
Extern kopiemottagare: bugtraq@securityfocus.com
Mottagare: Bugtraq (import) <23378>
Kommentar till text 8791696 av Andrew Pimlott <andrew@pimlott.net>
Ärende: Re: RAZOR advisory: Linux util-linux chfn local root vulnerability
------------------------------------------------------------
From: Michal Zalewski <lcamtuf@bos.bindview.com>
To: Andrew Pimlott <andrew@pimlott.net>
Cc: bugtraq@securityfocus.com
Message-ID: <Pine.LNX.4.42.0207300952550.4453-100000@nimue.bos.bindview.com>

On Tue, 30 Jul 2002, Andrew Pimlott wrote:

> If he is smart, he will check whether the file is open (eg with fuser)
> before removing it.  So your attack does require an administrator
> mistake.

Not really. The file does not have to be open to be present in the
system.  It is prefectly possible to leave a dangling root-owned file
several times, so that the administrator can do very little to
determine where it came from. The attack itself requires the file to
be open, but it can happen long after the administor started removing
this file routinely.

> However!  There appears to be an attack that does not require any
> administrator action.

Appears to be true, good point.

-- 
_____________________________________________________
Michal Zalewski [lcamtuf@bos.bindview.com] [security]
[http://lcamtuf.coredump.cx] <=-=> bash$ :(){ :|:&};:
=-=> Did you know that clones never use mirrors? <=-=
          http://lcamtuf.coredump.cx/photo/
(8792214) /Michal Zalewski <lcamtuf@bos.bindview.com>/(Ombruten)
Kommentar i text 8792259 av Andrew Pimlott <andrew@pimlott.net>
8792259 2002-07-30 10:48 -0400  /31 rader/ Andrew Pimlott <andrew@pimlott.net>
Sänt av: joel@lysator.liu.se
Importerad: 2002-07-31  00:11  av Brevbäraren
Extern mottagare: Michal Zalewski <lcamtuf@bos.bindview.com>
Extern kopiemottagare: bugtraq@securityfocus.com
Mottagare: Bugtraq (import) <23379>
Kommentar till text 8792214 av Michal Zalewski <lcamtuf@bos.bindview.com>
Ärende: Re: RAZOR advisory: Linux util-linux chfn local root vulnerability
------------------------------------------------------------
From: Andrew Pimlott <andrew@pimlott.net>
To: Michal Zalewski <lcamtuf@bos.bindview.com>
Cc: bugtraq@securityfocus.com
Message-ID: <20020730144831.GG1593@pimlott.net>

On Tue, Jul 30, 2002 at 09:59:36AM -0400, Michal Zalewski wrote:
> On Tue, 30 Jul 2002, Andrew Pimlott wrote:
> 
> > If he is smart, he will check whether the file is open (eg with fuser)
> > before removing it.  So your attack does require an administrator
> > mistake.
> 
> Not really. The file does not have to be open to be present in the system.
> It is prefectly possible to leave a dangling root-owned file several
> times, so that the administrator can do very little to determine where it
> came from.

Correct, but: the admin should still verify that it is not open
before deleting it (in his cron job).  IOW, when the file is present
but not open, the admin has no way to trace it, but at least
removing it is harmless.  When the file is present and open, the
clever admin will not only foil your exploit (by not removing the
file), but find the culprit (via fuser).

Maybe this is assuming too much prescience from the admin, but I
don't think so.  After all, an open /etc/ptmp could well be involved
in a legitimate chfn, and the admin wouldn't want to disrupt that.

Andrew
(8792259) /Andrew Pimlott <andrew@pimlott.net>/-----
Kommentar i text 8795563 av Andreas Beck <becka@uni-duesseldorf.de>
8795563 2002-07-31 09:11 +0200  /22 rader/ Andreas Beck <becka@uni-duesseldorf.de>
Sänt av: joel@lysator.liu.se
Importerad: 2002-07-31  18:56  av Brevbäraren
Extern mottagare: bugtraq@securityfocus.com
Mottagare: Bugtraq (import) <23398>
Kommentar till text 8792259 av Andrew Pimlott <andrew@pimlott.net>
Ärende: Re: RAZOR advisory: Linux util-linux chfn local root vulnerability
------------------------------------------------------------
From: Andreas Beck <becka@uni-duesseldorf.de>
To: bugtraq@securityfocus.com
Message-ID: <20020731091120.A1249@uni-duesseldorf.de>

Andrew Pimlott <andrew@pimlott.net> wrote:
> > > If he is smart, he will check whether the file is open (eg with fuser)
> > Not really. The file does not have to be open to be present in the system.
> > It is prefectly possible to leave a dangling root-owned file several
> > times, 
> Correct, but: the admin should still verify that it is not open
> before deleting it (in his cron job).  

As long as there is no atomic "check-if-file-is-open-and-if-not-delete-it"
this just makes exploitation harder by introducing another race condition.


CU, Andy

-- 
= Andreas Beck                    |  Email :  <becka@bedatec.de>             =
(8795563) /Andreas Beck <becka@uni-duesseldorf.de>/-
8792686 2002-07-30 12:12 +0200  /26 rader/ Szemkel <eliandir@poczta.wp.pl>
Sänt av: joel@lysator.liu.se
Importerad: 2002-07-31  07:05  av Brevbäraren
Extern mottagare: bugtraq@securityfocus.com
Mottagare: Bugtraq (import) <23389>
Kommentar till text 8785839 av Michal Zalewski <lcamtuf@coredump.cx>
Ärende: Re: RAZOR advisory: Linux util-linux chfn local root vulnerability
------------------------------------------------------------
From: Szemkel <eliandir@poczta.wp.pl>
To: bugtraq@securityfocus.com
Message-ID: <20020730101259.GA559@localhost.localdomain>

Michal Zalewski wrote:
>    The First instance of chfn is still holding an open descriptor to
>    /etc/ptmptmp, which later became /etc/ptmp - and, if we send SIGCONT
>    to this process, will be renamed to /etc/passwd. Step 3 will fall
>    through because there is no error checking, and new information will
>    be written into a descriptor that will de facto become /etc/passwd.
If I understand this correctly, ptmp and ptmptmp don't have anything to
do with passwd before this rename(ptmp, passwd) call? So, technique of
cutting second write of ptmp by killing first chfn process, will not
work, not in way you described. chfn 1 will still be working on ptmp,
and if you'll kill it, ptmp won't be renamed to passwd, so attack will
fail - you'll get modificated ptmp and untouched passwd.
But attack is still possible by sending SIGSTOP to second chfn before
rename(), writting part of data by first chfn, killing it, and getting
back to second chfn, which will rename ptmp to passwd.

I'm curious if you were able to reproduce this bug - race condition is
very strict here, I think real attack needs a lot of tries.

Szemkel
(8792686) /Szemkel <eliandir@poczta.wp.pl>/---------