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

Okay, here's my quandary. Our church website was written by someone who has now moved away. I have taken over the site, but know very little about perl. The site ran fine until recently when I updated the server from XP to Windows 7. Now running the original perlscript gives a 502 error.
The perlscript in question was designed to search the contents of a specified folder and find all of the .wmv files (recorded sermons). It then creates an HTML form from a template, providing links to these files. It also listed the date and speaker for each file, which is determined by the filename.
I have tried very simple scripts and they have all worked fine, but the original script does not. I think that the problem may reside in the upgrade from 32 bit to 64 bit, or possibly the upgrade in ActivePearl.
Here is the code where I suspect the problem lies. Please keep in mind, I didn't write this! LOL!

#!d:/perl/bin/perl -w ######!/usr/bin/perl -w $yeardir=$ENV{'QUERY_STRING'}; use HTMLTMPL; # Create the template object and load it. $templ = new HTMLTMPL; $templ->src('d:/wwwroot/calvarybaptist/cgi-bin/sermon/sermons.html'); #get the list of audio files from the sermons directory #for this to work correctly the files should be names xxxxxxsP.ram # replace the xxxxxx with the date ie 100399 # replace the P with G for Pastor Gerhardt or V for Guest Speaker # replace the s with M for morning sermon, e for evening sermon or w f +or midweek # ex 100399MG would be the sermon for October 3, 1999 Morning's Sermon + by Pastor Gerhardt # if there is a technical problem with the sermon add a t or T to the +end ie # ex 100399MGt #opendir(DIR, "/webpages/calvarybaptist/sermons/"); #opendir(DIR, "/home/rmserver/Content/"); #opendir(DIR, "d:/Sermons/"); opendir(DIR, "d:/wwwroot/CalvaryBaptist/Sermons/".$yeardir); @ramFiles = sort(grep(/\.wmv$/,readdir(DIR))); #@ramFiles = sort(grep(/\.rm$/,readdir(DIR))); #@ramFiles = sort(grep(/\.ram$/,readdir(DIR))); #@ramFiles = sort(grep(/\.HTML$/,readdir(DIR))); closedir(DIR); foreach $i (@ramFiles) { #MMDDYYSD #MM = Month 0-1 (2) #DD = Day 2-3 (2) #YY = Year 4-5 (2) #S = Sermon (1) # M = Morning # e = Evening # w = Wednesday # s = Sunday School # x = Special #D = Who delivered # G = Gerhardt # H = Halverson # B = Brown # V = Guest # N = None $month=substr($i,0,2); $day=substr($i,2,2); $year=substr($i,4,2); if ((substr($i,6,1) eq "m") or (substr($i,6,1) eq "M")){ $whichsermon="Morning Sermon"; } elsif ((substr($i,6,1) eq "e") or (substr($i,6,1) eq "E")){ $whichsermon="Evening Sermon"; } elsif ((substr($i,6,1) eq "w") or (substr($i,6,1) eq "W")){ $whichsermon="Midweek Sermon"; } elsif ((substr($i,6,1) eq "s") or (substr($i,6,1) eq "S")){ $whichsermon="Sunday School"; } elsif ((substr($i,6,1) eq "x") or (substr($i,6,1) eq "X")){ $whichsermon="Special"; } else { $whichsermon="ERROR Determing Sermon."; } # Determin who delivered the sermon #if ((substr($i,7,1) eq "g") or (substr($i,7,1) eq "G")){ # $speaker="Pastor Gerhardt"; #} #elsif ((substr($i,7,1) eq "b") or (substr($i,7,1) eq "B")){ # $speaker="Asst. Pastor Brown"; #} #elsif ((substr($i,7,1) eq "h") or (substr($i,7,1) eq "H")){ # $speaker="Pastor Halverson"; #} #elsif ((substr($i,7,1) eq "v") or (substr($i,7,1) eq "V")){ # $speaker="Guest Speaker"; #} #elsif ((substr($i,7,1) eq "n") or (substr($i,7,1) eq "N")){ # $speaker=""; #} #else { # $speaker="ERROR code for speaker is incorrect." #} #Check to see of there was a technical problem with the sermon. # if ((substr($i,8,1) eq "T") or (substr($i,8,1) eq "t")){ # $speaker="Technical Problems"; # } $desc=substr($i,8,length($i)-12); #.' '.(length($i)).' '.$i.'!'; $filename=$yeardir."/".$i; $test=$month.'/'.$day.'/'.$year.' '.$whichsermon.', '.$desc.' '; # $templ->filename("$i", 'x_details'); $templ->filename("$filename", 'x_details'); $templ->desc("$test", 'x_details'); } # Send the completed html document to the web server. $templ->output('Content-Type: text/html');
Here is the script that I suspect is in question.

