Как защитить базу данных в C#
Запросы к базе данных — уязвимая часть любого приложения. Объясняем, как защитить их от возможных атак и последующих ошибок и сбоев.
vlada_maestro / shutterstock
Если в приложении нет защиты от атак или ошибок, то оно будет не только нестабильным, но и опасным. Например, оно может закрыться в самый неподходящий момент — и пропадут не сохраненные пользователем данные, его могут взломать — и информацию из СУБД украдут или удалят.
Невозможно написать приложение, которое будет абсолютно стабильно и безопасно работать с базой данных. Однако есть простые способы защиты от большинства угроз:
- проверка вводимой информации;
- обработка исключений;
- использование параметров и процедур;
- шифрование данных и установка паролей.
Рассмотрим эти способы на примере регистрации и аутентификации в WPF-приложении (полный код приложения можно найти в этом репозитории на GitHub).
Валидация данных
Валидация — это проверка вводимых данных: в идеале нужно проверять всё, что только вносится в базу. К примеру, смотрим:
- правильный ли выбран тип — цифры в int, а не в string, и даты, выбранные с помощью DatePicker, преобразованы в DateTime из DateTime?;
- находится ли значение в допустимых пределах — строки не превышают указанную длину, цифры умещаются в свой тип, а даты находятся в заданных пределах (например, день рождения может быть от 1900 до 2019);
- находятся ли переданные значения в черном или белом списках — например, можно запретить указывать в качестве имени пользователя матерные слова;
- введены ли вообще какие-то данные;
- нет ли чего-то лишнего — пробелов в начале или конце, HTML-кода.
Вот пример того, как данные могут проверяться на соответствие этим требованиям:
Вот что будет, если попробовать ввести некорректные данные:
Примечание
Чтобы улучшить пользовательский опыт, можно подсвечивать некорректно заполненные поля красным цветом.
Обработка исключений
Несмотря на валидацию, иногда возникают ошибки (исключения), которые могут привести к закрытию приложения: отсутствие подключения к базе данных, неверный пароль, превышение интервала ожидания и так далее.
Все эти исключения можно обработать с помощью блока try-catch — например, поместить в него подключение к базе данных:
Так можно быть уверенным, что приложение не закроется, если возникнет какая-то ошибка.
Примечание
Обрабатывайте исключения везде, где они могут возникнуть.
Использование параметров
Параметры позволяют передавать данные отдельно от запроса. Это важно потому, что это один из лучших способов защитить базу от SQL-инъекции:
Таким образом, база данных сначала получает запрос, а потом подставляет значения в места, где указаны параметры. То есть, даже если пользователь попробует ввести команду удаления таблицы, ничего не произойдет — команда будет воспринята как обычная строка. Поэтому в базе может появиться поле с таким значением:
Использование процедур
Хранимые процедуры позволяют еще быстрее и безопаснее выполнять запросы. Их суть в том, что запросы хранятся на сервере, а из программы туда просто передаются параметры.
Создать хранимую процедуру можно в MS SQL Server Management Studio. Для этого нажмите правой кнопкой мыши на название базы —> Programmability —> Stored Procedures и контекстном меню выберите пункт Stored Procedure…:
В появившемся окне нужно ввести вот такой код:
Чтобы процедура добавилась, нажмите Execute. Вот как выглядит запрос с использованием хранимой процедуры:
Теперь сервер сможет выполнить запрос быстрее, потому что ему нужно только получить входные данные. Кроме того, злоумышленник не узнает подробности работы с СУБД, если ему удастся получить исходный код приложения.
Шифрование и установка пароля
Всё вышеперечисленное защищает базу данных от неправильного ввода и появления ошибок. Но взломщик может попытаться получить доступ к ней напрямую. Если ему это удастся, то он сможет выполнять любые запросы.
Чтобы уменьшить шансы на взлом, можно установить на базу данных пароль. Для этого зайдите в MS SQL Management Studio и добавьте нового пользователя:
А затем установите для него пароль:
Другой важный и полезный способ защиты — шифрование. Оно позволяет преобразовать информацию так, чтобы данные нельзя было прочесть без ключа. Шифрование можно установить на базу целиком в меню создания или настроек базы — для этого нужно изменить значение Encryption Enabled:
Недостаток этого метода в том, что данные будут кодироваться и декодироваться при каждом запросе, что сильно скажется на производительности. Вместо этого лучше шифровать только отдельные столбцы, в которых содержатся:
- пароли;
- номера телефонов;
- адреса почтовых ящиков;
- физические и юридические адреса;
- имена;
- банковские реквизиты и другие конфиденциальные данные.
Узнать о реализации такой защиты можно в официальной документации Microsoft. Хотя это не лучший способ шифрования, он тоже очень эффективен, потому что значительно снижает риск потери данных. Эффективнее использовать программное кодирование по стандарту AES (англ. Advanced Encryption Standard — Расширенный стандарт шифрования), однако это сильно повлияет на производительность. Поэтому в большинстве случаев такие меры излишни.
Также в параметрах базы данных можно установить и другие полезные опции. Например, разрешить только чтение — тогда нельзя будет добавлять никакие новые сведения, изменять или удалять старые. Это позволит защитить информацию от несанкционированного удаления или изменения — сделать это не сможет даже администратор. Единственная возможность редактировать read only базу будет доступна в Management Studio.
Заключение
Несмотря на то что работа с базой данных может показаться простой, написать приложение, которое будет будет функционировать стабильно и без угрозы для хранимой информации, — сложная задача.
Конечно, это только часть методов. Также вы можете попробовать и другие варианты:
- транзакции;
- дополнительное шифрование;
- передачу данных в бинарном виде — и всё, на что хватит вашей фантазии или бюджета.