Thread: SQL injection

SQL injection

From
Yonatan Ben-Nes
Date:
Hi all,

I'm currently trying to build a defence against SQL INJECTION, after
reading some material on it I arrived to few possible solutions and I
would like to know if anyone can comment anything about them or maybe
add a solution of its own:

1. PachyRand: SQL Randomization for the PostgreSQL JDBC Driver - seems
to be the best solution (easiest and most protective) though I didnt
understood entirely if the solution is available for production
enviorments or not, information can be attained at:
http://nsl.cs.columbia.edu/projects/pachyrand/ &
http://mice.cs.columbia.edu/getTechreport.php?techreportID=355&format=pdf&

2. Running for each data which will be used at the db checks with
regular expressions to find out if its valid, this method is quite
complicated to me (dont know regular expressions too much) and it
demands diffrent checks to each data field (with quite big problems at
open text data), at the end im afraid that holes will exist..

3. Running PHP functions like settype($data, 'integer') to be sure that
the data which arrive is at the correct format and to the text run
pg_escape_string($data), I suspect that this method wont block even
close to 100% of the attacks, just like the former option.

Another factor is the overhead to the system, I think that the previous
methods don't create much overhead but if anyone have another idea of
course it will also need to be efficent.

Any new ideas or comments will be received gladly.

Thanks in advance!
   Yonatan Ben-Nes

Re: SQL injection

From
Alex Turner
Date:
I don't know too much about this solutions, but It always seemed to me
that simple numeric validation plus magic-quotes will work just fine.

Simply validate any numeric input (or you can just quote it with
postgresql, and postgres will do it for you), and auto-escape any
string inputs (particularly quotes).  replace("'","\\'");

I haven't figured out an attack that will get past this simple scheme
yet, I would love for somebody to correct me, because my sites are
built on this simple premise ;).

Alex

On 10/31/05, Yonatan Ben-Nes <da@canaan.co.il> wrote:
> Hi all,
>
> I'm currently trying to build a defence against SQL INJECTION, after
> reading some material on it I arrived to few possible solutions and I
> would like to know if anyone can comment anything about them or maybe
> add a solution of its own:
>
> 1. PachyRand: SQL Randomization for the PostgreSQL JDBC Driver - seems
> to be the best solution (easiest and most protective) though I didnt
> understood entirely if the solution is available for production
> enviorments or not, information can be attained at:
> http://nsl.cs.columbia.edu/projects/pachyrand/ &
> http://mice.cs.columbia.edu/getTechreport.php?techreportID=355&format=pdf&
>
> 2. Running for each data which will be used at the db checks with
> regular expressions to find out if its valid, this method is quite
> complicated to me (dont know regular expressions too much) and it
> demands diffrent checks to each data field (with quite big problems at
> open text data), at the end im afraid that holes will exist..
>
> 3. Running PHP functions like settype($data, 'integer') to be sure that
> the data which arrive is at the correct format and to the text run
> pg_escape_string($data), I suspect that this method wont block even
> close to 100% of the attacks, just like the former option.
>
> Another factor is the overhead to the system, I think that the previous
> methods don't create much overhead but if anyone have another idea of
> course it will also need to be efficent.
>
> Any new ideas or comments will be received gladly.
>
> Thanks in advance!
>    Yonatan Ben-Nes
>
> ---------------------------(end of broadcast)---------------------------
> TIP 5: don't forget to increase your free space map settings
>

Re: SQL injection

From
Ben
Date:
Maybe I'm not very creative, but it sure seems to me that if you escape your
strings, make sure your numbers are numbers, and your booleans are actually
booleans, then you're protected....

On Mon, 31 Oct 2005, Yonatan Ben-Nes wrote:

> Any new ideas or comments will be received gladly.
>

Re: SQL injection

From
Dan Sugalski
Date:
At 7:54 PM +0200 10/31/05, Yonatan Ben-Nes wrote:
>Hi all,
>
>I'm currently trying to build a defence against SQL INJECTION, after
>reading some material on it I arrived to few possible solutions and
>I would like to know if anyone can comment anything about them or
>maybe add a solution of its own:

Just out of curiosity, is this something that constant SQL (or SQL
generated by code) with placeholder variables won't protect against?
--
                Dan

--------------------------------------it's like this-------------------
Dan Sugalski                          even samurai
dan@sidhe.org                         have teddy bears and even
                                       teddy bears get drunk

Re: SQL injection

From
MaXX
Date:
Hi,

Yonatan Ben-Nes wrote:
> Hi all,
>
> I'm currently trying to build a defence against SQL INJECTION, after
> reading some material on it I arrived to few possible solutions and I
> would like to know if anyone can comment anything about them or maybe
> add a solution of its own:
[...]

If you're running PHP on an Apache server check mod_security, you'll have to
tune a little bit it's default ruleset, but it does a great job for me. It
will not protect you against tricks like 'chr(39)' (single quote) or
funnier 'cH%52(123-84)' unless you write specific rules. It inspect both
GET an POST payloads, performs unescaping and lots of other cool things
(protection agains shell command injection)...
Be warned, it has some side effects, as it will kick you off if you try to
publish SQL code on your site even if your code isn't malicious or
sentences that may look like sql (delete from something)...

