Код
#Руководства

Устраняем уязвимости: как защитить сайт от SQL-инъекции

SQL-инъекция — одна из самых опасных уязвимостей, которая не дает разработчикам спать по ночам. Научитесь бороться с ней, чтобы защитить свой сайт.

 vlada_maestro / shutterstock

Заводишь сайт, наполняешь его контентом, запускаешь рекламную кампанию — трафик стабильно растет, пользователи активно комментируют и делятся статьями. Всё хорошо до того момента, пока в один не предвещающий беды день на сайте не оказывается ни одной статьи. Заходишь в лог запросов и видишь, что кто-то сделал DROP…

Что такое SQL-инъекция

SQL-инъекция — это попытка изменить запрос к базе данных. Ввести ее можно через форму или ссылку, которая передает параметры методом GET. Представьте, что у вас на сайте есть форма регистрации, в которую пользователь вводит логин и пароль.

<form action='reg.php' method='post'>
<input type='text' name='login' placeholder='Логин' required><br>
<input type='password' name='password' placeholder='Пароль' required><br>
<input type='submit' value='Зарегистрироваться'>
</form>

Они отправляются на сервер и вставляются в запрос такого вида:

$query = «INSERT INTO userlist („.$keys.“) VALUES („.$values.“)»;

В переменной $keys содержатся ключи из супермассива $_POST, а в $values — значения:

$keys = "";
$values = "";
$first = 1;
foreach($_POST as $key => $value) {
if($first == 0) { //Добавляем запятую перед каждым пунктом, кроме первого
       $keys .= ",";
       $values .= ",";
}
$keys .= $key;
$values .= "'".$value."'";
$first = 0;
}

Это удобно, если в форме очень много полей, но из-за этого появляется уязвимость: если пользователь захочет запустить SQL-инъекцию, то он может просто создать в форме новое поле с нужным ему именем и ввести любое значение. Например, можно создать поле admin и ввести значение 1.

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

Как защитить сайт от SQL-инъекции

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

1. Используйте белые списки

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

$keys = "";
$values = "";
$first = 1;
$allowed = array("login", "password", "email","nickname");
foreach($_POST as $key => $array) {
$allowedKey = array_search($key,$allowed);
if($allowedKey) {
       if($first == 0) {
              $keys .= ",";
              $values .= ",";
       }
       $keys .= $allowedKey;
       $values .= "'".$value."'";
$first = 0;
}
}

Теперь в переменные $key и $values попадут только те значения, которые входят в белый список $allowed.

2. Не пользуйтесь методом GET в формах

Передавать переменные этим способом очень опасно, потому что они оказываются на виду у пользователей. Если информация важная, то лучше используйте POST. Из ссылки злоумышленник может узнать не только имена переменных, но и какие значения должны быть в них — так он сможет выбрать оптимальную переменную для ввода инъекции.

Не советуем использовать переменные прямиком из супермассива — лучше поместить их в другую переменную, предварительно проверив данные.

3. Обрабатывайте переменные

Старайтесь экранировать кавычки, заменять служебные символы, удалять лишние пробелы и так далее. Давайте посмотрим, что будет, если этого не делать:

Используйте функции trim (убирает лишние пробелы), htmlspecialchars (заменяет треугольные скобки и другие спецсимволы), addslashes (экранирует кавычки и специальные символы) и другие.

В приведенной форме регистрации, например, злоумышленник мог бы использовать кавычки и запятые, чтобы добавить новый ключ и новое значение. То есть, введя в поле что-то вроде «pass’, ’something», он бы добавил какую-нибудь еще информацию, которая не проходит белый список.

Также вы можете проверять типы переменных — число, строка, файл и так далее.

4. Проверяйте, откуда пришли данные

Недостаточно просто обработать данные — нужно узнать, откуда они пришли. Отследить источник можно несколькими способами:

  • проверять его в $_SERVER[’HTTP_REFERER’];
  • создать скрытое поле в форме;
  • указать имя формы;
  • указать имя кнопки отправки и так далее.

Конечно, это лишь незначительный бонус к защите, но зато он отсеивает часть неопытных взломщиков, которые бросят свои потуги после нескольких попыток.

5. Используйте PDO

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

$db = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
$stmt = $db->prepare("SELECT * FROM articles WHERE id=':id'");
$stmt->bindParam(':id', $id);
$stmt->execute();

