ダチョウ式リダイレクトと名付けてみる修行

ダチョウ式リダイレクト
リダイレクトさせているつもりが後段の処理も走ってしまう

概要

WEB アプリケーションにおいて、ステータスコード 302 を返してリダイレクトさせているつもりだが、即座にレスポンスを戻さないので、実際には後段の処理も動作してしまっている現象。そのようなコード。
ダチョウのように head だけ対処して body への対処を怠っていることから命名

症例

PHP において、header("Location: xxx") 直後に exit() しないことで発生しやすい。header("Location: xxx") のあと、普通に処理が実行されるが、最終的な HTTP レスポンスのステータスコードは 302 Found になり、Location: ヘッダもつくので、ブラウザは普通にリダイレクト処理を行う。
したがって、ブラウザで普通にアクセスしている限り、この問題が発生していることに気づかない。実際には HTTP レスポンスボディに、処理結果が入っている。

弊害

プログラムの設計者は、header () 関数以降は処理が走っていないと考えていると推測される。それが覆されるので、さまざまな問題が発生しうる。

  • 認証を通っていない人による情報の参照、更新。(ログインチェック失敗時にリダイレクトさせている場合)
  • HTTPS で暗号化されないデータの送受信。(HTTP リクエストを HTTPS にリダイレクトさせている場合)

処方

PHP の header 関数は「ブラウザにリダイレクトさせる機能」ではない。単に HTTP レスポンスヘッダに値を挿入しているだけと肝に銘ずべし。

新規にコードを書く際は、header 挿入後に exit() してしまうのが確実か。MVC 的な仕組みにし、モデルは「コンテンツを返すか、リダイレクトすべきか」の結果を返し、コントローラが実際にさばく、という設計にすることでも確実性は高まる。

新たに対処する場合は、かまわず exit() 処理をして、デグレがないか調査するのがいいかもしれない。ブラウザで見ているだけではテストにならないので注意。

追記 2009-08-09

行儀のよさ

RFC 的には 302 を返す場合、レスポンスボディにリンクを提示するべき (SHOULD)。RFC2616 http://www.ietf.org/rfc/rfc2616.txt の「10.3.3 302 Found」から引用。

   The temporary URI SHOULD be given by the Location field in the
   response. Unless the request method was HEAD, the entity of the
   response SHOULD contain a short hypertext note with a hyperlink to
   the new URI(s).
ダチョウ狩

ダチョウ式リダイレクトに対する理解を深める一助になるよう、例示できるネット上のダチョウ式リダイレクトを集めている。最近のダチョウ狩の成果は↓。

より認知されている名前

CWE - CWE-698: Execution After Redirect (EAR) (3.2)