Replies are listed 'Best First'.
Re: HTML Template
by MidLifeXis (Monsignor) on May 07, 2015 at 12:40 UTC

    You also have a possible exploit waiting to happen (although, imo, the risk in this case is pretty small):

    $yeardir=$ENV{'QUERY_STRING'}; ... opendir(DIR, "d:/wwwroot/CalvaryBaptist/Sermons/".$yeardir);

    $yeardir is unsanitized, meaning that an external user (the person controlling the web browser), is able to specify any directory on your D: drive to search. The risk is mitigated somewhat because you are searching for stuff that ends in .wmv. However, if there are other protected directories containing wmv files that the general user should not have access to, that protection could be bypassed here. In general, you want to sanitize your inputs from untrusted sources.

    --MidLifeXis

      Since I am unskilled in Perl as I said before, would you be able to suggest a solution to "sanitize" this line of code?
        suggest a solution to "sanitize" this line of code
        $yeardir=$ENV{'QUERY_STRING'}; ... opendir(DIR, "d:/wwwroot/CalvaryBaptist/Sermons/".$yeardir);

        Assuming year must be a four-digit number starting with 19, 20 or 21:

        $yeardir=$ENV{'QUERY_STRING'}; $yeardir=~/^(19|20|21)[0-9]{2}$/ or die "Bad year\n"; ... opendir(DIR, "d:/wwwroot/CalvaryBaptist/Sermons/".$yeardir);

        Note that or die will cause a "500 Internal Server Error" when your script is called with an invalid number. You may want to generate a nicer error page instead:

        $yeardir=$ENV{'QUERY_STRING'}; unless ($yeardir=~/^(19|20|21)[0-9]{2}$/) { print "Content-Type: text/plain\r\n\r\n"; print "Bad year."; exit; # <-- important. Don't run into the following code. } ... opendir(DIR, "d:/wwwroot/CalvaryBaptist/Sermons/".$yeardir);

        For a more robust solution, don't try to parse the CGI environment by yourself. There are tons of CGI modules on CPAN, CGI was in core for ages, but it is fat and full of legacy code. CGI::Minimal provides the essential parts, skipping generating HTML and much legacy code. CGI::Simple strips generating HTML and moves the functional interface into a separate module CGI::Simple::Standard, but attempts to stay compatible with CGI. CGI::Lite is yet another instance of "CGI without generating HTML". Modules compatible with the CGI API offer a method named param() that allows you to fetch parameter values from the query string.

        Also, consider use strict;, use warnings;, enabling taint mode (#!perl -T). Note that taint mode will cause your script to die when you attempt to pass unverified ("tainted") data to critical functions. You need to verify all data. See perlsec.

        You may also want to use CGI::Carp for a better error handling and autodie to have automatic error checks for the I/O operations.

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
Re: HTML Template
by thomas895 (Deacon) on May 07, 2015 at 01:36 UTC

    Does this sound like your problem? If so, you'll have to fiddle with IIS settings, can't help you there I'm afraid.

    Could you also give us the source of the HTMLTMPL module, and the relevant excerpts of the IIS error logs (once you have them)? It doesn't seem like there are any problems with the script you posted.

    -Thomas
    "Excuse me for butting in, but I'm interrupt-driven..."
      I will look into this at my next opportunity and let you know what I find.

        Here is the code for the HTML template:

        <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> <HTML> <HEAD> <TITLE>Sermons</TITLE> </HEAD> <!-- bgcolor is R-37 G-74 B-128--> <BODY BGCOLOR="#20407F" TEXT="#00FFFF" LINK="#00FF00" VLINK="#C0DCC0" +ALINK="#FF0000"> <TABLE WIDTH=100% HEIGHT=100% BORDER=0> <TR><TD height=5%>&nbsp;</TD></TR> <TR> <TD valign=top height=90%> <!--- enter text here --> <CENTER> <IMG SRC="../../images/sermon.gif" BORDER=0 WIDTH=372 HEIGHT=135> </CENTER><br><br> To listen to a sermon click the <IMG SRC="../../images/speaker.gif" BO +RDER=0 WIDTH=25 HEIGHT=26> next to the sermon you would like to hear. <br> <!--To save a sermon on your computer click the <IMG SRC="images/downl +oad.gif" BORDER=0 WIDTH=16 HEIGHT=16> next to the sermon you would li +ke to save.--> <br><br> In order to listen to the sermons you will need <A HREF="http://www.mi +crosoft.com/windows/windowsmedia/en/default.asp" target=_blank>Window +s Media 6 </a> or above installed. <br><br> <A HREF="/sermons.html">Back to the Main Sermons menu</A> <br><br> <A HREF="/sermons/live.asx"><FONT COLOR="#66FFFF">See us LIVE. Click H +ere.</A> <br><br> <CENTER> <TABLE BORDER=1 CELLSPACING=1> __x_details__ <TR> <TD>__desc__</TD> <TD><A HREF="/sermons/__filename__"><IMG SRC="../../images/speak +er.gif" BORDER=0 WIDTH=25 HEIGHT=26></A></TD> </TR> __x_details__ </TABLE> </center> <br><br> <br><br> <BR> <!-- Last modifed --> <script> var moddate moddate=document.lastModified document.write("This page was last modified: "+moddate) </script> <!--End Last Modified--> <BR> </FONT> </CENTER> </TD> </TR> </TABLE> </BODY> </HTML>
Re: HTMLTMPL.pm
by Anonymous Monk on May 07, 2015 at 00:57 UTC
      Do you have a suggestion? I'm not sure how an HTML code could deal with decoding a constantly changing folder of video files that need to be decoded and listed, without updating the code after every service.

        html code wouldn't deal it, the monkey adding files to the folder would deal with it :)

        It takes about a second to hit copy/paste to start copying files to the folder,

        Then 5-10 seconds per file to type up a link and description for each file

        Easier than learning to program right? :)

Re: HTML Template
by soonix (Chancellor) on May 11, 2015 at 08:42 UTC

    Could you meanwhile rule out the environment? During your "update from XP to 7", possibly you (re)moved your perl.exe or something like this.

    If you temporarily replace your script by the following, does it say something understandable, or is it still giving the 502 error?

    #!d:/perl/bin/perl -w print "Content-Type: text/plain\n\nHi there!";
    If it still gives the error, this means there is something wrong with your Perl installation, or your Webserver doesn't find it (e.g. it isn't in D:\perl\bin anymore).
    If it says Hi there! then, of course, all the hints from the other monks apply.
        That's right, but (at least XAMPP's) Apache does mimic /bin/sh's behaviour. This is configurable, so the OP should possibly check this.