Thread: design, plpgsql and sql injection in dynamically generated sql

design, plpgsql and sql injection in dynamically generated sql

From
Ivan Sergio Borgonovo
Date:
I've several list of items that have to be rendered on a web apps in
the same way.

The structure is:

create table items (
  itemid int primary key,
  /* some fields */
);

create table headert1 (
  ht1 int primary key,
  /* several other fields that varies in nature */
);

create table itemlistt1 (
  ht1 int references headert1 ht1,
  itemid references items (itemid)
);

The query always match this pattern:

select i.fieldA, i.fieldB, ..., from itemlistt1 il
  join items i on i.itemid=il.itemid
  where il.ht1=[somevalue];

the nature of the lists and their usage pattern is very different.
So unless someone come up with a better design I still would like to
keep the item lists in different tables.

I'd like to build up a function that takes the name of the table and
the key to dynamically build up the query... but I don't know what
should I use to sanitize them.

create or replace function getitemlist(listtable text, listkey text,
keyvalue int,
, out ....) rerurns setof records as
$$
declare
  statement text;
begin
  statement:='select i.fieldA, i.fieldB, ..., from ' ||
   escapefunc1(listtable) ||
   ' il join items i on i.itemid=il.itemid ' ||
   ' where il.' || escapefunc2(listtable) || '=' || keyvalue;
  return query execute statement; // can I?

is it quote_ident the right candidate for escapefuncN?

