====================================================================== 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@bar.com&email=userid&email=0 the above example should print out 'email = foo@bar.comuserid0' 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@bar.com', 'userid', '0'}); Which is of course equivalent to this: $db->update({'email' => 'foo@bar.com', '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@pacsec.jp, 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