Elijah has asked for the wisdom of the Perl Monks concerning the following question:

I am in the process of re-designing my website and have ran into a couple of snags. I wrote this script below to be envoked by hyperlinks passing a cgi perameter to the script so the script knows which source code file to grab and show.
#!/usr/bin/perl -w use strict; use CGI qw(param); my $cgi = new CGI; my @param = $cgi->param(); my $path = "/home/master/webroot/newdesign/scripts/"; my @source; error() unless @param; my $full = $path.$param[0]; if (-e $full) { open(FILE, "$full") || error(); @source = <FILE>; close(FILE); print "Content-type: text/html; charset=ISO-8859-1\n\n"; print <<last; <html> <head><title>$param[0]</title> </head> <body bgcolor="#000000" text="#808080" leftmargin="0" marginwidth="0" +topmargin="0" marginheight="0"> <table border="0" cellspacing="0" cellpadding="0" width="100%"> <tr> <td> last for (@source) { print; print "<br>\n"; } print <<last2; </td> </tr> </table> </body> </html> last2 }else{ error(); } sub error { print "Content-type: text/html; charset=ISO-8859-1\n\n"; print <<end; <html> <head><title>Error!</title> </head> <body bgcolor="#000000" text="#808080" leftmargin="0" marginwidth="0" +topmargin="0" marginheight="0"> <table border="0" cellspacing="0" cellpadding="0" width="100%"> <tr> <td> There was an error while trying to post script source! </td> </tr> </table> </body> </html> end exit(0); }
Now this script works fine but when this script sends the target script source code to the web browser the cgi source code in the script gets parsed as html code. Is there anyway I can use this method and not have the web browser parse the cgi source code as html code and simply display as text?

Also along the same lines all the scripts source code formatting (spaces, indentation, basically all whitespace) gets stripped from the source code and all source code is aligned with the left margin. This is not as big of a deal but I would like the scripts to keep their formatting after being sent to the browser.

You can see this script in action and actually see the indications I am talking about above in action at the production server link that follows: http://4.46.66.37/master/webroot/newdesign/scripts.htm


www.perlskripts.com

Replies are listed 'Best First'.
Re: issues displaying cgi script source?
by diotalevi (Canon) on Jul 06, 2004 at 20:49 UTC

    Your script contains a security hole. The value of ( param() )[0] is given directly to your two-arg-open() call. It looks like your -e test might be enough to prevent people from taking over your shell but it is at least giving the world access to read any file on your hard drive.

    Please read perlsec, turn on tainting, and learn to use three-arg-open: open ..., "<", $full or die "Couldn't open $full for reading: $!"

      I can see your concern but do not really see how anyone can read any file on my filesystem by this usage. Permissions will not allow for any privilaged file to be read by a webserver running as "nobody" or any other non-privilaged user.

      Not to mention the hard coded variable of $path which is not changeable by the user and is the entire first portion of the variable $full's value.

      If there is a way to break out of this directory with the current state of this script please be specific because I do not see it.

      I have read about the two and three arg open calls but do not see in this implementation how a three arg open call will help any. Now I am not saying it won't because I am the farthest thing from an expert but if it will please again be more specific.

      Edit: Ohh wait a minute! Oh crap I see it and tested it and yes you are correct. Big oversight on my part. Thanks for the heads up! Permissions do save me on privilaged files but there are some un-privilaged files Apache can read that people have no buisness looking at and can lead to further exploitation.


      www.perlskripts.com
        See about using File::Spec and functions like splitpath() or no_upwards(). Also, use the three-arg open because even if a user gives you a filename like " foo |" or ">bar" then you are specifying the "action" part of the open separately. It tells perl that everything in the filename portion of the function is a filename and no part of that is to be interpreted specially.
Re: issues displaying cgi script source?
by diotalevi (Canon) on Jul 06, 2004 at 22:27 UTC
    Say, I notice that your submit-script has a problem that lets me write to any file on your hard drive. Fix that too. Also fix your scripts to use CGI instead of trying to parse stuff in %ENV and STDIN. Again, use taint on all of those. These are just some general comments on some specific problems I saw while looking at your code and some hints to techniques that will help you get rid of them.
      I locked down this script using some of the methods you suggested mbut was not able to use taint mode. I got the famous error saying it was too late for taint mode. I tried -wT, -Tw, -w -T, -T -w. The only way I could get taint mode to be used was envoke it via command line but this is not an option running the script over the web.

      I changed the two-arg-open call to a three-arg-open after your explanation. I had never considered the laziness of the two-arg implication function.


      www.perlskripts.com
        #!/usr/bin/perl -wT

        Um... that should be enough. Are you using mod_perl instead of cgi? That would do that - you'd load -T during the startup.pl in your apache configration then.

Re: issues displaying cgi script source?
by Joost (Canon) on Jul 06, 2004 at 20:37 UTC
Re: issues displaying cgi script source?
by jZed (Prior) on Jul 06, 2004 at 20:30 UTC
    Is there anyway I can use this method and not have the web browser parse the cgi source code as html code and simply display as text?
    Use <pre> tags.
      Ahh yes this works great for spacing and indention but html is still rendered inside the pre tag.

      www.perlskripts.com

        You're already using CGI so why not just import escapeHTML and use it on the contents of the script?

        antirice    
        The first rule of Perl club is - use Perl
        The
        ith rule of Perl club is - follow rule i - 1 for i > 1

•Re: issues displaying cgi script source?
by merlyn (Sage) on Jul 06, 2004 at 23:03 UTC
    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: issues displaying cgi script source?
by sgifford (Prior) on Jul 07, 2004 at 04:50 UTC
    If you don't mind losing the formatting and just want to display the script, use Content-type: text/plain instead of HTML. That would make the script easier for a user to save and download too.
A reply falls below the community's threshold of quality. You may see it by logging in.