Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 15 Apr 1998 21:01:45 -0400 (EDT)
From:      Robert Watson <robert@cyrus.watson.org>
To:        freebsd-security@FreeBSD.ORG
Subject:   securelevels and more liberal use of schg on system files (fwd)
Message-ID:  <Pine.BSF.3.96.980415210113.29364I-100000@fledge.watson.org>

next in thread | raw e-mail | index | archive | help

(resend due to stuttering mailing lists :)

---------- Forwarded message ----------
Date: Tue, 7 Apr 1998 17:29:10 -0400 (EDT)
From: Robert Watson <robert@cyrus.watson.org>
Reply-To: Robert Watson <robert+freebsd@cyrus.watson.org>
To: security@freebsd.org
Subject: securelevels and more liberal use of schg on system files (fwd)


The following discussion of securelevels is the result of some
experimentation and largely consists of brainstorming, but might make for
some interesting discussion (if other people find it interesting :).
BSD/OS and others make use of securelevels in their production releases to
prevent time rewinds, etc.  It may be desirable that FreeBSD do so in the
future.  Currently, however, securelevels do little if anything to
actually increase the security of a system.  I think this can be improved
through some careful thinking out of the issues, and would like to see
this happen in FreeBSD. :)  All experimentation was performed on
2.2-STABLE a few days ago.

--

Through securelevels, FreeBSD can be hardened against a root compromise --
securelevel >= 2 prevents (short list):

1) Modification of init that might result in the securelevel being lowered
   (via ptrace, procfs)
2) Writing to /dev/kern-type files where kernel modifications could be
   used to lower the securelevel
3) Prevent writing to character and block devices for mountable hard
   drives, etc, that might be used to modify the kernel on disk, etc.
4) securelevel can only be raised, never lowered using sysctl
5) the schg, sappnd and sunlnk flags are now enforced for uid 0

(also, other behavior depending on the file system, syscalls, etc)

Additionally, make installworld applies the schg flag to a few key files
to prevent modification that might result on problems going to single-user
mode, or next boot:

/kernel			# technically during install of kernel
/bin/rcp
/sbin/init
/usr/sbin/sliplogin
/usr/bin/chfn
/usr/bin/chpass
/usr/bin/chsh
/usr/bin/crontab
/usr/bin/login
/usr/bin/man
/usr/bin/passwd
/usr/bin/rlogin
/usr/bin/rsh
/usr/bin/su
/usr/bin/ypchfn
/usr/bin/ypchpass
/usr/bin/ypchsh
/usr/bin/yppasswd
/usr/lib/libc.so.3.1
/usr/lib/libcipher.so.2.0
/usr/lib/libdescrypt.so.2.0
/usr/libexec/ld.so
/usr/libexec/mail.local

There may be others, but I have not found them in my cursory search.  It
is now useful to observe how it is we get into a non- -1 securelevel.  The
man page init(8) makes the following recommendation:

     If the security level is initially -1, then init leaves it unchanged.
     Otherwise, init arranges to run the system in level 0 mode while
     single user and in level 1 mode while multiuser.  If level 2 mode is
     desired while running multiuser, it can be set while single user,
     e.g., in the startup script /etc/rc, using sysctl(8).

Note that it is not init(8) itself that performs the sysctl activity, but
rather the rc(8) script.  In a sense, it cannot be init(8), as the rc(8) 
script later runs fsck(8) to clean the file systems, and it requires write
access to the block devices.  However, this does leave us with a few
problems.  Neither /etc/rc nor /usr/sbin/sysctl are protected by schg. 
For that matter, neither is fsck, or any number of utilities used by rc(8)
prior to being able to raise the securelevel.  While some of the above
files clearly deserve to be schg, there do appear to be a few interlopers
(passwd? :) on the domain of the carefully protected.

thithle:/# sysctl kern.securelevel
kern.securelevel: 2
thithle:/# cp /bin/echo /usr/sbin/sysctl

or better,

thithle:/# cp ~hacked/rc /etc/rc


Additionally, while we notice that the files are protected against
modification (and links to them), the directories are *NOT*.  /sbin/init
is schg, but the directory /sbin is not!  Similarly with all of the other
non-/ files (i.e., all but /kernel).  To replace init(8) at the next boot,
I can happily do the following:

thithle:/# mv /sbin /sbinsbin
thithle:/# mkdir /sbin
thithle:/# cp /sbinsbin/* /sbin
thithle:/# cp ~hacked/myinit /sbin/init
thithle:/# reboot

