# Безопасность движка: pg_hba, роли, SECURITY DEFINER _Эксплуатация и наблюдаемость · PostgreSQL Knowledge Base_ **TL;DR:** pg_hba.conf решает, кого вообще пускать и как проверять - метод trust пускает без пароля кого попало. Роли несут привилегии. Функция SECURITY DEFINER исполняется с правами владельца, и при незакреплённом search_path это готовый канал эскалации привилегий. ## Три рубежа Безопасность движка стоит на трёх вопросах по порядку: кого пускать (аутентификация), что ему можно (авторизация), от чьего имени исполнять код (контекст функций). Дыра на любом рубеже обесценивает остальные. ## pg_hba.conf: кого и как пускать Файл `pg_hba.conf` - первый барьер, ещё до пароля. Каждая строка: «для такого-то типа подключения, такой-то базы, роли и адреса - проверять вот таким методом». Строки читаются сверху вниз, побеждает первая подходящая. ``` # TYPE DATABASE USER ADDRESS METHOD host all all 10.0.0.0/8 scram-sha-256 host all all 0.0.0.0/0 trust # ОПАСНО ``` Метод `trust` означает «пускать без проверки пароля вообще». Уместен разве что для локального сокета в одноразовом сэндбоксе. Строка с `trust` на широком диапазоне адресов - это открытая дверь: знаешь имя роли, и ты внутри. Боевой метод - `scram-sha-256`. ## Роли и привилегии В PostgreSQL пользователь и группа - это одна сущность, роль. Роль может логиниться (`LOGIN`), может владеть объектами, может входить в другие роли. Привилегии выдаются `GRANT` и наследуются по членству. Базовая гигиена: приложение не ходит суперпользователем. Под суперюзером не действуют права на таблицы и не работает row-level security - один такой коннект, утёкший наружу, открывает всё. Приложению дают роль ровно с нужными `GRANT` на нужные таблицы. ## SECURITY DEFINER + search_path: канал эскалации Обычная функция (`SECURITY INVOKER`) исполняется с правами вызвавшего. Функция `SECURITY DEFINER` - с правами **владельца**. Это нужно, чтобы дать пользователю выполнить контролируемое действие над данными, к которым у него прямого доступа нет. Опасность - в `search_path`. Если внутри SECURITY-DEFINER-функции, принадлежащей суперпользователю, есть неквалифицированный вызов (`SELECT ... FROM accounts`, а не `public.accounts`), то злоумышленник может создать в своей схеме объект с тем же именем и подсунуть его, сдвинув свой `search_path`. Функция выполнит подделку с правами владельца - вот и эскалация. ```sql -- защита: прибить search_path к самой функции CREATE FUNCTION admin_action() RETURNS void LANGUAGE sql SECURITY DEFINER SET search_path = pg_catalog, public -- фиксируем, не наследуем от вызвавшего AS $$ ... $$; ``` Правило для любой SECURITY DEFINER-функции: всегда `SET search_path` явно и квалифицируй имена объектов схемой. Без этого «удобная» функция превращается в лазейку. ## Минимальный чеклист - в `pg_hba.conf` нет `trust` на сетевых адресах, метод - `scram-sha-256`; - приложение работает не под суперпользователем; - у каждой `SECURITY DEFINER`-функции закреплён `search_path`; - привилегии выданы по принципу наименьших прав через `GRANT`. Как DROP без бэкапа превращается в катастрофу - [backup-pitr](/courses/postgres/kb/backup-pitr.md); типовые ошибки в самих запросах - [anti-patterns](/courses/postgres/kb/anti-patterns.md). ## Команды ```sql SELECT * FROM pg_hba_file_rules; ``` Прочитать действующие правила pg_hba.conf через SQL, без доступа к файлу ```sql SELECT rolname, rolsuper, rolcanlogin FROM pg_roles; ``` Кто суперпользователь и кто может логиниться ```sql SHOW search_path; ``` Текущий порядок поиска схем - основа эскалации через SECURITY DEFINER ## См. также - [Backup и восстановление на точку (PITR)](/courses/postgres/kb/backup-pitr.md) - [Каталог анти-паттернов (cheat sheet)](/courses/postgres/kb/anti-patterns.md) - [Карта pg_stat_* и pg_stat_statements](/courses/postgres/kb/pg-stat-map.md)