pg18: Virtual generated columns are not (yet) safe when superuser selects from them

From: Feike Steenbergen <feikesteenbergen(at)gmail(dot)com>
To: PostgreSQL mailing lists <pgsql-hackers(at)postgresql(dot)org>
Subject: pg18: Virtual generated columns are not (yet) safe when superuser selects from them
Date: 2025-05-23 08:43:06
Message-ID: CAK_s-G2Q7de8Q0qOYUR=_CTB5FzzVBm5iZjOp+meVWpMpmfO0w@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi,

While evaluating the PostgreSQL 18 beta, I had a thought experiment where I
thought it might be possible to use the new virtual generated columns to
gain
superuser privileges for a regular user.

Attached is a sample exploit, that achieves this, key components:

- the GENERATED column uses a user defined immutable function
- this immutable function cannot ALTER ROLE (needs volatile)
- therefore this immutable function calls a volatile function
- the volatile function can contain any security exploit

The problem I think for PostgreSQL 18 is quite high, as I think it is more
likely that a superuser issues a `SELECT` against any table (graphical DB
clients for example, showing the first N rows in a window)

However, the problem *also* exists for the GENERATED [...] STORED columns,
so
probably all pg versions >= 12? although it is less likely that a superuser
would `INSERT` into those tables?

Here's a transcript of the output of the file that shows it:

You are now connected to database "postgres" as user "regular". CREATE
FUNCTION
CREATE FUNCTION CREATE TABLE INSERT 0 1 i | j ---+--- 1 | 1 (1 row)

You are now connected to database "postgres" as user "postgres". stage |
case
-------------------------------+-------------- Before superuser did a
SELECT |
regular user (1 row)

i | j
---+--- 1 | 1 (1 row)

stage | case
------------------------------+----------- After superuser did a SELECT |
superuser (1 row)

Forwarding this discussion from security(at)postgresql(dot)org:

On Fri, 16 May 2025 at 23:12, Noah Misch <noah(at)leadboat(dot)com> wrote:
>
> On Fri, May 16, 2025 at 07:16:13PM +0200, Feike Steenbergen wrote:
> > On Fri, 16 May 2025 at 19:00, Noah Misch <noah(at)leadboat(dot)com> wrote:
> > > Thanks for the report. Does this attack work if the reader uses COPY
> > instead of SELECT? COPY has been safe, so we should think twice before
> > > making it unsafe.
> >
> > Plain COPY seems safe, that's a very good thing:
> >
> > -- This does not cause the regular user to become superuser COPY
> > exploit_generated.generated_sample TO STDOUT;
> >
> > -- This is safe, with a useful error: COPY
> > exploit_generated.generated_sample(i, j) TO STDOUT;
> >
> > ERROR: column "j" is a generated column DETAIL: Generated columns
cannot be
> > used in COPY.
> >
> > Copy wrapped around a select however is not safe, (not a suprise I
think):
> >
> > -- This is unsafe COPY (SELECT * FROM
exploit_generated.generated_sample) TO
> > STDOUT;
>
> That suggests virtual generated table columns have the same risk as
views, not
> more risk. That is good news.
>
> > > In other words, virtual generated columns make a table into a hybrid
of
> > > view and table, so anything odd that we've needed to do to views and
> > foreign tables may apply to tables containing virtual generated columns.
> >
> > Yeah, that to me is the gist of the issue, that a plain `SELECT`
against any
> > such table can be used to run arbitrary function calls.

On Fri, 16 May 2025 at 23:12, Noah Misch <noah(at)leadboat(dot)com> wrote:
>
> If nothing else, I think the project will need to extend
> restrict_nonsystem_relation_kind so virtual generated columns become one
of
> the things it can block.

Attachment Content-Type Size
exploit_generated.sql application/octet-stream 2.1 KB

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Álvaro Herrera 2025-05-23 08:46:09 Re: PG 18 release notes draft committed
Previous Message Daniel Gustafsson 2025-05-23 08:21:42 Re: Retiring some encodings?