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

Hi Monks,

I have a little problem at the moment which has got me stumped.
I'm submitting a form to a cgi script and would like to use one of the fields (a non-user-defined hidden field) submitted as a variable in the cgi script - specifically to create a file on a linux file system.
It appears however that there is something at the front of this variable but I cant in anyway see it....
Here's some simplified code to demonstrate:
my $field = $q->param("author"); $field =~ s/ /_/g; open(OUTFILE,">"./$field.txt") || die($!); print OUTFILE "blah"; close(OUTFILE);
The above creates the file perfectly but a
if ($item =~ /^$field\.(txt|foo|bar)$/i)
wont match until I remove the initial "^".
And if I
$field = "blah-$field";
before the creation of the "OUTFILE", the script dies while trying to create the file with the message
No such file or directory

Does anyone know of any issues concerning this or maybe how to check for some special characters in some way??

Cheers,
Reagen

Update:
OK, the form was pulling the hidden field value from a mysql database and then passing it onto the cgi script. I have now completely bypassed the form and am getting it straight from the database in the cgi script and it is still behaving in the same way. So it appears to be a mysql thing, but I have no idea what...

Replies are listed 'Best First'.
Re: Special Chars in CGI form variables
by cazz (Pilgrim) on Apr 20, 2005 at 13:14 UTC
    Why open yourself up to risk if you don't have to? I highly recommend using something akin to CGI::Session and storing the data attached to a session, just providing the user with a cryptograpicly generated cookie (sessionid).

    If you *really* must specify this data via a form, you shouldn't worry about special characters. You should decide what characters are acceptable and filter everything else out. (Or bitch if the value has anything unacceptable.)

Re: Special Chars in CGI form variables
by polettix (Vicar) on Apr 20, 2005 at 13:25 UTC
    Why don't you simply print "$field" inside the file? I guess there's a prefix slash in this variable, which makes ".//something" perfectly valid (duplicated slashes are tolerated) while "./blah-/something" whould fail miserably (unless you've a "blah-" subdirectory, of course).

    As a general note you should avoid doing things like this, even if you're dealing with an hidden field - these are no more secure than visible ones. Use tainted mode, and place strict restrictions upon filenames you allow, like:

    $field =~ s/[^\w.-]//g; # keep alpha, num, and "_.-" if ($field =~ /([\w.-]+)/) { $field = $1; } else { $field = undef; } # now $field is untainted
    Another advice: use the three-argument open instead of appending filename to the ">" char.

    All that said, take a deep look at perldoc perlsec!

    Flavio (perl -e "print(scalar(reverse('ti.xittelop@oivalf')))")

    Don't fool yourself.
      I've tried "print", "warn", you name it, but it still shows up nothing.

      The filename is extremely simple "smith_rj.txt" and i was only using the form field, cause it was not to be used by users - so no security issues...
        Just because a form variable is "hidden" doesn't mean someone can't edit it. This is a very common misconception regarding CGI programming.
        Did you print also after the "blah-" prefix addition? Did you try to print something like "($field)" (note parens)? As a last resort, try to print:
        print join "\n", map { "0x" . unpack("h2", ord($_)) } split //, $field; print $/;
        which will give you the hex dump of the string.

        Flavio (perl -e "print(scalar(reverse('ti.xittelop@oivalf')))")

        Don't fool yourself.