schg does prevent modifications to init(8) that might result in paging in
replacement pages of text into the current init, but not against actions
over reboot.

One response to the problem of key binaries in / and /etc is to mount the
root partition (and /etc) as read-only devices instead of read-write. 
However, securelevel does not prevent the remounting of devices as
read-write from an initial read-only state: 

thithle:/# grep wd0s1a /etc/fstab
/dev/wd0s1a             /               ufs     ro              1       1
thithle:/# mount
/dev/wd0s1a on / (local, read-only)
...
thithle:/# mount -o rwd /
thithle:/# mount
/dev/wd0s1a on / (local)
...
thithle:/#

So there are some fairly severe problems with the current behavior of
FreeBSD with securelevel in use.  Just to sumarize:

1) The set of files installed with schg is not sufficient for any
environment where file systems containing binaries are writable by
software (i.e., not a CD-ROM or a write-protected floppy).  Even though
some of the required files are protected, their directories are not
protected in the default install.  Default installs probably do not
benefit from having so many key directories (/usr/lib, /sbin, /etc) be
schg, but if securelevels are to be used, it must be published that they
cannot just be "turned on" as described in init(8).

2) A read-only mount can be converted into a read-write mount without any
prevention of the kernel.  With the use of chroot(8), life can be made
much harder for the uid 0 user when it comes to modifying key system
files.  However, through creation of device nodes (which is permitted in
securelevel>=2) in mfs partitions, it may be possible to break out and
remount / read-write.  The current policy for mounting/umounting
partitions in high securelevels may not be adequate, given the desire to
protect key system directories against attacks over a reboot.

3) Unmentioned above, the init search path in the kernel actual attempts
to run a series of possible programs:

init_main.c:
  /*
   * List of paths to try when searching for "init".
   */
  static char *initpaths[] = {
          "/sbin/init",
          "/sbin/oinit",
          "/sbin/init.bak",
          "/stand/sysinstall",
          NULL,
  };

Even the ability to move /sbin/init out of the way in any form is
dangerous -- let alone replacing it.

While the kernel is effective at protecting against its securelevel being
lowered in the course of a particular boot/running time, FreeBSD is
currently extremely succeptible to manipulation of its configuration files
and key binaries.  Similarly, the possibility of embedding a trojan in any
number of standard UNIX utilities (inclding /stand/sysinstall) makes the
system entirely untrustworthy even in single-user mode.  The promise of
schg/securelevels can only be kept if all instances of binaries executed
while in a lower securelevel (i.e., in boot and in single-user mode) are
protected against execution in lower securelevels (multi-user mode).

Recommendations: Reconsider the ability to mount anything but nodev/nosuid
partitions under securelevel>=2.  Give thought to the issue of readonly
mounts, and possibly how to protect against remounting readwrite
(especially for /).  Perhaps provide a fascistflags utility that makes all
key binaries and directories schg.  Also, notes indicating that the
current securelevel behavior recommended in init(8) is not sufficient.

As a side note, it is interesting that make buildworld installs files as
schg in the binary tree it builds.  This seems highly inappropriate -- the
flags should only be set on an installworld!  Otherwise make clean will
not work on a securelevel>=1 system, so builds cannot be repeated in the
same tree without dropping to a lower securelevel to clean the tree.
installworld clearly requires a low securelevel, but often build machines
are not the same as user machines.

I am also interested to know why such an interesting array of commands is
schg -- for example, there is no reason why passwd(1) should be schg that
I can think of.  Either way it aquires root access, or uses NIS.  A uid-0
user could easily compile there own.  Presumably this is to allow
passwords to be changed safely after a penetration; this idea is probably
bogus.

Incidently, init(8) attempts to lower the securelevel when going out of
multi-user mode on a shutdown.  It cannot succeed in doing this with the
current implementation, as it is not possible to lower the securelevel.
However, if it were, we would also be in bad shape -- processes do not
necessarily die on the transition to single user mode (if blocked on a
resource, for example) -- if init(8) successfully lowered the securelevel,
this process would now retain uid 0, but be running in a normal
securelevel, allowing it to modify schg files, etc.  Since this doesn't
work, this is actually OK.  init(8) does have some misconceptions, though
:-).

  Robert N Watson 


----
Carnegie Mellon University  http://www.cmu.edu/
Trusted Information Systems http://www.tis.com/
SafePort Network Services   http://www.safeport.com/
robert@fledge.watson.org    http://www.watson.org/~robert/




To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe security" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.3.96.980415210113.29364I-100000>