perlmunky wrote:
On Jan 11, 2008 6:47 PM, Chris Charley <[EMAIL PROTECTED]> wrote:

See this colimn by Randal L. Schwartz. It descibes injection attacks.
http://www.stonehenge.com/merlyn/UnixReview/col58.html

Thanks, I read the page, alongside the wikipedia page and I think I
understand what an sql injection is.  My code follows.  The first section is
for a text suggestion drop-down menu - it produces a selection based on the
current user input in a text box and runs a DBI query to get suggestions for
a user.  The details are passed by a javascript routine to catalyst.

sub _build_suggestion_list {
    my ($self, $c) = @_;

    my $table_and_col_name = $c->req->params->{column_name};
    my $current_text       = $c->req->params->{text_input};

    my @well_column_names = @{_get_column_names($c,"T1")};
    my @gi_column_names   = @{_get_column_names($c,"T2")};

    my %genuine_columns = ();
    for (@gi_column_names)   { $genuine_columns{${$_}[0]} = 1; }
    for (@well_column_names) { $genuine_columns{${$_}[0]} = 1; }

Why copy two the two arrays when you can just use the references directly? The dereferencing syntax is usually $_->[0] not ${$_}[0]. You can remove a lot of the duplication by doing it like this:

my %genuine_columns = map { $_->[0] => 1 }
                      map @{ _get_column_names( $c, $_ ) },
                      qw/T1 T2/;


#I dont think I need the {1,}
    if ($current_text =~ /\:{1,}|\--{1,}|\#{1,}|\;|insert|drop|create|^$/ig)

The characters ':', '-', '#' and ';' are not special in regular expressions so they don't have to be escaped. The quantifier '{1,}' could be written more simply as '+'. The pattern is evaluated in boolean context so the /g option is extraneous.


{
        my $tc = "<ul><li>Invalid Input (: ; --; #)</li></ul>";
        $c->res->body($tc);
    } else {
        if ( exists $genuine_columns{$table_and_col_name}) {
            my ($table, $column) = split /\./, $table_and_col_name;
            my $model            = $c->model(q(DB));
            my $dbh              = $model->storage->dbh;

            my $select = ("select distinct $table\.$column from $table where
$table\.$column LIKE \'\%$current_text\%\'");

The characters ".", "'" and "%" are not special in a double quoted string so they don't have to be escaped.


            my $sql_exe = $dbh->prepare($select); $sql_exe->execute();
            my $results = $sql_exe->fetchall_arrayref();

            my $options = "<ul>";
            for (@$results) {
                $options .= "<li>${$_}[0]</li>";

${$_}[0] is usually written as $_->[0].

            }
            $options .= "</ul>";
            $c->res->body($options);
            }    else {
                my $tc = "<ul><li>The column names are invalid - please see
admin</li></ul>";
                $c->res->body($tc);
            }
    }
}

The next section contains the query constructor.  This takes all the user
input from multiple rows (users can create as many as they want).  I have
limited the options but this, i think, doesn't help because someone could
craft their own post and submit that. The query is run in another subroutine
which returns the data to the template toolkit end of things.

sub _query : Local {
    my ( $self, $c ) = @_;

    my $href_params = ($c->request->parameters());

    delete $$href_params{'button'};

$$href_params{'button'} is usually written as $href_params->{button}

    my @well_column_names = @{_get_column_names($c,"T1")};
    my @gi_column_names   = @{_get_column_names($c,"T2")};

    my %genuine_columns = ();
    for (@gi_column_names)   { $genuine_columns{${$_}[0]} = 1; }
    for (@well_column_names) { $genuine_columns{${$_}[0]} = 1; }

Same as with the other subroutine:

my %genuine_columns = map { $_->[0] => 1 }
                      map @{ _get_column_names( $c, $_ ) },
                      qw/T1 T2/;


    #Are the columns the ones that they should be?
    @{$$href_params{'select_these'}} = grep { $genuine_columns{$_} }
@{$$href_params{'select_these'}};

@{$$href_params{'select_these'}} is usually written as @{ $href_params->{ select_these } }

[ The same applies to every other instance where this occurs. ]


    my $select = "";
    if ( ref($$href_params{'select_these'}) =~ 'ARRAY' or
ref($$href_params{'select_these'}) =~ 'REF') {

You are using '=~' when you should be using 'eq'.

if ( ref( $href_params->{ select_these } ) eq 'ARRAY' or ref( $href_params{ select_these } ) eq 'REF' ) {


        if ( @{$$href_params{'select_these'}} == 0 ) { $select = " T2.y ";}
        else { $select = join(" ,", @{$$href_params{'select_these'}}); }
    } else {
        if ($$href_params{'select_these'} eq "") { $select = "T1.x"; }
        else {
            if ( exists $genuine_columns{$$href_params{'select_these'}}) {
                $select = $$href_params{'select_these'};
            } else {
                $select = "T1.x";
            }
        }
    }

#Two blocks - one for where there are multiple user conditions and the other
for singles
    my $conditional = "";
    if ( ref($$href_params{'conditional_type'}) =~ 'ARRAY' or
ref($$href_params{'conditional_type'}) =~ 'REF') {

You are using '=~' when you should be using 'eq'.


        for (my $i = 0; $i < @{$$href_params{'conditional_type'}}; $i++) {

That is usually written as:

         for my $i ( 0 .. $#{ $href_params->{ conditional_type } } ) {


                $conditional .= ${$$href_params{'conditional_type'}}[$i]   .
' ';
                $conditional .= ${$$href_params{'select_column_name'}}[$i] .
' ';

                #Check for foul play
                if (${$$href_params{'user_text'}}[$i] =~
/\;|:|--|#|insert|drop|create|\'|\"|null/ig ) {

The characters ';', "'" and '"' are not special in regular expressions so they don't have to be escaped. The pattern is evaluated in boolean context so the /g option is extraneous.


                    ${$$href_params{'user_text'}}[$i] = "null"; #This can't
be 'null'
                }

                if ( ${$$href_params{'case_option'}}[$i] =~ /^like$/ig ) {

The pattern is evaluated in boolean context so the /g option is extraneous. Since the pattern is anchored at beginning and end you should probably use 'eq' instead:

              if ( 'like' eq lc $href_params->{ case_option }[ $i ] ) {


                    $conditional .= "${$$href_params{'case_option'}}[$i]
'\%${$$href_params{'user_text'}}[$i]\%'"        . ' ';

The '%' character is not special in a double quoted string.

${$$href_params{'user_text'}}[$i] is usually written as $href_params->{user_text}[$i]


                } else {
                    $conditional .=
${$$href_params{'case_option'}}[$i]        . ' ';
                    $conditional .=
${$$href_params{'user_text'}}[$i]          . ' ';
                }
        }
    } else {
            if ($$href_params{'user_text'} =~
/\;|:|--|#|insert|drop|create|\'|\"|null/ig ) {

The characters ';', "'" and '"' are not special in regular expressions so they don't have to be escaped. The pattern is evaluated in boolean context so the /g option is extraneous.


                $$href_params{'user_text'} = "null";
            }
            if ($$href_params{'case_option'} =~ /like/ig) {

Use 'eq' instead:

             if ( 'like' eq lc $href_params->{ case_option } ) {


                $$href_params{'user_text'} =
"'\%$$href_params{'user_text'}\%' ";
            }
            $conditional = $$href_params{'conditional_type'} . " " .
$$href_params{'select_column_name'} . " " . $$href_params{'case_option'} . "
" . $$href_params{'user_text'};

You could use a hash slice to simplify that:

$conditional = "@{ $href_params }{ qw/conditional_type select_column_name case_option user_text/ }";


    }

    _construct_query($self, $c, \$select, \$conditional);

Do you really need to pass references to scalars?


    #pass to Catalyst stash + template
}



John
--
Perl isn't a toolbox, but a small machine shop where you
can special-order certain sorts of tools at low cost and
in short order.                            -- Larry Wall

--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/


Reply via email to