As suggested, parameters validation is required, regexps are great for this
job and are easy to learn (do it you'll see). Do the validation in your PHP
before sending the query to your server (do not rely only on checking
inside stored procedures as the injection can take place before the actual
checking)

HTH,
--
MaXX

Re: SQL injection

From
Alex Turner
Date:
Can you demonstrate a URL/attack that would constitute an injection
attack that would get around magic-quotes, or provide some links to
such?

Alex

On 10/31/05, MaXX <bs139412@skynet.be> wrote:
> Hi,
>
> Yonatan Ben-Nes wrote:
> > Hi all,
> >
> > I'm currently trying to build a defence against SQL INJECTION, after
> > reading some material on it I arrived to few possible solutions and I
> > would like to know if anyone can comment anything about them or maybe
> > add a solution of its own:
> [...]
>
> If you're running PHP on an Apache server check mod_security, you'll have to
> tune a little bit it's default ruleset, but it does a great job for me. It
> will not protect you against tricks like 'chr(39)' (single quote) or
> funnier 'cH%52(123-84)' unless you write specific rules. It inspect both
> GET an POST payloads, performs unescaping and lots of other cool things
> (protection agains shell command injection)...
> Be warned, it has some side effects, as it will kick you off if you try to
> publish SQL code on your site even if your code isn't malicious or
> sentences that may look like sql (delete from something)...
>
> As suggested, parameters validation is required, regexps are great for this
> job and are easy to learn (do it you'll see). Do the validation in your PHP
> before sending the query to your server (do not rely only on checking
> inside stored procedures as the injection can take place before the actual
> checking)
>
> HTH,
> --
> MaXX
>
> ---------------------------(end of broadcast)---------------------------
> TIP 5: don't forget to increase your free space map settings
>

Re: SQL injection

From
MaXX
Date:
Alex Turner wrote:

> Can you demonstrate a URL/attack that would constitute an injection
> attack that would get around magic-quotes, or provide some links to
> such?
>
[...]
Just quoting an article in Hackin9 (N°5/2005) I was just reading before
writing my post (page 53, translated from french): "The PHP function
magic_quote() allow to cancel automaticaly the effect of a single quote
using backslashes; however this function is used in conjunction with  the
function strip_slashes(), the escaping characters are suppressed."

I admit that I haven't tried and don't realy know how to implement this one
but I presume they have tried. I'll google on this to see if I can find
some demonstration as this is the first time I read this magazine.

After reading this article I tested some of the suggested attacks agains my
Perl CMS engine based on Pg and hopefully the given examples work with
MySQL but I'm reviewing my regexps just in case...

--
MaXX


Re: SQL injection

From
"Jim C. Nasby"
Date:
Does PHP support prepared queries with bound parameters for PostgreSQL?
Not only is that foolproof (unless you're calling a function that uses
an argument to build a query string...), you'll get a performance boost
as well since PostgreSQL won't have to reparse and plan every query.

On Mon, Oct 31, 2005 at 07:54:58PM +0200, Yonatan Ben-Nes wrote:
> Hi all,
>
> I'm currently trying to build a defence against SQL INJECTION, after
> reading some material on it I arrived to few possible solutions and I
> would like to know if anyone can comment anything about them or maybe
> add a solution of its own:
>
> 1. PachyRand: SQL Randomization for the PostgreSQL JDBC Driver - seems
> to be the best solution (easiest and most protective) though I didnt
> understood entirely if the solution is available for production
> enviorments or not, information can be attained at:
> http://nsl.cs.columbia.edu/projects/pachyrand/ &
> http://mice.cs.columbia.edu/getTechreport.php?techreportID=355&format=pdf&
>
> 2. Running for each data which will be used at the db checks with
> regular expressions to find out if its valid, this method is quite
> complicated to me (dont know regular expressions too much) and it
> demands diffrent checks to each data field (with quite big problems at
> open text data), at the end im afraid that holes will exist..
>
> 3. Running PHP functions like settype($data, 'integer') to be sure that
> the data which arrive is at the correct format and to the text run
> pg_escape_string($data), I suspect that this method wont block even
> close to 100% of the attacks, just like the former option.
>
> Another factor is the overhead to the system, I think that the previous
> methods don't create much overhead but if anyone have another idea of
> course it will also need to be efficent.
>
> Any new ideas or comments will be received gladly.
>
> Thanks in advance!
>   Yonatan Ben-Nes
>
> ---------------------------(end of broadcast)---------------------------
> TIP 5: don't forget to increase your free space map settings
>

--
Jim C. Nasby, Sr. Engineering Consultant      jnasby@pervasive.com
Pervasive Software      http://pervasive.com    work: 512-231-6117
vcard: http://jim.nasby.net/pervasive.vcf       cell: 512-569-9461

Re: SQL injection

From
Alex Turner
Date:
I didn't think query plans were cached between sessions, in which case
prepeared statements aren't worth much for most HTTP based systems
(not counting luckily re-using the same connection using pgpool)...

Please correct me if I'm mistaken - I like being wrong ;)

Alex

On 10/31/05, Jim C. Nasby <jnasby@pervasive.com> wrote:
> Does PHP support prepared queries with bound parameters for PostgreSQL?
> Not only is that foolproof (unless you're calling a function that uses
> an argument to build a query string...), you'll get a performance boost
> as well since PostgreSQL won't have to reparse and plan every query.
>
> On Mon, Oct 31, 2005 at 07:54:58PM +0200, Yonatan Ben-Nes wrote:
> > Hi all,
> >
> > I'm currently trying to build a defence against SQL INJECTION, after
> > reading some material on it I arrived to few possible solutions and I
> > would like to know if anyone can comment anything about them or maybe
> > add a solution of its own:
> >
> > 1. PachyRand: SQL Randomization for the PostgreSQL JDBC Driver - seems
> > to be the best solution (easiest and most protective) though I didnt
> > understood entirely if the solution is available for production
> > enviorments or not, information can be attained at:
> > http://nsl.cs.columbia.edu/projects/pachyrand/ &
> > http://mice.cs.columbia.edu/getTechreport.php?techreportID=355&format=pdf&
> >
> > 2. Running for each data which will be used at the db checks with
> > regular expressions to find out if its valid, this method is quite
> > complicated to me (dont know regular expressions too much) and it
> > demands diffrent checks to each data field (with quite big problems at
> > open text data), at the end im afraid that holes will exist..
> >
> > 3. Running PHP functions like settype($data, 'integer') to be sure that
> > the data which arrive is at the correct format and to the text run
> > pg_escape_string($data), I suspect that this method wont block even
> > close to 100% of the attacks, just like the former option.
> >
> > Another factor is the overhead to the system, I think that the previous
> > methods don't create much overhead but if anyone have another idea of
> > course it will also need to be efficent.
> >
> > Any new ideas or comments will be received gladly.
> >
> > Thanks in advance!
> >   Yonatan Ben-Nes
> >
> > ---------------------------(end of broadcast)---------------------------
> > TIP 5: don't forget to increase your free space map settings
> >
>
> --
> Jim C. Nasby, Sr. Engineering Consultant      jnasby@pervasive.com
> Pervasive Software      http://pervasive.com    work: 512-231-6117
> vcard: http://jim.nasby.net/pervasive.vcf       cell: 512-569-9461
>
> ---------------------------(end of broadcast)---------------------------
> TIP 3: Have you checked our extensive FAQ?
>
>                http://www.postgresql.org/docs/faq
>

Re: SQL injection

From
"Matthew D. Fuller"
Date:
On Mon, Oct 31, 2005 at 10:12:45AM -0800 I heard the voice of
Ben, and lo! it spake thus:
> Maybe I'm not very creative, but it sure seems to me that if you
> escape your strings, make sure your numbers are numbers, and your
> booleans are actually booleans, then you're protected....

Once nice touch is that booleans and numbers will be accepted by Pg if
they're escaped and quoted like strings.  So, in PHP, I always run
EVERYTHING through a wrapper db_quote() function that returns
something like ("'" . pg_escape_string(foo) . "'") (or its equivalent
in MySQL, etc) and just call it fixed.  Of course, I do type checks
for user feedback and such as well, but in case something slips
through, it's all escaped.


--
Matthew Fuller     (MF4839)   |  fullermd@over-yonder.net
Systems/Network Administrator |  http://www.over-yonder.net/~fullermd/
           On the Internet, nobody can hear you scream.

Re: SQL injection

From
Kevin Murphy
Date:
Can some knowledgeable person set the record straight on SQL injection,
please?  I thought that the simple answer was to use prepared statements
with bind variables (except when you are letting the user specify whole
chunks of SQL, ugh), but there are many people posting who either don't
know about prepared statements or know something I don't.

Thanks,
Kevin Murphy

P.S.  I don't use PHP, but google informs me that PHP definitely has
prepared statement options: PEAR::DB, PDO in 5.X+, etc.

Re: SQL injection

From
Tom Lane
Date:
Kevin Murphy <murphy@genome.chop.edu> writes:
> Can some knowledgeable person set the record straight on SQL injection,
> please?  I thought that the simple answer was to use prepared statements
> with bind variables (except when you are letting the user specify whole
> chunks of SQL, ugh), but there are many people posting who either don't
> know about prepared statements or know something I don't.

That's a good way to do it if you are using a client library that
supports it.  It's not the Only Way though.

In my mind the issue is not just whether a particular technique is
bulletproof; it's how sure you can be that you have not missed applying
it anywhere.  If you rely on applying an escaping function then it's
pretty easy to forget it in one or two places, and it only takes one
hole to be vulnerable :-(.  The nice thing about prepared statements is
that it's relatively easier to be sure you haven't messed up, because
the coding rule is pretty simple: if all SQL commands are constant
strings you're definitely safe.

The downside of course is that this approach doesn't handle all cases,
for instance if you have to generate AND/OR where-conditions on the fly
(think of a search engine for example).

            regards, tom lane

Re: SQL injection

From
"Jim C. Nasby"
Date:
On Mon, Oct 31, 2005 at 10:13:20PM -0500, Alex Turner wrote:
> I didn't think query plans were cached between sessions, in which case
> prepeared statements aren't worth much for most HTTP based systems
> (not counting luckily re-using the same connection using pgpool)...
>
> Please correct me if I'm mistaken - I like being wrong ;)

No, you're right, but if you're not using connection pooling you clearly
don't care about performance anyway...
--
Jim C. Nasby, Sr. Engineering Consultant      jnasby@pervasive.com
Pervasive Software      http://pervasive.com    work: 512-231-6117
vcard: http://jim.nasby.net/pervasive.vcf       cell: 512-569-9461

Re: SQL injection

From
Scott Marlowe
Date:
On Tue, 2005-11-01 at 09:09, Jim C. Nasby wrote:
> On Mon, Oct 31, 2005 at 10:13:20PM -0500, Alex Turner wrote:
> > I didn't think query plans were cached between sessions, in which case
> > prepeared statements aren't worth much for most HTTP based systems
> > (not counting luckily re-using the same connection using pgpool)...
> >
> > Please correct me if I'm mistaken - I like being wrong ;)
>
> No, you're right, but if you're not using connection pooling you clearly
> don't care about performance anyway...

Depends on what you mean by performance.  I've written apps that were
used by one or two people at once, and spit out 100M at a shot for an
excel spread sheet or made huge 100 page pdfs.  They had to run fast,
but connection time wasn't an issue.  Since the average run time of
those scripts as 1 to 30 seconds, the connect time was absolutely not an
issue.

Re: SQL injection

From
"Jim C. Nasby"
Date:
On Tue, Nov 01, 2005 at 11:19:12AM -0600, Scott Marlowe wrote:
> On Tue, 2005-11-01 at 09:09, Jim C. Nasby wrote:
> > On Mon, Oct 31, 2005 at 10:13:20PM -0500, Alex Turner wrote:
> > > I didn't think query plans were cached between sessions, in which case
> > > prepeared statements aren't worth much for most HTTP based systems
> > > (not counting luckily re-using the same connection using pgpool)...
> > >
> > > Please correct me if I'm mistaken - I like being wrong ;)
> >
> > No, you're right, but if you're not using connection pooling you clearly
> > don't care about performance anyway...
>
> Depends on what you mean by performance.  I've written apps that were
> used by one or two people at once, and spit out 100M at a shot for an
> excel spread sheet or made huge 100 page pdfs.  They had to run fast,
> but connection time wasn't an issue.  Since the average run time of
> those scripts as 1 to 30 seconds, the connect time was absolutely not an
> issue.

Hrm... what's that quote about stereotyping? :)

Granted, sometimes connection startup time doesn't matter. But in most
web environments (we are talking PHP here remember) you'll either be
using a connection pool or not caring at all about performance...
--
Jim C. Nasby, Sr. Engineering Consultant      jnasby@pervasive.com
Pervasive Software      http://pervasive.com    work: 512-231-6117
vcard: http://jim.nasby.net/pervasive.vcf       cell: 512-569-9461

Re: SQL injection

From
Scott Marlowe
Date:
On Tue, 2005-11-01 at 12:12, Jim C. Nasby wrote:
> On Tue, Nov 01, 2005 at 11:19:12AM -0600, Scott Marlowe wrote:
> > On Tue, 2005-11-01 at 09:09, Jim C. Nasby wrote:
> > > On Mon, Oct 31, 2005 at 10:13:20PM -0500, Alex Turner wrote:
> > > > I didn't think query plans were cached between sessions, in which case
> > > > prepeared statements aren't worth much for most HTTP based systems
> > > > (not counting luckily re-using the same connection using pgpool)...
> > > >
> > > > Please correct me if I'm mistaken - I like being wrong ;)
> > >
> > > No, you're right, but if you're not using connection pooling you clearly
> > > don't care about performance anyway...
> >
> > Depends on what you mean by performance.  I've written apps that were
> > used by one or two people at once, and spit out 100M at a shot for an
> > excel spread sheet or made huge 100 page pdfs.  They had to run fast,
> > but connection time wasn't an issue.  Since the average run time of
> > those scripts as 1 to 30 seconds, the connect time was absolutely not an
> > issue.
>
> Hrm... what's that quote about stereotyping? :)
>
> Granted, sometimes connection startup time doesn't matter. But in most
> web environments (we are talking PHP here remember) you'll either be
> using a connection pool or not caring at all about performance...

What's that quote about all generalizations?  :)

In all honesty, in a corporate intranet for about 1500 users, with an
average of 10 to 20 logged in at a time, our average page response time
was well under a second, and server was rock solid and stable.  Our
effort was better spent elsewhere, like tuning SQL queries, than
worrying about connection pooling.  It was more a solution in search of
a problem.  This on a site that connected to the database for almost
every page it delivered.

Now, if it was for amazon.com s front page, well, of course, connection
times might well have meant a lot more.  But it wasn't, and performance
was important.  We just didn't have 1,000 users pounding on the door for
a drink of water, we had dozens going to the well with 5 gallon buckets.

Re: SQL injection

From
Yonatan Ben-Nes
Date:
Jim C. Nasby wrote:
> Does PHP support prepared queries with bound parameters for PostgreSQL?
> Not only is that foolproof (unless you're calling a function that uses
> an argument to build a query string...), you'll get a performance boost
> as well since PostgreSQL won't have to reparse and plan every query.
>
> On Mon, Oct 31, 2005 at 07:54:58PM +0200, Yonatan Ben-Nes wrote:
>
>>Hi all,
>>
>>I'm currently trying to build a defence against SQL INJECTION, after
>>reading some material on it I arrived to few possible solutions and I
>>would like to know if anyone can comment anything about them or maybe
>>add a solution of its own:
>>
>>1. PachyRand: SQL Randomization for the PostgreSQL JDBC Driver - seems
>>to be the best solution (easiest and most protective) though I didnt
>>understood entirely if the solution is available for production
>>enviorments or not, information can be attained at:
>>http://nsl.cs.columbia.edu/projects/pachyrand/ &
>>http://mice.cs.columbia.edu/getTechreport.php?techreportID=355&format=pdf&
>>
>>2. Running for each data which will be used at the db checks with
>>regular expressions to find out if its valid, this method is quite
>>complicated to me (dont know regular expressions too much) and it
>>demands diffrent checks to each data field (with quite big problems at
>>open text data), at the end im afraid that holes will exist..
>>
>>3. Running PHP functions like settype($data, 'integer') to be sure that
>>the data which arrive is at the correct format and to the text run
>>pg_escape_string($data), I suspect that this method wont block even
>>close to 100% of the attacks, just like the former option.
>>
>>Another factor is the overhead to the system, I think that the previous
>>methods don't create much overhead but if anyone have another idea of
>>course it will also need to be efficent.
>>
>>Any new ideas or comments will be received gladly.
>>
>>Thanks in advance!
>>  Yonatan Ben-Nes
>>
>>---------------------------(end of broadcast)---------------------------
>>TIP 5: don't forget to increase your free space map settings
>>
>
>

Won't that create a performance penalty to extremly dynamic sites cause
the plan will be planned only once and the data may vary alot?
Beside that I still won't have a solution to places where I create a
query which can vary alot (JOIN diffrent tables, diffrent WHERE etc...),
it doesn't seem logical to me to start and create all of the diffrent
possibilites of queries when I create such an option at a site.

Thanks alot everyone and sorry for posting something and then not
returning for so long (though everything seem like rolling alone nicely :)).
   Yonatan Ben-Nes

Re: SQL injection

From
"Jim C. Nasby"
Date:
On Tue, Nov 01, 2005 at 08:27:21PM +0200, Yonatan Ben-Nes wrote:
> Won't that create a performance penalty to extremly dynamic sites cause
> the plan will be planned only once and the data may vary alot?
> Beside that I still won't have a solution to places where I create a
> query which can vary alot (JOIN diffrent tables, diffrent WHERE etc...),
> it doesn't seem logical to me to start and create all of the diffrent
> possibilites of queries when I create such an option at a site.

Yes, when you start getting into dynamically generated SQL you quickly
loose the performance benefit of prepared statements just because odds
are good that nothing else will use it. But you still have the benefit
of bound parameters and protection from injection.
--
Jim C. Nasby, Sr. Engineering Consultant      jnasby@pervasive.com
Pervasive Software      http://pervasive.com    work: 512-231-6117
vcard: http://jim.nasby.net/pervasive.vcf       cell: 512-569-9461

Re: SQL injection

From
Dan Sugalski
Date:
At 8:57 AM -0500 11/1/05, Tom Lane wrote:
>Kevin Murphy <murphy@genome.chop.edu> writes:
>>  Can some knowledgeable person set the record straight on SQL injection,
>>  please?  I thought that the simple answer was to use prepared statements
>>  with bind variables (except when you are letting the user specify whole
>>  chunks of SQL, ugh), but there are many people posting who either don't
>  > know about prepared statements or know something I don't.

[snippage]

>The nice thing about prepared statements is
>that it's relatively easier to be sure you haven't messed up, because
>the coding rule is pretty simple: if all SQL commands are constant
>strings you're definitely safe.
>
>The downside of course is that this approach doesn't handle all cases,
>for instance if you have to generate AND/OR where-conditions on the fly
>(think of a search engine for example).

The lack of entirely-constant SQL isn't necessarily a barrier to
using prepared statements and bound variables -- I'm doing this in a
pretty large app, and it's not that big a deal to safely and
dynamically generate the SQL and still use bound variables.

The single biggest issue it that the planner has no access to the
data in the where clause, so it unconditionally rules out some paths.
(LIKE clauses with constant prefix text, like "FOO%", get hit hard by
this)

It's certainly not as simple as all-constant SQL text, but it's
definitely doable, and worth looking into.
--
                Dan

--------------------------------------it's like this-------------------
Dan Sugalski                          even samurai
dan@sidhe.org                         have teddy bears and even
                                       teddy bears get drunk

Re: SQL injection

From
Yonatan Ben-Nes
Date:
Jim C. Nasby wrote:
> On Tue, Nov 01, 2005 at 08:27:21PM +0200, Yonatan Ben-Nes wrote:
>
>>Won't that create a performance penalty to extremly dynamic sites cause
>>the plan will be planned only once and the data may vary alot?
>>Beside that I still won't have a solution to places where I create a
>>query which can vary alot (JOIN diffrent tables, diffrent WHERE etc...),
>>it doesn't seem logical to me to start and create all of the diffrent
>>possibilites of queries when I create such an option at a site.
>
>
> Yes, when you start getting into dynamically generated SQL you quickly
> loose the performance benefit of prepared statements just because odds
> are good that nothing else will use it. But you still have the benefit
> of bound parameters and protection from injection.

My problem with the dynamically generated SQL is that I'll have to
create and maintain lots of prepared statements and be sure that I dont
miss any available option, and also every time that ill have to do basic
changes at the queries I'll have to update each one of those prepared
statements.... it seems to me like of extra work for sites which can
create many dynamic queries.

And about the performance penalty, I don't really care about losing the
benefit of prepared statements, I'm actually more afraid of receiving
penalty of using them... the following is quoted from the manual:
"In some situations, the query plan produced for a prepared statement
will be inferior to the query plan that would have been chosen if the
statement had been submitted and executed normally. This is because when
the statement is planned and the planner attempts to determine the
optimal query plan, the actual values of any parameters specified in the
statement are unavailable. PostgreSQL collects statistics on the
distribution of data in the table, and can use constant values in a
statement to make guesses about the likely result of executing the
statement. Since this data is unavailable when planning prepared
statements with parameters, the chosen plan may be suboptimal."

Thanks again,
   Yonatan Ben-Nes

Re: SQL injection

From
Martijn van Oosterhout
Date:
On Tue, Nov 01, 2005 at 11:31:36PM +0200, Yonatan Ben-Nes wrote:
> And about the performance penalty, I don't really care about losing the
> benefit of prepared statements, I'm actually more afraid of receiving
> penalty of using them... the following is quoted from the manual:
> "In some situations, the query plan produced for a prepared statement
> will be inferior to the query plan that would have been chosen if the
> statement had been submitted and executed normally. This is because when

<snip>

Note: Just because your coding style uses prepared statements doesn't
mean it uses them in the server. For example, in Perl DBI it has that
whole prepare/execute cycle, but the values are actually interpolated
(with appropriate quoting) on the client side and sent as a normal
query.

Hence have your cake and eat it too...

Now, in theory a newer DBI version could use server side prepared
statements but I imagine I'll be turning them off. I don't have any
queries with a significant parse/plan cost to make it worth the costs
you mention here...

It's a pity the protocol doesn't have a single shot prepare/bind
command which would allow you to send the values out-of-line (no
quoting issues) but still provide them at the planning/optimising stage
to get good plans. Ah well, can't have everything.

Have a nice day,
--
Martijn van Oosterhout   <kleptog@svana.org>   http://svana.org/kleptog/
> Patent. n. Genius is 5% inspiration and 95% perspiration. A patent is a
> tool for doing 5% of the work and then sitting around waiting for someone
> else to do the other 95% so you can sue them.

Attachment

Re: SQL injection

From
"Jim C. Nasby"
Date:
On Tue, Nov 01, 2005 at 11:31:36PM +0200, Yonatan Ben-Nes wrote:
> Jim C. Nasby wrote:
> >Yes, when you start getting into dynamically generated SQL you quickly
> >loose the performance benefit of prepared statements just because odds
> >are good that nothing else will use it. But you still have the benefit
> >of bound parameters and protection from injection.
>
> My problem with the dynamically generated SQL is that I'll have to
> create and maintain lots of prepared statements and be sure that I dont
> miss any available option, and also every time that ill have to do basic
> changes at the queries I'll have to update each one of those prepared
> statements.... it seems to me like of extra work for sites which can
> create many dynamic queries.

So don't maintain them. Just re-plan every time. My point is using bound
parameters to protect against injection.

As for the sub-optimal planning, I don't think that's normally an issue
unless your data distribution is uneven.
--
Jim C. Nasby, Sr. Engineering Consultant      jnasby@pervasive.com
Pervasive Software      http://pervasive.com    work: 512-231-6117
vcard: http://jim.nasby.net/pervasive.vcf       cell: 512-569-9461

Re: SQL injection

From
"Jim C. Nasby"
Date:
On Tue, Nov 01, 2005 at 11:00:26PM +0100, Martijn van Oosterhout wrote:
> It's a pity the protocol doesn't have a single shot prepare/bind
> command which would allow you to send the values out-of-line (no
> quoting issues) but still provide them at the planning/optimising stage
> to get good plans. Ah well, can't have everything.

Is there any reason that couldn't be added? Sounds like it might make a
good newbie TODO...
--
Jim C. Nasby, Sr. Engineering Consultant      jnasby@pervasive.com
Pervasive Software      http://pervasive.com    work: 512-231-6117
vcard: http://jim.nasby.net/pervasive.vcf       cell: 512-569-9461

Re: SQL injection

From
Tino Wildenhain
Date:
Am Dienstag, den 01.11.2005, 23:31 +0200 schrieb Yonatan Ben-Nes:
> Jim C. Nasby wrote:
> > On Tue, Nov 01, 2005 at 08:27:21PM +0200, Yonatan Ben-Nes wrote:
> >
> >>Won't that create a performance penalty to extremly dynamic sites cause
> >>the plan will be planned only once and the data may vary alot?
> >>Beside that I still won't have a solution to places where I create a
> >>query which can vary alot (JOIN diffrent tables, diffrent WHERE etc...),
> >>it doesn't seem logical to me to start and create all of the diffrent
> >>possibilites of queries when I create such an option at a site.
> >
> >
> > Yes, when you start getting into dynamically generated SQL you quickly
> > loose the performance benefit of prepared statements just because odds
> > are good that nothing else will use it. But you still have the benefit
> > of bound parameters and protection from injection.
>
> My problem with the dynamically generated SQL is that I'll have to
> create and maintain lots of prepared statements and be sure that I dont
> miss any available option, and also every time that ill have to do basic
> changes at the queries I'll have to update each one of those prepared
> statements.... it seems to me like of extra work for sites which can
> create many dynamic queries.

You could just wrap the creation and execution of your SQL in your
database abstraction layer. Where execute() prepares and then executes
and executemany() prepares and then runs an array of data to execute.




Re: SQL injection

From
"Matthew D. Fuller"
Date:
On Tue, Nov 01, 2005 at 08:57:04AM -0500 I heard the voice of
Tom Lane, and lo! it spake thus:
>
> If you rely on applying an escaping function then it's pretty easy
> to forget it in one or two places, and it only takes one hole to be
> vulnerable :-(.

The trick is to make it a religious ritual.  I escape things into _q
variables:

$name = $_REQUEST['name'];
$name_q = db_quote($name);

And have myself thoroughly trained to ONLY use _q variables in
building queries.  Of course, once in a while, I forget to _create_
the _q version before using it, but then I get a nice loud error
message castigating me for it.  I often (not consistently) create _q
variables even for known-good strings and such that I hardcode into
the program.

It could well be that using prepared statements is by various metrics
a "better" way to go about things.  But I'm far too lazy to try and
reprogram my fingers    ;-)


--
Matthew Fuller     (MF4839)   |  fullermd@over-yonder.net
Systems/Network Administrator |  http://www.over-yonder.net/~fullermd/
           On the Internet, nobody can hear you scream.

Re: SQL injection

From
Alex Turner
Date:
My point is that with magic_quotes on in PHP, php already escapes
quotes for you in all inbound variables.  This makes the process
automatic, and therefore fool proof, which is kinda the whole point.
You want a mechanism that there isn't an easy way around, like
forgetting to db_quote once in a while.  I'm just trying to find out
if there is an example where magic quotes by itself doesn't work, and
there is a viable injection attack possible, and if so, what it is, so
I can figure out how to prevent it ;).

Alex.

On 11/1/05, Matthew D. Fuller <fullermd@over-yonder.net> wrote:
> On Tue, Nov 01, 2005 at 08:57:04AM -0500 I heard the voice of
> Tom Lane, and lo! it spake thus:
> >
> > If you rely on applying an escaping function then it's pretty easy
> > to forget it in one or two places, and it only takes one hole to be
> > vulnerable :-(.
>
> The trick is to make it a religious ritual.  I escape things into _q
> variables:
>
> $name = $_REQUEST['name'];
> $name_q = db_quote($name);
>
> And have myself thoroughly trained to ONLY use _q variables in
> building queries.  Of course, once in a while, I forget to _create_
> the _q version before using it, but then I get a nice loud error
> message castigating me for it.  I often (not consistently) create _q
> variables even for known-good strings and such that I hardcode into
> the program.
>
> It could well be that using prepared statements is by various metrics
> a "better" way to go about things.  But I'm far too lazy to try and
> reprogram my fingers    ;-)
>
>
> --
> Matthew Fuller     (MF4839)   |  fullermd@over-yonder.net
> Systems/Network Administrator |  http://www.over-yonder.net/~fullermd/
>            On the Internet, nobody can hear you scream.
>
> ---------------------------(end of broadcast)---------------------------
> TIP 9: In versions below 8.0, the planner will ignore your desire to
>        choose an index scan if your joining column's datatypes do not
>        match
>

Re: SQL injection

From
Michael Glaesemann
Date:
On Nov 3, 2005, at 4:26 , Alex Turner wrote:

> My point is that with magic_quotes on in PHP, php already escapes
> quotes for you in all inbound variables.  This makes the process
> automatic, and therefore fool proof, which is kinda the whole point.
> You want a mechanism that there isn't an easy way around, like
> forgetting to db_quote once in a while.  I'm just trying to find out
> if there is an example where magic quotes by itself doesn't work, and
> there is a viable injection attack possible, and if so, what it is, so
> I can figure out how to prevent it ;).


