Аудит PHP-кода: чек-лист, этапы и инструменты
Три ряда одинаковых пустых карточек на подложке, в свободной ячейке лежит маленький зелёный шарик

Аудит PHP-кода: чек-лист, этапы и инструменты

Аудит PHP-кода — это проверка проекта на уязвимости, ошибки, медленные места и технический долг. Разбираем этапы, инструменты и типичные ошибки.

Аудит PHP-кода: как найти уязвимости и технический долг до того, как они выстрелят

Аудит PHP-кода — это комплексная проверка проекта на уязвимости, ошибки, узкие места производительности и технический долг. Её проводят с помощью статических анализаторов (PHPStan, Psalm, SonarQube) и ручного ревью, а результатом становится отчёт с приоритизированным списком исправлений.

Хороший аудит отвечает на три вопроса: насколько проект безопасен, сколько стоит его развитие и что нужно чинить в первую очередь.

PHP до сих пор работает на огромной доле сайтов, интернет-магазинов и корпоративных систем. Многие из них живут по 7–10 лет, переходили от одного подрядчика к другому и обросли «временными» решениями, которые стали постоянными. В этой статье разберём, что именно входит в аудит, какие инструменты использовать, как выстроить процесс по шагам и какие ошибки чаще всего портят результат.

Что такое аудит PHP-кода и чем он отличается от обычного code review

Code review — это ежедневная практика: коллега просматривает небольшой набор изменений перед слиянием в основную ветку. Он отвечает на вопрос «хороша ли эта правка?». Аудит решает другую задачу: он оценивает весь проект целиком — кодовую базу, зависимости, конфигурацию сервера, процессы разработки и развёртывания.

По сути, аудит — это диагностика. Вы получаете независимую оценку состояния системы и понимаете, где риски, а где всё в порядке. Именно поэтому аудит чаще всего заказывают в ключевые моменты жизни проекта: при покупке или передаче сайта, смене подрядчика, подготовке к масштабированию, миграции на новую версию PHP или после взлома.

Важно, что аудит не сводится к «найти баги». Хороший аудитор оценивает также читаемость и предсказуемость кода: насколько легко новому разработчику войти в проект, сколько времени уходит на типовую доработку и насколько безопасно вносить изменения без риска что-то сломать.

Когда аудит PHP-кода действительно необходим

  1. 01

    Проект достался вам от другой команды или подрядчика, и никто не знает, что внутри

  2. 02

    Сайт был взломан, заражён вирусом или попал в список небезопасных у Яндекса или Google

  3. 03

    Страницы стали загружаться заметно медленнее, а нагрузка на сервер растёт быстрее, чем трафик

  4. 04

    Любая небольшая правка ломает несвязанные части системы, а разработка замедляется

  5. 05

    Планируется переход с PHP 7.x на 8.x или смена фреймворка (например, с самописной CMS на Laravel или Symfony)

  6. 06

    Нужно подтвердить безопасность перед сертификацией, интеграцией с банком или сделкой по продаже бизнеса

  7. 07

    Перед запуском крупной рекламной кампании в Яндекс Директ и Google Ads, когда простой сайта означает прямые потери бюджета

Четыре направления проверки

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

Важно сразу договориться, какие направления входят в задачу. Если вам нужен только быстрый «срез безопасности» перед релизом, глубокий анализ архитектуры будет лишним. А если вы готовите проект к масштабированию, одной проверки на уязвимости совершенно недостаточно.

четыре оси аудита php-проекта
01 / безопасность

Уязвимости

SQL-инъекции, XSS, CSRF, небезопасная загрузка файлов, хранение паролей и секретов, права доступа.

02 / качество

Код и архитектура

Типизация, дублирование, цикломатическая сложность, связность модулей, соблюдение PSR.

03 / скорость

Производительность

N+1 запросы, индексы БД, OPcache, кеширование, медленные участки в профайлере.

04 / среда

Зависимости и процессы

Версия PHP, пакеты Composer с уязвимостями, тесты, CI/CD, логирование, резервные копии.

Безопасность: с чего начинать

