Как предотвратить PHP, SQL и XSS инъекции (Безопасность)

Я конечно не супер-профессионал по безопасности, но некоторые познания в области безопасности php скриптов есть. Итак, часто встречающиеся дыры в php скриптах:
- PHP инъекция.
- SQL инъекция.
- XSS.
Вот про борьбу с этими уязвимостями и пойдёт речь. Статей по безопасности конечно уйма, но всё же, внесу и свою лепту.

Что же это такое PHP-инъекция?
PHP-инъекция - способ взлома сайта путём выполнения на сайте стороннего PHP кода. Например, вы хотите подключить необходимый файл, в зависимости от параметра, пришедшего из GET:
# Получаем имя файла
$action = isset($_GET['action']) ? $_GET['action'] : null; 

# Тут какие-то действия
# ...

# Подключаем файл
include($action);

Если ввести такой URL: http://ваш_сайт/ваш_файл.php?action=http://сайт_взломщика/файл то, если в файле php.ini на вашем сервере включена директива allow_url_include, злоумышленник может внести код, который хочет выполнить на вашем сайте, в тот файл, на который он указал ссылку и код успешно выполнится на вашем сайте. Ваш сайт взломан.

Как поступить? Можно проверять наличие файла сервере функцией file_exists() - на файлы на строннем сервере (http://сайт_взломщика/файл) она вернёт FALSE.

Уже неплохо. Выполнение PHP кода с удалённого сервера на вашем сайте не пройдёт. Но, например, пользователи имеют возможность загружать свои файлы на ваш сайт. Злоумышленник может создать PHP код и назвать файл с кодом "моё фото.jpeg" и, если не обработать файл должным образом, злоумышленник может сделать так: http://ваш_сайт/ваш_файл.php?action=/папка с изображениями/его изображение/ и выше приведённый php код, который подключает файлы в зависимости от параметра, выполнит его, т.е. код, который находится в "изображении", успешно отработает.
Следовательно ваш сайт успешно взломан. Как быть? - Нужно проверять тип файла функциями работы с изображениями, например, getimagesize (https://www.php.net/ ... etimagesize.php) кроме размеров вернёт ещё и тип изображения.
Значит можно проверить, действительно ли правильный тип изображения приходит и делать соответствующие выводы.

SQL инъекция
SQL инъекция - взлом базы данных сайта путём дополнения запроса на сервере своим, хакерским. Может быть проведена, если данные, приходящие от пользователя (из формы на сайте)
вставляются в SQL запрос к базе без предварительной обработки. Например, вы используйте такой SQL запрос для проверки логина и пароля:
$sql = "SELECT `id`, `password` FROM `users` WHERE `login`='".$_POST['login']."'";

Злоумышленник может ввести в поле "Логин" на сайте такое:
'; DELETE FROM `users` WHERE 1 = 1;

В итоге на вашем сайте сформируется такой запрос (подставляется из массива POST):
$sql = "SELECT `id`, `password` FROM `users` WHERE `login` = ''; DELETE FROM `users` WHERE 1 = 1;";

Та же история и с данными из GET. Всё удалится из таблицы "users". Но запрос может быть любым, как вы поняли. Как этого избежать? - Всё просто, достаточно 2-х функций (или даже одной):
- Если вы ожидаете из запроса число (ID записи например), то можно писать так:
# Получаем число
$id = isset($_GET['id']) ? intval($_GET['id']) : 0;

# Можно написать так:
# $id = isset($_GET['id']) ? (int) $_GET['id'] : 0;

$sql = "SELECT `id`, `password` FROM `users` WHERE `id`='" . $id . "'";

На всё, что до вопроса внимания не обращайте, в данный момент к делу отношения не имеет. Теперь можно смело использовать $id в запросе, так как intval() или (int) преобразует данные от пользователя в число, и, если придут некорректные данные - они будут просто преобразованы в ноль.
- Если вы ждёте от пользователя из формы не число, а набор разных символов (строку), то нужно использовать функцию mysqli_real_escape_string(), если вы используете БД MySQL, (https://php.net/manu ... cape-string.php):
# Получаем строку (в данном случае логин)
$login = isset($_POST['login']) ? mysqli_real_escape_string($_POST['login']) : NULL;

$sql = "SELECT `id`, `password` FROM `users` WHERE `id`='".$login."'";

Ссылку выше я дал на официальный сайт php - почитайте что делает mysqli_real_escape_string(). Если злоумышленник введёт такое:
'; DELETE FROM `users` WHERE 1 = 1;

То все спецсимволы (а в частности одинарная кавычка) проэкранируются (т.е. перед ними будет добавлен слэш \) и в запросе хакерский код будет выглядеть так, что воспримется как обычная строка и не повредит вашей базе.
Если ваша база данных не MySQL и не PostgreSQL (для неё используйте pg_escape_string() (https://php.net/manu ... cape-string.php), то нужно использовать функцию addslashes() (https://php.net/manual/ru/function.addslashes.php). Если же база MySQL или PostgreSQL, используйте специальные функции для вашей БД (информация выше).

Часто встречаются такие обработки:
$login = htmlspecialchars(addslashes($_POST['login']));

Нет смысла в такой конструкции. Читайте документацию, кто не знает почему.

XSS инъекция
XSS - это внедрение клиентского кода (JS, HTML например, т.е. тех что используются в браузере) в ваш сайт. Например, у вас есть форма в гостевой книге, злоумышленник, введя в неё HTML или JS код, при условии, что нет проверок на вашем сайте, сможет получить возможность обработки его кода в браузере другого посетителя. Можно воровать COOKIE, загружать вирусы на компьютер пользователя.
Выход: обязательно преобразовывать данные перед выводом в браузер с помощью htmlspecialchars() (https://secure.php.n ... pecialchars.php) или htmlententies() (https://www.php.net/ ... tmlentities.php),
первая преобразует спец-символы html в их сущности, а вторая преобразует ВСЕ ВОЗМОЖНЫЕ символы в html сущности. Код обрабатывать лучше перед выводом в браузер, а не при записи в БД (считается хорошим тоном). Так вот, если злоумышленник введёт такой (простой пример) код в форму:
<script>
    while(1)
        alert("Бесконечный ALERT");
</script>

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

Ну и в завершении пару слов:
  • Не светите пароли от FTP, SSH, администраторского раздела своего сайта.
  • Меняйте их для надёжности хотя бы раз в четверть года.
  • Просматривайте свой код на предмет "дыр" в безопасности, лучше вы найдёте дыру, чем злоумышленник.
  • На рабочем сайте отключите показ ошибок, так злоумышленник не будет видеть путей и названий файлов, ну и конечно же самих ошибок, из которых он может сделать выводы свои.

Спасибо за внимание!
Автор:  21:03 17.06.2017