I'm wondering if using magic_quotes will have issues down the pipe
when backslash escaping is no longer the default in PostgreSQL to
follow SQL spec. Am I correct in thinking that either the SQL
statements would have to be rewritten to use E'' strings, the server
setting would have to allow the use of backslashes, or magic_quotes
would have to be turned off and variables otherwise escaped to
prevent SQL injection?

As an aside, it's interesting to see that the PHP documentation states:
---
Magic Quotes is a process that automagically escapes incoming data to
the PHP script. It's preferred to code with magic quotes off and to
instead escape the data at runtime, as needed.
---
http://jp.php.net/magic_quotes

Michael Glaesemann
grzm myrealbox com




Re: SQL injection

From
Matthew Terenzio
Date:
On Nov 2, 2005, at 6:08 PM, Michael Glaesemann wrote:

> As an aside, it's interesting to see that the PHP documentation states:
> ---
> Magic Quotes is a process that automagically escapes incoming data to
> the PHP script. It's preferred to code with magic quotes off and to
> instead escape the data at runtime, as needed.
Haven't been totally immersed in this thread but here are reasons given
for not using Magic Quotes:

http://us2.php.net/manual/en/security.magicquotes.whynot.php

And here is pg_escape_string() :

http://us3.php.net/manual/en/function.pg-escape-string.php


