Обсуждение: pgsql: Fix search_path to a safe value during maintenance operations.

Поиск
Список
Период
Сортировка

pgsql: Fix search_path to a safe value during maintenance operations.

От
Jeff Davis
Дата:
Fix search_path to a safe value during maintenance operations.

While executing maintenance operations (ANALYZE, CLUSTER, REFRESH
MATERIALIZED VIEW, REINDEX, or VACUUM), set search_path to
'pg_catalog, pg_temp' to prevent inconsistent behavior.

Functions that are used for functional indexes, in index expressions,
or in materialized views and depend on a different search path must be
declared with CREATE FUNCTION ... SET search_path='...'.

This change addresses a security risk introduced in commit 60684dd834,
where a role with MAINTAIN privileges on a table may be able to
escalate privileges to the table owner. That commit is not yet part of
any release, so no need to backpatch.

Discussion: https://postgr.es/m/e44327179e5c9015c8dda67351c04da552066017.camel%40j-davis.com
Reviewed-by: Greg Stark
Reviewed-by: Nathan Bossart

Branch
------
master

Details
-------
https://git.postgresql.org/pg/commitdiff/05e17373517114167d002494e004fa0aa32d1fd1

Modified Files
--------------
contrib/amcheck/verify_nbtree.c                             |  2 ++
src/backend/access/brin/brin.c                              |  2 ++
src/backend/catalog/index.c                                 |  8 ++++++++
src/backend/commands/analyze.c                              |  2 ++
src/backend/commands/cluster.c                              |  2 ++
src/backend/commands/indexcmds.c                            |  6 ++++++
src/backend/commands/matview.c                              |  2 ++
src/backend/commands/vacuum.c                               |  2 ++
src/bin/scripts/t/100_vacuumdb.pl                           |  4 ----
src/include/utils/guc.h                                     |  6 ++++++
src/test/modules/test_oat_hooks/expected/test_oat_hooks.out |  4 ++++
src/test/regress/expected/privileges.out                    | 12 ++++++------
src/test/regress/expected/vacuum.out                        |  2 +-
src/test/regress/sql/privileges.sql                         |  8 ++++----
src/test/regress/sql/vacuum.sql                             |  2 +-
15 files changed, 48 insertions(+), 16 deletions(-)


Re: pgsql: Fix search_path to a safe value during maintenance operations.

От
Jeff Davis
Дата:
On Fri, 2023-06-09 at 20:54 +0000, Jeff Davis wrote:
> Fix search_path to a safe value during maintenance operations.

Looks like this is causing pg_amcheck failures in the buildfarm.
Investigating...

Regards,
    Jeff Davis




Re: pgsql: Fix search_path to a safe value during maintenance operations.

От
Jeff Davis
Дата:
On Fri, 2023-06-09 at 15:16 -0700, Jeff Davis wrote:
> On Fri, 2023-06-09 at 20:54 +0000, Jeff Davis wrote:
> > Fix search_path to a safe value during maintenance operations.
>
> Looks like this is causing pg_amcheck failures in the buildfarm.
> Investigating...

It looks related to bt_index_check_internal(), which is called by SQL
functions bt_index_check() and bt_index_parent_check(). SQL functions
can be called in parallel, so it raises the error:

  ERROR:  cannot set parameters during a parallel operation

because commit 05e1737351 added the SetConfigOption() line. Normally
those functions would not be called in parallel, but
debug_parallel_mode makes that happen.

Attached a patch to mark those functions as PARALLEL UNSAFE, which
fixes the problem.

Alternatively, I could just take out that line, as those SQL functions
are not controlled by the MAINTAIN privilege. But for consistency I
think it's a good idea to leave it in so that index functions are
called with the right search path for amcheck.


--
Jeff Davis
PostgreSQL Contributor Team - AWS


Вложения

Re: pgsql: Fix search_path to a safe value during maintenance operations.

От
Jeff Davis
Дата:
On Fri, 2023-06-09 at 17:37 -0700, Jeff Davis wrote:
> Attached a patch to mark those functions as PARALLEL UNSAFE, which
> fixes the problem.

On second thought, that might not be acceptable for amcheck, depending
on how its run.

I think it's OK if run by pg_amcheck, because that runs it on a single
index at a time in each connection, and parallelizes by opening more
connections.

But if some users are calling the check functions across many tables in
a single select statement (e.g. in the targetlist of a query on
pg_class), then they'll experience a regression.

> Alternatively, I could just take out that line, as those SQL
> functions
> are not controlled by the MAINTAIN privilege. But for consistency I
> think it's a good idea to leave it in so that index functions are
> called with the right search path for amcheck.

