
Как проверить PHP-сайт на уязвимости: пошаговый план
Проверка PHP-сайта на уязвимости: сканеры, статический анализ, аудит зависимостей и настроек php.ini. Пошаговый план и чек-лист.
Как проверить сайт на уязвимости PHP
Чтобы проверить PHP-сайт на уязвимости, объедините четыре способа: автоматическое сканирование (OWASP ZAP, Nikto), статический анализ кода (Psalm, Semgrep), аудит зависимостей командой composer audit и ручную проверку настроек php.ini и веб-сервера.
PHP исполняется на сервере, поэтому ошибка в одном скрипте может открыть злоумышленнику доступ к базе данных, файлам и почтовым функциям хостинга. Ниже разобрано, какие уязвимости искать, в каком порядке проводить проверку, какими инструментами пользоваться и как закрывать найденные проблемы.
Что именно мы ищем
Под проверкой на уязвимости понимают поиск слабых мест, через которые сайт можно взломать, подменить на нём контент или украсть данные. Для PHP-проекта их удобно делить на три слоя: собственный код, сторонние компоненты (CMS, плагины, пакеты Composer) и окружение (версия PHP, настройки сервера, права на файлы).
Каждый слой даёт свою долю проблем. В собственном коде это чаще всего отсутствие проверки входных данных и экранирования вывода. В сторонних компонентах основная опасность в том, что обновления не ставятся месяцами, а уязвимости в популярных плагинах WordPress, модулях Joomla или расширениях 1С-Битрикс публикуются открыто и сразу попадают в арсенал автоматических ботов. В окружении типичны открытые для чтения служебные файлы, включённый вывод ошибок и версии PHP, снятые с поддержки (например, 7.4 и 8.0).
По классификации OWASP Top 10 внедрение вредоносного кода (injection), нарушения контроля доступа и использование устаревших компонентов стабильно входят в число главных рисков для веб-приложений. Именно с них и стоит начинать.
Шесть классов уязвимостей, с которых начинается проверка PHP-сайта
В параметр запроса подставляется SQL-код, и атакующий читает или меняет базу данных.
проверка:sqlmap, ZAP, анализ кода
Чужой скрипт выводится на странице без экранирования и выполняется в браузере посетителя.
проверка:ZAP, ручной ввод в формы и параметры
Запрос выполняется от имени авторизованного пользователя без его ведома.
проверка:токены в формах, атрибут SameSite у cookie
Через include или require подключается произвольный файл, имя которого пришло из URL.
проверка:поиск include с переменной, allow_url_include
PHP-скрипт загружается под видом картинки и запускается прямо из каталога uploads.
проверка:тип файла, расширение, запрет исполнения
В CMS, плагине или библиотеке есть известная уязвимость, для которой уже выпущено исправление.
проверка:composer audit, список обновлений CMS
Как понять, что с сайтом уже что-то не так
Иногда проверку запускают не по плану, а после тревожных симптомов. К ним относятся незнакомые файлы в каталогах uploads, cache и tmp, внезапные редиректы на сторонние ресурсы (часто только для посетителей, пришедших из поиска), резкий рост нагрузки на хостинг, всплеск исходящей почты и жалобы пользователей на всплывающие окна.
Второй источник сигналов — сами поисковики. В Яндекс Вебмастере есть раздел «Безопасность и нарушения», а в Google Search Console — отчёт «Проблемы безопасности». Если там появилось предупреждение о вредоносном коде или взломе, сайт уже попал в зону риска: в выдаче может появиться пометка об опасности, а позиции начнут падать.
Но важно помнить обратное: отсутствие симптомов не означает безопасности. Многие бэкдоры месяцами ничем себя не выдают и ждут, пока их используют для рассылки спама или размещения чужих ссылок.
Пошаговый план проверки PHP-сайта на уязвимости
- 01
Подготовьте тестовую среду: сделайте полную резервную копию файлов и базы данных и разверните копию сайта на отдельном поддомене или локально. Активные сканеры шлют сотни запросов и могут изменить данные, поэтому боевой сайт для этого не подходит.
- 02
Проверьте версии и зависимости: узнайте версии PHP, CMS и плагинов, выполните composer audit (доступна в Composer 2.4 и новее), сверьте список обновлений. Всё, что не получает патчи безопасности, кандидат на замену или обновление.
- 03
Запустите автоматический сканер: OWASP ZAP в режиме baseline или полного сканирования и Nikto для проверки веб-сервера. Сохраните отчёты и отсортируйте находки по критичности.
- 04
Проведите статический анализ кода: Psalm с анализом заражённых данных (taint analysis), Semgrep с правилами для PHP и PHPStan на высоком уровне строгости. Они находят места, где пользовательские данные попадают в SQL-запрос, вывод или файловую функцию без обработки.
- 05
Проверьте вручную точки входа: все формы, параметры GET и POST, cookie, заголовки, загрузку файлов, API-эндпоинты. Попробуйте ввести одинарную кавычку, тег script и путь вида ../../ и посмотрите, как реагирует приложение.
- 06
Проверьте конфигурацию: директивы php.ini, права на файлы (обычно 644 для файлов и 755 для каталогов), доступность служебных файлов .env, .git, резервных копий и дампов базы по прямым URL, наличие HTTPS и защитных заголовков.
- 07
Поищите следы взлома: найдите недавно изменённые файлы (например, командой find с параметром -mtime), проверьте код на конструкции eval, base64_decode, gzinflate и preg_replace с модификатором e, просмотрите журналы доступа на подозрительные запросы.
- 08
Сверьтесь с поисковиками: откройте Яндекс Вебмастер и Google Search Console, проверьте разделы о безопасности и нарушениях, а также индексацию — нет ли в ней незнакомых спамных страниц.
- 09
Зафиксируйте результаты и исправьте: составьте список проблем по приоритету, закройте критичные в первую очередь, затем повторите сканирование и убедитесь, что уязвимости действительно устранены.
Динамический и статический подход: в чём разница
Два главных метода проверки дополняют друг друга. Динамическое тестирование (DAST) работает как внешний атакующий: сканер не видит исходный код, а только отправляет запросы и анализирует ответы. Так находят проблемы, которые реально проявляются на работающем сайте, например отражённый XSS или открытые служебные файлы.
Статический анализ (SAST) читает исходный код без запуска и отслеживает путь данных от ввода до опасной функции. Он находит уязвимости в редко используемых ветках кода, куда сканер просто не дойдёт, но даёт больше ложных срабатываний.
На практике лучше всего работает связка: статический анализ на этапе разработки, динамический сканер на тестовом стенде перед релизом и ручная проверка самых чувствительных мест — авторизации, оплаты и личного кабинета.
| Инструмент | Что проверяет | Когда применять |
|---|---|---|
| OWASP ZAP | Веб-приложение снаружи: XSS, инъекции, небезопасные заголовки, cookie | Перед релизом и после крупных изменений |
| Nikto | Веб-сервер: устаревшее ПО, опасные файлы, небезопасная конфигурация | При первичном аудите и смене хостинга |
| sqlmap | Подверженность параметров SQL-инъекциям | Для подтверждения найденной проблемы на тестовой копии |
| Psalm (taint analysis) | Путь пользовательских данных к SQL, выводу и файловым функциям | В процессе разработки и при код-ревью |
| Semgrep | Опасные шаблоны в коде по наборам правил | В автоматической проверке при каждой сборке |
| composer audit | Известные уязвимости в пакетах Composer | Перед каждым обновлением и по расписанию |
| Яндекс Вебмастер и Google Search Console | Сообщения о вирусах, взломе и подозрительных страницах | Постоянно, как система раннего оповещения |
Что делать с найденными проблемами
Отчёт сканера — это только начало. Большинство критичных уязвимостей в PHP закрываются четырьмя базовыми приёмами. Первый — подготовленные запросы (PDO или mysqli с параметрами) вместо склейки SQL-строк. Второй — экранирование вывода через htmlspecialchars с явной кодировкой во всех местах, где данные пользователя попадают в HTML. Третий — CSRF-токены во всех формах, которые что-то меняют, и атрибут SameSite у cookie. Четвёртый — строгая проверка загружаемых файлов: белый список расширений, проверка реального типа содержимого, случайные имена и запрет исполнения скриптов в каталоге загрузок.
Ниже наглядный пример: типичный уязвимый фрагмент и его безопасный вариант.
Один и тот же код до и после исправления
$id = $_GET['id'];
$res = $db->query(
'SELECT * FROM users WHERE id = ' . $id
);
echo 'Привет, ' . $_GET['name'];- Параметр id идёт прямо в SQL: возможна инъекция
- Имя выводится без экранирования: возможен XSS
$stmt = $pdo->prepare(
'SELECT * FROM users WHERE id = :id'
);
$stmt->execute(['id' => (int) $_GET['id']]);
echo 'Привет, ' . htmlspecialchars(
$_GET['name'], ENT_QUOTES, 'UTF-8'
);- Данные передаются параметром, а не частью запроса
- Вывод экранирован, скрипт превратится в обычный текст
Обратите внимание на деталь: приведение (int) для идентификатора тоже полезно, но главную защиту даёт именно подготовленный запрос. Валидация типа и экранирование работают как дополнительные слои, а не как замена друг другу.
Если сайт построен на фреймворке (Laravel, Symfony, Yii) или CMS, значительная часть защиты уже встроена: ORM, шаблонизатор с автоматическим экранированием, CSRF-механизмы. Уязвимости появляются там, где разработчик обходит эти механизмы: пишет сырые SQL-запросы, выводит данные в обход шаблонизатора или отключает проверку токена ради «удобства».
Типичные ошибки при проверке PHP-сайта
Как делают неправильно
- Запускают активный сканер сразу на боевом сайте и получают сбои или испорченные данные
- Ограничиваются одним сканером и считают, что проблем нет
- Игнорируют сторонние плагины и считают, что уязвим только собственный код
- Закрывают уязвимость в одном месте, но не ищут такой же шаблон в остальном коде
- Не перепроверяют сайт после исправлений
Как правильно
- 01
Тестируйте на копии сайта с отдельной базой данных
- 02
Комбинируйте сканер, статический анализ, аудит зависимостей и ручную проверку
- 03
Включайте в аудит все плагины, темы и пакеты Composer, включая неиспользуемые
- 04
После исправления ищите по всему проекту аналогичные конструкции
- 05
Повторяйте сканирование после каждой серии исправлений и сохраняйте отчёты для сравнения
Конфигурация: то, что часто упускают
Безопасный код можно легко обесценить небезопасными настройками. Если на сервере включён вывод ошибок, посетитель видит пути к файлам и фрагменты SQL-запросов, а это готовая подсказка для атаки. Если каталог с резервными копиями лежит в корне сайта и открыт по прямой ссылке, злоумышленнику не нужно ничего взламывать: достаточно скачать архив.
Поэтому отдельно проверьте, что по прямым адресам недоступны файлы .env, .git, composer.json с lock-файлом, дампы базы данных (.sql), архивы (.zip, .tar.gz), а также служебные скрипты вроде phpinfo.php и тестовые страницы. Закройте листинг каталогов и убедитесь, что сайт работает по HTTPS с корректными защитными заголовками.
Ниже собран короткий чек-лист ключевых директив php.ini, которые стоит проверить в первую очередь.
Семь настроек, которые закрывают типовые дыры
Как часто проверять и как встроить это в работу
Одноразовый аудит быстро устаревает: появляются новые версии библиотек, новые найденные уязвимости и новый код. Разумный минимум — проверка раз в квартал, а также перед каждым крупным релизом, после обновления CMS и после установки нового плагина.
Если у проекта есть разработчики, автоматизируйте то, что поддаётся автоматизации. Запуск composer audit, Semgrep и статического анализатора можно включить в процесс сборки, чтобы код с известной уязвимостью не попадал на боевой сервер. Ежедневный взгляд в Яндекс Вебмастер и Google Search Console занимает пару минут, но позволяет быстро заметить предупреждения о безопасности.
Отдельно настройте резервное копирование с хранением копий вне сервера. Это не заменяет защиту, но превращает возможный взлом из катастрофы в рабочую неприятность.
Что даёт регулярная проверка на уязвимости
- 01
Защита данных клиентов, заказов и учётных записей от утечек
- 02
Сохранение позиций в Яндексе и Google: сайт без вредоносного кода не получает пометок об опасности и санкций
- 03
Экономия на восстановлении: найти дыру дешевле, чем чистить взломанный сайт и объясняться с клиентами
- 04
Соответствие требованиям закона о защите персональных данных (152-ФЗ) при работе с формами и личными кабинетами
- 05
Стабильная работа хостинга без блокировок за спам-рассылки и нагрузку от вредоносных скриптов
Итоги: безопасность PHP-сайта — это процесс, а не разовая акция
- 01
Подготовьте тестовую копию и резервные копии, прежде чем запускать активные сканеры
- 02
Используйте связку OWASP ZAP, Nikto, Psalm или Semgrep и composer audit вместо одного инструмента
- 03
Закрывайте типовые дыры: подготовленные запросы, экранирование вывода, CSRF-токены, проверка загрузки файлов
- 04
Следите за разделами безопасности в Яндекс Вебмастере и Google Search Console и повторяйте проверку регулярно
Начните с самого простого: обновите PHP, CMS и плагины, выполните composer audit и посмотрите отчёты безопасности в Вебмастере и Search Console. Уже это закроет значительную часть известных рисков. Если сайт обрабатывает платежи или персональные данные, доверьте глубокий аудит специалистам: свежий взгляд почти всегда находит то, что давно примелькалось команде проекта.
Часто задаваемые вопросы
Запустите автоматический сканер (OWASP ZAP или Nikto) на тестовой копии сайта, выполните команду composer audit для проверки зависимостей и посмотрите разделы безопасности в Яндекс Вебмастере и Google Search Console. Это займёт 1–2 часа и покажет самые заметные проблемы.
Чаще всего находят SQL-инъекции, XSS (внедрение скриптов в вывод), CSRF, небезопасную загрузку файлов, подключение произвольных файлов через include и устаревшие библиотеки или плагины CMS с известными дырами.
Нет, только с письменного разрешения владельца. Активное сканирование без согласия может быть расценено как неправомерный доступ к компьютерной информации и повлечь ответственность по ст. 272 УК РФ.
Минимум раз в квартал, а также перед каждым крупным релизом, после обновления CMS или добавления нового плагина. Проверку зависимостей лучше встроить в автоматический процесс сборки и запускать при каждом изменении кода.
Нет. Сканер находит только то, что видно снаружи. Логические ошибки, уязвимости в закрытых разделах и проблемы конфигурации выявляют статический анализ кода, ручная проверка и аудит настроек сервера.
Подозреваете дыры в PHP-коде? Проведём аудит безопасности вашего сайта
Найдём уязвимости в коде, плагинах и настройках сервера и дадим понятный план исправлений
Спасибо за заявку!
Мы свяжемся с вами в ближайшее время.
Проверено на сотнях PHP-проектов



