CyberFix Note
セキュアコーディング

オープンリダイレクトの仕組みと対策。信頼済みドメインが踏み台になる欠陥を塞ぐ

対象の目安: Webアプリ開発・実務

ソウ攻撃・脆弱性リサーチ担当
・ 約12分で読めます
オープンリダイレクトの仕組みと対策。信頼済みドメインが踏み台になる欠陥を塞ぐ

ログイン後の画面へ戻す遷移先や、外部サイトへの案内リンクを、クエリパラメータで受け取る実装はよく使われます。このとき受け取った値をそのままリダイレクト先に使うと、自分のドメインを踏み台にして利用者を任意の外部サイトへ飛ばせてしまいます。これがオープンリダイレクト(CWE-601)です。単体では利用者を別サイトへ送るだけの小さな欠陥に見えますが、リンクの見かけ上のドメインが正規のまま実際の遷移先だけが攻撃者のサイトになるため、フィッシングやOAuthの認可コード窃取の足場として悪用価値が高い欠陥です。

この記事はWebアプリの開発者を対象に、オープンリダイレクトが成立する機構と、許可リストを中心にした正しい防御設計を整理します。攻撃を再現する具体的なペイロードは示しません。挙動を確かめる検証は、自分が管理するアプリか、明示的に許可されたアプリに対してのみ行う前提です。記述はOWASPの資料とMITRE CWE、OAuthのセキュリティ最新ベストプラクティスを定めるRFC 9700にもとづきます。

オープンリダイレクトとは何か

オープンリダイレクトは、アプリが利用者から受け取った入力値を検証せずにリダイレクト先の生成に使うことで生じます。遷移先を指定するクエリパラメータとして、?url= や ?next= 、?returnUrl= 、?redirect= といった名前がよく使われます。こうしたパラメータに外部サイトのURLを入れられると、アプリはその値をそのまま遷移先として扱い、利用者を任意のサイトへ送ってしまいます。

MITREはこの欠陥をCWE-601(URL Redirection to Untrusted Site)として整理しています。OWASPでは同じ問題をUnvalidated Redirects and Forwardsと呼び、遷移先を利用者入力で決める設計そのものに注意を促しています。遷移先を選ばせる機能自体は正当でも、入力値を無検証で信頼する点が欠陥の本体です。

こうした遷移先パラメータは、ログイン後に元の画面へ戻す処理や、決済や外部サービスとの連携から戻ってくる導線など、利便性を高める場面で自然に登場します。機能として悪いわけではなく、受け取った値を検証せずに信頼してしまう実装だけが問題になります。そのため、パラメータをなくすことより、値の扱い方を正すことが対策の主眼になります。

MITRE CWE-601は、Webアプリが信頼できない入力を使って別サイトへのリンクを生成し、その入力を検証しないことでフィッシング等に悪用されうる状態をURL Redirection to Untrusted Site(Open Redirect)と定義しています。

サーバ側とクライアント側の二つの経路

オープンリダイレクトが成立する経路は、大きく二つに分かれます。実装を点検するときは、この二経路を分けて確認すると漏れが減ります。

一つはサーバ側リダイレクトです。サーバがHTTPレスポンスのLocationヘッダに利用者入力をそのまま入れ、302などのステータスコードで遷移を指示する形です。入力値がヘッダに直接反映されるため、外部URLを指定されればブラウザはその宛先へ移動します。

もう一つはクライアント側、いわゆるDOMベースのリダイレクトです。ブラウザ上のJavaScriptが利用者入力を location.href や location.assign 、location.replace に渡したり、meta refreshの遷移先に使ったりする形です。サーバのレスポンスヘッダには痕跡が残らず、コードの実行時に遷移先が決まるため、サーバ側のログだけを見ても気づきにくい特徴があります。OWASPのテストガイドは、この経路を独立した検証項目として扱っています。

OWASP WSTGのTesting for Client-side URL Redirectは、利用者が制御できる入力がlocationやwindow.locationなどに渡ることでクライアント側のリダイレクトが起こる点を挙げ、DOMベースのリダイレクト経路をサーバ側とは別に検証するよう示しています。

フィッシングで悪用される理由

