vendredi 31 juillet 2015

Best way to strip and untaint CGI values in Perl?

I'm writing a global subroutine to "wrap" CGI::param() and I want it to strip out characters based on situational "patterns." For example, if it's a session id it might require digits only. If it's an html page it might be letters, a period and possibly a dash. If it's a password it could allow digits, letters and some special characters.

I came up with this approach and want to know if there's a more elegant way to do it. And also if this would be acceptable security in an online application?

#!/usr/bin/perl -T

use strict;
use warnings;

my $x = shift || '';
my $y = ParamData($x,'d');
print "[$y]\n";
$y = ParamData($x,'w');
print "[$y]\n";
$y = ParamData($x,'dw');
print "[$y]\n";
$y = ParamData($x,'dw ');
print "[$y]\n";
$y = ParamData($x,'dw- .');
print "[$y]\n";
$y = ParamData($x,'w ');
print "[$y]\n";
exit(0);

sub ParamData {
  my $v = shift || return; # value
  my $p = shift || return; # pattern
  my $r = '';   # regex
  print "[$p] = ";
  foreach my $i (0 .. length($p) - 1) {
    my $c = substr($p,$i,1);
    for ($c) {
      /^d$/ and do { $r .= '0-9'; last; };
      /^w$/ and do { $r .= 'A-Za-z'; last; };
      /^ $/ and do { $r .= ' '; last; };
      /^-$/ and do { $r .= '-'; last; };
      /^\.$/ and do { $r .= '\.'; last; };
    }
  }
  $v =~ s/[^$r]//g;
  if ($v =~ /^([$r]).$/) {
    $v = $1; # untaint
  }
  return($v);
}

Here's output of a sample run:

$ ./paramdata.pl 'h.-1-.i m.2.o+m.3'
[d] = [123]
[w] = [himom]
[dw] = [h1im2om3]
[dw ] = [h1i m2om3]
[dw- .] = [h.-1-.i m.2.om.3]
[w ] = [hi mom]

What do you think? Thanks.

Aucun commentaire:

Enregistrer un commentaire