Базы данных - MySQL - статьи

Использование хранимых процедур


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

Для иллюстрации понятия SQL Injection приведем простой пример, взятый нами из книги Майкла Ховарда и Дэвида Леблана «Защищенный код» (издательство «Русская редакция», 2003). Представим себе следующий код клиентского приложения:

String sql = «select * from customer where name= ‘ «+ name +» ’»

значение переменной name в котором вводится пользователем. Если пользователь ввел в эту переменную значение «Иванов», он получит записи таблицы Customer, содержащие в поле Name

значение «Иванов».

Но если он ввел в это поле следующее значение:

Иванов’ or 1=1 —

то такая команда вернет все строки таблицы — записи таблицы Customer, содержащие в поле Name значение «Иванов», плюс записи, удовлетворяющие условию 1=1 (то есть все записи таблицы!). А если злоумышленник ввел в это поле значение

Иванов’ drop table customer

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

С точки зрения безопасности приложения не должны использовать конструкции SELECT, INSERT, UPDATE и DELETE для запросов к базе данных. Вместо этого правильнее обращаться к хранимым процедурам, выполняющим подобные операции. Кроме того, их применение позволяет отказаться от предоставления пользователям прав доступа к таблицам и представлениям. Отметим, что применение хранимых процедур позволяет сделать клиентские приложения независимыми от схемы базы данных, что позволяет изменять ее без необходимости внесения изменений в само приложение. Это упрощает сопровождение таких приложений, позволяя избежать развертывания его новых версий.


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

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

Sqlstring = @» exec sp_GetName ‘» + name + +» ’»; SqlCommand cmd = new SqlCommand (sqlstring, sql);

Если пользователь ввел в поле Name

Иванов’ or 1=1 —

он не получит все строки таблицы. Но, введя Иванов’ drop table customer —

он удалит таблицу, как и в предыдущем случае. И наконец, хранимые процедуры бывают и такими:

CREATE PROCEDURE sp_MyProc @input varchar(128) AS exec (@input)

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


Содержание раздела