Не пропусти главное событие года - Конференцию веб-разработчиков DevConf!
Москва, 21-22 июня.

Безопасность PHP скриптов

Файлы
SQL Injection
Eval
Mail Injection
XSS
CSRF, Cross-site Request Forging
HTTP Injection
Заливка файлов на сервер
ОПС
Комментарии (12)

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

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

Файлы
В хорошем современном сайте уже редко можно встретить передачу имени файла в скрипт - данные хранятся в базе, а модули подключаются по более сложным алгоритмам, чем просто передача имени файла в адресной строке. Однако начинающие программисты просто без этого не могут. Доходит до анекдота - "хочу, чтобы было index.php?module=news потому что news.php - не солидно, сайт не выглядит крутым!". Ну, на что не пойдешь ради того, чтобы выглядеть круто. Надо только не забывать о безопасности. О том, что подсунуть для инклюда можно через адресную строку что угодно - от файла на другом сервере (с любым пхп-кодом!), до файла на своем - с настройками или паролями.

Для борьбы с такими подстановками есть несколько методов. Можно проверять имя файла регулярками, но мне ближе всего функция basename(), которая отрезает от имени файла все лишнее.
Если надо передавать файл вместе с путем к нему, к примеру, themes/green/balloons.php, то проверка будет сложнее. Поэтому я бы рекомендовал, все-таки, передавать только имя файла. Или не передавать ничего.

SQL Injection
Для предотвращения инъекций нужно соблюдать два простых правила:

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

Для подготовленных запросов следует использовать Как работать с PDO? Полное руководство.. проверка по белым спискам также рассмотрена в этой статье. Хочется лишь добавить, что защита от инъекций - не главное, а побочный продукт. Первая и главная задача состоит в соблюдении правильного синтаксиса, чтобы какая-нибудь запятая в данных не порушила нам весь запрос. А как следствие, у нас будет и защита от инъекций.

Eval
Удивительно, но многие программисты не осознают того факта, что применять eval к пользовательским данным - это все равно, что лично вручать вору ключ от сейфа. Этой функцией и так-то следует пользоваться очень осторожно, а на обработку ей введенных пользователем данных и вовсе должен быть жесткий запрет.
При этом следует понимать, что пользовательские данные остаются таковыми и после того, как пользователь непосредственно отправил их в скрипт. Полученные из базы данных при последующих исполнениях скрипта, они не становятся менее опасными.

Mail Injection
Получившая распространение в последнее время атака так же уже рассмотрена на этом сайте, Mail injection. Работа с e-mail средствами PHP.. Коротко можно сказать, что нельзя допускать наличие переводов строки в данных, которые попадут в заголовки письма.

XSS
Тип атаки, так же получивший распространение сравнительно недавно. В отличие от всех предыдущих, которые атакуют непосредственно код скрипта, XSS атакует его функциональность: заставляет выполнять пользователя действия, нужные хакеру, или ворует его, пользователя, данные.
Методы весьма разнообразны и многочисленны, однако наиболее распространенный и опасный - это внедрение javascript инструкций в безобидные теги - <img>, <a> и так далее.
Наиболее действенным методом борьбы с этим является полный запрет на ввод пользователем какого бы то ни было HTML кода. Методов борьбы с этим достаточно много, но следует помнить, что функция strip_tags() не убирает опасные вставки из разрешенных тегов. поэтому лично я предпочитаю пользоваться функцией htmlspecialchars(), при выводе любых пользовательских данных.
Но главная проблема при защите от XSS - не сам метод, а последовательность его применения. практически все известные атаки были произведены в тех частях сайта, где никто и подумать не мог об обработке пользовательских данных. А зря. Обрабатывать их надо везде и всегда.

Так же к этому разделу можно отнести атаки на сессии. Связанные с кражей или подстановкой идентификатора. подробнее можно почитать в разделе Сессии. Подробное описание работы и объяснение механизма.

CSRF, Cross-site Request Forging
Формирование на сайте хакера запроса, который будет выполнен браузером пользователя (и, как следствие - со всеми правами пользователя!). То есть, просто авторизация от этой атаки не спасает. Для защиты от этого типа атак следвет взять за правило добавлять ко всем важным формам скрытое поле, содержащее уникальную строку (сгенерированную случайным образом только для этой формы), записывать её в сессию и сравнивать при обработке формы. Хакер добавить такую строку в свою форму не сможет, и атака не сработает.

HTTP Injection
XSS уязвимость, похожая на mail injection, только объектом атаки являются не заголовки письма, а HTTP-заголовки. Атака экзотическая, но знать про неё надо. Хакеру ничего не стоит дописать к урлу код с яваскриптом, который благополучно через переменную PHP_SELF или REQUEST_URI программист сам вставит в свою страницу.

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

ОПС
Статья Сергея Круглова, http://www.captcha.ru/articles/antihack/