Message ID | 20240307113848.847275-1-soumya.sambu@windriver.com |
---|---|
State | New |
Headers | show |
Series | [meta-oe,kirkstone,1/1] postgresql: Fix CVE-2024-0985 | expand |
On Thu, 2024-03-07 at 03:39 -0800, Soumya via lists.openembedded.org wrote: > From: Soumya Sambu <soumya.sambu@windriver.com> > > Late privilege drop in REFRESH MATERIALIZED VIEW CONCURRENTLY in > PostgreSQL > allows an object creator to execute arbitrary SQL functions as the > command > issuer. The command intends to run SQL functions as the owner of the > materialized view, enabling safe refresh of untrusted materialized > views. > The victim is a superuser or member of one of the attacker's roles. > The > attack requires luring the victim into running REFRESH MATERIALIZED > VIEW > CONCURRENTLY on the attacker's materialized view. As part of > exploiting > this vulnerability, the attacker creates functions that use CREATE > RULE to > convert the internally-built temporary table to a view. Versions > before > PostgreSQL 15.6, 14.11, 13.14, and 12.18 are affected. The only known > exploit does not work in PostgreSQL 16 and later. For defense in > depth, > PostgreSQL 16.2 adds the protections that older branches are using to > fix > their vulnerability. > > Upstream commit have wrong CVE mentioned but the correct one is CVE- > 2024-0985 > > References: > https://nvd.nist.gov/vuln/detail/CVE-2024-0985 > https://security-tracker.debian.org/tracker/CVE-2024-0985 I think this should instead be upgraded to 14.11 bug fix release. Thanks, Anuj > > Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com> > --- > .../postgresql/files/CVE-2024-0985.patch | 98 > +++++++++++++++++++ > .../recipes-dbs/postgresql/postgresql_14.9.bb | 1 + > 2 files changed, 99 insertions(+) > create mode 100644 meta-oe/recipes-dbs/postgresql/files/CVE-2024- > 0985.patch > > diff --git a/meta-oe/recipes-dbs/postgresql/files/CVE-2024-0985.patch > b/meta-oe/recipes-dbs/postgresql/files/CVE-2024-0985.patch > new file mode 100644 > index 000000000..24245406c > --- /dev/null > +++ b/meta-oe/recipes-dbs/postgresql/files/CVE-2024-0985.patch > @@ -0,0 +1,98 @@ > +From f2fdea198b3d0ab30b9e8478a762488ecebabd88 Mon Sep 17 00:00:00 > 2001 > +From: Heikki Linnakangas <heikki.linnakangas@iki.fi> > +Date: Mon, 5 Feb 2024 11:01:23 +0200 > +Subject: [PATCH] Run REFRESH MATERIALIZED VIEW CONCURRENTLY in right > security > + context > + > +The internal commands in REFRESH MATERIALIZED VIEW CONCURRENTLY are > +correctly executed in SECURITY_RESTRICTED_OPERATION mode, except for > +creating the temporary "diff" table, because you cannot create > +temporary tables in SRO mode. But creating the temporary "diff" > table > +is a pretty complex CTAS command that selects from another temporary > +table created earlier in the command. If you can cajole that CTAS > +command to execute code defined by the table owner, the table owner > +can run code with the privileges of the user running the REFRESH > +command. > + > +The proof-of-concept reported to the security team relied on CREATE > +RULE to convert the internally-built temp table to a view. That's > not > +possible since commit b23cd185fd, and I was not able to find a > +different way to turn the SELECT on the temp table into code > +execution, so as far as I know this is only exploitable in v15 and > +below. That's a fiddly assumption though, so apply this patch to > +master and all stable versions. > + > +Thanks to Pedro Gallegos for the report. > + > +Security: CVE-2023-5869 > +Reviewed-by: Noah Misch > + > +CVE: CVE-2024-0985 > + > +Upstream-Status: Backport > [https://git.postgresql.org/gitweb/?p=postgresql.git;a=patch;h=f2fdea > 198b3d0ab30b9e8478a762488ecebabd88] > + > +Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com> > +--- > + src/backend/commands/matview.c | 33 ++++++++++++++++++++++++++----- > -- > + 1 file changed, 26 insertions(+), 7 deletions(-) > + > +diff --git a/src/backend/commands/matview.c > b/src/backend/commands/matview.c > +index 3fc50e8..0aa0a74 100644 > +--- a/src/backend/commands/matview.c > ++++ b/src/backend/commands/matview.c > +@@ -655,13 +655,35 @@ refresh_by_match_merge(Oid matviewOid, Oid > tempOid, Oid relowner, > + > SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1)))); > + } > + > ++ /* > ++ * Create the temporary "diff" table. > ++ * > ++ * Temporarily switch out of the > SECURITY_RESTRICTED_OPERATION context, > ++ * because you cannot create temp tables in SRO context. > For extra > ++ * paranoia, add the composite type column only after > switching back to > ++ * SRO context. > ++ */ > + SetUserIdAndSecContext(relowner, > + save_sec_context > | SECURITY_LOCAL_USERID_CHANGE); > ++ resetStringInfo(&querybuf); > ++ appendStringInfo(&querybuf, > ++ "CREATE TEMP TABLE %s (tid > pg_catalog.tid)", > ++ diffname); > ++ if (SPI_exec(querybuf.data, 0) != SPI_OK_UTILITY) > ++ elog(ERROR, "SPI_exec failed: %s", querybuf.data); > ++ SetUserIdAndSecContext(relowner, > ++ save_sec_context > | SECURITY_RESTRICTED_OPERATION); > ++ resetStringInfo(&querybuf); > ++ appendStringInfo(&querybuf, > ++ "ALTER TABLE %s ADD COLUMN > newdata %s", > ++ diffname, tempname); > ++ if (SPI_exec(querybuf.data, 0) != SPI_OK_UTILITY) > ++ elog(ERROR, "SPI_exec failed: %s", querybuf.data); > + > +- /* Start building the query for creating the diff table. */ > ++ /* Start building the query for populating the diff table. > */ > + resetStringInfo(&querybuf); > + appendStringInfo(&querybuf, > +- "CREATE TEMP TABLE %s AS " > ++ "INSERT INTO %s " > + "SELECT mv.ctid AS tid, > newdata.*::%s AS newdata " > + "FROM %s mv FULL JOIN %s > newdata ON (", > + diffname, tempname, > matviewname, tempname); > +@@ -790,13 +812,10 @@ refresh_by_match_merge(Oid matviewOid, Oid > tempOid, Oid relowner, > + "WHERE newdata.* > IS NULL OR mv.* IS NULL " > + "ORDER BY tid"); > + > +- /* Create the temporary "diff" table. */ > +- if (SPI_exec(querybuf.data, 0) != SPI_OK_UTILITY) > ++ /* Populate the temporary "diff" table. */ > ++ if (SPI_exec(querybuf.data, 0) != SPI_OK_INSERT) > + elog(ERROR, "SPI_exec failed: %s", querybuf.data); > + > +- SetUserIdAndSecContext(relowner, > +- save_sec_context > | SECURITY_RESTRICTED_OPERATION); > +- > + /* > + * We have no further use for data from the "full-data" temp > table, but we > + * must keep it around because its type is referenced from > the diff table. > +-- > +2.40.0 > diff --git a/meta-oe/recipes-dbs/postgresql/postgresql_14.9.bb > b/meta-oe/recipes-dbs/postgresql/postgresql_14.9.bb > index a879de20c..d9911fd4a 100644 > --- a/meta-oe/recipes-dbs/postgresql/postgresql_14.9.bb > +++ b/meta-oe/recipes-dbs/postgresql/postgresql_14.9.bb > @@ -12,6 +12,7 @@ SRC_URI += "\ > file://CVE-2023-5868.patch \ > file://CVE-2023-5869.patch \ > file://CVE-2023-5870.patch \ > + file://CVE-2024-0985.patch \ > " > > SRC_URI[sha256sum] = > "b1fe3ba9b1a7f3a9637dd1656dfdad2889016073fd4d35f13b50143cbbb6a8ef" > > -=-=-=-=-=-=-=-=-=-=-=- > Links: You receive all messages sent to this group. > View/Reply Online (#109194): > https://lists.openembedded.org/g/openembedded-devel/message/109194 > Mute This Topic: https://lists.openembedded.org/mt/104785281/3616702 > Group Owner: openembedded-devel+owner@lists.openembedded.org > Unsubscribe: > https://lists.openembedded.org/g/openembedded-devel/unsub [ > anuj.mittal@intel.com] > -=-=-=-=-=-=-=-=-=-=-=- >
Got it. I will upgrade to 14.11. Regards, Soumya
diff --git a/meta-oe/recipes-dbs/postgresql/files/CVE-2024-0985.patch b/meta-oe/recipes-dbs/postgresql/files/CVE-2024-0985.patch new file mode 100644 index 000000000..24245406c --- /dev/null +++ b/meta-oe/recipes-dbs/postgresql/files/CVE-2024-0985.patch @@ -0,0 +1,98 @@ +From f2fdea198b3d0ab30b9e8478a762488ecebabd88 Mon Sep 17 00:00:00 2001 +From: Heikki Linnakangas <heikki.linnakangas@iki.fi> +Date: Mon, 5 Feb 2024 11:01:23 +0200 +Subject: [PATCH] Run REFRESH MATERIALIZED VIEW CONCURRENTLY in right security + context + +The internal commands in REFRESH MATERIALIZED VIEW CONCURRENTLY are +correctly executed in SECURITY_RESTRICTED_OPERATION mode, except for +creating the temporary "diff" table, because you cannot create +temporary tables in SRO mode. But creating the temporary "diff" table +is a pretty complex CTAS command that selects from another temporary +table created earlier in the command. If you can cajole that CTAS +command to execute code defined by the table owner, the table owner +can run code with the privileges of the user running the REFRESH +command. + +The proof-of-concept reported to the security team relied on CREATE +RULE to convert the internally-built temp table to a view. That's not +possible since commit b23cd185fd, and I was not able to find a +different way to turn the SELECT on the temp table into code +execution, so as far as I know this is only exploitable in v15 and +below. That's a fiddly assumption though, so apply this patch to +master and all stable versions. + +Thanks to Pedro Gallegos for the report. + +Security: CVE-2023-5869 +Reviewed-by: Noah Misch + +CVE: CVE-2024-0985 + +Upstream-Status: Backport [https://git.postgresql.org/gitweb/?p=postgresql.git;a=patch;h=f2fdea198b3d0ab30b9e8478a762488ecebabd88] + +Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com> +--- + src/backend/commands/matview.c | 33 ++++++++++++++++++++++++++------- + 1 file changed, 26 insertions(+), 7 deletions(-) + +diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c +index 3fc50e8..0aa0a74 100644 +--- a/src/backend/commands/matview.c ++++ b/src/backend/commands/matview.c +@@ -655,13 +655,35 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner, + SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1)))); + } + ++ /* ++ * Create the temporary "diff" table. ++ * ++ * Temporarily switch out of the SECURITY_RESTRICTED_OPERATION context, ++ * because you cannot create temp tables in SRO context. For extra ++ * paranoia, add the composite type column only after switching back to ++ * SRO context. ++ */ + SetUserIdAndSecContext(relowner, + save_sec_context | SECURITY_LOCAL_USERID_CHANGE); ++ resetStringInfo(&querybuf); ++ appendStringInfo(&querybuf, ++ "CREATE TEMP TABLE %s (tid pg_catalog.tid)", ++ diffname); ++ if (SPI_exec(querybuf.data, 0) != SPI_OK_UTILITY) ++ elog(ERROR, "SPI_exec failed: %s", querybuf.data); ++ SetUserIdAndSecContext(relowner, ++ save_sec_context | SECURITY_RESTRICTED_OPERATION); ++ resetStringInfo(&querybuf); ++ appendStringInfo(&querybuf, ++ "ALTER TABLE %s ADD COLUMN newdata %s", ++ diffname, tempname); ++ if (SPI_exec(querybuf.data, 0) != SPI_OK_UTILITY) ++ elog(ERROR, "SPI_exec failed: %s", querybuf.data); + +- /* Start building the query for creating the diff table. */ ++ /* Start building the query for populating the diff table. */ + resetStringInfo(&querybuf); + appendStringInfo(&querybuf, +- "CREATE TEMP TABLE %s AS " ++ "INSERT INTO %s " + "SELECT mv.ctid AS tid, newdata.*::%s AS newdata " + "FROM %s mv FULL JOIN %s newdata ON (", + diffname, tempname, matviewname, tempname); +@@ -790,13 +812,10 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner, + "WHERE newdata.* IS NULL OR mv.* IS NULL " + "ORDER BY tid"); + +- /* Create the temporary "diff" table. */ +- if (SPI_exec(querybuf.data, 0) != SPI_OK_UTILITY) ++ /* Populate the temporary "diff" table. */ ++ if (SPI_exec(querybuf.data, 0) != SPI_OK_INSERT) + elog(ERROR, "SPI_exec failed: %s", querybuf.data); + +- SetUserIdAndSecContext(relowner, +- save_sec_context | SECURITY_RESTRICTED_OPERATION); +- + /* + * We have no further use for data from the "full-data" temp table, but we + * must keep it around because its type is referenced from the diff table. +-- +2.40.0 diff --git a/meta-oe/recipes-dbs/postgresql/postgresql_14.9.bb b/meta-oe/recipes-dbs/postgresql/postgresql_14.9.bb index a879de20c..d9911fd4a 100644 --- a/meta-oe/recipes-dbs/postgresql/postgresql_14.9.bb +++ b/meta-oe/recipes-dbs/postgresql/postgresql_14.9.bb @@ -12,6 +12,7 @@ SRC_URI += "\ file://CVE-2023-5868.patch \ file://CVE-2023-5869.patch \ file://CVE-2023-5870.patch \ + file://CVE-2024-0985.patch \ " SRC_URI[sha256sum] = "b1fe3ba9b1a7f3a9637dd1656dfdad2889016073fd4d35f13b50143cbbb6a8ef"