Spec-Zone.ru › MySQL 8.4

27.6 Управление доступом к хранимым объектам

Хранимые программы (процедуры, функции, триггеры и события) и представления определяются до использования и, при обращении к ним, выполняют действия в контексте безопасности, определяющем их привилегии. Привилегии, применимые к выполнению хранимого объекта, контролируются его атрибутом DEFINER и характеристикой SQL SECURITY.

  • Атрибут DEFINER

  • Характеристика SQL SECURITY

  • Примеры

  • Хранимые объекты-сироты

  • Рекомендации по минимизации рисков

Атрибут DEFINER

Определение хранимого объекта может включать атрибут DEFINER, который указывает на учетную запись MySQL. Если определение опускает атрибут DEFINER, по умолчанию определяет объект пользователь, который его создал.

Следующие правила определяют, какие учетные записи вы можете указать в качестве атрибута DEFINER для хранимого объекта:

  • Если у вас есть привилегия SET_ANY_DEFINER, вы можете указать любую учетную запись в качестве атрибута DEFINER. Если учетная запись не существует, генерируется предупреждение. Кроме того, чтобы установить атрибут хранимого объекта DEFINER на учетную запись, имеющую привилегию SYSTEM_USER, вам необходимо иметь привилегию SYSTEM_USER.

  • В противном случае единственная разрешенная учетная запись — ваша собственная, указанная либо явно, либо как CURRENT_USER или CURRENT_USER(). Вы не можете установить для определённого объекта другой пользователь.

Создание хранимого объекта с несуществующей учетной записью DEFINER создает объект-сироту, что может иметь негативные последствия; см. Хранимые объекты-сироты.

Характеристика SQL SECURITY

Для хранимых процедур (процедур и функций) и представлений определение объекта может включать характеристику SQL SECURITY со значением DEFINER или INVOKER, чтобы указать, выполняет ли объект действия в контексте пользователя-определяющего (definer) или вызывающего (invoker). Если определение опускает характеристику SQL SECURITY, по умолчанию используется контекст пользователя-определяющего.

Триггеры и события не имеют характеристики SQL SECURITY и всегда выполняются в контексте пользователя-определяющего. Сервер вызывает эти объекты автоматически по мере необходимости, поэтому нет вызывающего пользователя.

Контексты безопасности пользователя-определяющего (definer) и вызывающего (invoker) различаются следующим образом:

  • Хранимый объект, выполняемый в контексте безопасности пользователя-определяющего, выполняется с привилегиями учетной записи, указанной в его атрибуте DEFINER. Эти привилегии могут полностью отличаться от привилегий вызывающего пользователя. Вызывающий пользователь должен иметь соответствующие привилегии для обращения к объекту (например, EXECUTE для вызова хранимой процедуры или SELECT для выборки из представления), но во время выполнения объекта привилегии вызывающего пользователя игнорируются, и учитываются только привилегии учетной записи DEFINER. Если учетная запись DEFINER имеет ограниченный набор привилегий, объект также ограничен в выполняемых операциях. Если учетная запись DEFINER имеет высокие привилегии (например, административная учетная запись), объект может выполнять мощные операции независимо от того, кто его вызывает.

  • Хранимая процедура или представление, выполняемая в контексте безопасности вызывающего пользователя, может выполнять только те операции, для которых вызывающий пользователь имеет привилегии. Атрибут DEFINER не оказывает влияния на выполнение объекта.

Примеры

Рассмотрим следующую хранимую процедуру, объявленную с SQL SECURITY DEFINER, чтобы выполняться в контексте безопасности пользователя-определяющего:

CREATE DEFINER = 'admin'@'localhost' PROCEDURE p1()
SQL SECURITY DEFINER
BEGIN
  UPDATE t1 SET counter = counter + 1;
END;

Любой пользователь, имеющий привилегию EXECUTE для p1, может вызвать её с помощью оператора CALL. Однако, когда p1 выполняется, она делает это в контексте безопасности пользователя-определяющего и, таким образом, выполняется с привилегиями учетной записи 'admin'@'localhost', указанной в качестве ее атрибута DEFINER. Эта учетная запись должна иметь привилегию EXECUTE для p1, а также привилегию UPDATE для таблицы t1, указанной в теле объекта. В противном случае процедура завершится с ошибкой.

Теперь рассмотрим эту хранимую процедуру, идентичную p1, за исключением того, что ее характеристика SQL SECURITY имеет значение INVOKER:

CREATE DEFINER = 'admin'@'localhost' PROCEDURE p2()
SQL SECURITY INVOKER
BEGIN
  UPDATE t1 SET counter = counter + 1;
END;

В отличие от p1, p2 выполняется в контексте безопасности вызывающего пользователя и, таким образом, с привилегиями вызывающего пользователя независимо от значения атрибута DEFINER. p2 завершится с ошибкой, если у вызывающего пользователя отсутствуют привилегии EXECUTE для p2 или UPDATE для таблицы t1.

