发信人: saka.bbs@bbs.neu.edu.cn (机器猫), 信区: cnlinux
标  题: perl(20)
发信站: 白山黑水BBS (Wed Apr  2 17:38:50 1997)
转信站: Lilac!ustcnews!ustcnews!sjtunews!neubbs
出  处: conger.neu.edu.cn

--------------7EC61FF29F4
Content-Type: text/plain; charset=us-ascii; name="perlsec.txt"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="perlsec.txt"

NAME

perlsec - Perl security

---------------------------------------------------------------------------

DESCRIPTION

Perl is designed to make it easy to write secure setuid and setgid scripts.
Unlike shells, which are based on multiple substitution passes on each line
of the script, Perl uses a more conventional evaluation scheme with fewer
hidden ``gotchas''. Additionally, since the language has more built-in
functionality, it has to rely less upon external (and possibly
untrustworthy) programs to accomplish its purposes.

Beyond the obvious problems that stem from giving special privileges to
such flexible systems as scripts, on many operating systems, setuid scripts
are inherently insecure right from the start. This is because that between
the time that the kernel opens up the file to see what to run, and when the
now setuid interpreter it ran turns around and reopens the file so it can
interpret it, things may have changed, especially if you have symbolic
links on your system.

Fortunately, sometimes this kernel ``feature'' can be disabled.
Unfortunately, there are two ways to disable it. The system can simply
outlaw scripts with the setuid bit set, which doesn't help much.
Alternately, it can simply ignore the setuid bit on scripts. If the latter
is true, Perl can emulate the setuid and setgid mechanism when it notices
the otherwise useless setuid/gid bits on Perl scripts. It does this via a
special executable called suidperl that is automatically invoked for you if
it's needed.

If, however, the kernel setuid script feature isn't disabled, Perl will
complain loudly that your setuid script is insecure. You'll need to either
disable the kernel setuid script feature, or put a C wrapper around the
script. See the program wrapsuid in the eg directory of your Perl
distribution for how to go about doing this.

There are some systems on which setuid scripts are free of this inherent
security bug. For example, recent releases of Solaris are like this. On
such systems, when the kernel passes the name of the setuid script to open
to the interpreter, rather than using a pathname subject to mettling, it
instead passes /dev/fd/3. This is a special file already opened on the
script, so that there can be no race condition for evil scripts to exploit.
On these systems, Perl should be compiled with
-DSETUID_SCRIPTS_ARE_SECURE_NOW. The Configure program that builds Perl
tries to figure this out for itself.

When executing a setuid script, or when you have turned on taint checking
explicitly using the -T flag, Perl takes special precautions to prevent you
from falling into any obvious traps. (In some ways, a Perl script is more
secure than the corresponding C program.) Any command line argument,
environment variable, or input is marked as ``tainted'', and may not be
used, directly or indirectly, in any command that invokes a subshell, or in
any command that modifies files, directories, or processes. Any variable
that is set within an expression that has previously referenced a tainted
value also becomes tainted (even if it is logically impossible for the
tainted value to influence the variable). For example:

    $foo = shift;               # $foo is tainted
    $bar = $foo,'bar';          # $bar is also tainted
    $xxx = <>;                  # Tainted
    $path = $ENV{'PATH'};       # Tainted, but see below
    $abc = 'abc';               # Not tainted
    system "echo $foo";         # Insecure
    system "/bin/echo", $foo;   # Secure (doesn't use sh)
    system "echo $bar";         # Insecure
    system "echo $abc";         # Insecure until PATH set
    $ENV{'PATH'} = '/bin:/usr/bin';
    $ENV{'IFS'} = '' if $ENV{'IFS'} ne '';
    $path = $ENV{'PATH'};       # Not tainted
    system "echo $abc";         # Is secure now!
    open(FOO,"$foo");           # OK
    open(FOO,">$foo");          # Not OK
    open(FOO,"echo $foo|");     # Not OK, but...
    open(FOO,"-|") || exec 'echo', $foo;        # OK
    $zzz = `echo $foo`;         # Insecure, zzz tainted
    unlink $abc,$foo;           # Insecure
    umask $foo;                 # Insecure
    exec "echo $foo";           # Insecure
    exec "echo", $foo;          # Secure (doesn't use sh)
    exec "sh", '-c', $foo;      # Considered secure, alas

The taintedness is associated with each scalar value, so some elements of
an array can be tainted, and others not.

If you try to do something insecure, you will get a fatal error saying
something like ``Insecure dependency'' or ``Insecure PATH''. Note that you
can still write an insecure system call or exec, but only by explicitly
doing something like the last example above. You can also bypass the
tainting mechanism by referencing subpatterns--Perl presumes that if you
reference a substring using $1, $2, etc, you knew what you were doing when
you wrote the pattern:

    $ARGV[0] =~ /^-P(\w+)$/;
    $printer = $1;              # Not tainted

This is fairly secure since \w+ doesn't match shell metacharacters. Use of
/.+/ would have been insecure, but Perl doesn't check for that, so you must
be careful with your patterns. This is the ONLY mechanism for untainting
user supplied filenames if you want to do file operations on them (unless
you make $> equal to $< ).

For ``Insecure $ENV{PATH}'' messages, you need to set $ENV{'PATH'} to a
known value, and each directory in the path must be non-writable by the
world. A frequently voiced gripe is that you can get this message even if
the pathname to an executable is fully qualified. But Perl can't know that
the executable in question isn't going to execute some other program
depending on the PATH.

It's also possible to get into trouble with other operations that don't
care whether they use tainted values. Make judicious use of the file tests
in dealing with any user-supplied filenames. When possible, do opens and
such after setting $> = $<. (Remember group IDs, too!) Perl doesn't prevent
you from opening tainted filenames for reading, so be careful what you
print out. The tainting mechanism is intended to prevent stupid mistakes,
not to remove the need for thought.

This gives us a reasonably safe way to open a file or pipe: just reset the
id set to the original IDs. Here's a way to do backticks reasonably safely.
Notice how the exec() is not called with a string that the shell could
expand. By the time we get to the exec() , tainting is turned off, however,
so be careful what you call and what you pass it.

    die unless defined $pid = open(KID, "-|");
    if ($pid

--------------7EC61FF29F4--

--
※ 来源:.白山黑水站 bbs.neu.edu.cn.[FROM: ygh@rose.dlut.edu.cn]
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:2.275毫秒