Ach ta public schema stale zlobi - tipy a triky na hardening

40 views
Skip to first unread message

mcmiazga

unread,
May 12, 2025, 9:49:33 AMMay 12
to PostgreSQL-cz
Dobry den kolegovia.

Pri sucasnych clankoch o BETA PG18 je moj prispevok tak trochu off topic, ale v korporatoch to s novymi verziami ide pomalsie, preto som sa rozhodol podelit o moje aktualne "skusenosti" s nadejou, ze to pomoze aj niekomu dalsiemu.

Standardne public schemu nepouzivam, ale ani ju nemazem ked vytvaram novu databazu. V piatok som s horucou hlavou riesil problem, kde som si bol isty, ze aj ked mam PG13, uzivatel bez pristupu do public schemy nevie zapisovat (CVE-2018-1058). Strasny omyl... Tu vidim, ze som nieco zanedbal. V PG15 a vyssie problem s public schemou nie je. No pocet 13 a 14 databaz u nas nie je zanedbatelny.

Zhrozeny som zacal vsade aplikovat:
REVOKE CREATE ON SCHEMA public FROM PUBLIC;
Povedal som si ze je spravny cas, doplnit do Zabbixu novy check na CREATE pre PUBLIC pseudo role.

Slovami klasika:
- Vite co to znamena? Znamena to ze sme zase o krok pred nima.
- A bude to stacit, myslis?

Preto by som sa chcel poradit, co vsetko v produkcii hardenujete?
REVOKE ALL ON database my_database from PUBLIC;
REVOKE ALL ON SCHEMA my_schema FROM PUBLIC;
REVOKE ALL ON SCHEMA public FROM my_user;
DROP SCHEMA public;


Pekny den.

Ako som testoval:
-- Na test som si na windowse nainstaloval PG13
psql (13.20)
Type "help" for help.

-- Vytvoril user1
postgres=# create user user1 password 'user1';
CREATE ROLE

-- Vytvoril user2
postgres=# create user user2 password 'user2';
CREATE ROLE

-- Vytvoril databazu user1 naschval aby bolo jasne komu to patri
postgres=# create database user1 owner user1;
CREATE DATABASE

-- Pripojil som sa uzivatelom user1 do databazy user1
postgres=# \c user1 user1
Password for user user1:

You are now connected to database "user1" as user "user1".

-- Zobrazil zoznam schem
user1=> \dn+
                          List of schemas
  Name  |  Owner   |  Access privileges   |      Description
--------+----------+----------------------+------------------------
 public | postgres | postgres=UC/postgres+| standard public schema
        |          | =UC/postgres         |
(1 row)

-- Vytvoril som si v public scheme tabulku test1
user1=> create table public.test1 as select * from pg_catalog.pg_database;
SELECT 4

-- Switchol som sa na user2 do databazy user1
user1=> \c user1 user2
Password for user user2:

You are now connected to database "user1" as user "user2".

-- Skontroloval kto je owner - je vidiet ze user2 nema Access privileges (aj ked to nemusi nic znamenat)
user1=> \l+ user1
                                                                             List of databases
   Name    |  Owner   | Encoding |       Collate        |        Ctype         |   Access privileges   |  Size   | Tablespace |                Description
-----------+----------+----------+----------------------+----------------------+-----------------------+---------+------------+--------------------------------------------
 user1     | user1    | UTF8     | Slovak_Slovakia.1250 | Slovak_Slovakia.1250 |                       | 7917 kB | pg_default |
(4 rows)

-- Creatol som tabulku test2 v public scheme a po vystupe SELECT 4 je vidiet, ze aj ked uzivatel nema ziadne prava, tak pseudo rola PUBLIC
user1=> create table public.test2 as select * from pg_catalog.pg_database;
SELECT 4

-- Pozrieme si kto je owner ktorych objektov
user1=> \dt+ public.*
                         List of relations
 Schema | Name  | Type  | Owner | Persistence | Size  | Description
--------+-------+-------+-------+-------------+-------+-------------
 public | test1 | table | user1 | permanent   | 16 kB |
 public | test2 | table | user2 | permanent   | 16 kB |
(2 rows)

-- Pripojime sa opatovne ako user1 do databazy user1 a skusime zmazat tabulku test2
postgres=# \c user1 user1
Password for user user1:

You are now connected to database "user1" as user "user1".

