php2shell-checker: два навыка от OpenAI для проверки уязвимости PHP

· 6 мин чтения
security php agent-skills codex tools
📂 Исходный код на GitHub

Репозиторий от OpenAI: Node.js-скрипт phpcheck и два навыка для Codex (phpcheck-url и phpcheck-server), которые проверяют версию PHP по HTTP-заголовкам или через php -v и определяют, уязвима ли эта версия к php2shell по встроенной таблице пороговых версий.

php2shell-checker: два навыка от OpenAI для проверки уязвимости PHP

OpenAI выложила репозиторий php2shell-checker. В нём лежит небольшой Node.js-скрипт и два навыка (skill) для Codex. Инструмент отвечает на один вопрос: уязвима ли версия PHP, которая обслуживает ваш сайт, к уязвимости php2shell. Проверить можно и удалённый сайт по URL, и локальный PHP-бинарник на своей машине.

Установить оба навыка в Codex можно одной командой:

$skill-installer install both skills from https://github.com/openai/php2shell-checker

В репозитории два навыка. phpcheck-url — когда у вас есть только адрес сайта. phpcheck-server — когда у вас есть доступ к самому серверу. Пример работы:

$phpcheck-url check https://example.com
$phpcheck-server check the PHP version serving my site

Зачем это нужно

PHP-сайты часто подставляют свою версию в HTTP-заголовки ответа. Заголовки Server и X-Powered-By можно прочитать обычным curl или браузером — без доступа к серверу. Если версия видна, её можно сравнить со списком уязвимых выпусков. Именно это и делает проверяющий скрипт.

php2shell — уязвимость в PHP. Репозиторий не описывает, как именно работает эксплойт. Он отвечает только за проверку номера версии: попадает ли он в уязвимый диапазон для своей ветки.

Что лежит в репозитории

  • phpcheck.js — точка входа для прямого запуска;
  • phpcheck.test.js — тесты;
  • skills/phpcheck-url/ — навык для проверки по URL;
  • skills/phpcheck-server/ — навык для проверки на сервере.

Проверяющая логика живёт внутри навыка phpcheck-url, в файле scripts/phpcheck.js. Корневой phpcheck.js просто подключает этот же файл.

Прямой запуск без агента

Навык Codex не обязателен. Скрипт запускается напрямую через Node.js:

node phpcheck.js "https://example.com"

Проверка локального PHP:

node phpcheck.js --local

Доступные флаги из кода скрипта:

Флаг Что делает
--json Вывод в формате JSON вместо текста
--timeout SECONDS Таймаут запроса. По умолчанию 10 секунд, максимум 60
--local Проверить локальный PHP через php -v вместо URL
--php PATH Путь к PHP-бинарнику для режима --local. По умолчанию php
--version Показать версию самого скрипта (сейчас 1.0.0)
--help Показать подсказку

Задать одновременно URL и --local нельзя — скрипт выдаст ошибку и завершится с кодом 2. Такой же код возврата бывает при неверных аргументах: пустой URL, таймаут вне диапазона, логин или пароль в адресе, фрагмент после #.

Как читать результаты

Результат Код возврата Значение
OK 0 Стабильный патч-релиз выше встроенного порога для известной ветки
VULNERABLE 1 Версия PHP равна порогу или ниже него
UNKNOWN 3 Версии нет, ветка неизвестна, либо это более новый предрелиз

В режиме --json возвращается объект с полями patch_status (ok, vulnerable или unknown), php_version, reason и exit_code.

Важно: коды 1 и 3 — это не сбой самого скрипта. Это ответы «уязвимо» и «неизвестно». Об этом отдельно напоминает навык phpcheck-url.

Пороговые версии

Версии уязвимы к php2shell в следующих диапазонах (данные из навыка phpcheck-server по состоянию на 20 октября 2026 года):

Ветка PHP Уязвимый диапазон (включительно)
5.4 5.4.0 — 5.4.45
5.5 5.5.0 — 5.5.38
5.6 5.6.0 — 5.6.40
7.0 7.0.0 — 7.0.33
7.1 7.1.0 — 7.1.33
7.2 7.2.0 — 7.2.34
7.3 7.3.0 — 7.3.33
7.4 7.4.0 — 7.4.33
8.0 8.0.0 — 8.0.30
8.1 8.1.0 — 8.1.34
8.2 8.2.0 — 8.2.34
8.3 8.3.0 — 8.3.35
8.4 8.4.0 — 8.4.26
8.5 8.5.0 — 8.5.11

Эта же таблица зашита в код скрипта в виде объекта VULNERABLE_THROUGH. Ветки, которых в списке нет, проверяющий считает неизвестными, пока сообщение о безопасности не подтвердит их статус.

Как скрипт работает внутри

Для URL скрипт делает запрос HEAD. Только если сервер отвечает кодами 405 или 501, он повторяет запрос через GET. Заголовки Server и X-Powered-By складываются в одну строку, из неё регулярным выражением вытаскивается номер версии вида PHP/8.3.15.

В режиме --local скрипт запускает php -v и парсит строку вида PHP 8.3.15 (...). Ответ может содержать предупреждения на старте — это учитывается.

Если в ответе нашлось несколько упоминаний PHP, правило простое: статус vulnerable всегда перебивает остальные. Баннер с версией OK не может скрыть уязвимую или неизвестную версию, найденную рядом.

Сборки с метками dev, alpha, beta или rc скрипт помечает как unknown. Предрелиз следующего патча — не доказательство того, что стабильный фикс уже вышел.

Чего инструмент не делает

Авторы честно описывают ограничения. Их важно знать, чтобы не получить ложное спокойствие.

  • Скрипт смотрит только на версию из HTTP-заголовков или из вывода php -v. Больше он ничего не анализирует.
  • Он не следует за редиректами и не читает тело ответа.
  • Если заголовки скрыты или изменены, результат будет UNKNOWN.
  • OK — это сравнение номеров. Скрипт предполагает, что любой более новый стабильный патч в той же ветке содержит фикс. Он не проверяет наличие фикса напрямую.
  • Вендоры (Red Hat, Debian и другие) часто переносят патчи безопасности в старые номера версий и не меняют номер, который виден снаружи. Поэтому UNKNOWN не означает, что цель защищена. И наоборот: OK по номеру не гарантирует, что патч реально применён.
  • Единственные по-настоящему надёжные проверки — это запущенная сборка PHP и официальные сообщения о безопасности от PHP и от вашего вендора. Настройки конфигурации сами по себе ничего не доказывают.

Навык phpcheck-server задаёт агенту тот же настрой: сначала php -v, потом сверка с тем PHP-FPM или Apache, который реально обслуживает сайт. Если проверить запущенную версию не удалось — агент должен сообщить unknown, а не угадывать. Запускать эксплойты для проверки запрещено.

Навык phpcheck-url добавляет: для голого хоста используйте HTTPS. Результат по заголовкам — менее сильное доказательство, чем проверка версии и пакета прямо на сервере.

Тесты

Тесты запускаются штатным раннером Node.js:

node --test phpcheck.test.js

Тесты поднимают локальные HTTP-серверы и подставляют поддельный PHP-бинарник. Установленный PHP и доступ к реальным сайтам не нужны.

Лицензия и участие

Лицензия — Apache License 2.0. OpenAI не принимает внешний код в этот проект, но принимает отчёты об ошибках и обратную связь через GitHub issues. Подробности — в CONTRIBUTING.md.

Итог

php2shell-checker — тонкий инструмент с чёткой границей ответственности. Он сравнивает номер версии PHP с встроенной таблицей и честно говорит «не знаю», когда данных недостаточно. Для агента Codex это два навыка: один читает заголовки по URL, другой работает на сервере. Для всех остальных — обычный node phpcheck.js. Финальное решение о том, обновлять PHP или нет, остаётся за вами и за официальными сообщениями о безопасности от PHP и вашего вендора.

Источник: https://github.com/openai/php2shell-checker