Сироты хранимых объектов

Хранимый объект-сирота — это объект, для которого его атрибут DEFINER указывает на несуществующую учётную запись:

  • Хранимый объект-сирота может быть создан путём указания несуществующей DEFINER учётной записи во время создания объекта.

  • Существующий хранимый объект может стать сиротой в результате выполнения инструкции DROP USER, которая удаляет учётную запись объекта DEFINER, или инструкции RENAME USER, которая переименовывает учётную запись объекта DEFINER.

Хранимый объект-сирота может быть проблематичен в следующих отношениях:

  • Поскольку учётная запись DEFINER не существует, объект может не работать должным образом, если он выполняется в контексте безопасности определяющего пользователя:

    • Для хранимой процедуры ошибка возникает во время выполнения процедуры, если значение SQL SECURITY равно DEFINER, но определяющая учётная запись не существует.

    • Для триггера нежелательно, чтобы активация триггера происходила до фактического существования учётной записи. В противном случае поведение с точки зрения проверки привилегий является неопределённым.

    • Для события ошибка возникает во время выполнения события, если учётная запись не существует.

    • Для представления ошибка возникает при обращении к представлению, если значение SQL SECURITY равно DEFINER, но определяющая учётная запись не существует.

  • Объект может представлять собой угрозу безопасности, если несуществующая учётная запись DEFINER впоследствии будет создана с целью, не связанной с объектом. В этом случае учётная запись “усыновляет” объект и, имея соответствующие привилегии, может его выполнить, даже если это не предполагалось.

Сервер выполняет следующие проверки безопасности управления учётными записями, предназначенные для предотвращения операций, которые (возможно, непреднамеренно) приводят к тому, что хранимые объекты становятся сиротами, или к тому, что хранимые объекты, которые в настоящее время являются сиротами, усыновляются:

  • DROP USER завершается ошибкой, если любая удаляемая учётная запись указана в качестве атрибута DEFINER для любого хранимого объекта. (То есть, инструкция завершается ошибкой, если удаление учётной записи приведёт к тому, что хранимый объект станет сиротой.)

  • RENAME USER завершается ошибкой, если любая переименовываемая учётная запись указана в качестве атрибута DEFINER для любого хранимого объекта. (То есть, инструкция завершается ошибкой, если переименование учётной записи приведёт к тому, что хранимый объект станет сиротой.)

  • CREATE USER завершается ошибкой, если любая создаваемая учётная запись указана в качестве атрибута DEFINER для любого хранимого объекта. (То есть, инструкция завершается ошибкой, если создание учётной записи приведёт к тому, что учётная запись усыновит текущий хранимый объект-сироту.)

В некоторых ситуациях может потребоваться преднамеренно выполнить эти инструкции управления учётными записями, даже если они иначе завершатся ошибкой. Для этого, если у пользователя есть привилегия ALLOW_NONEXISTENT_DEFINER, эта привилегия переопределяет проверки безопасности объектов-сирот, и инструкции завершатся предупреждением, а не ошибкой.

Чтобы получить информацию об учётных записях, используемых в качестве определяющих пользователей хранимых объектов в установке MySQL, выполните запрос к таблице INFORMATION_SCHEMA.

Этот запрос определяет, какие таблицы INFORMATION_SCHEMA описывают объекты, имеющие атрибут DEFINER:

mysql> SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS
       WHERE COLUMN_NAME = 'DEFINER';
+--------------------+------------+
| TABLE_SCHEMA       | TABLE_NAME |
+--------------------+------------+
| information_schema | EVENTS     |
| information_schema | ROUTINES   |
| information_schema | TRIGGERS   |
| information_schema | VIEWS      |
+--------------------+------------+

