Безопасность PHP приложений

Периодически читая разнообразные книги, статьи и мануалы по разработке на PHP, я мечтал встретить краткий сводный список моментов, на которые стоит обратить внимание при разработке и эксплуатации PHP приложений. И вот этот счастливый день наступил, и я наткнулся на шпаргалку неизвестного мне иностранного камрада SK89Q. Далее следует перевод статьи больше для себя, но вдруг еще кому-то пригодится. Оригинал, кстати, удобно распечатать и приколотить на стену над рабочим местом, дабы бдить что:

Основы

  • Используются надежные пароли
  • Пароли хранятся безопасно.
  • Директива register_globals отключена.
  • Волшебные кавычки отключены.
  • Директива display_errors отключена.
  • Сервер физически защищен.

Ввод данных

  • Входящие данные в $_GET, $_POST, $_COOKIE и $_REQUEST считаются неблагонадежными.
  • Имеется понимание, что только некоторые значения в $_SERVER и $_ENV благонадежны.
  • $_SERVER[‘PHP_SELF’] экранируется, там где используется.
  • Входящие данные проверяются.
  • \0 (NUL, null-байт) отбрасывается при вводе.
  • Длина ввода ограничена.
  • Адреса электронной почты валидируются.
  • Приложение готово принять малые, очень большие, отрицательные числа и нуль. Научные обозначения тоже.
  • Приложение проверяет невидимые, внешне похожие и комбинируемые символы.
  • Юникод-символы управления вырезаются, когда требуется.
  • Выводимые данные «обеззараживаются».
  • HTML, введеный пользователем, обеззараживается HTMLPurifier-ом.
  • Стили CSS, введенные пользователем, обеззараживаются с использованием белого списка.
    • Свойства, которыми возможно злоупотребить (position, margin и т.д.), обрабатываются.
    • Отменяющие последовательности CSS обрабатываются.
    • JavaScript в CSS отбрасывается (expressions, behaviors, bindings).
  • URL-адреса обеззараживаются и неизвестные и ненужные протоколы не допускаются.
  • Встроенные плагины ограничены в исполнении JS.
  • Файлы встроенных плагинов (Flash роликов) внедрены таким образом, что загружается только предназначенный плагин.
  • Приложение использует безопасную кодировку.
    • Кодировка задается с помощью заголовка HTTP.
    • Введенные данные проверяются на соответствие выбранной кодировки при использовании небезопасной кодировки.

Загрузка файлов

  • Приложение проверяет тип файла.
    • Предоставленное пользователем значение mime-типа файла игнорируется.
    • Приложение анализирует содержание файлов, чтобы определить их тип.
    • Понимать, что даже идеально валидный файл может содержать произвольные данные.
  • Приложение проверяет размер загружаемых файлов.
    • Опция MAX_FILE_SIZE не используется.
    • Загрузка файлов не может «перебрать» свободного дискового пространства.
  • Содержание проверяется на наличие вредоносного кода.
    • Приложение использует сканер вредоносных программ (если требуется).
    • Загруженные HTML файлы отображаются безопасно.
  • Загруженные файлы не перемещаются в доступную из веб директорию.
  • Всесторонние проверки путей применяются при обслуживании файлов.
  • Загруженные файлы не обслуживаются через include().
  • Загруженные файлы обслуживаются в виде вложений с использованием Content-Disposition заголовка.
  • Приложение посылает X-Content-Type-Options: nosniff заголовок.
  • Файлы не обслуживаются как «application/octet-stream», «application/unknown» или «plain/text» без особой необходимости.

База данных

  • Данные, вставляемые в базу, правильно экранируются или используются параметризованные/подготовленные выражения.
    • Не используется addslashes().
  • Приложение не имеет больше привилегий в базе данных, чем требуется.
  • Удаленные подключения к базе данных отключены, если они не требуются.

Обслуживание файлов

  • Пользовательский ввод непосредственно не используется в наименовании путей.
    • Предотвращается обход директорий.
    • NUL (\0) в путях фильтруется.
    • Приложение учитывает «:»
    • PHP потоки фильтруются.
  • Доступ к файлам не ограничивается путем их сокрытия.
  • Внешние файлы не подключены через include().

Аутентификация

  • Использование плохих паролей пресекается.
    • Используется CAPTCHA.
  • SSL используется для предотвращения MITM.
  • Пароли не хранятся в cookie.
  • Пароли хешируются.
    • Пароли солятся данными пользователя.
    • crypt() используется с достаточным количеством раундов.
    • MD5 не используется.
  • Пользователь предупрежден об очевидных вопросах в восстановлении пароля.
  • Формы восстановления аккаунта не раскрывают электронною почту.
  • Страницы, отправляющие электронные письма, безопасны.

Сессии

  • Сессии используют только cookie. (session.use_only_cookies)
  • При выходе из системы данные сессии уничтожаются.
  • Сессия пересоздается при изменении уровня авторизации.
  • Сайты на одном сервере используют различные директории хранения сессий.

Модули третьих лиц

  • CSRFпредотвращается с помощью маркеров/ключей.
    • Рефереры не используются.
    • Страницы, которые выполняют действия, используют POST.
    • Важные страницы (выход из системы и т.д.) защищены.
  • Ваши страницы не написаны таким образом (например, JSON, JS), что они могут быть успешно подключены и прочитаны на удаленном веб-сайте.
  • Учитывается, что Flash может обойти проверку реферера для загрузки изображений и звуковых файлов.
  • Следующие вещи не будут раскрывать существенную информацию, если подключены удаленно:
    • Изображения
    • Страницы, требующие большого времени для загрузки.
    • CSS файлы.
    • Наличие или порядок фреймов.
    • Наличие переменных JS.
    • Детектирование обращения к URL.
  • Включение сайта в фрейм с отключенным JS не выявляет угрозу.
  • Приложение использует код разрыва фрейма и посылает X-Frame-Options заголовок.

Разное

  • Криптографически безопасный PRNG используется для секретных случайно сгенерированных ID (ссылки активации, секретные ID и т.д.).
    • Suhosin установлен или вы не используете rand() или mt_rand() для этого.
  • Все, что потребляет много ресурсов, должно быть контролируемым и ограниченным.
    • Страницы с API третьих сторон контролируются.
  • Вы не создали свой собственный алгоритм шифрования.
  • Аргументы внешних программ (например, exec()) проверяются.
  • Общие внутренние и внешние страницы переадресации защищены.
  • Приняты меры предосторожности против показа исходного кода страниц PHP из-за неправильной настройки.
  • Конфигурационные и критические файлы в недоступных из веб директорий.

Виртуальный хостинг

  • Используется безопасный виртуальный хостинг, где пользователи не могут получить доступ к файлам других пользователей.
  • Осознается, что пользователи хостинга:
    • Могут, если тот же адрес IP, выполнять запросы на ваш сайт через XMLHttpRequest в IE6.
    • Могут получить доступ к вашему веб-сайту через 127.0.0.1 или ::1.
    • Могут хостить сервер на том же IP адресе.
    • Не «удаленные» для вашей базы данных.
  • Директории сессий и загрузки файлов не разделяемые.