【入門編】OAuth 2.0のOpen Redirect脆弱性とredirect_uriの厳密なバリデーション – アプリケーションセキュリティ & 安全な開発防御ガイド

「ログインしたはずが、怪しいサイトへ…?」OAuth 2.0の落とし穴と、正しい鍵の作り方

こんにちは!セキュリティの世界へようこそ。
皆さんは普段、Webサイトで「Googleでログイン」や「Twitter(X)でログイン」といったボタンをよく見かけませんか?あれは「OAuth 2.0(オーオース)」という仕組みのおかげで、IDやパスワードを毎回入力しなくても安全にサービスを使える便利な技術です。

しかし、この便利な仕組みには「泥棒があなたの家を乗っ取るための、ちょっとした抜け穴」が隠されていることがあります。今回は、特に開発現場でうっかり放置されがちな「Open Redirect(オープンリダイレクト)」という脆弱性について、一緒に紐解いていきましょう。

そもそも「Open Redirect」って何?

家の鍵に例えてみましょう。
あなたは家の玄関(認可サーバー)で「この人はうちの住人だ!」と確認が終わった後、本来なら「リビング(元のアプリ画面)」へ案内されるべきですよね。

ところが、悪い泥棒が玄関の案内係を騙して、「確認が終わったら、裏口の怪しい倉庫へ案内してやってくれ」と指示を書き換えてしまったらどうなるでしょうか?

これが「Open Redirect」です。
ユーザーは「ログインできた!」と安心している間に、実は攻撃者が用意した偽のフィッシングサイトや、ウイルスを撒き散らすサイトへ勝手に飛ばされてしまうのです。

なぜこの攻撃は起きてしまうのか?

OAuthの仕組みの中には `redirect_uri` というパラメーターがあります。これは、「ログインが終わったら、どのURLに戻ればいい?」という目的地を指示するものです。

もし、サーバー側がこの `redirect_uri` を「送られてきた通りに信じ込んで」そのままリダイレクトさせてしまうと、泥棒の言いなりになってしまうわけです。

攻撃の仕組み(イメージ)

1. 攻撃者: 「ログイン後に `https://malicious-site.com`(悪意のあるサイト)へ飛ばすようなリンク」を仕込む。
2. ユーザー: そのリンクをクリックしてログイン。
3. サーバー: 「よし、ログイン成功!指示通り `https://malicious-site.com` へ案内しよう」と、ユーザーを追い出してしまう。

対策:ホワイトリストで「行き先」を制限しよう

では、どうすれば防げるのでしょうか?
答えは簡単です。「信頼できる場所リスト(ホワイトリスト)」を作っておくことです。

「案内係(サーバー)」にこう教えてあげてください。
「ログイン後の行き先は、うちのサイトの特定のページだけだよ。それ以外は絶対案内しちゃダメだぞ!」

実装のポイント:厳密な比較を行う

よくある間違いは「URLの中に自分のサイト名が含まれていればOK」としてしまうことです。これだと `https://my-app.com.attacker.com` のような偽URLを許してしまいます。

必ず「完全一致」でチェックしましょう。

コード例(概念的な実装)

// 許可されたリダイレクト先のリスト
const WHITELIST_REDIRECT_URIS = [
“https://myapp.com/callback”,
“https://myapp.com/dashboard”
];

function validateRedirectUri(requestedUri) {
// 1. リストの中に、送られてきたURLが完全に一致するものがあるか?
// 2. 「部分一致」ではなく「完全一致」で判定するのが鉄則です!
if (WHITELIST_REDIRECT_URIS.includes(requestedUri)) {
return true; // OK!案内して良し
} else {
// 3. 許可されていないURLなら、エラーを返して処理を中断する
console.error(“不正なリダイレクト先が検出されました: ” + requestedUri);
return false;
}
}

さらに一歩進んだ防御:設定のコツ

コードを書くときだけでなく、OAuth 2.0のプロバイダー(GoogleやGitHubなどの設定画面)でも、登録する `redirect_uri` は「完全なURL」で登録してください。

  • NG: `https://myapp.com/` とだけ登録し、後のパスを自由にさせる。
  • OK: `https://myapp.com/auth/callback` と、パスの最後の一文字まで正確に登録する。

また、開発中のテスト環境で「面倒だから」とワイルドカード(“)を使いたくなる気持ちは痛いほどわかります。でも、それは「家の玄関に誰でも入れる合鍵を置いておく」のと同じです。本番環境では絶対に避けてくださいね。

まとめ:セキュリティは「疑うこと」から始まる

今回学んだ「Open Redirect」は、一見すると些細なミスに見えるかもしれません。しかし、この小さな隙間から、ユーザーの個人情報やセッションが盗まれる深刻なインシデントに発展することがあります。

  • ホワイトリストを正義とする: 許可したもの以外は通さない。
  • 完全一致で判定する: 曖昧さは許さない。
  • 「面倒」を排除する: セキュリティ設定を疎かにしない。

セキュリティは、一度設定したら終わりではありません。今日書いたコードが、明日もユーザーを守り続けてくれる。そんな「堅牢な玄関」を一緒に作っていきましょう!

一歩ずつ、確実に学んでいけば大丈夫です。応援しています!

コメント

タイトルとURLをコピーしました