📄 ch11.htm
字号:
<HTML>
<HEAD>
<TITLE>Chapter 11 -- Security Issues in Perl </TITLE>
<META NAME="GENERATOR" CONTENT="Mozilla/3.0b5aGold (WinNT; I) [Netscape]">
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#CE2910">
<H1><FONT COLOR=#FF0000>Chapter 11</FONT></H1>
<H1><B><FONT SIZE=5 COLOR=#FF0000>Security Issues in Perl </FONT></B>
</H1>
<P>
<HR WIDTH="100%"></P>
<P>
<H3 ALIGN=CENTER><FONT COLOR="#000000"><FONT SIZE=+2>CONTENTS<A NAME="CONTENTS"></A>
</FONT></FONT></H3>
<UL>
<LI><A HREF="#AFewWordsBeforeWeBegin" >A Few Words Before We Begin</A>
<LI><A HREF="#SetuidScripts" >Setuid Scripts</A>
<LI><A HREF="#WhyIsPerlMoreSecure" >Why Is Perl More Secure Than Shell Scripts?</A>
<LI><A HREF="#SomeTipsonMakingScriptsSecure" >Some Tips on Making Scripts Secure</A>
<LI><A HREF="#ThePerlSafepmModule" >The Perl Safe.pm Module</A>
<UL>
<LI><A HREF="#UsingtheSafeClass" >Using the Safe Class</A>
</UL>
<LI><A HREF="#SetuidCGIScriptsandCGIwrap" >Setuid CGI Scripts and CGIwrap</A>
<LI><A HREF="#ReferenceBooks" >Reference Books</A>
<LI><A HREF="#Summary" >Summary</A>
</UL>
<HR>
<P>
This chapter addresses the security issues involved in writing
Perl scripts. Topics addressed in this chapter include writing
<TT><FONT FACE="Courier">setuid</FONT></TT> programs, tainted
variables, and using existing modules for use with Internet applications.
<H2><A NAME="AFewWordsBeforeWeBegin"><FONT SIZE=5 COLOR=#FF0000>A
Few Words Before We Begin</FONT></A></H2>
<P>
I feel like Chicken Little when discussing potential security
problems with Perl scripting. The potential problems discussed
here are hard to have all reside on one system. Also, a hacker
has to be really interested in your system (and malicious enough)
to really want to blow it away. However, being paranoid is better
than being lax about security, and having that one little hole
can cause you to lose your hard disk. There are a few weirdos
out there who get a kick out of obliterating other folks' data.
Sometimes exceedingly bright people commit the most idiotic acts.
<P>
Chances are that you'll not get hit, but a few precautionary steps
will not hurt. If you are a system administrator for a large institution
or university, your job is especially hard. The greater the number
of users on your system, the more likely you are to find someone
attempting to break into your system. There are some things you
can do such as running a <TT><FONT FACE="Courier">find</FONT></TT>
command every day to check whether there are <TT><FONT FACE="Courier">setuid</FONT></TT>
executable scripts on your system's <TT><FONT FACE="Courier">/home</FONT></TT>
directory. Please check the references at the end of this chapter
for books with more information about keeping your site secure.
<P>
Finally, this chapter is slanted towards Perl and CGI applications
using UNIX. More problems exist with C programs, daemons, and
so on with buffer overruns. Some reported problems even include
harmful results such as wiping a disk clean when you download
a PostScript file. For example, David Bonn reported in the <I>Linux
Journal</I> that downloading a Crusty the Clown PostScript image
wiped his hard disk clean. The offending commands were part of
a buffer overrun in his PostScript viewer.
<P>
I will get off the soapbox now.
<H2><A NAME="SetuidScripts"><TT><FONT SIZE=5 COLOR=#FF0000 FACE="Courier">Setuid</FONT></TT><FONT SIZE=5 COLOR=#FF0000>
Scripts</FONT></A></H2>
<P>
A <TT><FONT FACE="Courier">setuid</FONT></TT> script runs at the
level of the owner, not the calling program. In other words, if
a script has its <TT><FONT FACE="Courier">suid</FONT></TT> bit
set, it runs as root, even if it is being called by a non-root
program. In almost all cases, <TT><FONT FACE="Courier">setuid</FONT></TT>
scripts are bad news, a big security hole, and potentially dangerous
for your system. Most administrators write <TT><FONT FACE="Courier">setuid</FONT></TT>
scripts when they want to grant limited access to secure files
or devices. In most cases, these scripts are not necessary, and
in my humble opinion, should be written as compiled programs.
<P>
Calling scripts from within programs running as root is a very
big security hole in any system. For example, let's say a program
running as root calls a Perl script called <TT><FONT FACE="Courier">diskme.pl</FONT></TT>
in the <TT><FONT FACE="Courier">/usr/bin</FONT></TT> directory,
or worse, in an area that is accessible by users other than root.
When the program running as root executes <TT><FONT FACE="Courier">diskme.pl</FONT></TT>,
the code in <TT><FONT FACE="Courier">diskme.pl</FONT></TT> is
also run with root privileges. If the <TT><FONT FACE="Courier">diskme.pl</FONT></TT>
has permissions that allow it to be edited or overwritten, hackers
could write their own version of <TT><FONT FACE="Courier">diskme.pl</FONT></TT>
and place it where the root program expects it to be. When the
original root program calls <TT><FONT FACE="Courier">diskme.pl</FONT></TT>,
it will execute the rogue program instead of the original one.
<P>
One common way to avoid problems like this one is to use absolute
pathnames instead of relative pathnames. Using relative pathnames
opens your <TT><FONT FACE="Courier">setuid</FONT></TT> script
to unsafe links to rogue files. An absolute path defines a complete
path to the executable program. For example, <TT><FONT FACE="Courier">/home/khusain/scripts/test.pl</FONT></TT>
will always run the program <TT><FONT FACE="Courier">test.pl</FONT></TT>
in the <TT><FONT FACE="Courier">/home/khusain/scripts</FONT></TT>
directory. The forward slash (/) in the pathname is used to specify
the complete pathname. If the forward slash were left out, that
is, the name of the program was specified as <TT><FONT FACE="Courier">home/khusain/scripts/test.pl</FONT></TT>,
the program loads <TT><FONT FACE="Courier">test.pl</FONT></TT>
from a subdirectory under <TT><FONT FACE="Courier">./home/khusain/scripts</FONT></TT>.
Thus, it uses a path relative to its current location. It would
be easy to move the privileged program that calls the <TT><FONT FACE="Courier">test.pl</FONT></TT>
file over to another directory, create a subdirectory path <TT><FONT FACE="Courier">home/khusain/scripts</FONT></TT>
in this new location and place my own version of <TT><FONT FACE="Courier">test.pl</FONT></TT>
in there. Now the privileged program will call my version of <TT><FONT FACE="Courier">test.pl</FONT></TT>!
<P>
Another route to take for security reasons is to minimize the
time required to be root. Just because your script has to access
some portions of some data as root does not mean that the entire
application has to run as root. Just make a small, difficult-to-alter
Perl script that runs as root and leave the rest in an unprivileged
script.
<P>
Let me reiterate once more: <TT><FONT FACE="Courier">setuid</FONT></TT>
scripts are insecure. Regardless of how many precautions you take,
having a Perl script that may be influenced by its environment
is asking for trouble. If you can avoid writing <TT><FONT FACE="Courier">setuid</FONT></TT>
scripts, do so.
<H2><A NAME="WhyIsPerlMoreSecure"><FONT SIZE=5 COLOR=#FF0000>Why
Is Perl More Secure Than Shell Scripts?</FONT></A></H2>
<P>
Perl inherently has more features than most shells such as Bourne,
Korn, or Bash. Network, file system manipulation and binary file
access features built into Perl have to be mimicked through the
use of other external programs in shell scripts. When the <TT><FONT FACE="Courier">setuid</FONT></TT>
shell calls these external programs, they are opened to potential
problems because external programs can be replaced with less secure
imitations. Perl does not use such external programs because the
features required by Perl are built into itself. This would lead
you to think that Perl scripts are more secure than shell scripts.
On the contrary, Perl is not as secure as you think it is. Read
on.
<P>
First of all, use the <TT><FONT FACE="Courier">use strict;</FONT></TT>
statement whenever possible in your Perl scripts. Using the <TT><FONT FACE="Courier">strict</FONT></TT>
pragma forces Perl to do strict type checking, prevents strings
from becoming variables, and points out any dangling variables.
Using <TT><FONT FACE="Courier">strict</FONT></TT> forces you to
use the <TT><FONT FACE="Courier">my</FONT></TT> keyword when declaring
local variables. This, in turn, limits the scope of declared variables
from being destroyed accidentally by other subroutines in the
system.
<P>
Even without strict type checking, the Perl interpreter is more
efficient and security conscious than a shell. Shell script lines
are parsed more times per line than are lines of code in a Perl
script. Perl code can be further tightened to check for potential
problems or funny use of references by enabling the <TT><FONT FACE="Courier">-w</FONT></TT>
switch at the command line for the Perl interpreter. (The <TT><FONT FACE="Courier">-w</FONT></TT>
switch turns on warnings.)
<P>
Perl also supports the use of and recognizes "tainted"
variables. In Perl, any command-line argument, environment variable,
or input explicitly marked as tainted will not be used in subshells.
Tainted variables cannot be used in any commands that modify the
file and dir-ectory structure on the client on which the application
happens to be running. In fact, if a new value is derived from
a tainted value, the new value is also marked as tainted. This
way tainted variables cannot create a non-tainted variable. Once
a bad egg, always a bad egg! No mercy here.
<P>
Also, the "taintedness" of a variable is applied on
a Perl scalar basis. Arrays and hashes can contain both tainted
and untainted variables at one time. Perl checks for improper
use of tainted variables if the <TT><FONT FACE="Courier">-T</FONT></TT>
flag is set. So when in doubt, run with the <TT><FONT FACE="Courier">-T</FONT></TT>
option. Your header comment line will then look like this:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">#!/usr/local/bin/perl -T</FONT></TT>
</BLOCKQUOTE>
<P>
Here's a checklist to use to see whether a variable is tainted.
If you answer even one <I>yes</I> to any of the following questions,
the variable is most likely tainted:
<UL>
<LI><FONT COLOR=#000000>Was this variable passed in from the command
line?</FONT>
<LI><FONT COLOR=#000000>Was this variable set to a value passed
in from the command line?</FONT>
<LI><FONT COLOR=#000000>Is this value read directly from the command
line or a file handle?</FONT>
<LI><FONT COLOR=#000000>Is this value read directly from an environment
variable?</FONT>
<LI><FONT COLOR=#000000>Is this variable set from a variable whose
value was read directly from the command line or a file handle?</FONT>
<LI><FONT COLOR=#000000>Has the </FONT><TT><FONT FACE="Courier">PATH</FONT></TT>
been set to a known value before this value was set?
<LI><FONT COLOR=#000000>Was an external program used in determining
the value of this variable? That is, was this variable set by
a call like this one: </FONT><TT><FONT FACE="Courier">$name =
`cat $hokeyfilename`;</FONT></TT>?
<LI><FONT COLOR=#000000>Was there any system call to </FONT><TT><FONT FACE="Courier">unlink</FONT></TT>,
<TT><FONT FACE="Courier">umask</FONT></TT>, or overwrite files?
<LI><FONT COLOR=#000000>Was there any complete command between
single quotes? For example, using </FONT><TT><FONT FACE="Courier">exec
$cmd $arg</FONT></TT> instead of <TT><FONT FACE="Courier">exec
'$cmd'</FONT></TT>, <TT><FONT FACE="Courier">'arg1'</FONT></TT>,
<TT><FONT FACE="Courier">'arg2'</FONT></TT>, …?
</UL>
<P>
As you begin to use Perl scripts, you can see how variables can
be tainted and how system files can be corrupted by using potentially
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -