in reply to Re: Issuing a DELETE statement with DBI
in thread Issuing a DELETE statement with DBI

Be aware that directly using the results of the param function as key/value pairs for a hash opens up an interesting attack vector if you have more than one key/value pair. Assume the above code and the following query, which doubles the title parameter to whack the key/value pairing off by one, turning all subsequent keys into values and all subsequent values into keys:

?title=foo;title=user;bar=

This would send off the following query instead:

$db->delete('music', { title => 'foo', user => undef });

In this specific case, the attack isn't effective obviously, as you can still only add more restrictions on what rows to delete, instead of widening the query. If the attacker can guess one of the parameters that need to be overridden, this still can be an effective attack:

$db->insert('users', { is_admin => 0, user => param('username') });

Here, the attacker can easily overwrite admin to any value they want by supplying an appropriately formatted query:

?user=corion;user=is_admin;user=1

So, I think that one should never use the results of param() directly in another list that will get passed on without further scrunity. Note that no parameter validation that validates a single parameter will protect you against this vector.

Replies are listed 'Best First'.
Re^3: Issuing a DELETE statement with DBI
by bart (Canon) on Sep 01, 2006 at 12:11 UTC
    OK... So how about this?
    $db->delete('music', { title => scalar param('title') });
Re^3: Issuing a DELETE statement with DBI
by kwaping (Priest) on Sep 01, 2006 at 16:36 UTC
    I was curious about this, so I ran a quick test and was unable to duplicate your findings (CGI.pm version 3.05). In my output, the keys and values appear as I would expect. Can you please explain how you came to your conclusion? Here's my code:
    #!/usr/bin/perl use strict; use warnings; use CGI; my $cgi = CGI->new(); use Data::Dumper::Simple; print Dumper($cgi); print scalar $cgi->param('title'); print $/; __END__ > ./tmp.pl title=foo\;title=user\;bar= $cgi = bless( { '.parameters' => [ 'title', 'bar' ], 'bar' => [ '' ], '.charset' => 'ISO-8859-1', '.fieldnames' => {}, 'title' => [ 'foo', 'user' ], 'escape' => 1 }, 'CGI' ); foo
    Thanks!

    ---
    It's all fine and dandy until someone has to look at the code.

      Where are you getting the scalar from? I used the following to test my statement:

      perl -MCGI=param -le "print for param('title')" ?title=foo;title=bar foo bar

      To make this into a "really working" attack by injecting keys and values the author didn't foresee, I used this program:

      use strict; use Data::Dumper; use CGI; my $q = CGI->new('?title=foo;title=bar;title=injected_key;title=inject +ed_value'); my $query = { title => $q->param('title') }; print Dumper $query; __END__ # Outputs: $VAR1 = { 'injected_key' => 'injected_value', 'title' => 'bar' };
        Thank you for your explanation. Here's my code again, modified slightly to remove scalar and to more closely match the OP's model. The results are the same.
        #!/usr/bin/perl use strict; use warnings; use CGI; my $cgi = CGI->new(); use Data::Dumper::Simple; print Dumper($cgi); my $title = $cgi->param('title'); print $title; print $/; __END__ > ./tmp.pl title=foo\;title=user\;bar= $cgi = bless( { '.parameters' => [ 'title', 'bar' ], 'bar' => [ '' ], '.charset' => 'ISO-8859-1', '.fieldnames' => {}, 'title' => [ 'foo', 'user' ], 'escape' => 1 }, 'CGI' ); foo

        ---
        It's all fine and dandy until someone has to look at the code.