Re: [PyGreSQL] Plans for Addressing CVE-2018-1058 in PyGreSQL

2019-08-24 Thread Justin Pryzby
On Sat, Aug 24, 2019 at 10:05:46PM +0200, Christoph Zwerschke wrote:
> Am 16.08.2019 um 19:58 schrieb Shoaib Lari:
> > I was wondering if the PyGreSQL community has any plans to address
> > PostgreSQL security vulnerability
> > https://wiki.postgresql.org/wiki/A_Guide_to_CVE-2018-1058:_Protect_Your_Search_Path.
> 
> Hi Shoaib, thanks for bringing this to our attention.

Yes, thanks for mentioning it.

> The internal query used by the type cache looks something like this:
> 
> SELECT oid, typname, ... FROM pg_type WHERE oid=%s
> 
> As far as I understand, to make things secure at least what concerns
> PyGreSQL, we would need to change that query to:
> 
> SELECT oid, typname, ... FROM pg_catalog.pg_type
> WHERE oid OPERATOR(pg.catalog.=) %s

Yes, I think

> This would make the queries look more ugly and lengthy. Not sure about the
> performance impact - maybe it would be even faster because of the explicit
> schema name.

I agree that they're uglier...

> What do others think? Should we make these changes?

But I tend to think we should add schema quals, since that's what postgres
does.

See the commit for that CVE:
https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=3d2aed664ee8271fd6c721ed0aa10168cda112ea;hp=3bf05e096b9f8375e640c5d7996aa57efd7f240c

But it looks like that convention dates back to:
https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=039cb479884abc28ee494f6cf6c5e7ec26b88fc8

See describe.c
https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/bin/psql/describe.c

For example \d makes a half dozen queries which look like:

[pryzbyj@database ~]$ psql ts -Ec '\d pg_class'
* QUERY **
SELECT c.oid,
  n.nspname,
  c.relname
FROM pg_catalog.pg_class c
 LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE c.relname OPERATOR(pg_catalog.~) '^(pg_class)$'
  AND pg_catalog.pg_table_is_visible(c.oid)
ORDER BY 2, 3;
**

> Now, if someone was able to do that I think your goose has been cooked
> anyway since nearly every query will be affected.
...
> I think in practice you need to rely on users not being able to create
> objects in the public schema, otherwise you're set for deeper troubles
> anyway, no matter how secure your API is.

| Without adjusting the configuration or access control settings, any user that 
can connect to a database can also create objects in the public schema for that 
database. 

It's true that one shouldn't create untrusted DB users, but there's a privilege
system in place and it's intended to allow users to be at least partially
segregated.  If postgres/pygres and other projects don't use schema quals, then
it's hard to imagine that a typical admin will do so.
___
PyGreSQL mailing list
PyGreSQL@Vex.Net
https://mail.vex.net/mailman/listinfo/pygresql


Re: [PyGreSQL] Plans for Addressing CVE-2018-1058 in PyGreSQL

2019-08-24 Thread Christoph Zwerschke

Am 16.08.2019 um 19:58 schrieb Shoaib Lari:
> I was wondering if the PyGreSQL community has any plans to address
> PostgreSQL security vulnerability
> 
https://wiki.postgresql.org/wiki/A_Guide_to_CVE-2018-1058:_Protect_Your_Search_Path.


Hi Shoaib, thanks for bringing this to our attention.

> Now connect to the postgres database thorough pygresql, and issue a
> simple query.
>
> import pgdb
> conn = pgdb.connect(database='postgres')
> c = conn.cursor()
> c.execute('SELECT 1')
>
> You will get the following output:
>
> WARNING:  trojan

So what's happening here is that the equality operator used in the 
internal query used by the type cache is called which triggers the 
warning above because you have overridden the operator in the public 
schema which takes precedence before the default one in pg_catalog.


Now, if someone was able to do that I think your goose has been cooked 
anyway since nearly every query will be affected.


The internal query used by the type cache looks something like this:

SELECT oid, typname, ... FROM pg_type WHERE oid=%s

As far as I understand, to make things secure at least what concerns 
PyGreSQL, we would need to change that query to:


SELECT oid, typname, ... FROM pg_catalog.pg_type
WHERE oid OPERATOR(pg.catalog.=) %s

And there's another query for composite types that needs to be fixed in 
a similar way. We would also need to fix the internal query in the 
classic pg.py module, which has not only a type cache but also other 
higher level functions which run internal queries.


This would make the queries look more ugly and lengthy. Not sure about 
the performance impact - maybe it would be even faster because of the 
explicit schema name.


What do others think? Should we make these changes?

The guide that you linked to says this:

"If you write your queries with specific schema.object form, including 
objects that exist in the pg_catalog (e.g. calling SELECT 
pg_catalog.lower('ALICE');), then you are not immediately vulnerable to 
this issue."


But it does not mention operators in this context which are easily 
overlooked and which will make any query secured that way immediately 
become very ugly. In practice I think that's not feasible except when 
all queries are created automatically e.g. by an ORM.


I think in practice you need to rely on users not being able to create 
objects in the public schema, otherwise you're set for deeper troubles 
anyway, no matter how secure your API is.


-- Christoph














___
PyGreSQL mailing list
PyGreSQL@Vex.Net
https://mail.vex.net/mailman/listinfo/pygresql


[PyGreSQL] Plans for Addressing CVE-2018-1058 in PyGreSQL

2019-08-24 Thread Shoaib Lari
Hi,

I was wondering if the PyGreSQL community has any plans to address
PostgreSQL
security vulnerability
https://wiki.postgresql.org/wiki/A_Guide_to_CVE-2018-1058:_Protect_Your_Search_Path
.

Here is a simple test case to reproduce the problem.

Create the following two functions in, say, postgres database.

CREATE FUNCTION public.evil_eq(oid, integer) RETURNS boolean
LANGUAGE plpgsql
AS $$
begin
raise warning 'trojan';
return oideq($1, $2::oid);
end
$$;

CREATE OPERATOR public.= (
PROCEDURE = public.evil_eq,
LEFTARG = oid,
RIGHTARG = integer
);


Now connect to the postgres database thorough pygresql, and issue a simple
query.

import pgdb
conn = pgdb.connect(database='postgres')
c = conn.cursor()
c.execute('SELECT 1')

You will get the following output:

WARNING:  trojan
.
..

<< the above is repated 439 times>>


>>>

Running another query such as 'SELECT * FROM pg_catalog.pg_class LIMIT 1'
calls the public.evil_eq() function more than two thousand times.

Also, this happens when the first time you run the query after creating the
function and connecting.  Therefore, the call to OPERATOR(=) is done by
PyGreSQL internal queries to get metadata information from the server after
initial connect.


The Wiki
https://wiki.postgresql.org/wiki/A_Guide_to_CVE-2018-1058:_Protect_Your_Search_Path
provided instructions for DBAs to mitigate the impact of the vulnerability.
Essentially asking that references to the database objects and operators
should be fully schema-qualified to prevent an override from a less
privileged user.

Therefore, I was wondering if the PyGreSQL community has any plans to fully
schema-qualify objects and operators for all the internal queries that
PyGreSQL issues?

Thank you.

Shoaib
___
PyGreSQL mailing list
PyGreSQL@Vex.Net
https://mail.vex.net/mailman/listinfo/pygresql