Эта страница была переведена сообществом и не обязательно является актуальной. Обратитесь к справочной версии.
Эта страница была переведена сообществом и не обязательно является актуальной. Обратитесь к справочной версии.
Эта страница была переведена сообществом и не обязательно является актуальной. Обратитесь к справочной версии.
Этот документ описывает модель доверия FrankenPHP: какие входные данные являются доверенными, какие нет, и где проходит граница между ними. Он предназначен для помощи аудитам безопасности и автоматизированным сканерам в анализе самого FrankenPHP, а не PHP-приложений, которые он обслуживает.
Внутренние механизмы, упомянутые здесь (потоки, граница CGO, изоляция среды), см. в Внутреннее устройство. Сохранение состояния в долгоживущих процессах см. в Режим воркера.
FrankenPHP работает в стеке с четырьмя различными участниками:
| Участник | Доверие | Примечания |
|---|---|---|
| Удаленный клиент | Недоверенный | HTTP-запрос (метод, URI, заголовки, куки, тело, загрузки) является основным источником загрязненных входных данных. |
| Оператор | Доверенный | Предоставляет конфигурацию развертывания: Caddyfile, переменные среды, php.ini, установленные расширения PHP и модули Caddy, а также сам код приложения. |
| Код PHP-приложения | Доверенный по происхождению | Развертывается оператором, поэтому FrankenPHP никогда не выполняет код, предоставленный злоумышленником, но этот код потребляет недоверенные данные запроса. |
| FrankenPHP (Go + C) | Доверенная вычислительная база | Встраивает PHP, передает данные внутрь и наружу, а также изолирует запросы и потоки. Собственные дефекты FrankenPHP являются предметом рассмотрения этого документа. |
Это самое важное различие, которое разрешает большую часть путаницы “доверяем ли мы PHP или нет?”:
$_GET, $_POST, $_COOKIE, $_FILES, $_SERVER, php://input), является недоверенным, точно так же, как в любом PHP SAPI. Санитаризация данных — задача приложения.Таким образом, “мы доверяем тому, что поступает от PHP” верно для кода, в то время как “SAPI переносит недоверенный ввод” верно для данных: эти два утверждения не противоречат друг другу. Задача FrankenPHP — добросовестно переносить эти загрязненные данные и предотвращать утечку данных одного запроса в другой.
Доверенная вычислительная база выполняет три задачи. Дефекты безопасности в FrankenPHP находятся в одной из них:
php://input, а также передача вывода и заголовков PHP обратно клиенту, без внедрения инъекций (инъекция заголовка/CRLF, подмена запросов, выполнение неправильного файла).Это поверхности, которыми владеет FrankenPHP. Уязвимость здесь является уязвимостью FrankenPHP:
cgi.go, frankenphp_register_server_vars): создание $_SERVER, REMOTE_ADDR, SCRIPT_NAME, PATH_INFO и других CGI-переменных из запроса.split_path (по умолчанию .php) на SCRIPT_NAME / PATH_INFO, затем соединяется с корневым каталогом документа с помощью sanitizedPathJoin (filepath.Join(root, filepath.Clean("/"+reqPath))), что предотвращает выход SCRIPT_FILENAME за пределы корневого каталога документа (обход каталогов). Директива php_server дополнительно устанавливает перезапись try_files по умолчанию, которая маршрутизирует запросы к существующим файлам или фронт-контроллеру, уменьшая классическую проблему PHP-FPM, связанную с выполнением неправильного файла.$_GET, $_POST, $_COOKIE, $_FILES, $_SERVER и $_REQUEST между запросами, явно очищает $_SESSION (которая в противном случае будет утекать между запросами) и ошибки, возвращаемые error_get_last() и libxml_get_errors(), а также заголовки, возвращаемые http_get_last_response_headers(), состояние strtok() и переменные, добавленные output_add_rewrite_var(), но $_ENV не сбрасывается, а записи putenv(), static переменные, статические свойства классов, глобальные переменные и настройки движка времени выполнения (ini_set(), контекст потока по умолчанию, часовой пояс по умолчанию, рабочий каталог, …) сохраняются между запросами в одном и том же потоке. Данные, относящиеся к запросу или пользователю, оставленные в этом состоянии, могут утечь в последующий запрос (см. Режим воркера).frankenphp_putenv() / frankenphp_getenv() работают с потоко-локальной sandboxed_env. Записи putenv() остаются внутри этой песочницы и никогда не достигают глобальной среды ОС процесса, поэтому секрет, установленный одним запросом, не может утечь к дочерним процессам (proc_open, exec, …), на сторону Go/Caddy или к другим запросам. Дочернему процессу, который должен видеть такую переменную, она должна быть явно передана через аргумент среды proc_open() или exec() (см. Внутреннее устройство).C.CString() / free() на границе Go ↔ C./frankenphp/workers/restart и /frankenphp/threads, предоставляемые через Caddy’s admin API (который по умолчанию прослушивает localhost:2019). Предоставление этой конечной точки за пределы localhost является решением оператора.X-Forwarded-* всегда достигают PHP как загрязненные значения $_SERVER['HTTP_X_FORWARDED_*']; они считаются доверенными для определения реального IP-адреса клиента и схемы только при настроенном trusted_proxies.request_body_timeout), сбрасывая крайний срок перед каждым чтением, так что стабильная загрузка любого размера проходит успешно, в то время как застопорившаяся обрезается, а поток освобождается.См. документ SECURITY.md для получения информации о том, как сообщить о проблеме безопасности, затрагивающей FrankenPHP.
Редактировать эту страницу