Данные отправляются уже в виде переменных. То есть если бы в переменной кто-то поставил лишнюю кавычку, сервер бы не подумал, что она — часть запроса. Поэтому попытка испортить запрос через переменную не сработала бы.

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

Часто проверками пренебрегают самоучки, которые изучают темы «по верхушкам», — они могут решить задачу, но редко задумываются о том, чтобы устранить уязвимости. Поэтому мы предлагаем курс с системным обучением — вы научитесь создавать эффективные и надежные системы, которым не будут страшны инъекции и утечки данных.

Дополнительная защита сайта от взлома

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

1. Запретите прямой доступ к служебным файлам

Все файлы на сайте можно открыть или скачать, если знать их адрес. Например, можно попытаться скачать файл header.php, чтобы найти там уязвимости (если скачивание будет удачным).

Поэтому лучше все подключаемые файлы переместить в отдельную директорию и запретить к ней прямой доступ. Например, можно создать папку includes и поместить туда:

  • отдельные блоки сайта;
  • библиотеки пользовательских функций;
  • файл подключения к базе данных;
  • обработчики форм и так далее.

Для этого создайте в этой папке файл .htaccess и добавьте туда такую строчку:

deny from all

Прямой доступ заблокируется, но подключать эти файлы через PHP все еще будет можно.

2. Не выкладывайте свой код на форумы

Порой нам всем бывает нужна помощь коллег, поэтому мы выкладываем фрагменты своего кода на форумы или Stackoverflow. Делать это рекомендуется только в очень крайних случаях и лишь тогда, когда вы убедитесь, что никто не сможет вычислить ваш сайт.

Ничто не должно намекать на то, какой тематики сайт, какой у него адрес, на каком он хостинге и так далее. Чем больше информации вы добровольно расскажете, тем выше риск быть взломанным.

3. Проверяйте копипасту

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

В идеале лучше вручную переписывать код — так вы точно заметите все подозрительные команды.

4. Отключите вывод ошибок

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

Отключить вывод можно в файле .htaccess, добавив туда следующие строки:

php_flag display_errors offphp_value error_reporting 0

Кроме того, уберите вывод ошибок, который вы прописали в самом коде.

5. Ограничьте права пользователя базы данных

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

Пока ни одна галочка не отмечена — поставьте ее на пункт «Данные». Так можно будет оперировать существующими данными, но нельзя будет создать новую таблицу или удалить старую. Так вы защититесь в том числе и от атаки с помощью команды DROP, которая может удалить все статьи или комментарии с сайта.

Если же менеджеру вашего сайта все же регулярно нужны привилегии администрирования и изменения структуры, создайте отдельного пользователя, которого будете использовать в админке. Но риск того, что доступ к ней кто-то получит, все равно существует. Поэтому стоит ограничить максимальное количество подключений и запросов.

Также лучше поставить пароль на root, чтобы взломщик не смог подключиться через него.

6. Установите последнюю версию языка

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

Да, в обновлении тоже могут быть баги, но не такие опасные. Тем более о них никто не будет знать, если после релиза прошло немного времени.

7. Используйте сложный пароль

Банально, но простой пароль можно подобрать за несколько секунд. Особенно если он содержит персональные данные:

  • дату рождения;
  • кличку питомца;
  • годовщину свадьбы;
  • девичью фамилию матери и так далее.

Усугубляет положение то, что эту информацию мы часто выкладываем в свободный доступ.

Заключение

Безопасных систем не существует — вы можете только снизить вероятность взлома. Для этого нужно самому быть немного хакером:

  • вводите инъекции;
  • меняйте типы данных;
  • добавляйте в поля кавычки и знаки экранирования;
  • попробуйте загрузить на сайт файл .php с вредоносным кодом и так далее.

Пытайтесь взломать собственный сайт, чтобы узнать, какие у него есть уязвимости. Сделайте это, пока кто-то не опередил вас.

Изучайте IT на практике — бесплатно

Курсы за 2990 0 р.

Я не знаю, с чего начать
Научитесь: Профессия PHP-разработчик с нуля до PRO Узнать больше
Понравилась статья?
Да

Пользуясь нашим сайтом, вы соглашаетесь с тем, что мы используем cookies 🍪

Ссылка скопирована