Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 25 Dec 1998 00:06:46 -0500 (EST)
From:      Robert Watson <robert@cyrus.watson.org>
To:        Barrett Richardson <brich@aye.net>
Cc:        Casper <casper@acc.am>, "freebsd-security@FreeBSD.ORG" <freebsd-security@FreeBSD.ORG>
Subject:   Re: Magic
Message-ID:  <Pine.BSF.3.96.981224235402.22485A-100000@fledge.watson.org>
In-Reply-To: <Pine.BSF.3.96.981224161747.26595A-100000@phoenix.aye.net>

next in thread | previous in thread | raw e-mail | index | archive | help
On Thu, 24 Dec 1998, Barrett Richardson wrote:

> On Fri, 25 Dec 1998, Casper wrote:
> 
> > Did anyone tried to cjange loader's MAGIK in the exec's header and recompile
> > system ... I think it'll disallow to upload some executable and run it on target
> > system ......
> > So if you have recompiled system , chrooting all your network services - from
> > telnetd till httpd, ftpd & etc. , dont place compiler, mknod in chrooted dirs
> > and disallow reading of executable files ..only --x , how intruder can break
> > this protection ?
> > Of course i assume that system configured properly ......
> 
> I used a different means to the same end. I used a flag bit that
> can only be set by root and require it to be set in imgact_aout.c,
> imgact_elf.c and imgact_gzip.c for non root users. Wrote a util
> to set the flag on files in /bin, /sbin, /usr/{bin,sbin},
> /usr/libexec, /usr/local/{bin,sbin}. Used the same return code
> for a bad magic number. Whenever you try to execute a binary
> that doesn't have the flag set it spits out "cannot execute
> binary file". A user can even copy a system binary to his directory,
> and the copy won't run -- and only root can set the flag to make it
> run. Got the idea from John Dyson.
> 
> I have been thinking of incorporating the behaviour into one of the
> securelevels on my system.

The problem with limitations on execve() are that it is very hard to tell
when a file is exec'd :).  The execve() syscall is only one possible way
in which code can become executable (that is, might end up in the path of
execution, and in a process that might execute it).  Some examples might
be--

- Perl (or any other interpretter) interpretters, especially those with
  optimization
- Shells with scripting
- Php3 support in apache
- Buffer overflows in any executable (not just suid ones)
- elisp in emacs
- Dynamically linked applications
- Debugging support

The old LD_LIBRARY_PATH trick plays on the last one, but the ability to
change the shared library linked against is essentially equivilent to
being able to create an executable.  Being able to attach with a debugger
might also be equivilent, if you can change mappings on the processes
address space, manipulate registers, code ordering, etc.  I.e., you can
attach a debugger to joe process and cause it to act however you want just
by moving the instruction pointer around appropriately and single-stepping
it with argument modifications to syscalls.  Needless to say, any debugger
that couldn't do this wouldn't be very useful :).

As a simple example, I spent last night writing some simple trust analysis
modifications to my FreeBSD kernel on one of my notebooks.  I added a
bunch of hooks around execve, chmod, etc, to monitor

a) Execution of binaries owned by another user, or by a group if the file
   is group writable
b) Creation, deletion of setuid binaries
c) Modification of ownership, interesting file modes

Etc.  That is, interesting situations from the point of view of a formal
trust model.  I then added a syscall to pull down the stored records on
demand from the kernel.  I'll post the results in a few days.  But an
immediate conclusion was that most of the executable code on the system is
not executed using execve() :).  Much of it is shell script executed as an
argument to the interpretter, instead of via the execve interpretter
support.  Similarly, much is dynamically linked.  When you log in, the
shell goes out and runs all kinds of scripts--none of this is visible via
execve.  Similarly, insertion of code via buffer overflow is invisible to
monitoring at that level.

To really crack down on this behavior, you'd have to:

1) remove dynamic linking against anything but strictly approved code
2) not allow any manipulation of a process except through io
(specifically, not via a debugger where the instruction pointer can be
manipulated to cause it to jump around syscalls, modify arguments, etc)
3) know that all programs do exactly what you want, and never anything
else (i.e., no interpretters, no exploitable programs, etc).

I have concluded that it is essentially impossible to gain any serious
protection by restricting the binaries that may be run on the system.  The
only good approach is through proper access control on syscalls, strong
authentication, and adequate protection of process resources.

On the other hand, signed executables or a chflag flag will confuse the
hell out of joe hacker if joe hacker is really joe script-kiddie. :-)
I'm not above confusing script kiddies, but I think this flag may not
actually improve security, just perceived security without significant
modification of the OS.

  Robert N Watson 

robert@fledge.watson.org              http://www.watson.org/~robert/
PGP key fingerprint: 03 01 DD 8E 15 67 48 73  25 6D 10 FC EC 68 C1 1C

Carnegie Mellon University            http://www.cmu.edu/
TIS Labs at Network Associates, Inc.  http://www.tis.com/
SafePort Network Services             http://www.safeport.com/


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-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.981224235402.22485A-100000>