🚨 Пятница, вечер. Мониторинг замечает скачок чтения в таблице платежей. У ИБ три вопроса:
1. Кто обращался к данным?
2. С какого адреса?
3. Сколько строк прочитал?
Обычный журнал PostgreSQL редко дает такой ответ. log_statement = all смешивает запросы с сообщениями сервера и приложений, а log_line_prefix лишь добавляет к текстовым строкам роль или IP. pgAudit улучшает аудит команд и объектов, но нужные поля остаются в общем серверном логе. Триггер тоже не спасет: он не увидит SELECT — основной канал утечки.
Нужен заранее подготовленный структурированный аудит. В Postgres Pro Enterprise его обеспечивает pg_proaudit: записывает в отдельный CSV-журнал роль, IP клиента, тип операции, объект, статус, текст запроса и число затронутых строк.
Чтобы не утонуть в событиях, правила задают выборочно: DML для public.payments, операции с ролями, невременный DDL, входы и отключения. Доступ к системному каталогу включают через pg_proaudit.log_catalog_access = on и DML-правило для интересующей роли — здесь это insider.
Две детали решают исход расследования. object_name указывают вместе со схемой: правило для payments сохранится, но не сработает, нужно public.payments, а pg_proaudit.log_rows = on фиксирует объем чтения.
Затем pgpro-otel-collector разбирает CSV на 20 полей и отправляет события по OTLP HTTP в VictoriaLogs. LogsQL дает быстрый поиск, Grafana — обзор аномалий.
🔍 Вернемся к платежам. Запрос по object_name:payments находит событие:
role_name=insider
user_ip=172.24.0.5
event_type=SELECT
status=SUCCESS
query_text=SELECT * FROM payments
rows=5000
Пять тысяч строк еще не доказывают утечку. Нужен baseline. Приложение и аналитик читали таблицу небольшими порциями — с LIMIT 50 или через count(*). Инсайдер выполнил полный скан без LIMIT. Аномалия здесь — не просто большой SELECT, а отклонение от привычного объема для этой роли и адреса.
Дальше проверяют смежные события: ALL_ROLE — выдачу прав и попытки эскалации, ALL_DDL_NONTEMP — изменения схемы, AUTHENTICATE и DISCONNECT — входы и отключения. Чтения pg_class, pg_attribute, pg_roles выдают разведку. Даже запрещенное обращение к pg_authid остается в журнале со status=FAILURE.
Фильтр по роли и IP сшивает цепочку: разведка по каталогу, неудачные входы, затем успешное чтение 5000 платежей. Теперь известно, кто, откуда, сколько данных прочитал и что делал до этого.
📊 На дашборде полезно следить за долей отказов, максимумом строк за запрос, новыми ролями, адресами и пиками чтения. Grafana помогает заметить, LogsQL — разобраться.
🔗 Пошаговая настройка pg_proaudit, конфиг коллектора, запросы для пяти сценариев и устройство дашборда — в подробном разборе на Хабре.
🔔 Читайте нас в MAX
1. Кто обращался к данным?
2. С какого адреса?
3. Сколько строк прочитал?
Обычный журнал PostgreSQL редко дает такой ответ. log_statement = all смешивает запросы с сообщениями сервера и приложений, а log_line_prefix лишь добавляет к текстовым строкам роль или IP. pgAudit улучшает аудит команд и объектов, но нужные поля остаются в общем серверном логе. Триггер тоже не спасет: он не увидит SELECT — основной канал утечки.
Нужен заранее подготовленный структурированный аудит. В Postgres Pro Enterprise его обеспечивает pg_proaudit: записывает в отдельный CSV-журнал роль, IP клиента, тип операции, объект, статус, текст запроса и число затронутых строк.
Чтобы не утонуть в событиях, правила задают выборочно: DML для public.payments, операции с ролями, невременный DDL, входы и отключения. Доступ к системному каталогу включают через pg_proaudit.log_catalog_access = on и DML-правило для интересующей роли — здесь это insider.
Две детали решают исход расследования. object_name указывают вместе со схемой: правило для payments сохранится, но не сработает, нужно public.payments, а pg_proaudit.log_rows = on фиксирует объем чтения.
Затем pgpro-otel-collector разбирает CSV на 20 полей и отправляет события по OTLP HTTP в VictoriaLogs. LogsQL дает быстрый поиск, Grafana — обзор аномалий.
🔍 Вернемся к платежам. Запрос по object_name:payments находит событие:
role_name=insider
user_ip=172.24.0.5
event_type=SELECT
status=SUCCESS
query_text=SELECT * FROM payments
rows=5000
Пять тысяч строк еще не доказывают утечку. Нужен baseline. Приложение и аналитик читали таблицу небольшими порциями — с LIMIT 50 или через count(*). Инсайдер выполнил полный скан без LIMIT. Аномалия здесь — не просто большой SELECT, а отклонение от привычного объема для этой роли и адреса.
Дальше проверяют смежные события: ALL_ROLE — выдачу прав и попытки эскалации, ALL_DDL_NONTEMP — изменения схемы, AUTHENTICATE и DISCONNECT — входы и отключения. Чтения pg_class, pg_attribute, pg_roles выдают разведку. Даже запрещенное обращение к pg_authid остается в журнале со status=FAILURE.
Фильтр по роли и IP сшивает цепочку: разведка по каталогу, неудачные входы, затем успешное чтение 5000 платежей. Теперь известно, кто, откуда, сколько данных прочитал и что делал до этого.
📊 На дашборде полезно следить за долей отказов, максимумом строк за запрос, новыми ролями, адресами и пиками чтения. Grafana помогает заметить, LogsQL — разобраться.
🔗 Пошаговая настройка pg_proaudit, конфиг коллектора, запросы для пяти сценариев и устройство дашборда — в подробном разборе на Хабре.
🔔 Читайте нас в MAX