この文書は2016年以降更新されていません
未検証のリダイレクトと転送に関するチートシート
最終改訂日 (yy/mm/dd):2014/08/21 はじめに未検証のリダイレクトと転送は、Web アプリケーションが、信頼されていない入力を受け入れて、入力内に含まれる URL にリクエストをリダイレクトすることで発生します。信頼されていない URL 入力を有害なサイトに変更することによって、攻撃者はフィッシングを行ったり、ユーザーの認証情報を取得したりします。変更されたリンク内のサーバー名は元のサイトとまったく同じであるため、フィッシングの企みは見た目にはわからず、あたかも信頼されたサイトのように見えることがあります。また、未検証のリダイレクト / 転送攻撃は、アプリケーションのアクセス制限を回避して、通常ならアクセス不可能な特権機能へのアクセスを許してしまう有害な URL を作成する目的でも使用されます。 安全な URL リダイレクトユーザーを別のページに自動的に (ハイパーリンクのクリックなどのアクションをユーザーが行うことなく) リダイレクトさせたい場合は、たとえば次のようなコードを実装します。 Java response.sendRedirect("http://www.mysite.com"); PHP <?php /* ブラウザーのリダイレクト */ header("Location: http://www.mysite.com/"); ?> ASP.NET Response.Redirect("~/folder/Login.aspx") Rails redirect_to login_path 上の例では、コード内で URL が明示的に宣言されており、攻撃者が操作することはできません。 危険な URL リダイレクト以下の例では、安全でないリダイレクトおよび転送コードを示します。 危険な URL リダイレクトの例 1次の Java コードは、GET の "url" パラメーターから URL を取得して、その URL にリダイレクトします。 response.sendRedirect(request.getParameter("url")); 次の PHP コードは、クエリ文字列から URL を取得して、その URL にユーザーをリダイレクトします。 $redirect_url = $_GET['url']; header("Location: " . $redirect_url); 同様のことを行う C# .NET での脆弱なコードの例: string url = request.QueryString["url"]; Response.Redirect(url); Rails の例: redirect_to params[:url] 入力値検証や他の方法によるURL の安全性確認を行わなければ、上記のコードは攻撃に対して脆弱なものとなります。フィッシング詐欺において、この脆弱性はユーザーを有害なサイトにリダイレクトすることに悪用される可能性があります。URL の検証を行っていない場合、例えば次のようなハイパーリンクを作ることで、ユーザーを有害な Web サイトにリダイレクトさせることが可能です。 http://example.com/example.php?url=http://malicious.example.com 画面上に表示されるのは信頼された元のサイト (example.com) を示すリンクであるため、このようなリダイレクトが実行されるおそれがあることにユーザーは気付きません。 危険な URL リダイレクトの例 2ASP.NET MVC 1 および 2 の Web サイトは特に、オープンリダイレクト攻撃に対して脆弱です。この脆弱性を回避するには、MVC 3 を適用する必要があります。 ASP.NET MVC 2 アプリケーションでの LogOn アクションのコードを以下に示します。ログインに成功すると、コントローラーは returnUrl へのリダイレクトを返します。このコードでは、returnUrl パラメーターに対する検証が何も行われていません。 リスト 1: AccountController.cs での ASP.NET MVC 2 の LogOn アクション [HttpPost] public ActionResult LogOn(LogOnModel model, string returnUrl) { if (ModelState.IsValid) { if (MembershipService.ValidateUser(model.UserName, model.Password)) { FormsService.SignIn(model.UserName, model.RememberMe); if (!String.IsNullOrEmpty(returnUrl)) { return Redirect(returnUrl); } else { return RedirectToAction("Index", "Home"); } } else { ModelState.AddModelError("", "The user name or password provided is incorrect. (ユーザー名またはパスワードが正しくありません。)"); } } // ここまで来たら、何かエラーが起きているので、フォームを再表示する return View(model); } 危険な転送の例FIXME: この例は誤っています。forward() の呼び出しさえ行っていません。 この例の場合、(たとえば) ある URL へのアクセスを阻止するための security-constraint が web.xml に含まれているべきです。 そして、アプリケーション内からのその URL への転送を行うことでその制約がバイパスされてしまうという例にするのがよいでしょう。 アプリケーションにおいて、ユーザー入力に基づくサイト内の他の部分間へのリクエストの転送が可能になっている場合、当該 URL へのアクセスおよび URL が提供する機能の実行がユーザーに認可されているか、およびURL リクエストは適切なものかのチェックをアプリケーションで実行する必要があります。アプリケーションでこれらのチェックが実行されない場合、攻撃者が作成した URL がアプリケーションのアクセス制御を通過し、その結果、通常なら許可されない管理機能に攻撃者を転送してしまうおそれがあります。 http://www.example.com/function.jsp?fwd=admin.jsp 次に示す Java サーブレットのコードは、ブラウザーのリダイレクト先のアドレスを指定した url パラメーターを持つ GET リクエストを受け取ります。リクエストから url パラメーター値を取得し、その URL アドレスにブラウザーをリダイレクトするレスポンスを送信します。 public class RedirectServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String query = request.getQueryString(); if (query.contains("url")) { String url = request.getParameter("url"); response.sendRedirect(url); } } } 未検証のリダイレクトと転送の防止リダイレクトと転送を安全に使用するには、以下の方法があります。
参考資料
Authors and Primary EditorsSusanna Bezold - susanna.bezold[at]owasp.org Other CheatsheetsDeveloper Cheat Sheets (Builder)
Assessment Cheat Sheets (Breaker)
Mobile Cheat Sheets OpSec Cheat Sheets (Defender) Draft Cheat Sheets
|