オープンリダイレクトがフィッシングで重宝されるのは、リンクの見かけ上のドメインが正規のまま保たれるからです。攻撃者は、信頼されている正規サイトのURLに遷移先パラメータを付けたリンクを配ります。リンクのホスト部分は正規ドメインなので、受け取った利用者や、送信元ドメインで信頼度を測るメールフィルタは、そのリンクを安全なものとみなしやすくなります。

ところがリンクをたどると、正規サイトを経由したうえで最終的に攻撃者のサイトへ着地します。着地先が正規サイトそっくりの資格情報入力ページであれば、利用者は正規ドメインから案内されたという安心感のまま情報を入力してしまいます。オープンリダイレクトが単体では小さく見えても軽視できないのは、こうして信頼済みドメインの評判を借りて誘導の成功率を押し上げる足場になるためです。フィッシングの手口と利用者側の見分け方は次の記事で整理しています。

あわせて読みたい

フィッシングの手口と対策の基本。個人と組織でできることを徹底解説

OAuthとリダイレクト先の検証

OAuthやOIDCでは、認可サーバが処理の結果を戻す宛先としてredirect_uriを使います。ここに登録済みのホストを指定する仕組みのため、そのホスト上にオープンリダイレクトがあると、認可の流れを正規のredirect_uri経由で開始しつつ、途中のオープンリダイレクトで最終的な着地先を攻撃者のサイトへずらせてしまいます。この経路で認可コードやトークンが攻撃者へ渡ると、利用者になりすましてリソースへアクセスされる恐れがあります。

このため、OAuth 2.0のセキュリティ最新ベストプラクティスを定めるRFC 9700は、認可サーバがredirect_uriを完全一致(exact match)の許可リストで照合するよう求めています。前方一致や部分一致による照合は、余地を突かれて別の宛先を通されうるため認められません。登録済みホスト側のアプリにオープンリダイレクトを残さないことも、この防御を実効あるものにする前提になります。OAuthとOIDCの基本的な仕組みは次の記事で整理しています。

RFC 9700(OAuth 2.0 Security Best Current Practice)は、認可サーバがリクエストのredirect_uriを事前登録された値と単純な文字列比較による完全一致で照合すべきとし、パターンマッチングによる照合を避けるよう求めています。

あわせて読みたい

OAuth 2.0とOpenID Connectの基礎。認可と認証の違いを仕組みから整理する

ブロックリストが破られる理由

危険そうな文字列を弾くブロックリスト方式でオープンリダイレクトを防ごうとすると、URL構文の多様さに追いつけず回避されやすくなります。URLには判定を誤らせる要素が多く、代表的なものだけでも次のとおりです。

スキーム相対の形は、先頭が // で始まりホスト名が続きます。これはブラウザには絶対URLとして解釈されますが、相対パスと見分けにくく、素朴なチェックをすり抜けがちです。userinfo部を使う形は、ホスト名の前に @ を挟み、@ の前を利用者情報として、後ろを実際の接続先ホストとして解釈させます。信頼ドメインが文字列の中に見えても、実際の宛先は別ホストになりえます。類似ドメインは、信頼ドメインを部分文字列として含む別のドメインで、単純な部分一致判定を通過します。さらにバックスラッシュや空白、各種のエンコード表現、パーサ間の解釈差なども、検証側と実際に遷移するブラウザとで解釈をずらす材料になります。

これらはURLの正規の構文や表記の揺れであって、特殊な細工とは限りません。危険な文字列を列挙して弾くという発想は、こうした表記の組み合わせを網羅できないため、原理的に取りこぼしを生みます。防御は許可したものだけを通す方向で組むのが基本です。

OWASPのUnvalidated Redirects and Forwards Cheat Sheetは、リダイレクト先を利用者入力で決めることを避け、必要な場合は許可された値のリストと照合するアプローチを推奨し、ブロックリストではなく許可リストで防ぐ設計を示しています。

正しい防御設計

