オープンリダイレクトとは、Webアプリケーションが検証されていないユーザー入力、通常は ?next= や ?url= のようなクエリパラメータから目的地URLを取得し、チェックせずにブラウザをそこへ転送してしまう脆弱性です。リンクは被害者が信頼するドメインから始まるため検査を通過し、それから静かに別の場所へ着地させます。修正はリダイレクトをやめることではありません。リダイレクトの行き先をリクエストに決めさせるのをやめることです。
この区別が重要なのは、リダイレクトはどこにでもあり、そのほとんどは問題ないからです。ログインして欲しかったページに戻る、決済プロバイダーへ引き渡す、OAuth コールバック。すべて普通のことで、すべてリダイレクトです。CWE-601 として記載され、OWASP Top 10 のアクセス制御の不備の下にまとめられているこのバグは、ターゲットがユーザー支配下の入力から来て、それを最初に検証するものが何もない場合に特定されます。攻撃者が自分のURLを供給し、信頼されたサイトがそこへ転送し、クリックとともに信頼が転移するのです。
私は日々リダイレクトの経路に取り組んでいるので、これは意見を持っているテーマです。短縮リンクは定義上リダイレクトであり、そのため「短縮サービスは単なるオープンリダイレクトなのか?」は正当な問いです。そして正しくやれば、答えは明快にノーです。それは後述します。リダイレクトの仕組みがまだ馴染みのないものなら、リダイレクトの種類が入門書になり、URL短縮サービスの仕組みがリダイレクト層の基本をカバーします。
オープンリダイレクトとは実際には何か#
仕組みまで削ぎ落としましょう。あるページが次にどこへ行くかを指定するパラメータを受け取り、それが許可された場所を指しているか確認せずに HTTP リダイレクトに使う、というものです。
https://trusted.example/login?next=https://evil.example/fake-login
被害者は先頭の trusted.example を見てクリックします。ログイン後、アプリは next を読み取り、evil.example へのリダイレクトを発行します。ブラウザは従います。リダイレクトは単なる Location ヘッダーと 3xx ステータスにすぎないからです。HTTP の仕様はその挙動を明白に定義しており、ブラウザにはこの特定のターゲットが敵対的だと知る術がありません。すでにリンクを信頼した後でアドレスバーが変わるのを見ているユーザーは、しばしば気づきません。
OWASP は中心的な危険をあっさりこう述べています。改変されたリンク内のサーバー名が元のサイトと同一であるため、悪意あるリダイレクトに信憑性を与えてしまう、と。脆弱性はサイトがリダイレクトすることではありません。部外者が目的地を選んだことです。
なぜ「無害な」リダイレクトが本当の脅威なのか#
つい肩をすくめたくなります。誰かを別のWebサイトに送るだけ、何が害なのか、と。害は借りた信頼であり、それは規模を拡大します。
フィッシングが代表的な用途です。銀行、SaaS のログイン、政府ポータルで始まるリンクは、ほとんどの人が行う素早い目視チェックをすり抜け、先頭ドメインしか検査しない驚くほど多くの自動フィルターもすり抜けます。被害者は、期待していたログインページのピクセル単位で完璧な偽物に、1ホップ前には正しく見えたドメイン上で到着し、パスワードを入力します。マルウェアもなく、風変わりなペイロードもなく、ただリダイレクトと複製があるだけです。
リダイレクトが認証の近くにあると、さらに悪化します。OAuth フローのオープンリダイレクトは、攻撃者の支配下にある redirect_uri へ認可コードやトークンを漏洩させ、「軽微な」バグを完全なアカウント乗っ取りへとエスカレートさせます。だからオープンリダイレクトは脚注ではなく、バグバウンティ報告の定番なのです。同じ手口は評判の洗浄にも使われます。スパマーやマルウェア運用者は信頼されたドメインを経由するのが大好きです。それで本物のリンクをブロックリストの先へ通せるからです。より広いカテゴリはURL短縮サービスのセキュリティチェックリストでカバーし、訪問者側から見た信頼の観点はURL短縮サービスは安全かでカバーしています。
オープンリダイレクトを防ぐ方法#
修正には階層があり、その頂点にあるものが実際に問題を終わらせるものです。OWASP のチートシートはそれらをランク付けしており、その順序に従う価値があります。
- URLをリクエストから一切受け取らない。 クライアントには短い名前、ID、トークンを送らせ、それをサーバー側で完全な目的地に解決します。OWASP はこれを最高度の保護と呼びます。受信リクエストがもはや任意のターゲットを指定できなくなるからです。そのパターンに聞き覚えがあるなら、当然です。URL短縮サービスの仕組みそのものだからです。
- 拒否リストではなく許可リストを使う。 目的地を受け取らなければならないときは、信頼されたホストのリストか厳密な正規表現に対して照合します。許可リストはフェイルクローズです。明示的に許可されていないものはすべて拒否されます。拒否リストはフェイルオープンで、攻撃者はあなたが忘れた項目を見つける報酬をもらっているのです。
- 厳密にパースする。 プロトコル相対URL(
//evil.example)を拒否し、バックスラッシュを正規化し、検証する前にデコードし、文字列のプレフィックスだけでなくホストをチェック対象として扱います。フィルター回避のほとんどは、いいかげんなパースの中に潜んでいます。 - 最後の砦として中間ページを表示する。 外部サイトへのリダイレクトが避けられない場合、目的地を明示してユーザーに確認を求めるページを経由させます。摩擦ではありますが、静かなリダイレクトを情報を伴ったものに変えます。
繰り返し現れるテーマは、安全なリダイレクトはサーバーが、サーバーがすでに信頼しているデータから決めるものであって、クエリで届いたどんな文字列によってでもない、ということです。
製品にリダイレクトを組み込んでいて、この失敗モードを自分で抱えたくないなら、Elido の開発者プラットフォームは設計上、コードを目的地にサーバー側で対応づけます。API クイックスタートから始めて、二度と ?url= パラメータを手作りしないでください。
なぜ短縮リンクはバグではなく防御なのか#
ここが人々を驚かせる部分です。正しく構築された URL短縮サービスは、OWASP のオープンリダイレクト修正の第一位の教科書的な実装です。
短縮リンクが作成されるとき、その目的地は検証され、サーバー側に保存され、短いコードに紐づけられます。誰かが訪れると、リダイレクト層はそのコードを検索し、保存されたターゲットへ転送します。目的地は決して受信リクエストから来ません。訪問者は ?url= を付け足してリンクをよそへねじ曲げることができません。ねじ曲げるためのそのパラメータが存在しないからです。それこそ OWASP が推奨するトークンからURLへのマッピングそのものであり、本番環境で1日に何百万回も稼働しています。アーキテクチャ上これは私たちのエッジリダイレクト層に存在し、それが支払う遅延予算はリダイレクトで p95 を 15ms 未満に抑えるの主題です。
正直な注意点として、短縮サービスは依然として悪用されえます。ただし、オープンリダイレクト経由ではありません。プラットフォームが誰にでもスキャンやモデレーションなしで何でもリンクを作らせてしまうと、攻撃者はそのドメイン評判を使って自分の悪意ある目的地を覆い隠します。だから責任ある短縮サービスはターゲットをスキャンし、悪用ポリシーを強制するのです。これはコンテンツモデレーションの問題であり、この記事が扱っている入力検証の欠陥とは別物で、混同しない価値があります。目的地を意図的に隠すという関連する手法はリンククローキングとURLマスキングの解説でカバーし、これらすべてのソーシャルエンジニアリングの従兄弟、つまり敵対的なQRコードはQRコードは安全かでカバーしています。
一行のまとめ#
あなたのコードがリクエストから目的地を読み取ってそこへリダイレクトしているなら、見つかるのを待っているオープンリダイレクトを抱えています。代わりに ID をサーバー側のターゲットに対応づけ、入力から取らざるをえないものは許可リストで管理し、攻撃されることを予期してパースしてください。リスクはリダイレクトではありません。行き先をリクエストに選ばせることです。301 と 302 のリダイレクトにおける 301 と 302 の違いは、その1つのルールの隣では脚注にすぎません。
ブログの関連記事#
Elidoを試す
URLを貼り付けて短縮リンクを取得
登録不要。リンクは30日間有効。永久に保存するには登録してください。
Free、登録不要 · 1日あたり2件