But this is still at risk of misuse... (eg. passing ('items',
'fieldA', 1) may return something that was not meant to be seen.

One way would be to build up a table of permitted (table, key) and
then just pass the table and the key value.
What should be the equivalent of quote_ident in PHP?

thanks

--
Ivan Sergio Borgonovo
http://www.webthatworks.it


Re: design, plpgsql and sql injection in dynamically generated sql

From
Pavel Stehule
Date:
Hello

I am not sure, if it's possible for you. PostgreSQL 8.4 has EXECUTE
USING clause, it is 100% safe.

Pavel

2009/8/17 Ivan Sergio Borgonovo <mail@webthatworks.it>:
> I've several list of items that have to be rendered on a web apps in
> the same way.
>
> The structure is:
>
> create table items (
>  itemid int primary key,
>  /* some fields */
> );
>
> create table headert1 (
>  ht1 int primary key,
>  /* several other fields that varies in nature */
> );
>
> create table itemlistt1 (
>  ht1 int references headert1 ht1,
>  itemid references items (itemid)
> );
>
> The query always match this pattern:
>
> select i.fieldA, i.fieldB, ..., from itemlistt1 il
>  join items i on i.itemid=il.itemid
>  where il.ht1=[somevalue];
>
> the nature of the lists and their usage pattern is very different.
> So unless someone come up with a better design I still would like to
> keep the item lists in different tables.
>
> I'd like to build up a function that takes the name of the table and
> the key to dynamically build up the query... but I don't know what
> should I use to sanitize them.
>
> create or replace function getitemlist(listtable text, listkey text,
> keyvalue int,
> , out ....) rerurns setof records as
> $$
> declare
>  statement text;
> begin
>  statement:='select i.fieldA, i.fieldB, ..., from ' ||
>   escapefunc1(listtable) ||
>   ' il join items i on i.itemid=il.itemid ' ||
>   ' where il.' || escapefunc2(listtable) || '=' || keyvalue;
>  return query execute statement; // can I?
>
> is it quote_ident the right candidate for escapefuncN?
>
> But this is still at risk of misuse... (eg. passing ('items',
> 'fieldA', 1) may return something that was not meant to be seen.
>
> One way would be to build up a table of permitted (table, key) and
> then just pass the table and the key value.
> What should be the equivalent of quote_ident in PHP?
>
> thanks
>
> --
> Ivan Sergio Borgonovo
> http://www.webthatworks.it
>
>
> --
> Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
> To make changes to your subscription:
> http://www.postgresql.org/mailpref/pgsql-general
>

Re: design, plpgsql and sql injection in dynamically generated sql

From
Sam Mason
Date:
On Mon, Aug 17, 2009 at 12:36:49PM +0200, Ivan Sergio Borgonovo wrote:
> I've several list of items that have to be rendered on a web apps in
> the same way.
[..]
> the nature of the lists and their usage pattern is very different.
> So unless someone come up with a better design I still would like to
> keep the item lists in different tables.

As you've explained it, I'd be tempted to have a function for each
table.  You're going to have special code outside the database for each
one, so why not a (small) amount for each one inside the database.

> I'd like to build up a function that takes the name of the table and
> the key to dynamically build up the query... but I don't know what
> should I use to sanitize them.

I'd stay away from this; they may be doing similar things at the moment
but if they really are as different as you seem to suggest then having
them as separate functions would make this easier.

If they really are that similar then you should have all the data in one
table anyway!

--
  Sam  http://samason.me.uk/

Re: design, plpgsql and sql injection in dynamically generated sql

From
Ivan Sergio Borgonovo
Date:
On Mon, 17 Aug 2009 12:48:21 +0200
Pavel Stehule <pavel.stehule@gmail.com> wrote:

> Hello
>
> I am not sure, if it's possible for you. PostgreSQL 8.4 has EXECUTE
> USING clause, it is 100% safe.

Sorry I don't get it.

How can I use USING safely when the substitution involves a table
name?

The examples I've seen just involve column values.

Where is the corresponding fine manual page?

Still I don't get how USING could make safer plpgsql functions...
well... I'm going to check some prejudices I have on pg functions
firts...

I thought that if you passed eg. text to
create or replace function typetest(a int) returns text as
$$
begin
raise notice 'is this an int? %', a;
-- don't do anything else with a

and calling

select * from typetest('tonno');

was going to raise an error anyway.

So somehow I find the example here
http://okbob.blogspot.com/2008/06/execute-using-feature-in-postgresql-84.html
not really helpful in understanding what's going on.

Maybe an example with text comparing a version using quote_literal
and one using USING could be clearer...

or am I completely missing the point?

far from an optimal solution I've built a "client side" array of
permitted table, key to dynamically build the query on the client
side.

--
Ivan Sergio Borgonovo
http://www.webthatworks.it


Re: design, plpgsql and sql injection in dynamically generated sql

From
Pavel Stehule
Date:
2009/8/18 Ivan Sergio Borgonovo <mail@webthatworks.it>:
> On Mon, 17 Aug 2009 12:48:21 +0200
> Pavel Stehule <pavel.stehule@gmail.com> wrote:
>
>> Hello
>>
>> I am not sure, if it's possible for you. PostgreSQL 8.4 has EXECUTE
>> USING clause, it is 100% safe.
>
> Sorry I don't get it.
>
> How can I use USING safely when the substitution involves a table
> name?
>
> The examples I've seen just involve column values.
>
> Where is the corresponding fine manual page?
>
> Still I don't get how USING could make safer plpgsql functions...
> well... I'm going to check some prejudices I have on pg functions
> firts...

some unsafe function:

create or replace function foo(tablename varchar, parameter varchar)
returns int as $$
declare _result integer;
begin
  execute 'select i from ' || table_name || ' where x = \'' ||
parameter || '\'' into _result;
  return result;
end;
$$ language plpgsql strict;

I thing, so there are two safe variants

create or replace function foo(tablename varchar, parameter varchar)
returns int as $$
declare _result integer;
begin
  execute 'select i from ' || quote_ident(table_name) || ' where x = '
|| quote_literal(parameter) into _result;
  return _result;
end;
$$ language plpgsql strict;

or

create or replace function foo(tablename varchar, parameter varchar)
returns int as $$
declare _result integer;
begin
  execute 'select i from ' || table_name::regclass || ' where x = $1'
using parameter into _result;
  return _result;
end;
$$ language plpgsql strict;

"USING" works like prepared statements.

regards
Pavel Stehule

>
> I thought that if you passed eg. text to
> create or replace function typetest(a int) returns text as
> $$
> begin
> raise notice 'is this an int? %', a;
> -- don't do anything else with a
>
> and calling
>
> select * from typetest('tonno');
>
> was going to raise an error anyway.
>
> So somehow I find the example here
> http://okbob.blogspot.com/2008/06/execute-using-feature-in-postgresql-84.html
> not really helpful in understanding what's going on.
>
> Maybe an example with text comparing a version using quote_literal
> and one using USING could be clearer...
>
> or am I completely missing the point?
>
> far from an optimal solution I've built a "client side" array of
> permitted table, key to dynamically build the query on the client
> side.
>
> --
> Ivan Sergio Borgonovo
> http://www.webthatworks.it
>
>
> --
> Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
> To make changes to your subscription:
> http://www.postgresql.org/mailpref/pgsql-general
>

Re: design, plpgsql and sql injection in dynamically generated sql

From
Ivan Sergio Borgonovo
Date:
On Tue, 18 Aug 2009 12:38:49 +0200
Pavel Stehule <pavel.stehule@gmail.com> wrote:

> some unsafe function:

I suspected something similar.

I think many would appreciate if you put these examples here
http://www.okbob.blogspot.com/2008/06/execute-using-feature-in-postgresql-84.html
and substitute the int example there with the text one.

thanks

--
Ivan Sergio Borgonovo
http://www.webthatworks.it


Re: design, plpgsql and sql injection in dynamically generated sql

From
Pavel Stehule
Date:
2009/8/18 Ivan Sergio Borgonovo <mail@webthatworks.it>:
> On Tue, 18 Aug 2009 12:38:49 +0200
> Pavel Stehule <pavel.stehule@gmail.com> wrote:
>
>> some unsafe function:
>
> I suspected something similar.
>
> I think many would appreciate if you put these examples here
> http://www.okbob.blogspot.com/2008/06/execute-using-feature-in-postgresql-84.html
> and substitute the int example there with the text one.

actualized
http://okbob.blogspot.com/2008/06/execute-using-feature-in-postgresql-84.html

regards
Pavel

>
> thanks
>
> --
> Ivan Sergio Borgonovo
> http://www.webthatworks.it
>
>