Re: SQL injection

From
Alex Turner
Date:
Curiously none are security reasons, they are more portability reasons
(and pretty thin ones at that)... but then this is PHP we are talking
about - let me just say register_globals and end it there.

I would have to say that for security purposes - I would want magic
quotes _on_ rather than off for the whole reasons of SQL Injection
that we already talked about.  Generally most scripts I write spend
more time sending data to the DB then re-reading straight from the DB
rather than re-using data pushed through POST/GET, and the functions
that are exceptions auto unescape the data again for me...

Alex

On 11/2/05, Matthew Terenzio <matt@jobsforge.com> wrote:
>
> On Nov 2, 2005, at 6:08 PM, Michael Glaesemann wrote:
>
> > As an aside, it's interesting to see that the PHP documentation states:
> > ---
> > Magic Quotes is a process that automagically escapes incoming data to
> > the PHP script. It's preferred to code with magic quotes off and to
> > instead escape the data at runtime, as needed.
> Haven't been totally immersed in this thread but here are reasons given
> for not using Magic Quotes:
>
> http://us2.php.net/manual/en/security.magicquotes.whynot.php
>
> And here is pg_escape_string() :
>
> http://us3.php.net/manual/en/function.pg-escape-string.php
>
>

Re: SQL injection

From
Hannes Dorbath
Date:
On 03.11.2005 04:12, Alex Turner wrote:
> I would have to say that for security purposes - I would want magic
> quotes _on_ rather than off for the whole reasons of SQL Injection
> that we already talked about.

