The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

Каталог документации / Раздел "Базы данных, SQL" / Оглавление документа

10 Общие проблемы защиты и система привилегий доступа MySQL

MySQL имеет продвинутую, но ненормативную систему защиты и привилегий. Этот подробно раздел описывает, как она работает.

10.1 Управление привилегиями

10.1.1 Синтаксис GRANT и REVOKE

GRANT priv_type [(column_list)] [, priv_type [(column_list)] ...]
      ON {tbl_name|*|*.*|db_name.*} TO user_name [IDENTIFIED BY 'password']
      [, user_name [IDENTIFIED BY 'password'] ...] [REQUIRE {SSL|X509}
      [ISSUER issuer] [SUBJECT subject]] [WITH GRANT OPTION]

REVOKE priv_type [(column_list)] [, priv_type [(column_list)] ...]
       ON {tbl_name|*| *.*|db_name.*}
       FROM user_name [, user_name ...]

GRANT реализован в MySQL Version 3.22.11 или позже. Для более ранних версий MySQL инструкция GRANT не делает ничего.

Команды GRANT и REVOKE позволяют администраторам системы создавать пользователей, предоставлять и отменять права на MySQL-пользователей в четырех уровнях привилегий:

Глобальный уровень (Global level)
Глобальные привилегии обращаются ко всем базам данных на данном сервере. Эти привилегии сохранены в таблице mysql.user.
Уровень баз данных (Database level)
Привилегии баз данных обращаются ко всем таблицам в данной базе данных. Эти привилегии сохранены в таблицах mysql.db и mysql.host.
Уровень таблиц (Table level)
Привилегии таблиц обращаются ко всем столбцам в данной таблице. Эти привилегии сохранены в таблице mysql.tables_priv.
Уровень столбцов (Column level)
Привилегии столбцов обращаются к одиночным столбцам в данной таблице. Эти привилегии сохранены в таблице mysql.columns_priv.

Если Вы даете привилегии пользователю, который не существует, он будет автоматически создан.

Для инструкций GRANT и REVOKE аргумент priv_type может быть определен как любой из следующего списка:

ALL PRIVILEGES   FILE         RELOAD     ALTER   INDEX     SELECT
CREATE           INSERT       SHUTDOWN   DELETE  PROCESS   UPDATE
DROP             REFERENCES   USAGE

ALL представляет собой синоним для ALL PRIVILEGES. REFERENCES пока не реализовано. USAGE в настоящее время представляет собой синоним для ``no privileges''. Это может быть применено, когда Вы хотите создать пользователя, который не имеет никаких привилегий.

Чтобы отменять привилегию предоставленную командой grant, используйте значение priv_type параметра GRANT OPTION:

REVOKE GRANT OPTION ON ... FROM ...;

Значения priv_type, которые Вы можете определять для таблицы: SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, GRANT, INDEX и ALTER.

Значения priv_type, которые Вы можете определять для столбца (то есть, когда Вы используете аргумент column_list): SELECT, INSERT и UPDATE.

Вы можете устанавливать глобальные привилегии, используя синтаксис ON *.*. Вы можете устанавливать привилегии базы данных, используя синтаксис ON db_name.*. Если Вы определяете ON *, и Вы имеете текущую базу данных, Вы установите привилегии именно для этой базы данных. ПРЕДУПРЕЖДЕНИЕ: Если Вы определяете ON *, и Вы не имеете текущей базы данных, Вы будете воздействовать на глобальные привилегии!