Если времени мало, начинайте именно с безопасности: последствия уязвимостей самые тяжёлые — утечка клиентской базы, подмена содержимого страниц, рассылка спама с вашего сервера, блокировка хостером.

В PHP-проектах чаще всего встречаются одни и те же проблемы. SQL-инъекции — запросы, собранные конкатенацией строк с данными из `$_GET` и `$_POST`. XSS — вывод пользовательских данных без `htmlspecialchars` или экранирования в шаблонизаторе. CSRF — формы и AJAX-запросы без проверки токена. Небезопасная загрузка файлов — проверка только по расширению, а не по содержимому, и сохранение в публичную папку с возможностью выполнения. Опасные функции — `eval`, `unserialize` на пользовательских данных, `include` с переменным путём.

Отдельно проверяют работу с паролями (должны использоваться `password_hash` и `password_verify`, а не MD5 или SHA1), настройки сессий (флаги `HttpOnly`, `Secure`, `SameSite`), отключённый `display_errors` на продакшене и отсутствие файлов `.env`, дампов базы и резервных копий в публичной директории.

Ниже — самый показательный пример из практики аудитов: типовая SQL-инъекция и её исправление.

пример находки: sql-инъекция
было / уязвимо
$sql = 'SELECT * FROM users WHERE id = '
     . $_GET['id'];
$res = $pdo->query($sql);

Параметр попадает в запрос как есть. Значение вида1 OR 1=1вернёт всех пользователей, а более сложный payload позволит читать и менять данные.

стало / безопасно
$stmt = $pdo->prepare(
  'SELECT id, name FROM users WHERE id = :id'
);
$stmt->execute(['id' => (int) $_GET['id']]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);

Подготовленный запрос отделяет код SQL от данных, а явное приведение типа и выборка нужных полей снижают риски и нагрузку.

Качество кода и архитектура

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

Первый — размер и ответственность классов и функций. Файлы на 3 000 строк, контроллеры, в которых смешаны SQL-запросы, бизнес-логика и вёрстка, — классический сигнал, что любая правка будет рискованной. Второй — дублирование: одна и та же логика расчёта цены, скопированная в пять мест, гарантирует, что в шестом месте про неё забудут. Третий — типизация: наличие декларации `declare(strict_types=1)`, типов аргументов и возвращаемых значений, которые доступны начиная с PHP 7 и существенно расширены в PHP 8.

Четвёртый — соответствие стандартам PSR (PSR-1, PSR-4, PSR-12): автозагрузка через Composer вместо россыпи `require_once`, единый стиль, понятные пространства имён. Пятый — тесты. Не обязательно стопроцентное покрытие, но критичные сценарии (оплата, регистрация, расчёты) должны быть защищены автоматическими проверками, иначе обновление PHP или библиотек превращается в лотерею.

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

ЗадачаИнструментыЧто показывают
Анализ типов и поиск ошибок без запускаPHPStan, PsalmОбращения к несуществующим методам, неверные типы, недостижимый код
Стиль кода и соответствие PSR-12PHP_CodeSniffer, PHP CS FixerНарушения форматирования, которые можно исправить автоматически
Сложность и дублированиеPHPMD, PHPMetricsФункции с высокой цикломатической сложностью, раздутые классы
Уязвимости в зависимостяхcomposer audit, Roave Security AdvisoriesПакеты с известными CVE и рекомендуемые версии для обновления
Поиск небезопасных паттерновSemgrep, SonarQubeКонкатенацию в SQL, использование eval и опасных функций
Профилирование производительностиXdebug, Blackfire, XHProfСамые медленные функции, тяжёлые запросы, потребление памяти
Тесты и их качествоPHPUnit, InfectionПокрытие кода и «слабые» тесты, которые не ловят ошибки

Автоматика даёт основу, но не заменяет голову

Запуск инструментов — это быстрая и недорогая часть аудита, которая выявляет «низко висящие плоды». Например, PHPStan на высоком уровне строгости на старом проекте легко выдаст тысячи замечаний. Это нормально: главное — не пытаться исправить всё сразу, а зафиксировать текущее состояние (baseline) и не допускать появления новых ошибок.

