Перейти к основному содержимому

Правила и привилегии

примечание

Эта страница переведена при помощи нейросети GigaChat.

Из-за переписывания запросов системой правил PostgreSQL доступ осуществляется к другим таблицам/представлениям, отличным от тех, которые используются в исходном запросе. С правилами для изменения возможна так же и запись в другие таблицы.

Правила перезаписи не имеют отдельного владельца. Владелец отношения (таблицы или представления) автоматически является владельцем правил перезаписи, которые определены для него. Система правил PostgreSQL изменяет поведение системы контроля доступа по умолчанию. За исключением SELECT правил, связанных с представлением безопасности вызывающего абонента (см. CREATE VIEW), все отношения, которые используются из-за правил, проверяются на наличие привилегий у владельца правила, а не пользователя, который вызывает правило. Это означает, что, за исключением представлений безопасности вызывающего абонента, пользователям нужны только необходимые привилегии для таблиц/представлений, которые явно указаны в их запросах.

Например, у пользователя есть список телефонных номеров, некоторые из которых являются частными, другие представляют интерес для помощника офиса. Пользователь может создать следующее:

CREATE TABLE phone_data (person text, phone text, private boolean);
CREATE VIEW phone_number AS
SELECT person, CASE WHEN NOT private THEN phone END AS phone
FROM phone_data;
GRANT SELECT ON phone_number TO assistant;

Никто, кроме этого пользователя (и суперпользователей базы данных), не имеет доступа к таблице phone_data. Но благодаря GRANT, помощник (assistant) может выполнить SELECT на представлении phone_number. Система правил заменит SELECT от phone_number на SELECT от phone_data. Поскольку пользователь является владельцем phone_number и, следовательно, владельцем правила, проверка чтения доступа к phone_data теперь выполняется относительно привилегий пользователя, и запрос разрешен. Проверка доступа к phone_number также выполняется, но это делается относительно вызывающего пользователя, поэтому никто, кроме пользователя и помощника, не может его использовать.

Привилегии проверяются построчно. Так что пока помощник - единственный, кто может видеть общедоступные номера телефонов. Но помощник может настроить другое представление и предоставить доступ к нему общественности. Тогда любой сможет увидеть данные phone_number через представление помощника. То, что помощник не может сделать, - это создать представление, которое напрямую обращается к phone_data. (На самом деле помощник может, но это не сработает, поскольку каждый доступ будет отклонен во время проверок разрешений.) И как только пользователь заметит, что помощник открыл свое представление phone_number, пользователь может отозвать доступ помощника. Немедленно любой доступ к представлению помощника потерпит неудачу.

Можно подумать, что эта проверка правило за правилом является дырой в безопасности, но на самом деле это не так. Но если бы она работала иначе, помощник мог бы настроить таблицу с теми же столбцами, что и phone_number , и копировать данные туда один раз в день. Тогда это собственные данные помощника, и помощник может предоставить доступ всем, кого они хотят. Другими словами, команда GRANT означает «Я доверяю тебе». Если кто-то, кому доверяете, проделывает такие операции, стоит задуматься и, возможно, лишить его доступа к данным, применив REVOKE.

Обратите внимание, что хотя представления могут использоваться для скрытия содержимого определенных столбцов с помощью техники, показанной выше, они не могут надежно скрывать данные в невидимых строках, если флаг security_barrier не установлен. Например, следующий вид ненадежен:

CREATE VIEW phone_number AS
SELECT person, phone FROM phone_data WHERE phone NOT LIKE '412%';

Этот вид может показаться безопасным, поскольку система правил будет переписывать любой SELECT из phone_number в SELECT из phone_data и добавит условие о том, что нужны только записи, где phone не начинается с 412. Но если пользователь может создавать свои собственные функции, планировщику несложно выполнить функцию, определенную пользователем, перед выражением NOT LIKE. Например:

CREATE FUNCTION tricky(text, text) RETURNS bool AS $$
BEGIN
RAISE NOTICE '% => %', $1, $2;
RETURN true;
END;
$$ LANGUAGE plpgsql COST 0.0000000000000000000001;

SELECT * FROM phone_number WHERE tricky(person, phone);

Каждое лицо и номер телефона в таблице phone_data будут напечатаны как NOTICE, потому что планировщик выберет выполнение недорогой функции tricky перед более дорогой функцией NOT LIKE. Даже если пользователю запрещено определять новые функции, встроенные функции можно использовать в аналогичных атаках. (Например, большинство функций приведения включают их входные значения в сообщения об ошибках, которые они производят.)

Аналогичные соображения применимы и к правилам обновления. В примерах предыдущего раздела владелец таблиц в примере базы данных мог бы предоставить привилегии SELECT, INSERT, UPDATE, и DELETE на представление shoelace кому-то другому, но только SELECT на shoelace_log. Действие правила для записи записей журнала все равно будет выполнено успешно, и этот другой пользователь сможет увидеть записи журнала. Но они не могли создавать фальшивые записи или манипулировать существующими записями. В этом случае нет возможности подорвать правила, убедив планировщика изменить порядок операций, потому что единственное правило, которое ссылается на shoelace_log, является неквалифицированным INSERT. Это может быть неверно в более сложных сценариях.

Когда необходимо, чтобы представление обеспечивало безопасность на уровне строки, атрибут security_barrier должен применяться к представлению. Это предотвращает передачу значений из строк вредоносным функциям и операторам до тех пор, пока представление не выполнит свою работу. Например, если представленное выше представление было создано так, оно было бы безопасным:

CREATE VIEW phone_number WITH (security_barrier) AS
SELECT person, phone FROM phone_data WHERE phone NOT LIKE '412%';

Представления, созданные с использованием security_barrier, могут работать намного хуже, чем представления, созданные без этого параметра. В общем, избежать этого невозможно: самый быстрый возможный план должен быть отклонен, если он может поставить под угрозу безопасность. По этой причине эта опция не включена по умолчанию.

Планировщик запросов имеет большую гибкость при работе с функциями, которые не имеют побочных эффектов. Такие функции называются LEAKPROOF и включают многие простые, часто используемые операторы, такие как многие операторы равенства. Планировщик запросов может безопасно разрешать выполнение таких функций в любой точке процесса выполнения запроса, поскольку их вызов для невидимых для пользователя строк не приведет к утечке какой-либо информации о невидимых строках. Кроме того, функции, которым не передаются аргументы или которые не получают никаких аргументов от представления барьера безопасности, не должны помечаться как LEAKPROOF для понижения, поскольку они никогда не получают данные из представления. Напротив, функция, которая может выдать ошибку в зависимости от полученных в качестве аргументов значений (например, та, которая выдает ошибку в случае переполнения или деления на ноль), не защищена от утечек и могла бы предоставить значительную информацию о невидимых строках, если она применяется до фильтров строк представления безопасности.

Важно понимать, что даже представление, созданное с использованием опции security_barrier, предназначено быть безопасным только в ограниченном смысле, что содержимое невидимых кортежей не будет передано потенциально ненадежным функциям. У пользователя могут быть и другие способы делать выводы о скрытых данных; например, они могут видеть план запроса с помощью EXPLAIN, или измерять время выполнения запросов к представлению. Злонамеренный атакующий может быть способен сделать вывод о количестве невидимых данных или даже получить некоторую информацию о распределении данных или наиболее распространенных значениях (поскольку эти вещи могут повлиять на время выполнения плана; или даже, поскольку они также отражены в статистике оптимизатора, выбор плана). Если такие типы атак "скрытых каналов" вызывают беспокойство, вероятно, неразумно предоставлять какой-либо доступ к данным вообще.