in reply to Issuing a DELETE statement with DBI

You have a value quoting/placeholder problem, which b10m already pointed out to you. But I'd like to show you how the code can look when using DBIx::Simple, which allows using methods coming from SQL::Abstract, and takes care of those issues all by itself:
$db->delete('music', { title => param('title') });

A really nice thing about SQL::Abstract and, thus, DBIx::Simple is that it takes care of the special case where the value is undef, for a field value of NULL, too. Just using placeholders wouldn't do, as the SQL query

DELETE FROM music WHERE title = NULL
won't ever delete anything.

Replies are listed 'Best First'.
Re^2: Issuing a DELETE statement with DBI
by Corion (Patriarch) on Sep 01, 2006 at 12:07 UTC

    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.

      OK... So how about this?
      $db->delete('music', { title => scalar param('title') });
      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' };