📄 ch23_01.htm
字号:
<html><head><title>Security (Programming Perl)</title><!-- STYLESHEET --><link rel="stylesheet" type="text/css" href="../style/style1.css"><!-- METADATA --><!--Dublin Core Metadata--><meta name="DC.Creator" content=""><meta name="DC.Date" content=""><meta name="DC.Format" content="text/xml" scheme="MIME"><meta name="DC.Generator" content="XSLT stylesheet, xt by James Clark"><meta name="DC.Identifier" content=""><meta name="DC.Language" content="en-US"><meta name="DC.Publisher" content="O'Reilly & Associates, Inc."><meta name="DC.Source" content="" scheme="ISBN"><meta name="DC.Subject.Keyword" content=""><meta name="DC.Title" content="Security"><meta name="DC.Type" content="Text.Monograph"></head><body><!-- START OF BODY --><!-- TOP BANNER --><img src="gifs/smbanner.gif" usemap="#banner-map" border="0" alt="Book Home"><map name="banner-map"><AREA SHAPE="RECT" COORDS="0,0,466,71" HREF="index.htm" ALT="Programming Perl"><AREA SHAPE="RECT" COORDS="467,0,514,18" HREF="jobjects/fsearch.htm" ALT="Search this book"></map><!-- TOP NAV BAR --><div class="navbar"><table width="515" border="0"><tr><td align="left" valign="top" width="172"><a href="ch22_03.htm"><img src="../gifs/txtpreva.gif" alt="Previous" border="0"></a></td><td align="center" valign="top" width="171"><a href="part4.htm">Part 4: Perl as Culture</a></td><td align="right" valign="top" width="172"><a href="ch23_02.htm"><img src="../gifs/txtnexta.gif" alt="Next" border="0"></a></td></tr></table></div><hr width="515" align="left"><!-- SECTION BODY --><h1 class="chapter">Chapter 23. Security</h1><div class="htmltoc"><h4 class="tochead">Contents:</h4><p><a href="ch23_01.htm">Handling Insecure Data</a><br><a href="ch23_02.htm">Handling Timing Glitches</a><br><a href="ch23_03.htm">Handling Insecure Code</a><br></p></div><p><a name="INDEX-3951"></a><a name="INDEX-3952"></a>Whether you're dealing with a user sitting at the keyboard typingcommands or someone sending information across the network, you needto be careful about the data coming into your programs, since the otherperson may, either maliciously or accidentally, send you data that willdo more harm than good. Perl provides a special security-checkingmechanism called <em class="emphasis">taint mode</em>, whose purpose is to isolate tainteddata so that you won't use it to do something you didn't intend to do.For instance, if you mistakenly trust a tainted filename, you might endup appending an entry to your password file when you thought you wereappending to a log file. The mechanism of tainting is covered inthe section <a href="ch23_01.htm#ch23-sect-hid">Section 23.1, "Handling Insecure Data"</a>.</p><p>In multitasking environments, offstage actions by unseen actors canaffect the security of your own program. If you presume exclusive ownership of externalobjects (especially files) as though yours were the only processon the system, you expose yourself to errors substantially subtlerthan those that come from directly handling data or code of dubiousprovenance. Perl helps you out a little here by detecting somesituations that are beyond your control, but for those that you cancontrol, the key is understanding which approaches are proof againstunseen meddlers. The section <a href="ch23_02.htm#ch23-sect-htg">Section 23.2, "Handling Timing Glitches"</a> discussesthese matters.</p><p><a name="INDEX-3953"></a>If the data you get from a stranger happens to be a bit of source codeto execute, you need to be even more careful than you would with theirdata. Perl provides checks to intercept stealthy code masquerading asdata so you don't execute it unintentionally. If you do want toexecute foreign code, though, the <tt class="literal">Safe</tt> module lets you quarantinesuspect code where it can't do any harm and might possibly do somegood. These are the topics of the section <a href="ch23_03.htm#ch23-sect-hic">Section 23.3, "Handling Insecure Code"</a>.</p><h2 class="sect1">23.1. Handling Insecure Data</h2><a name="INDEX-3954"></a><a name="INDEX-3955"></a><a name="INDEX-3956"></a><p><a name="INDEX-3957"></a><a name="INDEX-3958"></a><a name="INDEX-3959"></a><a name="INDEX-3960"></a>Perl makes it easy to program securely even when your program is beingused by someone less trustworthy than the program itself. That is,some programs need to grant limited privileges to their users, withoutgiving away other privileges. Setuid and setgid programs fall intothis category on Unix, as do programs running in various privilegedmodes on other operating systems that support such notions. Even onsystems that don't, the same principle applies to network servers andto any programs run by those servers (such as CGI scripts, mailinglist processors, and daemons listed in<em class="emphasis">/etc/inetd.conf</em>). All suchprograms require a higher level of scrutiny than normal.</p><p><a name="INDEX-3961"></a>Even programs run from the command line are sometimes good candidatesfor taint mode, especially if they're meant to be run by a privilegeduser. Programs that act upon untrusted data, like those that generatestatistics from log files or use <tt class="literal">LWP::*</tt> or<tt class="literal">Net::*</tt> to fetch remote data, should probably runwith tainting explicitly turned on; programs that are not prudent riskbeing turned into "Trojan horses". Since programs don't get any kindof thrill out of risk taking, there's no particular reason for themnot to be careful.</p><p>Compared with Unix command-line shells, which are really justframeworks for calling other programs, Perl is easy to programsecurely because it's straightforward and self-contained. Unlikemost shell programming languages, which are based on multiple,mysterious substitution passes on each line of the script, Perluses a more conventional evaluation scheme with fewer hidden snags.Additionally, because the language has more built-in functionality,it can rely less upon external (and possibly untrustworthy) programsto accomplish its purposes.</p><p><a name="INDEX-3962"></a><a name="INDEX-3963"></a><a name="INDEX-3964"></a><a name="INDEX-3965"></a><a name="INDEX-3966"></a>Under Unix, Perl's home town, the preferred way to compromise systemsecurity was to cajole a privileged program into doing something itwasn't supposed to do. To stave off such attacks, Perl developed aunique approach for coping with hostile environments. Perlautomatically enables taint mode whenever it detects its programrunning with differing real and effective user or groupIDs.<a href="#FOOTNOTE-1">[1]</a> Even if thefile containing your Perl script doesn't have the setuid or setgidbits turned on, that script can still find itself executing in taintmode. This happens if your script was invoked by another program thatwas <em class="emphasis">itself</em> running under differing IDs. Perlprograms that weren't designed to operate under taint mode tend toexpire prematurely when caught violating safe tainting policy. Thisis just as well, since these are the sorts of shenanigans that werehistorically perpetrated on shell scripts to compromise systemsecurity. Perl isn't that gullible.</p><blockquote class="footnote"><a name="FOOTNOTE-1"></a><p>[1] The setuid bit in Unix permissions is mode 04000,and the setgid bit is 02000; either or both may be set to grant theuser of the program some of the privileges of the owner (or owners) ofthe program. (These are collectively known as set-id programs.) Otheroperating systems may confer special privileges on programs in otherways, but the principle is the same.</p></blockquote><p><a name="INDEX-3967"></a><a name="INDEX-3968"></a><a name="INDEX-3969"></a><a name="INDEX-3970"></a><a name="INDEX-3971"></a>You can also enable taint mode explicitly with the <span class="option">-T</span> command-lineswitch. You should do this for daemons, servers, and any programs thatrun on behalf of someone else, such as CGI scripts. Programs that canbe run remotely and anonymously by anyone on the Net are executing in themost hostile of environments. You should not be afraid to say "No!"occasionally. Contrary to popular belief, you can exercise a greatdeal of prudence without dehydrating into a wrinkled prude.</p><p>On the more security-conscious sites, running all CGI scripts underthe <span class="option">-T</span> flag isn't just a good a idea: it's the law. We're notclaiming that running in taint mode is sufficient to make yourscript secure. It's not, and it would take a whole book just tomention everything that would. But if you aren't executing yourCGI scripts under taint mode, you've needlessly abandoned thestrongest protection Perl can give you.</p><p><a name="INDEX-3972"></a><a name="INDEX-3973"></a><a name="INDEX-3974"></a>While in taint mode, Perl takes special precautions called <em class="emphasis">taintchecks</em> to prevent traps both obvious and subtle. Some of these checksare reasonably simple, such as verifying that dangerous environmentvariables aren't set and that directories in your path aren't writableby others; careful programmers have always used checks like these.Other checks, however, are best supported by the language itself, andit is these checks especially that contribute to making a privilegedPerl program more secure than the corresponding C program, ora Perl CGI script more secure than one written in any language withouttaint checks. (Which, as far as we know, is any language other thanPerl.)</p><p><a name="INDEX-3975"></a><a name="INDEX-3976"></a><a name="INDEX-3977"></a><a name="INDEX-3978"></a>The principle is simple: you may not use data derived from outsideyour program to affect something else outside your program--atleast, not by accident. Anything that comes from outside yourprogram is marked as tainted, including all command-line arguments,environment variables, and file input. Tainted data may not beused directly or indirectly in any operation that invokes a subshell,nor in any operation that modifies files, directories, or processes.Any variable set within an expression that has previously referenceda tainted value becomes tainted itself, even if it is logicallyimpossible for the tainted value to influence the variable. Becausetaintedness is associated with each scalar, some individual valuesin an array or hash might be tainted and others might not. (Only thevalues in a hash can be tainted, though, not the keys.)</p><p>The following code illustrates how tainting would work if you executedall these statements in order. Statements marked "Insecure"will trigger an exception, whereas those that are "OK" will not.<blockquote><pre class="programlisting">$arg = shift(@ARGV); # $arg is now tainted (due to @ARGV).$hid = "$arg, 'bar'"; # $hid also tainted (due to $arg).$line = <>; # Tainted (reading from external file).$path = $ENV{PATH}; # Tainted due to %ENV, but see below.$mine = 'abc'; # Not tainted.system "echo $mine"; # Insecure until PATH set.system "echo $arg"; # Insecure: uses sh with tainted $arg.system "echo", $arg; # OK once PATH set (doesn't use sh).system "echo $hid"; # Insecure two ways: taint, PATH.$oldpath = $ENV{PATH}; # $oldpath is tainted (due to $ENV).$ENV{PATH} = '/bin:/usr/bin'; # (Makes it OK to execute other programs.)$newpath = $ENV{PATH}; # $newpath is NOT tainted.delete @ENV{qw{IFS CDPATH ENV BASH_ENV}}; # Makes %ENV safer.system "echo $mine"; # OK, is secure once path is reset.system "echo $hid"; # Insecure via tainted $hid.open(OOF, "< $arg"); # OK (read-only opens not checked).open(OOF, "> $arg"); # Insecure (trying to write to tainted arg).open(OOF, "echo $arg|") # Insecure due to tainted $arg, but... or die "can't pipe from echo: $!";open(OOF,"-|") # Considered OK: see below for taint or exec "echo", $arg # exemption on exec'ing a list. or die "can't exec echo: $!";open(OOF,"-|", "echo", $arg # Same as previous, likewise OKish. or die "can't pipe from echo: $!";$shout = `echo $arg`; # Insecure via tainted $arg.$shout = `echo abc`; # $shout is tainted due to backticks.$shout2 = `echo $shout`; # Insecure via tainted $shout.unlink $mine, $arg; # Insecure via tainted $arg.umask $arg; # Insecure via tainted $arg.exec "echo $arg"; # Insecure via tainted $arg passed to shell.exec "echo", $arg; # Considered OK! (But see below.)exec "sh", '-c', $arg; # Considered OK, but isn't really!</pre></blockquote><a name="INDEX-3979"></a><a name="INDEX-3980"></a><a name="INDEX-3981"></a></p><p>If you try to do something insecure, you get an exception (whichunless trapped, becomes a fatal error) such as "<tt class="literal">Insecuredependency</tt>" or "<tt class="literal">Insecure $ENV{PATH}</tt>".See the section <a href="ch23_01.htm#ch23-sect-cuye">Section 23.1.2, "Cleaning Up Your Environment"</a> later.</p><p>If you pass a <em class="replaceable">LIST</em> to a<tt class="literal">system</tt>, <tt class="literal">exec</tt>, or pipe<tt class="literal">open</tt>, the arguments are not inspected fortaintedness, because with a <em class="replaceable">LIST</em> ofarguments, Perl doesn't need to invoke the potentially dangerous shellto run the command. You can still easily write an insecure<tt class="literal">system</tt>, <tt class="literal">exec</tt>, or pipe<tt class="literal">open</tt> using the <em class="replaceable">LIST</em>form, as demonstrated in the final example above. These forms areexempt from checking because you are presumed to know what you're
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -