このページはコミュニティによって翻訳されたもので、最新ではない可能性があります。参照用のバージョンをご覧ください。

このページはコミュニティによって翻訳されたもので、最新ではない可能性があります。参照用のバージョンをご覧ください。

このページはコミュニティによって翻訳されたもので、最新ではない可能性があります。参照用のバージョンをご覧ください。

提供
セキュリティモデル

セキュリティモデル

このドキュメントでは、FrankenPHP の信頼モデルについて説明します。具体的には、どの入力が信頼され、どの入力が信頼されず、その境界がどこにあるかです。 これは、FrankenPHP が提供する PHP アプリケーションではなく、FrankenPHP そのものに関するセキュリティ監査や自動スキャナーの検討に役立つことを意図しています。

ここで参照されている内部メカニクス(スレッド、CGO 境界、環境サンドボックス)については、内部構造を参照してください。 長期間実行されるプロセスにおける状態の永続性については、ワーカーモードを参照してください。

# 信頼境界

FrankenPHP は、4 つの異なるアクターを持つスタックで動作します。

アクター信頼度注記
リモートクライアント信頼されていないHTTP リクエスト(メソッド、URI、ヘッダー、クッキー、ボディ、アップロード)は、汚染された入力の主要なソースです。
オペレーター信頼されているデプロイ設定を提供します。具体的には、Caddyfile、環境変数、php.ini、インストールされている PHP 拡張機能と Caddy モジュール、およびアプリケーションコード自体です。
PHP アプリケーションコード由来によって信頼されているオペレーターによってデプロイされるため、FrankenPHP は攻撃者から提供されたコードを実行することはありませんが、このコードは信頼されていないリクエストデータを消費します。
FrankenPHP (Go + C)信頼できるコンピューティングベースPHP を組み込み、データの入出力を行い、リクエストとスレッドを分離します。本ドキュメントでは、FrankenPHP 自身の欠陥に焦点を当てています。

# コードの出所 vs. データの汚染

これは最も重要な区別であり、「PHP を信頼すべきか否か?」という混乱のほとんどを解消するものです。

  • コードの出所は信頼されています。 FrankenPHP は、オペレーターによってデプロイされた PHP ファイル(ドキュメントルート下で解決されるスクリプト、または設定されたワーカー スクリプト)のみを実行します。リクエスト自体に含まれるコード(ボディ、クエリ文字列、ヘッダー)は決して評価しません。SAPI 境界は信頼されていないコードではなく、データを伝達します。
  • リクエストデータは汚染されています。 PHP コードがリクエストから読み取るすべてのもの($_GET、$_POST、$_COOKIE、$_FILES、$_SERVER、php://input)は、他の PHP SAPI と同様に信頼されていません。これをサニタイズするのはアプリケーションの仕事です。

したがって、「PHP から来るものは信頼できる」というはコードについては真であり、「SAPI は信頼されていない入力を運ぶ」というのはデータについては真です。この 2 つは矛盾しません。 FrankenPHP の役割は、その汚染されたデータを忠実に運び、あるリクエストのデータが別のリクエストに漏洩するのを防ぐことです。

# FrankenPHP の責任範囲

信頼できるコンピューティングベースには 3 つの役割があります。FrankenPHP のセキュリティ上の欠陥は、そのいずれかに存在します。

  1. 忠実な転送: リクエストを PHP のスーパーグローバル変数と php://input にマッピングし、PHP の出力とヘッダーをクライアントに返送します。その際、インジェクション(ヘッダー/CRLF インジェクション、リクエスト密輸、誤ったファイルの実行)を引き起こさないようにします。
  2. 分離: リクエストスコープの状態が、リクエスト間、PHP スレッド間、およびワーカーのイテレーション間で交差するのを防ぎます。
  3. メモリ安全性: CGO 境界(Go ↔ C/PHP)をメモリを破損することなく管理します。

# 適用範囲: FrankenPHP 自身の攻撃対象領域

これらは FrankenPHP が所有する領域です。ここでの脆弱性は FrankenPHP の脆弱性となります。

  • リクエストからスーパーグローバルへのマッピング (cgi.go、frankenphp_register_server_vars):$_SERVER、REMOTE_ADDR、SCRIPT_NAME、PATH_INFO、およびその他の CGI 変数をリクエストから構築します。
  • PHP スクリプトパスの解決:リクエストパスは split_path (デフォルトでは .php) で SCRIPT_NAME / PATH_INFO に分割され、その後 sanitizedPathJoin (filepath.Join(root, filepath.Clean("/"+reqPath))) を使用してドキュメントルートに結合されます。これにより、SCRIPT_FILENAME がドキュメントルートから逸脱するのを防ぎます(パストラバーサル)。また、php_server ディレクティブは、既存のファイルまたはフロントコントローラーにリクエストをルーティングするデフォルトの try_files リライトを設定し、誤ったファイルを実行するという従来の PHP-FPM の落とし穴を軽減します。
  • ワーカーモードの状態分離:FrankenPHP は、リクエスト間で $_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() による書き込みはそのサンドボックス内に留まり、プロセスグローバルな OS 環境には決して到達しません。そのため、あるリクエストによって設定された秘密が子プロセス(proc_open、exec など)、Go/Caddy 側、または他のリクエストに漏洩することはありません。そのような変数を見る必要がある子プロセスには、proc_open() または exec() の環境引数を通じて明示的に与える必要があります(内部構造を参照)。
  • CGO メモリ境界:Go ↔ C 境界における Go 文字列のピン留めと C.CString() / free() のライフタイム。
  • Caddy 管理 API:Caddy の管理 API(デフォルトでは localhost:2019 でリッスン)を通じて公開される /frankenphp/workers/restart および /frankenphp/threads エンドポイント。このエンドポイントを localhost 以外に公開するかどうかはオペレーターの判断です。
  • 信頼されたプロキシ処理:受信する X-Forwarded-* ヘッダーは常に汚染された $_SERVER['HTTP_X_FORWARDED_*'] 値として PHP に到達します。これらは、trusted_proxies が設定されている場合にのみ、実際のクライアント IP とスキームを導出するために信頼されます。
  • 遅いリクエストボディ:ボディをアナウンスした後にデータを少量ずつ送ったり停止させたりするクライアントは、処理スレッドをその間ずっと保持します。制限されたスレッドプールでは、このような接続が十分に多くなるとプールを使い果たしてしまいます(Slow-POST DoS)。FrankenPHP は、デフォルトでボディの読み取りに 60 秒のアイドルタイムアウト(request_body_timeout)を適用します。これにより、各読み取り前にデッドラインがリセットされるため、任意のサイズの安定したアップロードは成功し、停止したものは切断されてスレッドが解放されます。

# 適用範囲外

  • アプリケーションの PHP コードの脆弱性(SQLインジェクション、XSS、安全でないデシリアライゼーションなど)。FrankenPHP は、信頼されていないリクエストデータをアプリケーションにそのまま渡します。これに対する防御は、他の SAPI と同様に、アプリケーションの責任です。
  • FrankenPHP が使用するアップストリームコンポーネントの欠陥(PHP、Caddy、Go)、またはその上に構築されたプロジェクト(Laravel Octane、Symfony Runtime)の欠陥。これらは関連するプロジェクトに報告してください。

# 脆弱性の報告

FrankenPHP に影響を与えるセキュリティ問題の報告方法については、SECURITY.md を参照してください。

このページを編集