In message [EMAIL PROTECTED], Wietse Venema write
s:
It is interesting to see that old problems with set-uid commands
keep coming back. Allow me to speed up the discussion a bit by
enumerating a few other channels for attack on set-uid commands.
A quick perusal of /usr/include/sys/proc.h reveals a large number
of inputs that a child process may inherit from a potentially
untrusted parent process.
The list includes, but is not limited to:
command-line array
environment array
open files
current directory
blocked/enabled signals
pending timers
resource limits
scheduling priority
All these sources of data can be, and have been, involved in attacks
on set-uid or set-gid commands (although I do not remember specific
details of pending timer attacks).
Indeed. With Henry's permission, I'm reposting his 1987 man page on
writing setuid programs.
---
..TH SETUID 7 local
..DA 21 Feb 1987
..SH NAME
setuid \- checklist for security of setuid programs
..SH DESCRIPTION
Writing a secure setuid (or setgid) program is tricky.
There are a number of possible ways of subverting such a program.
The most conspicuous security holes occur when a setuid program is
not sufficiently careful to avoid giving away access to resources
it legitimately has the use of.
Most of the other attacks are basically a matter of altering the program's
environment in unexpected ways and hoping it will fail in some
security-breaching manner.
There are generally three categories of environment manipulation:
supplying a legal but unexpected environment that may cause the
program to directly do something insecure,
arranging for error conditions that the program may not handle correctly,
and the specialized subcategory of giving the program inadequate
resources in hopes that it won't respond properly.
..PP
The following are general considerations of security when writing
a setuid program.
..de P
..nr x \\w'\(sq'u+1n
..TP \\nxu
\(sq
...
..P
The program should run with the weakest userid possible, preferably
one used only by itself.
A security hole in a setuid program running with a highly-privileged
userid can compromise an entire system.
Security-critical programs like
..IR passwd (1)
should always have private userids, to minimize possible damage
from penetrations elsewhere.
..P
The result of
..I getlogin
or
..I ttyname
may be wrong if the descriptors have been meddled with.
There is
..I no
foolproof way to determine the controlling terminal
or the login name (as opposed to uid) on V7.
..P
On some systems (not ours), the setuid bit may not be honored if
the program is run by
..IR root ,
so the program may find itself running as
..IR root .
..P
Programs that attempt to use
..I creat
for locking can foul up when run by
..IR root ;
use of
..I link
is preferred when implementing locking.
Using
..I chmod
for locking is an obvious disaster.
..P
Breaking an existing lock is very dangerous; the breakdown of a locking
protocol may be symptomatic of far worse problems.
Doing so on the basis of the lock being `old' is sometimes necessary,
but programs can run for surprising lengths of time on heavily-loaded
systems.
..P
Care must be taken that user requests for i/o are checked for
permissions using the user's permissions, not the program's.
Use of
..I access
is recommended.
..P
Programs executed at user request (e.g. shell escapes) must
not receive the setuid program's permissions;
use of daughter processes and
..I setuid(getuid())
plus
..I setgid(getgid())
after
..I fork
but before
..I exec
is vital.
..P
Similarly, programs executed at user request must not receive other
sensitive resources, notably file descriptors.
Use of
..IR closeall (3)
or close-on-exec arrangements,
on systems which have them,
is recommended.
..P
Programs activated by one user but handling traffic on behalf of
others (e.g. daemons) should avoid doing
..IR setuid(getuid())
or
..IR setgid(getgid()) ,
since the original invoker's identity is almost certainly inappropriate.
On systems which permit it, use of
..I setuid(geteuid())
and
..I setgid(getegid())
is recommended when performing work on behalf of the system as
opposed to a specific user.
..P
There are inherent permission problems when a setuid program executes
another setuid program,
since the permissions are not additive.
Care should be taken that created files are not owned by the wrong person.
Use of
..I setuid(geteuid())
and its gid counterpart can help, if the system allows them.
..P
Care should be taken that newly-created files do not have the wrong
permission or ownership even momentarily.
Permissions should be arranged by using
..I umask
in advance, rather than by creating the file wide-open and then using
..IR chmod .
Ownership can get sticky due to the limitations of the setuid concept,
although using a daughter process connected by a pipe can help.
..P
Setuid programs should be especially careful about error checking,
and the normal response to a strange situation should be termination,