この文書は2016年以降更新されていません

未検証のリダイレクトと転送に関するチートシート

OWASP 作成
ジャンプ先: 移動検索
Cheatsheets-header.jpg

最終改訂日 (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 リダイレクトの例 2

ASP.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);
       }
     }
   }

未検証のリダイレクトと転送の防止

リダイレクトと転送を安全に使用するには、以下の方法があります。

  • まず、リダイレクトと転送の使用は避けましょう。
  • もし使用する場合は、ユーザー入力をそのまま使って移動先 URL を決定しないこと。ユーザー入力を使って URL を決定する場合、URL を検証する方法を備えていなければなりません。
  • ユーザー入力が避けられない場合、提供されたが有効かつアプリケーションにとって適切なものであることを確認するとともに、その URL への移動がユーザーに認可されていることも確認します。
  • 移動先入力は、実際の URL または URL の一部を指定させるのではなく、サーバー側で実際の移動先 URL へ翻訳するための識別値にすることを推奨します。
  • 信頼された URL のリスト (ホストのリストまたは正規表現) を作成することによって、入力をサニタイズします。
  • すべてのリダイレクトに対して、サイトから離れることをユーザーに通知するページを最初に通過するように強制します。ユーザーには、このページで通知確認のリンクをクリックさせます。

参考資料

  1. オープンリダイレクトに関する OWASP の記事 https://www.owasp.org/index.php/Open_redirect
  2. オープンリダイレクトに関する CWE エントリ 601 http://cwe.mitre.org/data/definitions/601.html
  3. URL リダイレクターの悪用に関する WASC の記事 http://projects.webappsec.org/w/page/13246981/URL%20Redirector%20Abuse
  4. オープンリダイレクトの危険性に関する Google ブログ記事 http://googlewebmastercentral.blogspot.com/2009/01/open-redirect-urls-is-your-site-being.html
  5. Preventing Open Redirection Attacks (C#) http://www.asp.net/mvc/tutorials/security/preventing-open-redirection-attacks

Authors and Primary Editors

Susanna Bezold - susanna.bezold[at]owasp.org
Johanna Curiel - johanna.curiel[at]owasp.org
Jim Manico - jim[at]owasp.org

Other Cheatsheets

Developer Cheat Sheets (Builder)

Assessment Cheat Sheets (Breaker)

Mobile Cheat Sheets

OpSec Cheat Sheets (Defender)

Draft Cheat Sheets