If marking them PARALLEL UNSAFE is not acceptable, then this seems like
a fine solution.

Regards,
    Jeff Davis




Re: pgsql: Fix search_path to a safe value during maintenance operations.

От
Tom Lane
Дата:
Jeff Davis <pgsql@j-davis.com> writes:
> Attached a patch to mark those functions as PARALLEL UNSAFE, which
> fixes the problem.

> Alternatively, I could just take out that line, as those SQL functions
> are not controlled by the MAINTAIN privilege. But for consistency I
> think it's a good idea to leave it in so that index functions are
> called with the right search path for amcheck.

I concur with the upthread objection that it is way too late in
the release cycle to be introducing a breaking change like this.
I request that you revert it.

            regards, tom lane



Re: pgsql: Fix search_path to a safe value during maintenance operations.

От
Noah Misch
Дата:
On Sat, Jun 10, 2023 at 01:33:31AM -0400, Tom Lane wrote:
> Jeff Davis <pgsql@j-davis.com> writes:
> > Attached a patch to mark those functions as PARALLEL UNSAFE, which
> > fixes the problem.
> 
> > Alternatively, I could just take out that line, as those SQL functions
> > are not controlled by the MAINTAIN privilege. But for consistency I
> > think it's a good idea to leave it in so that index functions are
> > called with the right search path for amcheck.
> 
> I concur with the upthread objection that it is way too late in
> the release cycle to be introducing a breaking change like this.
> I request that you revert it.

The timing was not great, but this is fixing a purported defect in an older
v16 feature.  If the MAINTAIN privilege is actually fine, we're all set for
v16.  If MAINTAIN does have a material problem that $SUBJECT had fixed, we
should either revert MAINTAIN, un-revert $SUBJECT, or fix the problem a
different way.



Re: pgsql: Fix search_path to a safe value during maintenance operations.

От
Robert Haas
Дата:
On Mon, Jun 12, 2023 at 1:05 PM Noah Misch <noah@leadboat.com> wrote:
> > I concur with the upthread objection that it is way too late in
> > the release cycle to be introducing a breaking change like this.
> > I request that you revert it.
>
> The timing was not great, but this is fixing a purported defect in an older
> v16 feature.  If the MAINTAIN privilege is actually fine, we're all set for
> v16.  If MAINTAIN does have a material problem that $SUBJECT had fixed, we
> should either revert MAINTAIN, un-revert $SUBJECT, or fix the problem a
> different way.

I wonder why this commit used pg_catalog, pg_temp rather than just the
empty string, as AutoVacWorkerMain does.

--
Robert Haas
EDB: http://www.enterprisedb.com



Re: pgsql: Fix search_path to a safe value during maintenance operations.

От
Jeff Davis
Дата:
On Mon, 2023-06-12 at 13:33 -0400, Robert Haas wrote:
> I wonder why this commit used pg_catalog, pg_temp rather than just
> the
> empty string, as AutoVacWorkerMain does.

I followed the rules here for "Writing SECURITY DEFINER Functions
Safely":

https://www.postgresql.org/docs/16/sql-createfunction.html

which suggests adding pg_temp at the end (otherwise it is searched
first by default).

It's not exactly like a SECURITY DEFINER function, but running a
maintenance command does switch to the table owner, so the risks are
similar.

I don't see a problem with the pg_temp schema in non-interactive
processes, because we trust the non-interactive processes.

Regards,
    Jeff Davis




Re: pgsql: Fix search_path to a safe value during maintenance operations.

От
Jeff Davis
Дата:
On Mon, 2023-06-12 at 13:05 -0400, Noah Misch wrote:
> The timing was not great, but this is fixing a purported defect in an
> older
> v16 feature.  If the MAINTAIN privilege is actually fine, we're all
> set for
> v16.  If MAINTAIN does have a material problem that $SUBJECT had
> fixed, we
> should either revert MAINTAIN, un-revert $SUBJECT, or fix the problem
> a
> different way.

Someone with the MAINTAIN privilege on a table can use search_path
tricks against the table owner, if the code is susceptible, because
maintenance code runs with the privileges of the table owner.

I was concerned enough to bring it up on the -security list, and then
to -hackers followed by a commit (too late). But perhaps that was
paranoia: the practical risk is probably quite low, because a user with
the MAINTAIN privilege is likely to be highly trusted.

I'd like to hear from others on the topic about the relative risks of
shipping with/without the search_path changes.

I don't think a full revert of the MAINTAIN privilege is the right
thing -- the predefined role is very valuable and many other predefined
roles are much more dangerous than pg_maintain is.

Regards,
    Jeff Davis




