18 фев 2022

Поиск уязвимостей с PHP_CodeSniffer

#php, #php-codesniffer, #devsecops

Сегодня статические анализаторы кода являются обязательным условием разработки php-приложения. Команды встраивают их в свой процесс ci/cd, что позволяет сократить количество потенциальных уязвимостей и улучшить читаемость кода. В этой заметке мы поговорим об использовании инструмента под названием PHP_CodeSniffer, который имеет многолетнюю историю и зарекомендовал себя в PHP-комьюнити.

Поиск уязвимостей с PHP_CodeSniffer

Статический анализ

Инструменты статического позволяют решать следующие задачи:

  • Поддержка стиля кода в консистентном состоянии.
    Ведь даже в команде из 3-х человек, подходы к написанию у каждого будут свои. Не всегда помогает и договоренность о соблюдении PSR-1и PSR-12.
  • Автоматизация поиска потенциальных уязвимостей.
    Все разработчики люди, а значит могут ошибаться. Во всех приложениях есть слабые места, которые могут быть использованы хакерами.
  • Предупреждение о возможных ошибках.
    Php - это интерпретируемый язык, а значит он может быть запущен без этапа явной компиляции и многие опечатки и неточности иногда попадают в продакшн.

С чего начать

Как и множество других библиотек, с установкой CodeSniffer нам поможет composer. Установим его как dev-зависимость, что предполагает использование только при разработке:

    
        composer require --dev squizlabs/php_codesniffer
    

После установки станет доступна утилита phpcs, которая запускает анализ. Чтобы получить список доступных стандартов:

    
        ./vendor/bin/phpcs -i
    

Чтобы проверить код на соответствие стандартам PSR-1 и PSR-12 запустим в консоли:

    
        ./vendor/bin/phpcs ./src -standard=PSR1,PSR12
    

В качестве аргумента передается директория, а в аттрибуте standard список применяемых стандартов. Отчет об ошибках будет выглядеть примерно так:

Отчет об ошибках phpcs

Базовая конфигурация

Каждый раз обращаться к phpcs напрямую и передавать ей нужные аргументы неудобно. PHP_CodeSniffer позволяет описать все свои настройки в файле конфигурации:

    <?xml version="1.0"?>
        <ruleset name="My Standard" namespace="Standard">

            <!-- Описание проекта -->
            <description>Мой стандарт php проекта </description>

            <!-- Путь к директориям для проверок -->
            <file>./src</file>

            <!-- Используемые стандарты -->
            <rule ref="PSR1"/>
            <rule ref="PSR12"/>
        </ruleset>

Назовем это файл .phpcs.xml и расположим его в корне нашего проекта. Если DOCUMENT_ROOT указывает в этот же каталог, то не забудьте закрыть доступ к .phpcs.xml на уровне web-сервера.

Чтобы упростить рутину, перенесем вызов утилиты phpcs в composer, для этого в composer.json добавим секции script:

    
         "scripts": {
            "phpcs": "./vendor/bin/phpcs"
         }
    

Теперь для того, чтобы запустить статический анализ проекта, достаточно в консоли:

    
        composer run phpcs
    

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

Php-комьюнити разработало большое количество библиотек, расширяющих стандартные правила PHP_CodeSniffer, протестированные и одобренные значительным количеством разработчиков. Существует и возможность создавать свои.

Установим пакет pheromone/phpcs-security-audit:

    
        composer require --dev pheromone/phpcs-security-audit
    

В нем содержится стандарт для определения распространенных уязвимостей php-проектов. Чтобы использовать его с PHP_CodeSniffer, нужно поместить вместе с другими правилами к дистрибутиву PHP_CodeSniffer. Этот процесс упрощает библиотека dealerdirect/phpcodesniffer-composer-installer. Она самостоятельно выполнит все необходимые действия. Устанавливаем:

    
        composer require --dev dealerdirect/phpcodesniffer-composer-installer
    

Выедем список доступных стандартов:

    
        composer run phpcs -- -i
    

Список доступных стандартов PHP_CodeSniffer

Security - это и есть стандарт из пакета pheromone/phpcs-security-audit.

Теперь нам осталось доработать .phpcs.xml, добавим туда строчку:

     
        <rule ref="Security.BadFunctions.NoEvals"/>
     

С этого момента PHP_CodeSniffer начнет предупреждать нас об использовании опасной функции eval c динамически определяемыми аргументами.

Интеграция с IDE

Ручной запуск проверок и их исправление отвлекает программистов от работы. Поэтому все современные IDE из коробки или с помощью дополнительных плагинов интегрируются с популярными инструментами, в том числе и с PHP_CodeSniffer. Рассмотрим на примере PhpStorm.

У шторма отличная документация, поэтому сконцентрируюсь лишь на основных моментах.

Для интеграции вам потребуется последняя версия PhpStorm и установленный PHP_CodeSniffer. Далее открываем внутри IDE composer.json и кликаем на шестеренку в строке c squizlabs/php_codesniffer:

PhpStorm и PHP_CodeSniffer. Интеграция через composer.json

В открывшемся окне, для unix пользователей, нужно прописать путь до исполняемого файла phpcs, его можно найти по пути ./vendor/bin/phpcs. А вот для Windows потребуется файл .bat -> ./vendor/squizlabs/php_codesniffer/bin/phpcbf.bat.

В этом же окне кликаем на ссылку Php_CodeSniffer inspection и настраиваем стандарт. Нам нужно выбрать custom и указать путь до нашего конфига .phpcs.xml. Также не забудьте поставить галочку, чтобы активировать инспекции.

PhpStorm и PHP_CodeSniffer. Настройка стандарта

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

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

Все статьи

© 2020-2022 Александр Пантелеев