-- Ak ked je owner user1 databazy user1, tak skutocnym vlastnikom tabulky public.test2 je user2. A tu nastava problem.
user1=> drop table public.test2;
ERROR:  must be owner of table test2

-- Samozrejme nepomoze ani zmena ownera, lebo user1 nie je ownerom tabulky, aj ked je ownerom databazy
user1=> alter table public.test2 owner to user1;
ERROR:  must be owner of table test2

-- Tak to podme opravit, aby sa nam to nestalo. Pripojime sa ako SUPERUSER do databazy user1 (v tomto pripade som pouzil uzivatela postgres)
user1=> \c user1 postgres
Password for user postgres:

You are now connected to database "user1" as user "postgres".

-- Odoberieme problemove opravnenia
user1=# REVOKE CREATE ON SCHEMA public FROM PUBLIC;
REVOKE

-- Overime si, ci su OK a po kontrole opatovne kludnejsie spime :-))
user1=# \c user1 user2
Password for user user2:

You are now connected to database "user1" as user "user2".
user1=> create table public.test3 as select * from pg_catalog.pg_database;
ERROR:  permission denied for schema public





Pavel Stěhule

unread,
May 15, 2025, 12:11:42 AMMay 15
to PostgreSQL-cz
Ahoj

Dne pondělí 12. května 2025 v 15:49:33 UTC+2 uživatel mcmiazga napsal:
Dobry den kolegovia.

Pri sucasnych clankoch o BETA PG18 je moj prispevok tak trochu off topic, ale v korporatoch to s novymi verziami ide pomalsie, preto som sa rozhodol podelit o moje aktualne "skusenosti" s nadejou, ze to pomoze aj niekomu dalsiemu.

Standardne public schemu nepouzivam, ale ani ju nemazem ked vytvaram novu databazu. V piatok som s horucou hlavou riesil problem, kde som si bol isty, ze aj ked mam PG13, uzivatel bez pristupu do public schemy nevie zapisovat (CVE-2018-1058). Strasny omyl... Tu vidim, ze som nieco zanedbal. V PG15 a vyssie problem s public schemou nie je. No pocet 13 a 14 databaz u nas nie je zanedbatelny.

Zhrozeny som zacal vsade aplikovat:
REVOKE CREATE ON SCHEMA public FROM PUBLIC;
Povedal som si ze je spravny cas, doplnit do Zabbixu novy check na CREATE pre PUBLIC pseudo role.

Slovami klasika:
- Vite co to znamena? Znamena to ze sme zase o krok pred nima.
- A bude to stacit, myslis?

Preto by som sa chcel poradit, co vsetko v produkcii hardenujete?
REVOKE ALL ON database my_database from PUBLIC;
REVOKE ALL ON SCHEMA my_schema FROM PUBLIC;
REVOKE ALL ON SCHEMA public FROM my_user;
DROP SCHEMA public;


Pekny den.

Jeste jsem videl v nekterych doporucenich dropnuti databaze "postgres". Prijde mi to mozna az moc paranoidni - ale do jiste miry tomu rozumim. Na druhou stranu, pokud dropnete public, nebo databazi postgres,
tak nektere extenze nebo postupy, ktere jsou nekde na netu prestanou fungovat. V jednom korporatu jsem se setkal s tim, ze tym z roku 2010 efektivne databazi zabezpecil timto zpusobem. Databazovy tym z roku 2020,
ktery byl spis juniorni byl pak dost zmateny - samozrejme, ze temer vsichni lidi, kteri to predtim nastavovali, tak uz po roce 2020 tam nebyli.

CVE-2018-1058 je pro drtivou vetsinu aplikaci irelevantni - pozadavkem je mit kompromitovany ucet a pristup k databazi. V ten moment ale si uz utocnik muze vetsinou stahnout nebo modifikovat libovolna data
v 99% aplikaci, ktere jsem videl, a nejake maskarady s public schematem a search_path jsou uplne zbytecne.

Schema public samo o sobe az takove riziko neni - problem je az v kombinaci se search_path, a pak potencialne v moznosti presmerovani dotazu na jine objekty v pripade pouziti nekvalifikovanych indetifikatoru.

Kdyz uz dropnete public schema, tak urcite stoji za to zmenit nastaveni search_path, pripadne zafixovat jeho nastaveni (pokud je to cilem - nektere aplikace mohou vyzadovat dynamicke nastaveni search_path)

Hezky den

Pavel Stehule
Reply all
Reply to author
Forward
0 new messages