Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change

comment on

( #3333=superdoc: print w/replies, xml ) Need Help??
CGI security is a frequent topic of dicussion on this site so I thought I'd raise another issue that illustrates a variety of problems that people face when trying to write secure scripts. The following example is rather simple, but helps to illustrate the dangers involved (my information came from this Phrack article. tilly originally supplied me with the link).

I'm posting this here in part so that I can archive this and link to it from my online CGI course. I figured it would be a handy way to get people to use Perlmonks more :)

Consider the following code:

#!C:/perl/bin/perl.exe -wT use strict; use CGI; # Do not run this script on a server connected to the 'Net # It is supplied as a bad example my $cgi = CGI->new(); my $file = $cgi->param( 'file' ); # Bad taint checking! # This is, amongst other things, a deliberately incomplete list # of shell metacharacters my $data = $1 if $file =~ m#([^./\\`$"'&]+\.?[^./\\`$"'&]+)$#; $data .= '.dat'; my $userInfo; open FILE, "<$data" or die "Cannot open $data: $!\n"; { local $/; $userInfo = <FILE>; } close FILE; print $cgi->header, $cgi->start_html, $cgi->pre( $userInfo ), $cgi->end_html;
Hmm.... what's wrong with it? The author (me) uses warnings, strict, and taint checking. Users need to be able to get at the contents of .dat files on the server, but filenames can be very unpredictable. This script allows them to view those files from any browser. Therefore, we need to (gasp!) let user data near the shell.

The author, however, knows this is a security hole, so he conventiently supplies a list of shell metacharacters which he doesn't want. Further, he appends a ".dat" extension to guarantee that the user can only view files with said extension. Looks pretty secure to me!

I deliberately left the list of shell metacharacters incomplete so Monks wouldn't be tempted to use this technique.

So what's the problem? Perl, as many of you know, is written in C. C recognizes the null byte (ASCII zero) as the end of a string. Perl does not. If Perl tries to make a system call (such as open FILE, $somefile) with an embedded null byte in the data, the data is passed to the C underbelly, which happily ignores any information from the null byte on. So how does that affect our script?

I named the script insecure.cgi and ran it locally through a browser. I used the following URL:

See that embedded %00? Hmm... it's right after the name of my script. It passes our taint checking and Perl thinks it's trying to open insecure.cgi%00loser!.dat. However, the C underbelly tries to open insecure.cgi, and does! Then, the rest of the script happily dumps its source code to your browser.

This illustrates a couple of points:

  • Don't let user data near the shell.
  • If you must let user data near the shell, use taint checking and specify what you will allow!!!
  • Don't store data files in the same directory as your CGI scripts
Specifying what you won't allow forces you to go over everything that you missed and ensure that there are no security problems. How many would have guessed that ASCII zero would be a risk?

This node brought to you by the letter C


Join the Perlmonks Setiathome Group or just go the the link and check out our stats.

In reply to CGI Security and the null byte problem by Ovid

Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":

  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?

    What's my password?
    Create A New User
    and the web crawler heard nothing...

    How do I use this? | Other CB clients
    Other Users?
    Others lurking in the Monastery: (11)
    As of 2020-12-02 22:33 GMT
    Find Nodes?
      Voting Booth?
      How often do you use taint mode?

      Results (47 votes). Check out past polls.