Чтобы приспосабливать предоставление прав на пользователей с произвольных компьютеров, MySQL поддерживает определение значения user_name в форме user@host. Если Вы хотите определять строку user или строку host, содержащую специальные или групповые символы (например, `-'), Вы можете цитировать имя пользователя или хоста (например, 'test-user'@'test-hostname').

Вы можете определять групповые символы в hostname. Например, user@"%.joker.botik.ru" применяется к user для любого компьютера в домене joker.botik.ru, а user@"144.155.166.%" будет применено к user с любой машины в сети 144.155.166 класса C.

Простая форма user представляет собой синоним для user@"%". ОБРАТИТЕ ВНИМАНИЕ: Если Вы позволяете анонимным пользователям соединяться с сервером MySQL (что является значением по умолчанию), Вы должны также добавить всех локальных пользователей как user@localhost потому, что иначе анонимная запись в таблице mysql.user будет применяться, когда пользователь попробует зарегистрироваться на сервере MySQL с локальной машины! Анонимные пользователи определены вставкой записей с User='' в таблицу mysql.user. Вы можете проверять, применяется ли это у Вас, выполняя такой запрос:

mysql> SELECT Host,User FROM mysql.user WHERE User='';

В настоящий момент GRANT поддерживает имена хоста, базы данных, таблицы и столбца длиной только до 60 символов. Имя пользователя может быть длиной до 16 символов.

Привилегии для таблицы или столбца сформированы из логического ИЛИ (OR) привилегий в каждом из четырех уровней привилегии. Например, если таблица mysql.user определяет, что пользователь имеет глобальную привилегию select, это не может быть отменено записью на других уровнях доступа!

Привилегии для столбца могут быть вычислены следующим образом:

global privileges OR
(database privileges AND host privileges) OR
table privileges OR column privileges

В большинстве случаев Вы предоставляете права пользователю только в одном из уровней привилегии, так что обычно это просто. Детали проверяющей привилегии процедуры подробно рассмотрены в разделе "10 Общие проблемы защиты и система привилегий доступа MySQL".

Если Вы предоставляете привилегии для комбинации user/hostname, которая не существует в таблице mysql.user, запись будет добавлена и останется там пока ее не удалят командой DELETE. Другими словами, GRANT может создавать записи в таблице user, но REVOKE не будет удалять их. Вы должны делать это явно, используя вызов DELETE.

В MySQL Version 3.22.12 или позже, если новый пользователь создан, или если Вы имеете глобальные привилегии, пароль пользователя будет установлен в пароль, определенный предложением IDENTIFIED BY, если оно задано. Если пользователь уже имел пароль, он будет заменен новым.

ПРЕДУПРЕЖДЕНИЕ: Если Вы создаете нового пользователя, но не определяете предложение IDENTIFIED BY, пользователь не имеет никакого пароля. Это опасно.

Пароли также могут быть установлены командой SET PASSWORD. Подробности в разделе "14.5.6 Синтаксис SET".

Если Вы предоставляете привилегии для базы данных, запись в таблице mysql.db будет создана, если необходимо. Когда все привилегии для базы данных будут удалены с помощью REVOKE, эта запись тоже будет удалена автоматически.

Если пользователь не имеет привилегий на таблице, данная таблица не отображается вообще, когда пользователь запрашивает список таблиц (например, инструкцией SHOW TABLES).

Предложение WITH GRANT OPTION дает пользователю способность передать другим пользователям любые привилегии, которые этот пользователь имеет в определенном уровне доступа. Вы должны быть внимательным к тому, кому Вы даете привилегию grant, поскольку два пользователя с различными привилегиями могут быть способны соединить свои привилегии!

Вы не можете предоставлять другому пользователю привилегию, которую Вы не имеете сами. Привилегия grant позволяет Вам передавать только те привилегии, которыми Вы реально обладаете.

Знайте, что, когда Вы предоставляете пользователю привилегию grant в специфическом уровне привилегии, любые привилегии, которые пользователь уже имеет (или получит в будущем!) в этом уровне также могут передаваться этим пользователем кому угодно. Предположите, что Вы предоставляете пользователю привилегию insert на базе данных. Если Вы затем предоставляете привилегию select на базе данных и определяете WITH GRANT OPTION, пользователь сможет передавать не только привилегию select, но и insert! Если Вы затем предоставляете ему еще и привилегию update на базе данных, этот пользователь сможет передавать insert, select и update.

Вы не должны предоставлять привилегию alter нормальному пользователю. Если Вы это сделаете, пользователь может попробовать разрушить систему привилегии, переименовывая таблицы!

Обратите внимание, что, если Вы используете привилегии столбца или таблицы даже для одного пользователя, сервер исследует привилегии столбца и таблицы для всех пользователей, и это замедлит немного MySQL.

Когда mysqld запускается, все привилегии читаются в память. Привилегии, связанные с базами данных, таблицами и столбцами начинают действовать сразу же, а связанные с пользователями сработают, когда пользователь соединится с сервером в следующий раз. Модификации к таблицам предоставления, которые Вы выполняете, используя GRANT или REVOKE воспринимаются сервером немедленно. Если Вы изменяете таблицы предоставления вручную (используя INSERT, UPDATE и т.д.), Вы должны выполнить инструкцию FLUSH PRIVILEGES или запустить команду mysqladmin flush-privileges, чтобы сервер перезагрузил все таблицы предоставления привилегий.

Самые большие различия между ANSI SQL и MySQL версиями оператора GRANT:

10.1.2 Имена и пароли пользователей MySQL

Имеются несколько различий между использованием имен и паролей MySQL и Unix или Windows:

Пользователи MySQL и их привилегии обычно создаются командой GRANT. Подробности в разделе "10.1 Синтаксис GRANT и REVOKE".

Когда Вы входите в систему на сервере MySQL с помощью клиента командной строки, Вы должны определить пароль с помощью опции --password=your-password. Подробности изложены в разделе "10.7 Связь с сервером MySQL":

mysql --user=monty --password=guess database_name

Если Вы хотите, чтобы Вас запросили относительно пароля, Вы должны использовать аргумент --password:

mysql --user=monty --password database_name

Или в кратком виде:

mysql -u monty -p database_name

Обратите внимание, что в последнем примере пароль НЕ database_name.

Если Вы хотите использовать опцию -p, чтобы задать пароль, сделайте это так:

mysql -u monty -pguess database_name

На некоторых системах библиотечный вызов, который MySQL использует для запроса пароля, автоматически урежет пароль до длины в 8 символов. Внутренне MySQL не имеет ограничений на длину пароля.

10.2 Общие принципы защиты

Любой, использующий MySQL на компьютере, связанном с Internet, должен прочитать этот раздел, чтобы избежать наиболее общих ошибок защиты. Данный раздел включен сюда, главным образом, по той причине, что предоставлять привилегии может (а в ряде случаев и должен) не только администратор, но и некоторые доверенные пользователи, например, начальник проекта должен предоставить исполнителю необходимые для выполнения задачи привилегии.

Очень важно уделить внимание проблемам безопасности всего сервера (а не только MySQL) и защите от всех типов атак.

MySQL использует защиту, основанную на списках управления доступом (Access Control Lists ACL) для всех подключений, запросов и других операций, которые пользователь может пытаться выполнять. Имеется также поддержка для соединений, зашифрованных SSL между клиентами и сервером MySQL. Многие из понятий, обсуждаемых здесь, не специфические для MySQL: те же самые общие идеи применимы вообще почти ко всем прикладным программам.

При запуске MySQL следуйте этим руководящим принципам:

10.2 Как защитить MySQL от хакеров

Когда Вы соединяетесь с сервером MySQL, Вы обычно должны использовать пароль. Он не передается открытым текстом, однако, алгоритм шифрования не очень силен, и с некоторым усилием умный нападаюший может расколоть пароль, если может перехватить трафик. Если подключение между пользователем и сервером проходит недоверенную сеть, Вы должны использовать SSH-туннель, чтобы шифровать связь. Увы, хакеры сделали шифрование совершенно мирной связи обычным делом. А думали ли мы все, что через три года будем совершенно спокойно воспринимать шифрование данных не в военных системах, а дома?

Вся другая информация будет перемещена как текст, который может читаться любым, кто способен наблюдать подключение. Если Вы обеспокоены относительно этого, Вы можете использовать сжатый протокол (в MySQL версии 3.22 и выше), чтобы делать такое чтение намного тяжелее. Чтобы сделать связь более безопасной, Вы должны использовать ssh. Вы можете скачать исходные тексты клиентской части ssh с http://www.openssh.org, коммерческая версия клиента ssh доступна на http://www.ssh.com. Теперь Вы можете получить шифрованное TCP/IP подключение к серверу MySQL.

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

10.3 Параметры запуска для mysqld, связанные с защитой

Следующие параметры mysqld воздействуют на защиту:

--safe-show-database
С этой опцией SHOW DATABASES возвращает только те базы данных, для которых пользователь имеет некоторую привилегию.
--safe-user-create
Если включено, пользователь не может создавать новых пользователей командой GRANT, если он не имеет права INSERT на таблице mysql.user. Если Вы хотите давать пользователю доступ к созданию новых пользователей с теми привилегиями, которые он имеет право предоставить, Вы должны дать ему следующую привилегию:
GRANT INSERT(user) on mysql.user to 'user''hostname';
Это гарантирует, что пользователь не может изменять любые столбцы привилегий непосредственно, а должен использовать команду GRANT, чтобы дать привилегии другим пользователям.
--skip-grant-tables
Эта опция заставляет сервер не использовать систему привилегий вообще. Это дает каждому полный доступ ко всем базам данных! Вы можете сообщить, чтобы сервер начал использовать таблицы привилегий снова, выполняя команду mysqladmin flush-privileges или mysqladmin reload.
--skip-name-resolve
Не преобразовывать имена. Все значения столбца Host в таблицах предоставления привилегий должны быть IP-адресами или localhost.
--skip-networking
Не слушать TCP/IP подключения вообще. Все взаимодействие с mysqld должно быть выполнено через сокеты Unix. Эта опция очень рекомендуется на системах, где позволяются только локальные запросы. Эта опция не подходит для систем, которые используют MIT-PTHREADS потому, что пакет MIT-PTHREADS не поддерживает Unix-сокеты.
--skip-show-database
Инструкция SHOW DATABASES не будет возвращать ничего.

10.4 Что делает система привилегий

Первичная функция системы привилегий MySQL состоит в том, что она должна опознать пользователя, соединяющегося с данного компьютера, и сопоставить этого пользователя с привилегиями на базе данных типа select, insert, update и delete.

Дополнительные функциональные возможности включают способность иметь анонимного пользователя и предоставлять привилегии для MySQL-функций, типа LOAD DATA INFILE, и административных операций.

10.5 Как работает система привилегий

Система привилегий MySQL гарантирует, что все пользователи могут делать точно те дела, которые им будут позволены. Когда Вы соединяетесь с сервером MySQL, Вы будете идентифицированы не только по логину, который ввели, но и по адресу хоста, с которого зашли в сеть.

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

Управление доступом MySQL включает две стадии:

Сервер использует таблицы user, db и host в базе данных mysql на обеих стадиях управления доступа. Поля в этих таблицах показаны ниже:

Имя таблицыuser dbhost
Поля контекстаHost HostHost
UserDb Db
PasswordUser
Поля привилегийSelect_priv Select_privSelect_priv
Insert_privInsert_priv Insert_priv
Update_privUpdate_priv Update_priv
Delete_privDelete_priv Delete_priv
Index_privIndex_priv Index_priv
Alter_privAlter_priv Alter_priv
Create_privCreate_priv Create_priv
Drop_privDrop_priv Drop_priv
Grant_privGrant_priv Grant_priv
References_priv
Reload_priv
Shutdown_priv
Process_priv
File_priv

Для второй стадии управления доступом (проверка запроса) сервер может, если запрос включает таблицы, дополнительно консультироваться с таблицами tables_priv и columns_priv. Поля этих таблиц:

Имя таблицыtables_priv columns_priv
Поля контекстаHost Host
DbDb
UserUser
Table_nameTable_name
Column_name
Поля привилегийTable_priv Column_priv
Column_priv
Прочие поляTimestamp Timestamp
Grantor

Каждая таблица содержит поля области (контекста) и поля привилегий.

Поля контекста определяют область (контекст) каждой записи в таблицах, то есть тот контекст, в котором применяется данная запись. Например, запись в таблице user со значениями Host и User 'thomas.joker.botik.ru' и 'bob' соответственно использовалась бы для подтверждения подключений, сделанных на сервер пользователем bob с компьютера thomas.joker.botik.ru. Точно так же запись таблицы db с полями Host, User и Db, выставленными соответственно в thomas.joker.botik.ru, bob и reports, использовалась бы, когда bob соединяется с компьютера thomas.joker.botik.ru, чтобы обратиться к базе данных отчетов (reports). Таблицы tables_priv и columns_priv хранят поля области (контекста), указывающие таблицы или комбинации таблицы/столбца, к которым применяется каждая запись.

Для целей проверки доступа значения Host нечувствительны к регистру. Зато User, Password, Db и значения Table_name еще как чувствительны! Column_name нечувствительны в MySQL версии 3.22.12 или позже.

Поля привилегий указывают привилегии, предоставленные записью таблицы, то есть какие операции могут выполняться. Сервер объединяет информацию из различных таблиц предоставления привилегий, чтобы сформировать полное описание прав данного пользователя. Правила, используемые, чтобы это сделать, подробно описаны в разделе "10.9 Контроль доступа, стадия 2: Проверка запросов".

Поля контекста представляют собой строки, объявленные как показано ниже. Значение по умолчанию для каждой: пустая строка:

Имя поляТип
HostCHAR(60)
UserCHAR(16)
Password CHAR(16)
DbCHAR(64) (CHAR(60) для таблиц tables_priv и columns_priv)
Table_nameCHAR(60)
Column_nameCHAR(60)

В таблицах user, db и host все поля привилегий объявлены как ENUM('N','Y'): каждое может иметь значение 'N' или 'Y', значение по умолчанию 'N'.

В таблицах tables_priv и columns_priv поля привилегий объявлены как поля SET:

Имя таблицыИмя поля Возможные элементы набора
tables_privTable_priv 'Select', 'Insert', 'Update', 'Delete', 'Create', 'Drop', 'Grant', 'References', 'Index', 'Alter'
tables_privColumn_priv 'Select', 'Insert', 'Update', 'References'
columns_priv Column_priv 'Select', 'Insert', 'Update', 'References'

Сервер использует таблицы предоставления подобно этому алгоритму:

Обратите внимание, что административные привилегии (reload, shutdown и т.д.) определены только в таблице user. Это потому, что административные операции выполняются непосредственно на сервере и не специфические для базы данных, так что нет никакой причины внести в список такие привилегии в других таблицах. Фактически, только таблица user должна использоваться, чтобы определить, можете ли Вы выполнять административную операцию или нет.

Привилегия file также определена только в таблице user. Это не административная привилегия, но ведь и Ваша способность читать или писать файлы на компьютере сервера также независима от базы данных, к которой Вы обращаетесь!

Сервер mysqld читает содержание таблиц только один раз, при своем запуске. Изменения для таблиц предоставления привилегий вступают в силу как сказано в разделе "10.11 Когда изменения привилегий вступают в силу".

Когда Вы изменяете содержание таблиц предоставления, стоит удостовериться, что Ваши изменения установили привилегии так, как Вы хотите. Для справки в диагностировании проблем обратитесь в раздел "10.10 Причины ошибки Access denied. Проблемы с защитой подробно рассмотрены в разделе "10.2 Как защитить MySQL от хакеров".

Полезный диагностический инструмент: скрипт mysqlaccess, который Yves Carlier предоставил для дистрибутива MySQL. Вызовите mysqlaccess с опцией --help, чтобы выяснить, как это работает. Обратите внимание, что mysqlaccess проверяет доступ, используя только таблицы user, db и host. Это не проверяет привилегии уровня столбца или таблицы.

10.6 Привилегии, предоставляемые MySQL

Информация относительно привилегий пользователя сохранена в таблицах user, db, host, tables_priv и columns_priv в базе данных mysql. Сервер MySQL читает содержание этих таблиц при запуске и при обстоятельствах, перечисленных в разделе "10.11 Когда изменения привилегий вступают в силу".

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

ПривилегияСтолбец Контекст (поле) действия
selectSelect_priv таблицы
insertInsert_priv таблицы
updateUpdate_priv таблицы
deleteDelete_priv таблицы
indexIndex_priv таблицы
alterAlter_priv таблицы
createCreate_privбазы данных, таблицы или индексы
dropDrop_privбазы данных или таблицы
grantGrant_privбазы данных или таблицы
referencesReferences_priv базы данных или таблицы
reloadReload_priv серверное администрирование
shutdownShutdown_priv серверное администрирование
processProcess_priv серверное администрирование
fileFile_privдоступ к файлам на сервере

Привилегии select, insert, update и delete позволяют Вам выполнять операции на строках в существующих таблицах в базе данных.

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

mysql> SELECT 1+1;
mysql> SELECT PI()*2;

Привилегия index позволяет создавать или удалять индексы.

Привилегия alter позволяет использовать ALTER TABLE.

Привилегии create и drop позволяют создавать новые базы данных и таблицы или удалять существующие.

Обратите внимание, что, если Вы предоставляете привилегию drop для базы данных mysql пользователю, он сможет удалить всю базу данных, в которой сохранены привилегии доступа MySQL!

Привилегия grant позволяет Вам давать другим пользователям те привилегии, которыми Вы непосредственно обладаете.

Привилегия file дает Вам разрешение читать и писать файлы на сервере, используя инструкции LOAD DATA INFILE и SELECT ... INTO OUTFILE. Любой пользователь, кому эта привилегия предоставляется, может читать или писать любой файл, который доступен на чтение или запись серверу MySQL.

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

ПривилегияКоманды, разрешенные держателям данной привилегии
reloadreload, refresh, flush-privileges, flush-hosts, flush-logs и flush-tables
shutdownshutdown
processprocesslist, kill

Команда reload сообщает, что сервер должен заново прочитать таблицы предоставления привилегий. Команда refresh сбрасывает на диск все таблицы, закрывает и заново открывает журналы. Привилегия flush-privileges является синонимом для reload. Другие команды flush-* выполняют функции, подобные refresh, но в более ограниченном контексте, и могут быть предпочтительны в некоторых ситуациях. Например, если Вы хотите только сбросить на диск журналы, команда flush-logs представляет собой лучший выбор, чем refresh.

Команда shutdown выключает сервер.

Команда processlist отображает информацию относительно процессов, выполняющихся внутри сервера. Команда kill уничтожает потоки сервера. Вы всегда можете отображать или уничтожать Ваши собственные процессы, но Вы нуждаетесь в привилегии process, чтобы отображать или уничтожать процессы, инициализированные другими пользователями.

Некоторые предосторожности при предоставлении привилегий:

Имеются некоторые вещи, которые Вы не можете делать с системой привилегий MySQL:

10.7 Связь с сервером MySQL

Клиент MySQL требует, чтобы Вы определили параметры подключения, когда Вы хотите обратиться к серверу MySQL: компьютер, с которым надо связаться, Ваше имя пользователя и пароль. Например, клиент mysql может быть запущен примерно так (факультативные параметры заключены в `[' и `]'):

shell> mysql [-h host_name] [-u user_name] [-pyour_pass]

Альтернативные формы параметров -h, -u и -p: --host=host_name, --user=user_name и --password=your_pass. Обратите внимание, что не должно быть никаких пробелов вообще между -p или --password= и паролем.

ОБРАТИТЕ ВНИМАНИЕ: Определение пароля в командной строке далеко не безопасно! Любой пользователь в Вашей системе может выяснить Ваш пароль командой, наподобие ps auxww.

mysql использует значения по умолчанию для параметров подключения, которые отсутствуют в командной строке:

Таким образом, для Unix-пользователя joe эквивалентно:

shell> mysql -h localhost -u joe
shell> mysql -h localhost
shell> mysql -u joe
shell> mysql

Другая MySQL-клиентура ведет себя аналогично.

На Unix-системах Вы можете определять различные значения по умолчанию, которые нужно использовать, когда Вы делаете подключение, так, чтобы не надо было вводить их в командную строку, каждый раз, когда Вы вызываете программу. Это может быть выполнено двумя разными способами: