要約
- CGIはHTTPヘッダーをUnixの環境変数へ移せた。脆弱なBashは関数らしい値を読み込み、関数の終端より後ろの文字列までコマンドとして処理し得た。
- 遠隔露出には、外部入力、環境への格納、Bashの起動という全経路が必要であり、「Bashがある」ことだけでは判定できない。
- 最初の修正は不完全だった。更新版の導入に加え、環境継承と不要なシェル呼び出しを減らし、古い状態を持つプロセスを更新した証拠が必要だった。
HTTPヘッダーは要求を説明する。環境変数はプロセスの文脈を伝える。関数定義はコードである。Shellshockでは、この三つの役割が短い経路の上で混ざった。
RFC 3875はCGIの変換を明記している。HTTPの要求ヘッダーはHTTP_で始まるメタ変数になり、Unixでは同名の環境変数としてスクリプトへ渡される。ここまでは設計されたデータ搬送であって、単独でコマンドを実行する仕組みではない。
一方、Bashには関数を別のBashプロセスへ輸出する機能があった。旧方式は関数定義を環境値に格納する。脆弱な版は起動時に関数の形を認識した後、定義が終わっても解析を止めない場合があり、後続文字列を命令として扱った。
したがって経路は、リモートヘッダー、CGIメタ変数、継承環境、Bash起動、関数取り込み、命令実行となる。一つでも欠ければ同じ遠隔経路は成立しない。CERT/CCとRed HatがCGI、限定コマンド用SSH設定、一部のDHCPクライアント処理を例示したのはこのためだ。同じパッケージを持つ二台でも、呼び出し構造が違えば露出は違う。
CVE-2014-6271は2014年9月24日に公開された。CERT/CCは翌日に脆弱性ノートを出し、実際の悪用を記録した。ところが最初の修正は全挙動を閉じず、Red Hatは26日に不完全だと告知した。残った問題にはCVE-2014-7169が割り当てられ、近接する解析問題も別の識別子を得た。「更新済み」という一語だけでは、どのパッケージとどの試験結果を指すのか分からなかった。
重要な修正は、既知の末尾文字列を塞ぐだけでなく、取り込み契約を狭くしたことにある。修正版では、輸出関数をBASH_FUNC_名前()のような識別可能な名前空間へ移した。互換性上の負担はあったが、通常の環境データと実行可能な宣言の区別を明確にした。
ディスク上の更新だけでは生きた状態は変わり切らない。Red Hatは、輸出関数を使うサービスの再起動を推奨し、ユーザーの再ログインやscreen、tmuxセッションの更新が必要になり得るとした。必要なのは、要求を実際に処理する実行ファイル、親プロセス、環境を観測することだった。
運用は呼び出し図から始めるべきだった。どの公開サービスが環境を作り、どの補助処理がBashを呼び、どのアカウントで動くのか。更新前から生きる親プロセスは何か。修正までの間、現場の所有者は不要なCGIを止め、境界で環境を洗浄し、シェルのラッパーを直接実行へ替えられなければならない。
Shellshockの教訓は環境変数を全面否定することではない。ある層のデータが、次の層でいつ「動詞」を得るのかを管理することだ。見た目だけでコードになるなら、権限はすでに深く隠れすぎている。
情報源
会員向け解説
プロフィールの詳細
適切な会員レベルでログインすると、解説全文と出典メモをご覧いただけます。
Strategic Circle 限定
Strategic Circle
すべての読者に公開されています。参加してログインすると プロフィール解説 を閲覧できます。
Strategic Circle に参加Leadership Alliance 会員限定
Leadership Alliance
対象となる IP 資産の所有者・管理者向けです。ログインすると Leadership Alliance の解説を閲覧できます。
Leadership Alliance に参加