Hi all, In light of CVE-2018-1058, user's applications need to be careful about the use of schema-unqualified queries. A lookup at the upstream code is showing four areas which are missing such handling: - psql has one problem in get_create_object_cmd which misses twice to qualify array_remove(). - isolationtester is missing one for a call to pg_backend_pid() - information_schema.sql has one problem as well: the function _pg_interval_type does not qualify upper(). Please note that there is no need to care about view's bodies because those use OID references, so only the function body need to be taken care of. - worker_spi scans pg_namespace and uses count() without schema qualification.
Attached is a patch which fixes all four of them, and which should be back-patched. For information_schema.sql, users can always replace the body of the function by redefining them (using SET search_path in CREATE FUNCTION would work as well however this is more costly than a simple qualification). Thoughts? -- Michael
From 44fafa6076a2108043e67ac76777c1c20664ea78 Mon Sep 17 00:00:00 2001 From: Michael Paquier <mich...@paquier.xyz> Date: Fri, 9 Mar 2018 16:43:06 +0900 Subject: [PATCH] Fix missing schema qualifications in code Per CVE-2018-1058, not using proper schema qualifications can allow an attacker who has an account on the server to execute arbitrary code as a superuser even if he has no such rights. After monitoring the whole code of Postgres, I have bumped into four places that need to be addressed: - isolationtester is missing one qualification when calling pg_backend_pid. - psql is missing two qualifications for array_remove - information_schema.sql has one problem within function _pg_interval_type - worker_spi scans pg_namespace and uses count() without qualifications. --- src/backend/catalog/information_schema.sql | 2 +- src/bin/psql/command.c | 2 +- src/test/isolation/isolationtester.c | 2 +- src/test/modules/worker_spi/worker_spi.c | 4 +++- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/backend/catalog/information_schema.sql b/src/backend/catalog/information_schema.sql index f4e69f4a26..4f2af408ac 100644 --- a/src/backend/catalog/information_schema.sql +++ b/src/backend/catalog/information_schema.sql @@ -186,7 +186,7 @@ CREATE FUNCTION _pg_interval_type(typid oid, mod int4) RETURNS text AS $$SELECT CASE WHEN $1 IN (1186) /* interval */ - THEN upper(substring(format_type($1, $2) from 'interval[()0-9]* #"%#"' for '#')) + THEN pg_catalog.upper(substring(pg_catalog.format_type($1, $2) from 'interval[()0-9]* #"%#"' for '#')) ELSE null END$$; diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index 3560318749..f345572c8c 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -4483,7 +4483,7 @@ get_create_object_cmd(EditableObjectType obj_type, Oid oid, printfPQExpBuffer(query, "SELECT nspname, relname, relkind, " "pg_catalog.pg_get_viewdef(c.oid, true), " - "array_remove(array_remove(c.reloptions,'check_option=local'),'check_option=cascaded') AS reloptions, " + "pg_catalog.array_remove(pg_catalog.array_remove(c.reloptions,'check_option=local'),'check_option=cascaded') AS reloptions, " "CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text " "WHEN 'check_option=cascaded' = ANY (c.reloptions) THEN 'CASCADED'::text ELSE NULL END AS checkoption " "FROM pg_catalog.pg_class c " diff --git a/src/test/isolation/isolationtester.c b/src/test/isolation/isolationtester.c index 4ecad038bd..64d666f5cd 100644 --- a/src/test/isolation/isolationtester.c +++ b/src/test/isolation/isolationtester.c @@ -184,7 +184,7 @@ main(int argc, char **argv) PQclear(res); /* Get the backend pid for lock wait checking. */ - res = PQexec(conns[i], "SELECT pg_backend_pid()"); + res = PQexec(conns[i], "SELECT pg_catalog.pg_backend_pid()"); if (PQresultStatus(res) == PGRES_TUPLES_OK) { if (PQntuples(res) == 1 && PQnfields(res) == 1) diff --git a/src/test/modules/worker_spi/worker_spi.c b/src/test/modules/worker_spi/worker_spi.c index 3b98b1682b..547bdb26c4 100644 --- a/src/test/modules/worker_spi/worker_spi.c +++ b/src/test/modules/worker_spi/worker_spi.c @@ -115,7 +115,9 @@ initialize_worker_spi(worktable *table) /* XXX could we use CREATE SCHEMA IF NOT EXISTS? */ initStringInfo(&buf); - appendStringInfo(&buf, "select count(*) from pg_namespace where nspname = '%s'", + appendStringInfo(&buf, + "select pg_catalog.count(*) " + "from pg_catalog.pg_namespace where nspname = '%s'", table->schema); ret = SPI_execute(buf.data, true, 0); -- 2.16.2
signature.asc
Description: PGP signature