⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch23_03.htm

📁 编程珍珠,里面很多好用的代码,大家可以参考学习呵呵,
💻 HTM
📖 第 1 页 / 共 2 页
字号:
string it finds there, and prints out the formatted result:<blockquote><pre class="programlisting">#!/usr/bin/perl -lTwuse strict;use CGI::Carp 'fatalsToBrowser';use CGI qw/:standard escapeHTML/;use Safe;print header(-type =&gt; "text/html;charset=UTF-8"),      start_html("Perl Expression Results");my $expr = param("EXPR") =~ /^([^;]+)/            ? $1 # return the now-taintless portion            : croak("no valid EXPR field in form");my $answer = Safe-&gt;new-&gt;reval($expr);die if $@;print p("Result of", tt(escapeHTML($expr)),               "is", tt(escapeHTML($answer)));</pre></blockquote>Imagine some evil user feeding you "<tt class="literal">print `cat /etc/passwd`</tt>" (orworse) as the input string.  Thanks to the restricted environment that disallows backticks, Perlcatches the problem during compilation and returns immediately.  Thestring in <tt class="literal">$@</tt> is "<tt class="literal">quoted execution (``, qx) trapped by operationmask</tt>", plus the customary trailing information identifying where theproblem happened.</p><p>Because we didn't say otherwise, the compartments we've been creatingall used the default set of allowable operations.  How you go about declaring specific operations permitted or forbiddenisn't important here.  What is important is that this is completelyunder the control of your program.  And since you can create multiple<tt class="literal">Safe</tt> objects in your program, you can confer various degrees oftrust upon various chunks of code, depending on where you got themfrom.</p><p>If you'd like to play around with <tt class="literal">Safe</tt>, here's a little interactivePerl calculator.  It's a calculator in that you can feed it numericexpressions and immediately see their results.  But it's not limitedto numbers alone.  It's more like the looping example under <tt class="literal">eval</tt>in <a href="ch29_01.htm">Chapter 29, "Functions"</a>, where you can take whatever they giveyou, evaluate it, and give them back the result.  The differenceis that the <tt class="literal">Safe</tt> version doesn't execute just anything you feellike.  You can run this calculator interactively at your terminal,typing in little bits of Perl code and checking the answers, to geta feel for what sorts of protection <tt class="literal">Safe</tt> provides.</p><blockquote><pre class="programlisting">#!/usr/bin/perl -w# safecalc - demo program for playing with Safeuse strict;use Safe;my $sandbox = Safe-&gt;new();while (1) {    print "Input: ";    my $expr = &lt;STDIN&gt;;    exit unless defined $expr;    chomp($expr);    print "$expr produces ";    local $SIG{__WARN__} = sub { die @_ };    my $result = $sandbox-&gt;reval($expr, 1);    if ($@ =~ s/at \(eval \d+\).*//) {        printf "[%s]: %s", $@ =~ /trapped by operation mask/            ? "Security Violation" : "Exception", $@;    }    else {        print "[Normal Result] $result\n";    }}</pre></blockquote><p>Warning: the <tt class="literal">Safe</tt> module is currently being redesigned to run eachcompartment within a completely independent Perl interpreter inside thesame process.  (This is the strategy that Apache's <tt class="literal">mod_perl</tt> employswhen running precompiled Perl scripts.)  Details are still hazy at thistime, but our crystal ball suggests that blindly poking at thingsinside the compartment using a named package won't get you very farafter the impending rewrite.  If you're running a version of Perl laterthan 5.6, check the release notes in <em class="emphasis">perldelta</em>(1) to see what'schanged, or consult the documentation for the <tt class="literal">Safe</tt> module itself.(Of course, you always do that anyway, right?)</p><a name="INDEX-4074"></a><a name="INDEX-4075"></a><a name="INDEX-4076"></a><a name="INDEX-4077"></a><a name="ch23-sect-masq"></a><h3 class="sect2">23.3.2. Code Masquerading as Data</h3><a name="INDEX-4078"></a><a name="INDEX-4079"></a><a name="INDEX-4080"></a><p><tt class="literal">Safe</tt> compartments are available for when the really scary stuff isgoing down, but that doesn't mean you should let down your guardtotally when you're doing the everyday stuff around home.  You need tocultivate an awareness of your surroundings and look at things fromthe point of view of someone wanting to break in.  You need to takeproactive steps like keeping things well lit and trimming thebushes that can hide various lurking problems.</p><p><a name="INDEX-4081"></a>Perl tries to help you in this area, too.  Perl's conventional parsingand execution scheme avoids the pitfalls that shell programminglanguages often fall prey to.  There are many extremely powerfulfeatures in the language, but by design, they're syntactically andsemantically bounded in ways that keep things under the control of theprogrammer.  With few exceptions, Perl evaluates each token only once.Something that looks like it's being used as a simple data variablewon't suddenly go rooting around in your filesystem.</p><p><a name="INDEX-4082"></a><a name="INDEX-4083"></a><a name="INDEX-4084"></a>Unfortunately, that sort of thing can happen if you call out to theshell to run other programs for you, because then you're running underthe shell's rules instead of Perl's.  The shell is easy to avoid,though--just use the list argument forms of the <tt class="literal">system</tt>, <tt class="literal">exec</tt>, orpiped <tt class="literal">open</tt> functions.  Although backticks don't have a list-argumentform that is proof against the shell, you can always emulate them asdescribed in the section <a href="ch23_01.htm#ch23-sect-access">Section 23.1.3, "Accessing Commands and Files UnderReduced Privileges"</a>.  (While there's no syntactic way to make backticks take anargument list, a multi-argument form of the underlying <tt class="literal">readpipe</tt>operator is in development; but as of this writing, it isn't quite readyfor prime time.)</p><p>When you use a variable in an expression (including when youinterpolate it into a double-quoted string), there's No Chance thatthe variable will contain Perl code that does something you aren'tintending.<a href="#FOOTNOTE-15">[15]</a> Unlikethe shell, Perl never needs defensive quotes around variables, nomatter what might be in them.<blockquote><pre class="programlisting">$new = $old;                # No quoting needed.print "$new items\n";       # $new can't hurt you.$phrase = "$new items\n";   # Nor here, neither.print $phrase;              # Still perfectly ok.</pre></blockquote>Perl takes a "what you see is what you get" approach.  If youdon't see an extra level of interpolation, then it doesn't happen.It <em class="emphasis">is</em> possible to interpolate arbitrary Perl expressions into strings,but only if you specifically ask Perl to do that.  (Even so, thecontents are still subject to taint checking if you're in taintmode.)<blockquote><pre class="programlisting">$phrase = "You lost @{[ 1 + int rand(6) ]} hit points\n";</pre></blockquote>Interpolation is not recursive, however. You can't just hide an arbitrary expression in a string:<blockquote><pre class="programlisting">$count = '1 + int rand(6)';             # Some random code.$saying = "$count hit points";          # Merely a literal.$saying = "@{[$count]} hit points";     # Also a literal.</pre></blockquote>Both assignments to <tt class="literal">$saying</tt> would produce "<tt class="literal">1 + int rand(6) hitpoints</tt>", without evaluating the interpolated contents of <tt class="literal">$count</tt>as code.  To get Perl to do that, you have to call <tt class="literal">eval</tt><em class="replaceable">STRING</em>explicitly:<blockquote><pre class="programlisting">$code = '1 + int rand(6)';$die_roll = eval $code;die if $@;</pre></blockquote>If <tt class="literal">$code</tt> were tainted, that <tt class="literal">eval</tt><em class="replaceable">STRING</em> would raise its ownexception.  Of course, you almost never want to evaluate random user code--butif you did, you should look into using the <tt class="literal">Safe</tt> module.  You may haveheard of it.</p><blockquote class="footnote"><a name="FOOTNOTE-15"></a><p>[15]Although if you're generating a web page, it'spossible to emit HTML tags, including JavaScript code, that might dosomething that the remote browser isn't expecting.</p></blockquote><p><a name="INDEX-4085"></a>There is one place where Perl can sometimes treat data as code; namely, when the pattern in a <tt class="literal">qr//</tt>, <tt class="literal">m//</tt>, or <tt class="literal">s///</tt> operator contains either ofthe new regular expression assertions, <tt class="literal">(?{</tt><em class="replaceable">CODE</em><tt class="literal">})</tt> or<tt class="literal">(??{</tt><em class="replaceable">CODE</em><tt class="literal">})</tt>.  These pose no security issues when used as literalsin pattern matches:<blockquote><pre class="programlisting">$cnt = $n = 0;while ($data =~ /( \d+ (?{ $n++ }) | \w+ )/gx) {    $cnt++;}print "Got $cnt words, $n of which were digits.\n";</pre></blockquote>But existing code that interpolates variables into matches was writtenwith the assumption that the data is data, not code.  The new constructsmight have introduced a security hole into previously secure programs.Therefore, Perl refuses to evaluate a pattern if an interpolated stringcontains a code assertion, and raises an exception instead.  If youreally need that functionality, you can always enable it with the lexically scoped<tt class="literal">use re 'eval'</tt> pragma.  (You still can't use tainted data for aninterpolated code assertion, though.)</p><p><a name="INDEX-4086"></a>A completely different sort of security concern that can come upwith regular expressions is denial-of-service problems.  These canmake your program quit too early, or run too long, or exhaust allavailable memory--and sometimes even dump core, depending on the phase of the moon.</p><p>When you process user-supplied patterns, you don't have to worryabout interpreting random Perl code. However, the regular expression enginehas its own little compiler and interpreter, and the user-suppliedpattern is capable of giving the regular expression compiler heartburn.If an interpolated pattern is not a valid pattern, a run-time exceptionis raised, which is fatal unless trapped.  If you do try to trap it,make sure to use only <tt class="literal">eval</tt><em class="replaceable">BLOCK</em>, not <tt class="literal">eval</tt><em class="replaceable">STRING</em>, becausethe extra evaluation level of the latter would in fact allow the executionof random Perl code.  Instead, do something like this:<blockquote><pre class="programlisting">if (not eval { "" =~ /$match/; 1 }) {    # (Now do whatever you want for a bad pattern.)}else {    # We know pattern is at least safe to compile.    if ($data =~ /$match/) { ... }}</pre></blockquote><a name="INDEX-4087"></a>A more troubling denial-of-service problem is that given the rightdata and the right search pattern, your program can appear to hangforever.  That's because some pattern matches require exponentialtime to compute, and this can easily exceed the MTBF rating on oursolar system.  If you're especially lucky, these computationallyintensive patterns will also require exponential storage.  If so,your program will exhaust all available virtual memory, bog downthe rest of the system, annoy your users, and either <tt class="literal">die</tt> withan orderly "<tt class="literal">Out of memory!</tt>" error or else leave behind a really bigcore dump file, though perhaps not as large as the solar system.</p><p><a name="INDEX-4088"></a>Like most denial-of-service attacks, this one is not easy to solve.If your platform supports the <tt class="literal">alarm</tt> function, you could time outthe pattern match.  Unfortunately, Perl cannot (currently) guaranteethat the mere act of handling a signal won't ever trigger a core dump.(This is scheduled to be fixed in a future release.)  You can alwaystry it, though, and even if it the signal isn't handled gracefully,at least the program won't run forever.</p><p><a name="INDEX-4089"></a>If your system supports per-process resource limits, you could setthese in your shell before calling the Perl program, or use the<tt class="literal">BSD::Resource</tt> module from CPAN to do so directly from Perl.  TheApache web server allows you to set time, memory, and file size limitson CGI scripts that it launches.</p><p>Finally, we hope we've left you with some unresolved feelings ofinsecurity.  Remember, just because you're paranoid doesn't meanthey're not out to get you.  So you might as well enjoy it.</p><a name="INDEX-4090"></a><a name="INDEX-4091"></a><a name="INDEX-4092"></a><a name="INDEX-4093"></a><a name="INDEX-4094"></a><!-- BOTTOM NAV BAR --><hr width="515" align="left"><div class="navbar"><table width="515" border="0"><tr><td align="left" valign="top" width="172"><a href="ch23_02.htm"><img src="../gifs/txtpreva.gif" alt="Previous" border="0"></a></td><td align="center" valign="top" width="171"><a href="index.htm"><img src="../gifs/txthome.gif" alt="Home" border="0"></a></td><td align="right" valign="top" width="172"><a href="ch24_01.htm"><img src="../gifs/txtnexta.gif" alt="Next" border="0"></a></td></tr><tr><td align="left" valign="top" width="172">23.2. Handling Timing Glitches</td><td align="center" valign="top" width="171"><a href="index/index.htm"><img src="../gifs/index.gif" alt="Book Index" border="0"></a></td><td align="right" valign="top" width="172">24. Common Practices</td></tr></table></div><hr width="515" align="left"><!-- LIBRARY NAV BAR --><img src="../gifs/smnavbar.gif" usemap="#library-map" border="0" alt="Library Navigation Links"><p><font size="-1"><a href="copyrght.htm">Copyright &copy; 2001</a> O'Reilly &amp; Associates. All rights reserved.</font></p><map name="library-map"> <area shape="rect" coords="2,-1,79,99" href="../index.htm"><area shape="rect" coords="84,1,157,108" href="../perlnut/index.htm"><area shape="rect" coords="162,2,248,125" href="../prog/index.htm"><area shape="rect" coords="253,2,326,130" href="../advprog/index.htm"><area shape="rect" coords="332,1,407,112" href="../cookbook/index.htm"><area shape="rect" coords="414,2,523,103" href="../sysadmin/index.htm"></map><!-- END OF BODY --></body></html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -