要約

  • CGI/1.1はHTTPサーバーとスクリプトの間に共通のリクエスト/レスポンス境界を設けた一方、一部の挙動はシステムまたは実装に委ねた。
  • RFC 3875が置いたTLSの範囲はクライアントとサーバーの間である。クライアントが認証するのはサーバーであり、スクリプトには呼び出し元を確認する仕組みも、完全性が保証されたCGIメッセージも与えられない。

接続は保護されている。だが、その先にアプリケーションがいるとは限らない。

2004年のCommon Gateway Interface(CGI)Version 1.1、RFC 3875にあるのは、この目立ちにくい境界だ。ブラウザーはWebサーバーとTLS接続を確立できる。サーバーはその後、CGIプログラムへリクエストデータを渡せる。しかしRFCが描くセキュリティ関係は、二度目の受け渡しをそのまま越えていかない。ネットワーク上の相手はサーバーであり、スクリプトはその後段のアプリケーションプロセスだ。

RFC 3875が出るずっと前から、CGIは実用に供されていた。HTTPサーバーはデータベースや既存の情報システムへのゲートウェイとなり、スクリプトがリクエストに応じた応答を作る。W3Cの歴史的なCGIページは、これをゲートウェイスクリプトやプログラムを統合するためのサーバー実装者間の合意と説明する。1995年のCGI 1.1更新案、そして事実上のインターフェースをInformational RFCにまとめるため1997年11月に再開された作業も記録している。最終文書は2004年10月、Independent Streamから刊行された。

この時間差は、標準化手続きの小話というより、文書が何を記録しようとしたかを示している。CGIはすでに現場の慣行だった。RFC 3875が動的Webアプリケーションを発明したのではない。ネットワークに面したサーバーからアプリケーションプログラムへリクエストが移る際の、実装をまたぐ契約を書き留めたのだ。

その契約はREQUEST_METHOD、QUERY_STRING、CONTENT_LENGTH、PATH_INFO、REMOTE_ADDRといった「メタ変数」を定義する。スクリプトがヘッダーと本文を返す方法や、文書応答とリダイレクトも規定する。異なるサーバー上のプログラムが共通の語彙を使えるようになった。責務も分かれている。クライアント接続、データ転送、ネットワークプロトコルはサーバーが扱い、データアクセスや文書処理などのアプリケーション業務はスクリプトが担う。

この分担によって、サーバーの義務が移るわけではない。RFC 3875は、スクリプトが仕様に適合しなくても、サーバーはクライアントに対してネットワークプロトコルへ適合する責任を負い続けるとする。認証を適用するサーバーは、定められたアクセス制御を通過する前にスクリプトを実行してはならない。サーバーは透過的なパイプではなく、不正な応答や確認漏れを子プロセスのせいにできない。

第9.4節では、信頼境界がさらに明確になる。TLS接続のセキュリティモデルはクライアントとサーバーの間に適用され、クライアントとスクリプトの間には適用されない。クライアントに認証されるのはサーバーだ。スクリプトが呼び出し元サーバーを認証する仕組みは仕様にない。CGIのリクエスト/レスポンスメッセージにも、強制された完全性保護はない。

これはスクリプトを必ず敵とみなせという意味でも、運用者がローカルのプロセス境界を守れないという意味でもない。OSの権限、専用の通信路などで守ることはできる。より限定された論点は、HTTPの入口にあるTLSだけでは、後段のスクリプトが同じ認証済みネットワーク相手だとは証明できないことだ。スクリプトがHTTPS=onやユーザー名を環境変数から受け取っても、それは値を受け取ったということにすぎない。CGIインターフェースは、それらを認証済みクライアントセッションに結び付ける暗号学的証明を渡さない。

設計も一つのプロセスモデルに限定されていない。RFC 3875は、サーバーのユーザーとグループで動く子プロセスを最も一般的な実装として記述する一方、サーバーにリンクされたスクリプトも認める。「system-defined」と「implementation-defined」の挙動も分けている。共通インターフェースはサーバー間で使えても、移植性には限りがあった。

Apacheのmod_cgi文書は一つの実装例であって、Web全体の調査ではない。handlerやScriptAliasによるスクリプトの選択と、その出力をクライアントへ返す流れを示している。受け渡しを理解する助けにはなるが、TLSの終点についてのRFCの記述を変えるものでも、すべてのサーバーの設定を示すものでもない。

CGIの歴史的な功績は、共通の受け渡し境界を作ったことだ。共通プロセスやエンドツーエンドのセキュリティチャネルを作ったわけではない。サーバーとスクリプトは名前の付いたインターフェースを介して協調しながら、異なる責務を持つ別々の主体であり続ける。この読み方なら、カテゴリーの取り違えを避けられる。ブラウザーとサーバーの保護されたリクエストが、ブラウザーとアプリケーションの保護された関係になるとは限らない。RFC 3875は分離を明示したが、なくしたわけではない。

出典