38.5. Правила и привилегии#

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

38.5. Правила и привилегии #

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

Правила перезаписи не имеют отдельного владельца. Владельцем отношения (таблицы или представления) автоматически становится владелец правил перезаписи, определенных для него. Система правил Tantor BE изменяет поведение системы контроля доступа по умолчанию. За исключением правил 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 ассистент может выполнить запрос SELECT на представлении phone_number. Система правил перепишет запрос SELECT с phone_number на 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 или измерять время выполнения запросов к представлению. Злонамеренный злоумышленник может сделать выводы о количестве невидимых данных или даже получить некоторую информацию о распределении данных или наиболее часто встречающихся значениях (поскольку эти вещи могут влиять на время выполнения плана; или даже, поскольку они также отражены в статистике оптимизатора, на выбор плана). Если такие типы "скрытых каналов" вызывают опасения, вероятно, нецелесообразно предоставлять доступ к данным вообще.