Однако у автоматики есть слепые зоны. Анализатор не поймёт, что скидка применяется дважды, что у менеджера есть доступ к чужим заказам по прямой ссылке (IDOR) или что API возвращает лишние поля с персональными данными. Такие вещи находят только при ручном просмотре ключевых сценариев: авторизации, оплаты, личного кабинета, административной панели.

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

Как провести аудит PHP-кода шаг за шагом

  1. 01

    Определите цели и границы. Зафиксируйте, что проверяете (весь проект или отдельные модули), что для вас приоритет — безопасность, скорость или поддерживаемость, и какие данные нужны для оценки (репозиторий, доступ к тестовому серверу, логи).

  2. 02

    Соберите инвентарь проекта. Выпишите версию PHP, фреймворк или CMS, список пакетов из composer.json и composer.lock, используемые расширения, базу данных, очереди, кеш и внешние интеграции.

  3. 03

    Запустите автоматические проверки. Выполните composer audit, PHPStan или Psalm, PHP_CodeSniffer, PHPMD и сканер безопасности вроде Semgrep. Сохраните результаты как отправную точку.

  4. 04

    Проверьте конфигурацию окружения. Изучите php.ini (display_errors, expose_php, open_basedir), права на файлы и папки, настройки веб-сервера, наличие HTTPS, заголовков безопасности и закрытость служебных файлов.

  5. 05

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

  6. 06

    Профилируйте производительность. Включите slow query log в базе, снимите профиль в Xdebug, Blackfire или XHProf на типовых сценариях, найдите N+1 запросы, отсутствующие индексы и места без кеширования.

  7. 07

    Оцените риски и приоритеты. Для каждой находки определите серьёзность (критическая, высокая, средняя, низкая), вероятность эксплуатации и трудоёмкость исправления.

  8. 08

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

Производительность и связь с SEO

Скорость — тема, которая интересует не только разработчиков, но и маркетологов. Медленный ответ сервера (высокий TTFB), долгая генерация страницы и ошибки 5xx напрямую влияют на поведение пользователей и на то, как поисковые системы обходят сайт. И Яндекс, и Google учитывают скорость и стабильность при оценке качества ресурса, а роботы могут сокращать частоту обхода, если сервер отвечает медленно или нестабильно.

Типичные причины тормозов в PHP-проектах — N+1 запросы (когда для каждой строки списка выполняется отдельный запрос), отсутствие индексов на полях фильтрации и сортировки, выборка `SELECT *` там, где нужны два поля, отключённый или неверно настроенный OPcache, отсутствие кеширования результатов тяжёлых вычислений в Redis или Memcached, а также синхронная отправка писем и обращений к внешним API прямо в момент запроса пользователя.

После исправлений полезно сравнить показатели «до» и «после»: время ответа, количество запросов к базе, пиковое потребление памяти. Динамику сайта в целом удобно отслеживать в Яндекс Метрике и Google Analytics, а технические ошибки обхода — в Яндекс Вебмастере и Google Search Console.

как приоритизировать находки аудита
01 / critical

Исправить немедленно

Работающая SQL-инъекция, доступ к админке без пароля, открытые дампы БД, утёкшие ключи. Срок — от часов до 1–2 дней.

02 / high

В ближайший спринт

XSS в формах, отсутствие CSRF-токенов, пакеты с известными CVE, устаревшая версия PHP без патчей безопасности.

03 / medium

Запланировать в квартале

N+1 запросы, отсутствие индексов, дублирование логики, слабое логирование и нехватка тестов в критичных модулях.

04 / low

Решать по мере работы

Нарушения стиля, неиспользуемый код, устаревшие комментарии. Автоматизируйте через PHP CS Fixer и Rector.

Отчёт, который можно превратить в работу

Результат аудита ценен ровно настолько, насколько по нему можно действовать. Отчёт на 80 страниц без приоритетов обычно остаётся лежать в папке. Хороший документ состоит из краткого резюме для руководителя (общий уровень риска, три-пять главных проблем и оценка трудозатрат) и детальной части для разработчиков.

