1. 'you gotta change the code'
This one is obvious; people must change their SUID programs'
source code to avoid nasty things like gets() sprintf() strcat() and
strcpy() using things like fgets() strncat() strncpy() as substitutes.
(there are many more 'problem' functions, i'm only listing a few here).
Any unbounded byte copying is suspect to buffer overruns, and needs to
be examined and changed. The drawbacks are obvious, thousands of lines
of source need to be changed/examined, re-written. However, many people
agree that this is the "right/proper/only" way to insure SUID 0 programs
are not exploited. Do we have a comprehensive list of function calls to
avoid, and suitable replacements? Spaf has some listed in Chapter 23 of
O'Reilly's 'Practical UNIX and Internet Security'. what we need is a
comprehensive list of functions, substitutions and guidelines to to
distribute to programmers. Anyone maintain such a list, or a list of
SUID programming guidelines?
Commercial products such as CodeCenter, or Pruify also
(supposedly) can help you catch buffer overflows. Anyone have opinions
about these? There's also Brian Marick's GCT (Generic Coverage Tool)
(ftp://ftp.cs.uiuc.edu/pub/misc/testing/) that's supposed to do similar
things, but has the advantage that it's distributed under the terms of
the GPL.
2. 'hmm. what if you change the compiler?'
C compilers could be modified to do bounds checking, and/or
problem functions could be made to complain to the user at compile time.
One implementation of bounds checking into C was done by Richard Jones
and Paul Kelly at Imperial College in July 1995.
(http://www-ala.doc.ic.ac.uk/~phjk/BoundsChecking.html)
Their patches to gcc are available in source and binary form
(ftp://dse.doc.ic.ac.uk/pub/misc/bcc/) for Linux, HPUX and SunOS &
Solaris. After such modifications to the compiler, the resulting code
is slower (which makes sense, because it now has to do a lot more to
look after itself) Furthermore, I can see the coming holy wars/flame
wars if the bcc patches were adopted widely, "C is supposed to be
simple, flexible and fast, it's not SUPPOSED to do bounds checking" (see
the "at the risk of another flamefest.." thread from BUGTRAQ, summer '96
(http://geek-girl.com/bugtraq/1996_3/index.html#60). IMHO, we want the
reliability and security if bounds checking in, say, ADA, but we don't
want to transform C into ADA! :) Can we simply write off these type of
patches/additions to C and its compilers as "incorrect/bad ideas"?
3. 'ok, what about the CPU/OS kernel stack exec permission?'
What about stopping the buffer overflow problem at the kernel
level? This might mean that you wouldn't have to inspect thousands of
lines of code, rebuild gcc, or recompile anything except the kernel.
Sounds nice, doesn't it.. well...
This has been a favorite one lately on BUGTRAQ and has come up a
few times on the linux-kernel mailing list. Solar Designer's recent
patches to the Linux kernel to remove stack exec permission, posted to
this list earlier this month, raised some interesting questions about
the buffer overflow problem, and how it can be implemented into an OS,
as well and the problems and dangers of doing this. In terms of Linux,
this type of patch has the danger of breaking things that use
"trampoline functions"(gcc & glibc), high level lisp interpreters,
objective C. Furthermore, returning from a signal requires an
executable stack (in Linux, anyways).. Workarounds for these problems
introduce new problems (buffer overflows in signal handlers?) and may
not be a suitable solution? I am assuming there are similar problems in
implementing this under other operating systems?
If BUGTRAQ readers are sick of discussing this, drop me some mail..
-- -Nate Smith <nate@millcomm.com> | http://millcomm.com/~nate/