Результат показывает, какие таблицы нужно запросить, чтобы узнать, какие значения хранимых объектов DEFINER существуют и какие объекты имеют определённое значение DEFINER:

  • Чтобы определить, какие значения DEFINER существуют в каждой таблице, используйте эти запросы:

    SELECT DISTINCT DEFINER FROM INFORMATION_SCHEMA.EVENTS;
    SELECT DISTINCT DEFINER FROM INFORMATION_SCHEMA.ROUTINES;
    SELECT DISTINCT DEFINER FROM INFORMATION_SCHEMA.TRIGGERS;
    SELECT DISTINCT DEFINER FROM INFORMATION_SCHEMA.VIEWS;
    

    Результаты запроса важны для любой учётной записи, отображаемой следующим образом:

    • Если учётная запись существует, её удаление или переименование приводит к тому, что хранимые объекты становятся сиротами. Если вы планируете удалить или переименовать учётную запись, сначала рассмотрите возможность удаления связанных хранимых объектов или переопределения их с использованием другого определяющего пользователя.

    • Если учётная запись не существует, её создание приводит к тому, что она усыновляет текущие хранимые объекты-сироты. Если вы планируете создать учётную запись, рассмотрите вопрос о том, должны ли к ней быть связаны объекты-сироты. Если нет, переопределите их с использованием другого определяющего пользователя.

    Чтобы переопределить объект с использованием другого определяющего пользователя, можно использовать ALTER EVENT или ALTER VIEW для непосредственного изменения учётной записи DEFINER событий и представлений. Для хранимых процедур и функций и триггеров необходимо удалить объект и создать его заново, чтобы назначить другую учётную запись DEFINER.

  • Чтобы определить, какие объекты имеют заданную учётную запись DEFINER, используйте эти запросы, заменив интересующую учётную запись на user_name@host_name:

    SELECT EVENT_SCHEMA, EVENT_NAME FROM INFORMATION_SCHEMA.EVENTS
    WHERE DEFINER = 'user_name@host_name';
    SELECT ROUTINE_SCHEMA, ROUTINE_NAME, ROUTINE_TYPE
    FROM INFORMATION_SCHEMA.ROUTINES
    WHERE DEFINER = 'user_name@host_name';
    SELECT TRIGGER_SCHEMA, TRIGGER_NAME FROM INFORMATION_SCHEMA.TRIGGERS
    WHERE DEFINER = 'user_name@host_name';
    SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.VIEWS
    WHERE DEFINER = 'user_name@host_name';
    

    Для таблицы ROUTINES запрос включает столбец ROUTINE_TYPE, чтобы строки вывода различали, является ли DEFINER хранимой процедурой или хранимой функцией.

    Если учётная запись, которую вы ищете, не существует, все объекты, отображённые этими запросами, являются объектами-сиротами.

Рекомендации по минимизации рисков

Для минимизации потенциальных рисков при создании и использовании хранимых объектов следуйте этим рекомендациям:

  • Не создавайте оторванные хранимые объекты; то есть, объекты, для которых атрибут DEFINER указывает на несуществующий аккаунт. Не допускайте, чтобы хранимые объекты становились оторванными, удаляя или переименовывая аккаунт, указанный атрибутом DEFINER любого существующего объекта.

  • Для хранимой процедуры или представления, используйте SQL SECURITY INVOKER в определении объекта, когда это возможно, чтобы он мог быть использован только пользователями с правами, соответствующими операциям, выполняемым объектом.

  • Если вы создаете хранимые объекты контекста определённого пользователем при использовании аккаунта, обладающего правом SET_ANY_DEFINER, укажите явный атрибут DEFINER, который назначает аккаунт, обладающий только необходимыми для выполняемых объектом операций правами. Указывайте высокопривилегированный аккаунт DEFINER только в том случае, если это абсолютно необходимо.

  • Администраторы могут предотвратить создание пользователями хранимых объектов, которые указывают высокопривилегированные аккаунты DEFINER, не предоставляя им право SET_ANY_DEFINER.

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

    • Хранимая процедура не может быть вызвана пользователем, который не имеет права EXECUTE для неё.

    • Представление не может быть вызвано пользователем, который не имеет соответствующих для него прав (SELECT для выбора из него, INSERT для вставки в него и так далее).

    Однако, такого контроля не существует для триггеров и событий, так как они всегда выполняются в контексте определённого пользователя. Сервер вызывает эти объекты автоматически по мере необходимости, и пользователи не ссылаются на них напрямую:

    • Триггер активируется доступом к таблице, с которой он связан, даже обычными обращениями к таблице со стороны пользователей без специальных привилегий.

    • Событие выполняется сервером по расписанию.

    В обоих случаях, если аккаунт DEFINER имеет высокие привилегии, объект может выполнять конфиденциальные или опасные операции. Это остается справедливым, даже если права, необходимые для создания объекта, отозваны у учётной записи пользователя, который его создал. Администраторы должны быть особенно внимательны при предоставлении пользователям прав на создание объектов.

  • По умолчанию, при выполнении процедуры с характеристикой SQL SECURITY DEFINER, сервер MySQL не устанавливает активные роли для учётной записи MySQL, указанной в предложении DEFINER, а только роли по умолчанию. Исключением является случай, когда переменная системы activate_all_roles_on_login включена, в этом случае сервер MySQL устанавливает все роли, предоставленные пользователю DEFINER, включая обязательные роли. Следовательно, по умолчанию любые привилегии, предоставленные через роли, не проверяются при выполнении операторов CREATE PROCEDURE или CREATE FUNCTION. Для хранимых программ, если выполнение должно происходить с ролями, отличными от по умолчанию, тело программы может выполнить SET ROLE для активации необходимых ролей. Это следует делать с осторожностью, так как привилегии, назначенные ролям, могут быть изменены.

© 2025 Oracle
Licensed under the GPLv2 License.
https://docs.oracle.com/cd/E17952_01/mysql-8.4-en/stored-objects-security.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API