Для каждой находки полезно указывать: что обнаружено, где (файл и строка), чем опасно, как воспроизвести и как исправить с примером кода. Дополнительно стоит приложить дорожную карту: что делаем сразу, что в ближайший месяц, что в долгосрочной перспективе. Так бизнес видит не просто список проблем, а понятный бюджет и сроки.

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

Частые ошибки при аудите PHP-кода

Даже опытные команды допускают просчёты, которые обесценивают результат проверки.

Как делать не стоит

  • Ограничиться запуском одного анализатора и считать аудит законченным
  • Проверять код только на тестовых данных, не глядя на настройки продакшена
  • Пытаться исправить все замечания PHPStan за один раз и остановить развитие продукта
  • Игнорировать зависимости: уязвимый пакет в vendor опаснее собственной небрежной функции
  • Поручать аудит автору кода, у которого «замылен» взгляд
  • Не фиксировать результаты и не проверять, что исправления действительно закрыли проблемы

Как правильно

  1. 01

    Сочетать статический анализ, проверку конфигурации и ручное ревью критичных сценариев

  2. 02

    Сверять код с реальным окружением: версия PHP, расширения, права, переменные окружения

  3. 03

    Использовать baseline и повышать строгость анализатора постепенно, уровень за уровнем

  4. 04

    Включить composer audit в CI и обновлять пакеты регулярно, а не раз в три года

  5. 05

    Привлекать независимого специалиста или хотя бы коллегу из другой команды

  6. 06

    Вести журнал находок, назначать ответственных и проводить повторную проверку после правок

Версии PHP 8.0 и ниже уже не получают обновлений безопасности. Если проект всё ещё работает на PHP 7.x или 5.x, переход на актуальную ветку 8.x — один из первых пунктов плана после аудита: он закрывает целый класс известных уязвимостей и обычно ускоряет приложение.

Внутренний аудит или внешний подрядчик: что выбрать

Внутренний аудит дешевле и быстрее запускается: команда знает проект, контекст и бизнес-логику. Но у него есть ограничения — «замыленность» взгляда, нехватка опыта в пентесте и естественное желание не выносить сор из избы.

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

Оптимальный вариант для большинства компаний — гибрид: регулярные автоматические проверки и внутреннее ревью в повседневной работе плюс независимый комплексный аудит раз в год или перед значимыми изменениями.

Итоги: как сделать аудит PHP-кода полезным

Аудит — не разовая акция, а часть цикла разработки: чем раньше найдена проблема, тем дешевле её исправление.
  1. 01

    Определите цели: безопасность, производительность, поддерживаемость или всё вместе

  2. 02

    Сочетайте автоматические инструменты (PHPStan, Psalm, composer audit, Semgrep) с ручным ревью критичных модулей

  3. 03

    Приоритизируйте находки по серьёзности и срокам, а не пытайтесь исправить всё сразу

  4. 04

    Фиксируйте результаты в отчёте с примерами исправлений и планом работ

  5. 05

    Встройте проверки в CI и повторяйте полноценный аудит не реже раза в год

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

Часто задаваемые вопросы

Закажите аудит PHP-кода и узнайте, где проект уязвим

Получите отчёт с приоритетами исправлений и понятным планом работ на ближайшие спринты

Бесплатная предоценкаОтчёт с приоритетамиРабота по NDA

Проверяем проекты на PHP 7.4–8.x

Политика конфиденциальности

При оставлении заявки на ресурсе «https://gurucontext.ru» пользователи предоставляют следующие сведения:

  • Имя
  • Контактный телефон или Telegram
  • Адрес сайта пользователя (не обязательно)

Также администрация сайта получает данные об IP-адресе посетителей, типе браузера, времени нахождения на сайте и прочие подобные сведения через сервисы статистики.

Использование информации

Вся полученная информация используется администрацией «https://gurucontext.ru» исключительно в целях связи с клиентом.

Защита персональных данных

Компания «https://gurucontext.ru» обязуется не разглашать сведения, полученные от пользователей, и хранит их в защищённом виде.

Предоставление данных третьим лицам

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

Контакты

Телефон: +7 (499) 955-47-00.
E-mail: info@gurucontext.ru.