magic_quotes is evil and does if anything only prevent the simplest
cases of SQL injections. Keep it turned off. Use
http://php.net/pg_query_params exclusively to build secure queries..


--
Regards,
Hannes Dorbath

Re: SQL injection

From
Yonatan Ben-Nes
Date:
Hannes Dorbath wrote:
> On 03.11.2005 04:12, Alex Turner wrote:
>
>> I would have to say that for security purposes - I would want magic
>> quotes _on_ rather than off for the whole reasons of SQL Injection
>> that we already talked about.
>
>
> magic_quotes is evil and does if anything only prevent the simplest
> cases of SQL injections. Keep it turned off. Use
> http://php.net/pg_query_params exclusively to build secure queries..
>
>

The problem with pg_query_params is that you will be forced to use an RC
version of PHP.... I don't know about you but I think that for
production sites I prefer to use the final versions.

I think that prepared statements is the best solution here even if its
encumbering everything alittle...

Re: SQL injection

From
Alex Turner
Date:
Please, enlighten us all and demostrate a case of SQL Injection that
gets around magic quotes.  I know am I trying to think of one - and I
can't come up with one.  Instead of just claiming it to be 'evil' why
don't you actualy back the statement up with some reasoned arguments?

I hate FUD.

Alex

On 11/3/05, Hannes Dorbath <light@theendofthetunnel.de> wrote:
> On 03.11.2005 04:12, Alex Turner wrote:
> > I would have to say that for security purposes - I would want magic
> > quotes _on_ rather than off for the whole reasons of SQL Injection
> > that we already talked about.
>
> magic_quotes is evil and does if anything only prevent the simplest
> cases of SQL injections. Keep it turned off. Use
> http://php.net/pg_query_params exclusively to build secure queries..
>
>
> --
> Regards,
> Hannes Dorbath
>
> ---------------------------(end of broadcast)---------------------------
> TIP 5: don't forget to increase your free space map settings
>