Re: pgsql: Fix search_path to a safe value during maintenance operations.

От
"David G. Johnston"
Дата:
On Mon, Jun 12, 2023 at 5:40 PM Jeff Davis <pgsql@j-davis.com> wrote:
On Mon, 2023-06-12 at 13:05 -0400, Noah Misch wrote:
> The timing was not great, but this is fixing a purported defect in an
> older
> v16 feature.  If the MAINTAIN privilege is actually fine, we're all
> set for
> v16.  If MAINTAIN does have a material problem that $SUBJECT had
> fixed, we
> should either revert MAINTAIN, un-revert $SUBJECT, or fix the problem
> a
> different way.

Someone with the MAINTAIN privilege on a table can use search_path
tricks against the table owner, if the code is susceptible, because
maintenance code runs with the privileges of the table owner.


Only change the search_path if someone other than the table owner or superuser is running the command (which should only be possible via the new MAINTAIN privilege)?

David J.

Re: pgsql: Fix search_path to a safe value during maintenance operations.

От
"David G. Johnston"
Дата:
On Monday, June 12, 2023, David G. Johnston <david.g.johnston@gmail.com> wrote:
On Mon, Jun 12, 2023 at 5:40 PM Jeff Davis <pgsql@j-davis.com> wrote:
On Mon, 2023-06-12 at 13:05 -0400, Noah Misch wrote:
> The timing was not great, but this is fixing a purported defect in an
> older
> v16 feature.  If the MAINTAIN privilege is actually fine, we're all
> set for
> v16.  If MAINTAIN does have a material problem that $SUBJECT had
> fixed, we
> should either revert MAINTAIN, un-revert $SUBJECT, or fix the problem
> a
> different way.

Someone with the MAINTAIN privilege on a table can use search_path
tricks against the table owner, if the code is susceptible, because
maintenance code runs with the privileges of the table owner.


Only change the search_path if someone other than the table owner or superuser is running the command (which should only be possible via the new MAINTAIN privilege)?

On a related note, are we OK with someone using this privilege setting their own default_statistics_target?


My prior attempt to open up analyze had brought this up as a reason to avoid having someone besides the table owner allowed to analyze the table.

David J.

Re: pgsql: Fix search_path to a safe value during maintenance operations.

От
Robert Haas
Дата:
On Mon, Jun 12, 2023 at 8:20 PM Jeff Davis <pgsql@j-davis.com> wrote:
> I followed the rules here for "Writing SECURITY DEFINER Functions
> Safely":
>
> https://www.postgresql.org/docs/16/sql-createfunction.html
>
> which suggests adding pg_temp at the end (otherwise it is searched
> first by default).

