<<< Date Index >>>     <<< Thread Index >>>

PacSec Hype Security Team: CGI.pm param injection



====================================================================== 

                 PacSec Hype Security Team

          param injection in CGI.pm and inheritors 
        allows SQL injection and manipulation of data
          bypassing many perl web form validators

====================================================================== 
Table of Contents

Affected Software....................................................1
Severity.............................................................2
Description of Software..............................................3
Description of Vulnerability.........................................4
Solution.............................................................5
Time Table...........................................................6
Credits..............................................................7
References...........................................................8
About PacSec.........................................................9
Verification........................................................10

====================================================================== 
1) Affected Software

CGI.pm and perl modules which inherit from it or behave compatibly.
Data::FormValidator is an example.

====================================================================== 
2) Severity 

Rating: Extra Crispy
Impact: Blatant shilling
        Overstated claims of insecurity
        Manipulation of data
        SQL Injection
Where:  A series of tubes

====================================================================== 
3) Description of Software 

CGI.pm is the defacto standard for handling forms in perl.  It is
included in core perl.

Data::FormValidator is the most common way of validating form data
in perl.  It is available as a plug in to Catalyst, CGI::Application,
and almost every other framework for building web apps in perl.

DBIx::Class is a pretty decent ORM for perl, Catalyst uses it by
default.



====================================================================== 
4) Description of Vulnerability

The CGI.pm documentation states (http://xrl.us/r6ev) that the 'param'
method will return an array if a named parameter is multivalued.
This can have unintended consequences if used as a hash value with the
assumption that 'param' will always return a scalar.

For example:

http://example.com/somecgi?name=value

The programmer may expect the following to work:

use CGI.pm
use Data::Dumper;
my $q = new CGI;
my $importanthash = {name => $q->param('name')};

print Dumper $importanthash;

will show something like this as expected:

VAR1 = {
          'name' => 'value',
        };


However in cases where the parameter is multivalued something
different will happen.

http://example.com/somecgi?name=1&name=2&name=evilkey&name=evilvalue

This is probably not expected:

$VAR1 = {
          'evilkey' => 'evilvalue',
          'name' => '2'
        };

This becomes more interesting because almost everything that deals
with the web in perl either inherits from CGI.pm or mimics its
behaviour.  This makes an interesting problem for data validation.

Data::FormValidator is quite commonly used to validate cgi
parameters (both GET and POST).  A typical validation profile
might look something like this:

use Data::FormValidator;
my $profile = {
        required => [qw( fullname 
                         phone 
                         email 
                         address )],

        constraint_methods => {
            email => qr/\w+/  
            #yes I know this is retarded, it's an example
        }
};

The expected behaviour is that the 'email' parameter must match the
supplied regular expression otherwise it will not be returned by the
'valid' method (see docs at http://xrl.us/r6e7).  A naive programmer
would assume that since the 'email' parameter has been validated, it
is hereafter safe to use.  The documentation even lulls the programmer
along, suggesting this construct:

my $results = Data::FormValidator->check($q->Vars, $profile);
foreach my $f ( $results->valid() ) {
        print $f, " =  ", $results->valid( $f ), "\n";
}

Obviously the above will not do what is expected when supplied with
multivalued parameters, but it is not yet actually dangerous.

When a multivalued parameter is supplied, say for example:

http://example.com/somecgi?email=foo@xxxxxxx&email=userid&email=0

the above example should print out

'email =  foo@xxxxxxxxxxxxxx'

Here's an example that is dangerous.  Rather than printing out the
name value pairs, the (supposedly) valid data is being used in
an update method for an ORM (in this case DBIx::Class).  This
can be used to do a SQL injection attack, despite the use of bind
variables by the ORM, and validation by Data::FormValidator.

#don't do this
foreach my $f ( $results->valid() ) {
        $db->update({$f, $results->valid($f) });
}

Our previous multivalue parameter query now causes the following:

$db->update({'email', 'foo@xxxxxxx', 'userid', '0'});

Which is of course equivalent to this:

$db->update({'email' => 'foo@xxxxxxx', 'userid' => '0'});

Probably not a good thing.

Finally, since columns in SQL can not have bind variables, there
exists the possibility of making this even more dangerous by 
inserting a sub-select.  This seems like a lot of work though, so
I'm going to handwave at the problem and leave it as an exercise
for the reader.

====================================================================== 
5) Solution 

Make sure that the result of a CGI 'param' method is forced into
scalar context.  You can use the 'scalar' function to do this:

$db->update({$f, scalar $results->valid($f)});


====================================================================== 
6) Time Table 

Aug 31 2006 - single slide explanation at YAPC::EU
Sep 2006    - sat on ass for a month
Oct 5 2006  - other people begin to notice
Oct 9 2006  - attempt to take credit and shill conference

====================================================================== 
7) Credits 

Discovered by mock@xxxxxxxxx, PacSec Hype Security Team.

====================================================================== 
8) References

http://sketchfactory.com/post/2006-08-30.11:37:00.At_YAPC_with_slides
http://xrl.us/r6fg

====================================================================== 
9) About PacSec

PacSec (http://pacsec.jp) is a conference on November 29th and 30th
in Tokyo, Japan put on by the fine folks who bring you CanSecWest
(http://cansecwest.com).  PacSec (http://pacsec.jp) features many
excellent talks (http://pacsec.jp/speakers.html) on important topics
in security research and promises to be the best damn technical
security conference you can pay for with your company's money.

PacSec Hype Security Team is a team of researchers devoted to
blatantly shilling their conference in the guise of security 
advisories.  When you come to PacSec (http://pacsec.jp) you
should buy them booze.

====================================================================== 
10) Verification 

You all know how to use Google code search.  Go forth and find stupid
perl CGI vulnerabilities, my flying monkey army.

======================================================================

-- 
World Security Pros. Cutting Edge Training, Tools, and Techniques
Tokyo, Japan    November 27-30 2006    http://pacsec.jp
pgpkey http://dragos.com/ kyxpgp