Skip Menu |

This queue is for tickets about the DBD-Pg CPAN distribution.

Report information
The Basics
Id: 41565
Status: resolved
Priority: 0/
Queue: DBD-Pg

People
Owner: greg [...] turnstep.com
Requestors: andrew [...] tao11.riddles.org.uk
Cc:
AdminCc:

Bug Information
Severity: Critical
Broken in: (no value)
Fixed in: 2.14.0



Subject: Type-specific quoting functions considered harmful (with bonus SQL-injection)
quote.c contains a number of functions for different types; most of these are broken, as follows: quote_geom rejects almost all valid geometric values, due to too-strict limitations on allowed characters (no provision for -, ., E, etc. -- coordinates are floating-point values) quote_path, quote_circle likewise quote_bool does what it is supposed to, but the logic is in completely the wrong place (see below). quote_integer seems, fortunately, to be dead code - if it were ever used it would break all kinds of stuff. and, to cap it off, the use of null_quote on integer fields can lead to SQL injection: $s=$d->prepare(q[select ? where 1=?], { pg_server_prepare => 0 }); $s->bind_param(2,undef,SQL_INTEGER); $s->execute(1,"2; drop table x;"); because nothing checks that the value is actually an integer. Putting type-specific logic like that of quote_bool into a quote_* function only handles half the job; it leaves out the question of what to do if a parameter of the same type is passed directly to PQexecParams or PQexecPrepared. This leads to, for example, boolean values other than exactly "0" or "1" being sometimes rejected and sometimes accepted, e.g. $s=$d->prepare(q[select 1 where ? or ?=1], { pg_server_prepare => 0 }); $s->bind_param(1,undef,SQL_BOOLEAN); $s->execute("f",2); # errors $s=$d->prepare(q[select 1 where ?], { pg_server_prepare => 0 }); $s->bind_param(1,undef,SQL_BOOLEAN); $s->execute("f"); # "f" treated as false (also, quote_bool treats perl "true" values, such as "0e0" or "0 but true" as though they were false, while these produce errors if passed as real parameters) This whole thing needs a redesign, not just patching up the existing code.
Subject: Re: [rt.cpan.org #41565] Type-specific quoting functions considered harmful (with bonus SQL-injection)
Date: Tue, 09 Dec 2008 18:30:40 +0000
To: bug-DBD-Pg [...] rt.cpan.org
From: Rudolf Lippan <rlippan [...] remotelinux.com>
On Tue, 09 Dec 2008 11:04:16 -0500, "Andrew Gierth via RT" <bug-DBD-Pg@rt.cpan.org> wrote: Show quoted text
> and, to cap it off, the use of null_quote on integer fields can lead to > SQL injection: > > $s=$d->prepare(q[select ? where 1=?], { pg_server_prepare => 0 }); > $s->bind_param(2,undef,SQL_INTEGER); > $s->execute(1,"2; drop table x;"); > > because nothing checks that the value is actually an integer.
Am I missing something here or is this not completely obvious? You are not using server side prepare, and you explicitly telling the driver to treat the incoming value as an integer. It is almost as if you were saying, 'Hello Mr. Driver, I am passing in a value into an integer column, please do not try and guess on how to quote this, but rather quote it as if you had guessed that it were an integer.' And What does the driver do when it sees an integer? Nothing. So the driver does nothing, just like you asked. Or look at it the other way, if the driver did not think that it looked like an integer, how would it quote it... Like an integer. Which is by doing nothing. So you see, you can't win here. Either way you get nothing ;) A good old fashioned croaking might be fun, though. croak "$value does not look like a number" if !looks_like_number($value); But, alas, with that you loose the ability to use SQL_INTEGER for the of abuse client side prepared statements (not that I have ever done that myself... I promise.) It would be possible, however, to pull off of the IV when something is bound as SQL_INTEGER, and that would probably make sense.... Except for the possible complaints of, "when I try to insert this string, I get some weird number in my database". -r
On Tue Dec 09 13:35:11 2008, RUDY wrote: Show quoted text
> > > On Tue, 09 Dec 2008 11:04:16 -0500, "Andrew Gierth via RT" > <bug-DBD-Pg@rt.cpan.org> wrote: >
> > and, to cap it off, the use of null_quote on integer fields can lead to > > SQL injection: > > > > $s=$d->prepare(q[select ? where 1=?], { pg_server_prepare => 0 }); > > $s->bind_param(2,undef,SQL_INTEGER); > > $s->execute(1,"2; drop table x;"); > > > > because nothing checks that the value is actually an integer.
> > Am I missing something here or is this not completely obvious? You are not > using server side prepare, and you explicitly telling the driver to treat > the incoming value as an integer.
The whole point of using placeholders is to guarantee that SQL injection can NOT occur regardless of whether the data passed in is as the application expects it or not. It is the driver's responsibility to either generate correct SQL or throw an error. For example, it would be quite reasonable for an integer placeholder to be replaced by a string such as (integer '1234') which is both type-correct and proof against injection. As for using server-side prepare; one serious problem with the driver as it stands is that the application writer can find it _very_ hard to predict whether any given prepare()/bind_param()*/execute() sequence will lead to the driver using prepare/execPrepared, execParams, or plain exec when it comes to the execute call - and the handling of type information is VERY different between those cases, to the extent that many queries (especially ones involving function calls) will succeed or fail according to which choice the driver makes. (There's also a performance reason to prefer execParams (one roundtrip) over prepare/execPrepared (two roundtrips) for statements that are only going to be executed once.)
From: bryce2 [...] obviously.com
Sounds like this should be assigned a CVE (See http://cve.mitre.org/ ).
Working on solutions for this: see r12857 or later, will be part of the next release.
On Sun Jul 12 14:45:41 2009, greg@turnstep.com wrote: Show quoted text
> Working on solutions for this: see r12857 or later, will be part of the > next release.
Have some quick fixes in place as of r13090
Should be fixed as of 2.14.0. If not, please reopen this ticket or create a new one. I've moved the non-deterministic exec* complaint to ticket 48272.