Interesting. The issue of "what is a safe search path?" is more
nuanced than I would prefer. :-(

--
Robert Haas
EDB: http://www.enterprisedb.com



Re: pgsql: Fix search_path to a safe value during maintenance operations.

От
Noah Misch
Дата:
On Mon, Jun 12, 2023 at 05:39:40PM -0700, Jeff Davis wrote:
> On Mon, 2023-06-12 at 13:05 -0400, Noah Misch wrote:
> > The timing was not great, but this is fixing a purported defect in an
> > older
> > v16 feature.  If the MAINTAIN privilege is actually fine, we're all
> > set for
> > v16.  If MAINTAIN does have a material problem that $SUBJECT had
> > fixed, we
> > should either revert MAINTAIN, un-revert $SUBJECT, or fix the problem
> > a
> > different way.
> 
> Someone with the MAINTAIN privilege on a table can use search_path
> tricks against the table owner, if the code is susceptible, because
> maintenance code runs with the privileges of the table owner.
> 
> I was concerned enough to bring it up on the -security list, and then
> to -hackers followed by a commit (too late). But perhaps that was
> paranoia: the practical risk is probably quite low, because a user with
> the MAINTAIN privilege is likely to be highly trusted.
> 
> I'd like to hear from others on the topic about the relative risks of
> shipping with/without the search_path changes.

I find shipping with the search_path change ($SUBJECT) to be lower risk
overall, though both are fairly low-risk.  Expect no new errors in non-FULL
VACUUM, which doesn't run the relevant kinds of code.  Tables not ready for
the search_path change in ANALYZE already cause errors in Autovacuum ANALYZE
and have since 2018-02 (CVE-2018-1058).  Hence, $SUBJECT poses less
compatibility risk than the CVE-2018-1058 fix.

Best argument for shipping without $SUBJECT: we already have REFERENCES and
TRIGGER privilege that tend to let the grantee hijack the table owner's
account.  Adding MAINTAIN to the list, while sad, is defensible.  I still
prefer to ship with $SUBJECT, not without.



Re: pgsql: Fix search_path to a safe value during maintenance operations.

От
Jeff Davis
Дата:
On Mon, 2023-06-12 at 17:50 -0700, David G. Johnston wrote:
> Only change the search_path if someone other than the table owner or
> superuser is running the command (which should only be possible via
> the new MAINTAIN privilege)?

That sounds like a reasonable compromise, but a bit messy. If we do it
this way, is there hope to clean things up a bit in the future? These
special cases are quite difficult to document in a comprehensible way.

If others like this approach I'm fine with it.

Regards,
    Jeff Davis




Re: pgsql: Fix search_path to a safe value during maintenance operations.

От
Jeff Davis
Дата:
On Tue, 2023-06-13 at 11:24 -0400, Robert Haas wrote:
> Interesting. The issue of "what is a safe search path?" is more
> nuanced than I would prefer. :-(

As far as I can tell, search_path was designed as a convenience for
interactive queries, where a lot of these nuances make sense. But they
don't make sense as defaults for code inside functions, in my opinion.

Regards,
    Jeff Davis




Re: pgsql: Fix search_path to a safe value during maintenance operations.

От
Jeff Davis
Дата:
On Mon, 2023-06-12 at 18:31 -0700, David G. Johnston wrote:
> On a related note, are we OK with someone using this privilege
> setting their own default_statistics_target?
>
> https://www.postgresql.org/docs/current/runtime-config-query.html#GUC-DEFAULT-STATISTICS-TARGET
>
> My prior attempt to open up analyze had brought this up as a reason
> to avoid having someone besides the table owner allowed to analyze
> the table.

Thank you for bringing it up. I don't see a major concern there, but
please link to the prior discussion so I can see the objections.

Regards,
    Jeff Davis




Re: pgsql: Fix search_path to a safe value during maintenance operations.

От
"David G. Johnston"
Дата:
On Tue, Jun 13, 2023 at 12:54 PM Jeff Davis <pgsql@j-davis.com> wrote:
On Mon, 2023-06-12 at 18:31 -0700, David G. Johnston wrote:
> On a related note, are we OK with someone using this privilege
> setting their own default_statistics_target?
>
> https://www.postgresql.org/docs/current/runtime-config-query.html#GUC-DEFAULT-STATISTICS-TARGET
>
> My prior attempt to open up analyze had brought this up as a reason
> to avoid having someone besides the table owner allowed to analyze
> the table.

Thank you for bringing it up. I don't see a major concern there, but
please link to the prior discussion so I can see the objections.


This is the specific (first?) message I am recalling.


David J.

Re: pgsql: Fix search_path to a safe value during maintenance operations.

От
Tom Lane
Дата:
Noah Misch <noah@leadboat.com> writes:
> Best argument for shipping without $SUBJECT: we already have REFERENCES and
> TRIGGER privilege that tend to let the grantee hijack the table owner's
> account.  Adding MAINTAIN to the list, while sad, is defensible.  I still
> prefer to ship with $SUBJECT, not without.

What I'm concerned about is making such a fundamental semantics change
post-beta1.  It'll basically invalidate any application compatibility
testing anybody might have done against beta1.  I think this ship has
sailed as far as v16 is concerned, although we could reconsider it
in v17.

Also, I fail to see any connection to the MAINTAIN privilege: the
committed-and-reverted patch would break things whether the user
was making any use of that privilege or not.  Thus, I do not accept
the idea that we're fixing something that's new in 16.

            regards, tom lane



Re: pgsql: Fix search_path to a safe value during maintenance operations.

От
Jeff Davis
Дата:
On Tue, 2023-06-13 at 13:22 -0700, David G. Johnston wrote:
> This is the specific (first?) message I am recalling.
>
> https://www.postgresql.org/message-id/A737B7A37273E048B164557ADEF4A58B53803F5A%40ntex2010i.host.magwien.gv.at

The most objection seems to be expressed most succinctly in this
message:

https://www.postgresql.org/message-id/16134.1456767564%40sss.pgh.pa.us

"if we allow non-owners to run ANALYZE, they'd be able to mess things
up by setting the stats target either much lower or much higher than
the table owner expected"

I have trouble seeing much of a problem here if there is an explicit
MAINTAIN privilege. If you grant someone MAINTAIN to someone, it's not
surprising that you need to coordinate maintenance-related settings
with that user; and if you don't, then it's not surprising that the
statistics could get messed up.

Perhaps the objections in that thread were because the proposal
involved inferring the privilege to ANALYZE from other privileges,
rather than having an explicit MAINTAIN privilege?

Regards,
    Jeff Davis




Re: pgsql: Fix search_path to a safe value during maintenance operations.

От
"David G. Johnston"
Дата:
On Tue, Jun 13, 2023 at 1:55 PM Jeff Davis <pgsql@j-davis.com> wrote:
Perhaps the objections in that thread were because the proposal
involved inferring the privilege to ANALYZE from other privileges,
rather than having an explicit MAINTAIN privilege?


That is true; but it seems worth being explicit whether we expect the user to only be able to run "ANALYZE" using defaults (like auto-analyze would do) or if this additional capability is assumed to be part of the grant.  I do imagine you'd want to be able to set the statistic target in order to do vacuum --analyze-in-stages with a non-superuser.

David J.

Re: pgsql: Fix search_path to a safe value during maintenance operations.

От
Tom Lane
Дата:
Jeff Davis <pgsql@j-davis.com> writes:
> The most objection seems to be expressed most succinctly in this
> message:
> https://www.postgresql.org/message-id/16134.1456767564%40sss.pgh.pa.us
> "if we allow non-owners to run ANALYZE, they'd be able to mess things
> up by setting the stats target either much lower or much higher than
> the table owner expected"

> I have trouble seeing much of a problem here if there is an explicit
> MAINTAIN privilege. If you grant someone MAINTAIN to someone, it's not
> surprising that you need to coordinate maintenance-related settings
> with that user; and if you don't, then it's not surprising that the
> statistics could get messed up.

I agree that granting MAINTAIN implies that you trust the grantee
not to mess up your stats.

> Perhaps the objections in that thread were because the proposal
> involved inferring the privilege to ANALYZE from other privileges,
> rather than having an explicit MAINTAIN privilege?

Exactly.

            regards, tom lane



Re: pgsql: Fix search_path to a safe value during maintenance operations.

От
Jeff Davis
Дата:
On Tue, 2023-06-13 at 16:23 -0400, Tom Lane wrote:
> What I'm concerned about is making such a fundamental semantics
> change
> post-beta1.

I have added the patch to the July CF for v17.

If someone does feel like something should be done for v16, David G.
Johnston posted one possibility here:

https://www.postgresql.org/message-id/CAKFQuwaVJkM9u+qpOaom2UkPE1sz0BASF-E5amxWPxncUhm4Hw@mail.gmail.com

But as Noah pointed out, there are other privileges that can be abused,
so a workaround for 16 might not be important if we have a likely fix
for MAINTAIN coming in 17.

Regards,
    Jeff Davis




Re: pgsql: Fix search_path to a safe value during maintenance operations.

От
Robert Haas
Дата:
On Thu, Jun 15, 2023 at 12:59 AM Jeff Davis <pgsql@j-davis.com> wrote:
> On Tue, 2023-06-13 at 16:23 -0400, Tom Lane wrote:
> > What I'm concerned about is making such a fundamental semantics
> > change
> > post-beta1.
>
> I have added the patch to the July CF for v17.
>
> If someone does feel like something should be done for v16, David G.
> Johnston posted one possibility here:
>
> https://www.postgresql.org/message-id/CAKFQuwaVJkM9u+qpOaom2UkPE1sz0BASF-E5amxWPxncUhm4Hw@mail.gmail.com
>
> But as Noah pointed out, there are other privileges that can be abused,
> so a workaround for 16 might not be important if we have a likely fix
> for MAINTAIN coming in 17.

Rather than is_superuser(userid) || userid == ownerid, I think that
the test should be has_privs_of_role(userid, ownerid).

I'm inclined to think that this is a real security issue and am not
very sanguine about waiting another year to fix it, but at the same
time, I'm somewhat worried that the proposed fix might be too narrow
or wrongly-shaped. I'm not too convinced that we've properly
understood what all of the problems in this area are. :-(

--
Robert Haas
EDB: http://www.enterprisedb.com



Re: pgsql: Fix search_path to a safe value during maintenance operations.

От
Jeff Davis
Дата:
On Mon, 2023-06-19 at 16:03 -0400, Robert Haas wrote:
> I'm inclined to think that this is a real security issue and am not

Can you expand on that a bit? You mean a practical security issue for
the intended use cases?

> very sanguine about waiting another year to fix it, but at the same
> time, I'm somewhat worried that the proposed fix might be too narrow
> or wrongly-shaped. I'm not too convinced that we've properly
> understood what all of the problems in this area are. :-(

Would it be acceptable to document that the MAINTAIN privilege (along
with TRIGGER and, if I understand correctly, REFERENCES) carries
privilege escalation risk for the grantor?

Regards,
    Jeff Davis