Re: SQL injection

From
Hannes Dorbath
Date:
On 03.11.2005 16:15, Alex Turner wrote:
> Please, enlighten us all and demostrate a case of SQL Injection that
> gets around magic quotes.

Just someone needs to forget to put quotes around a param..

$q = "DELETE FROM foo WHERE bar = {$_GET['id']};";

instead of

$q = "DELETE FROM foo WHERE bar = '{$_GET['id']}';";

It deadly, with or without magic_quotes. pg_query_params() prevents such
situations. Besides some encoding tricks to encode single quotes
(%2527).. mb_string, mod_rewrite there are many things that /can/
prevent MQ from working as expected, search google. And even if MQ does
what it should, errors like the above are very common. Oh, and why MQ is
evil, really not all data passed to a PHP script is meant to be used as
query params, and if so, create a recursive version of array_map() and
use that with pg_escape_string as callback.


--
Regards,
Hannes Dorbath

Re: SQL injection

From
Benjamin Smith
Date:
Prepared statements are the way to go.

I developed my own prepared statements methodology (I called it "SafeQuery")
some time back before discovering that others had done it. It's so nice,
since I've not worried about SQL injection for YEARS.

Sample of my API:

<?
$sql="SELECT auth.login
 FROM auth
 WHERE username='[username]'
 AND password='[password]'
 ";
$todb=array('username'=>$_REQUEST['username'],
 'password'=>$_REQUEST['password']);
if (!$res=$MDB->SafeQuery($sql, $todb))
 return Error("Database query failure");
?>

SafeQuery checks:
    1) That the variables in the query (in brackets) and in the input array all
match up.
    2) Runs pg_escape_string on all elements in $todb;
    3) Copy/Pastes strings from the array into the query.
    4) Runs query against DB, returns results from pg_exec();

-Ben

On Tuesday 01 November 2005 05:27, Kevin Murphy wrote:
> Can some knowledgeable person set the record straight on SQL injection,
> please?  I thought that the simple answer was to use prepared statements
> with bind variables (except when you are letting the user specify whole
> chunks of SQL, ugh), but there are many people posting who either don't
> know about prepared statements or know something I don't.
>
> Thanks,
> Kevin Murphy
>
> P.S.  I don't use PHP, but google informs me that PHP definitely has
> prepared statement options: PEAR::DB, PDO in 5.X+, etc.
>
> ---------------------------(end of broadcast)---------------------------
> TIP 2: Don't 'kill -9' the postmaster
>

--
"The best way to predict the future is to invent it."
- XEROX PARC slogan, circa 1978