OWASPのCheat Sheetにもとづくと、防御は許可リストを軸に段階的に組み立てられます。中心にあるのは、利用者入力をそのまま遷移先URLにしないという考え方です。

  1. 1

    可能な限り利用者入力に基づくリダイレクト自体を避ける。設計で遷移先を固定できないか先に検討する

  2. 2

    遷移先を選ばせる必要があるなら入力値をURLにせずIDやトークンで受け取り、サーバ側で既知のURLへ対応付ける間接参照にする

  3. 3

    外部への遷移が必要な場合はURLを標準ライブラリでパースし、ホスト名を信頼ドメインの厳格な許可リストと照合する

  4. 4

    内部遷移は同一オリジンに限定し、相対パスのみ許可して絶対URLやスキーム相対(//)を拒否する。照合の前に正規化する

  5. 5

    外部URLへ飛ばす場合は遷移先の完全なURLを見せる中間の警告ページを挟み、利用者が着地先を判断できるようにする

  6. 6

    OAuthを扱う場合はredirect_uriを完全一致の許可リストで検証する(RFC 9700)

間接参照は、遷移先の候補をサーバ側で持ち、利用者にはその識別子だけを渡す設計です。攻撃者が任意のURLを差し込む余地がなくなるため、最も確実な防ぎ方になります。許可リスト照合では、文字列マッチではなく標準のURLパーサでホスト名を取り出し、正規化したうえで許可ドメインと突き合わせます。内部遷移で相対パスのみ許可する場合も、// で始まる値がスキーム相対として外部へ抜けないよう、正規化と拒否条件を明確にしておきます。

警告ページを挟む手当ては、許可リストで機械的に判断しきれない外部遷移を残す場合の補完です。遷移先の完全なURLを明示し、利用者自身が着地先を確かめてから進める余地を作ります。これは許可リストの代わりではなく、許可リストを主とした設計にもう一段の判断機会を足す位置づけです。実装を点検するときは、サーバ側とクライアント側のどちらの経路にも同じ許可リストの考え方を通しているかを確かめます。

SSRFとの違い

オープンリダイレクトと混同されやすい欠陥にSSRF(Server-Side Request Forgery)があります。両者の違いは、誰がどこへ向かうかにあります。SSRFはサーバ自身が任意の宛先へリクエストを送ってしまう欠陥で、内部ネットワークやメタデータエンドポイントへの到達が問題になります。一方のオープンリダイレクトは、利用者のブラウザを任意の外部サイトへ飛ばす欠陥です。送るのがサーバか、飛ばされるのが利用者のブラウザかという主体の違いで整理すると区別しやすくなります。SSRFの仕組みは次の記事で整理しています。

あわせて読みたい

SSRFとは何か。サーバーを踏み台にする脆弱性の仕組みと許可リスト方式の防御を解説

実装チェックリスト

リダイレクトを扱うコードを点検するときの確認項目を整理します。

  • 利用者入力に基づくリダイレクトを、そもそも避けられないか検討したか
  • 遷移先を選ばせる箇所を、IDやトークンによる間接参照に置き換えたか
  • 外部URLへ遷移する箇所で、標準ライブラリのパーサでホスト名を取り出しているか
  • ホスト名を信頼ドメインの許可リストと照合し、文字列マッチやブロックリストに頼っていないか
  • 内部遷移を同一オリジンに限定し、絶対URLやスキーム相対(//)を拒否しているか
  • 照合の前に入力値を正規化しているか
  • 外部への遷移時に、完全なURLを見せる警告ページを挟んでいるか
  • サーバ側(Locationヘッダ)とクライアント側(location操作やmeta refresh)の両経路を確認したか
  • OAuthのredirect_uriを完全一致の許可リストで検証しているか

オープンリダイレクトは、遷移先を利用者入力で決めるという正当に見える設計の中に潜み、信頼済みドメインの評判を借りてフィッシングやトークン窃取の足場になります。防ぐ要点は、危険な値を弾く発想から、許可したものだけを通す発想へ切り替えることです。間接参照とホスト名の厳格な許可リスト照合を軸に据えれば、URL構文の揺れに振り回されずに塞げます。Webアプリ全体で優先して対処すべき欠陥の位置づけは次の記事で整理しています。

あわせて読みたい

OWASP Top 10とは。開発者が押さえるべきWebの代表的リスクと対策を一気に理解する

出典・参考

この記事をシェア

関連する記事