Re: ISO guidelines/strategies to guard injection attacks

From: Kynn Jones <kynnjo(at)gmail(dot)com>
To: Andy Colson <andy(at)squeakycode(dot)net>
Cc: PostgreSQL <pgsql-general(at)postgresql(dot)org>
Subject: Re: ISO guidelines/strategies to guard injection attacks
Date: 2010-01-21 21:53:44
Message-ID: c2350ba41001211353q16c07ad6q2ecf4b2e15fee036@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

On Tue, Jan 19, 2010 at 4:49 PM, Andy Colson <andy(at)squeakycode(dot)net> wrote:

> On 1/19/2010 3:39 PM, Andy Colson wrote:
>
>> On 1/19/2010 3:23 PM, Kynn Jones wrote:
>>
>>> I have a Perl CGI script (using DBD::Pg) that interfaces with a
>>> server-side Pg database. I'm looking for general
>>> guidelines/tools/strategies that will help me guard against SQL
>>> injection attacks.
>>>
>>> Any pointers/suggestions would be much appreciated.
>>>
>>> ~K
>>>
>>>
>> prepare your queries:
>>
>> my $q = $db->prepare('select something from table where key = $1');
>> $q->execute(42);
>>
>> and..
>> $db->do('update table set field = $1 where key = $2', undef, 'key', 42);
>>
>> (*guessed at the do(). I think there is an undef in there, or something*)
>>
>> -Andy
>>
>>
> Also, add to that, in general, use Taint Mode. Perl wont trust data until
> its been sanitized... and neither should you.
>

I can't get this to work in any way. At the end of this email, I post a
complete script that runs fine under Taint Mode, even though it DBI is being
passed tainted variables in various places.

Do I need to do anything else to force a failure with tainted data?

Demo script below; to run it, it requires four command-line arguments: the
name of a database, the name of a table in that database, the name of an
integer-type column in that table, and some integer. E.g., a run may look
like this:

$ perl -T demo_script.pl mydb mytable mycolum 42
1
1
1
1
1
1

NB: you will need to modify the user and password parameters in the call to
DBI->connect.

The important thing to note is that the connect, prepare, and execute
methods all receive tainted arguments, but run without any problem.
Furthermore, the subsequent fetchall_arrayref also runs without any
problem.

Hence, at least in this example, -T was no protection against SQL injection
attacks. Note, in particular, that the way that the $sql variable is
initialized is an ideal opportunity for an SQL injection attack.

#!/usr/bin/perl

use strict;
use warnings FATAL => 'all';

use DBI;

my $dbname = shift;
my $tablename = shift;
my $colname = shift;
my $id = shift;
my $sql = qq(SELECT * FROM "$tablename" WHERE "$colname" = \$1;);
my $connection_string = "dbi:Pg:dbname=$dbname";

# when this script is run under -T, the output from all the following
# print statements is 1; if the script is *not* run under -T, then
# they are all 0.
print +(is_tainted($dbname) ? 1 : 0), "\n";
print +(is_tainted($tablename) ? 1 : 0), "\n";
print +(is_tainted($colname) ? 1 : 0), "\n";
print +(is_tainted($id) ? 1 : 0), "\n";
print +(is_tainted($connection_string) ? 1 : 0), "\n";
print +(is_tainted($sql) ? 1 : 0), "\n";

my $dbh = DBI->connect($connection_string,
"kynn", undef,
+{
RaiseError => 1,
PrintError => 0,
PrintWarn => 0,
});

my $sth = $dbh->prepare($sql);
$sth->execute($id);
my $fetched = $sth->fetchall_arrayref;

sub is_tainted {
# this sub is adapted from Programming Perl, 3rd ed., p. 561
my $arg = shift;
my $empty = do {
no warnings 'uninitialized';
substr($arg, 0, 0);
};
local $@;
eval { eval "# $empty" };
return length($@) != 0;
}

~K

In response to

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Bob Pawley 2010-01-21 23:08:39 Old/New
Previous Message Scott Frankel 2010-01-21 20:48:03 Re: db cluster location