皆さん、こんにちは!
企業のIT担当になり立ての頃って、覚えることが山ほどあって本当に大変ですよね。「セキュリティ対策をしっかりするように」と言われても、専門用語ばかりでどこから手を付ければいいか途方に暮れてしまうこともあると思います。
今回は、Webサイトによくある「オープンリダイレクト」という脆弱性について、一緒に優しく学んでいきましょう!
小難しいサイバー攻撃の話に聞こえるかもしれませんが、身近な「防犯」の仕組みに置き換えてみると、すごくスッキリ理解できるようになりますよ。それでは、一歩ずつ紐解いていきましょう!
—
1. 家の鍵と「お助けコンシェルジュ」の防犯トラブル
まずは、私たちの身近な「お家の防犯」をイメージしてみてください。
あなたは大きなお屋敷の管理人さんです。来客者がやってきたとき、正面玄関に立っているコンシェルジュ(案内人)がこう尋ねます。
「どちら様にお伺いですか?」
来客者が「あそこの応接間です」と答えると、コンシェルジュが「かしこまりました、ではあちらへどうぞ!」と案内してくれますよね。これが、Webサイトにおける「リダイレクト(転送)機能」です。
例えば、ユーザーがログインした後に「さっき見ていたページ」へ自動で連れて行ってあげたり、別のページへスムーズに誘導したりするのに、この仕組みはなくてはならない便利なものです。
もし、コンシェルジュが「ウソの案内」を信じ込んでしまったら?
ある日、見知らぬ怪しい男(攻撃者)がやってきて、コンシェルジュにこう耳打ちしました。
「おい、あそこの泥棒の隠れ家(フィッシング詐欺サイト)まで、うちの主人を案内してくれよ」
もし、このコンシェルジュが少しお人好しすぎて、来客者が言った目的地を「言われた通りに、ろくに確認もせず」そのまま案内してしまったらどうなるでしょう?
主人は「いつもの応接間に行けるんだな」と安心してついていった結果、気づけば見知らぬ泥棒の巣窟に連れ込まれ、財産を根こそぎ奪われてしまいました……。
これが、「オープンリダイレクト脆弱性」の正体です。
Webサイトが、ユーザーをどこへ飛ばす(リダイレクトする)かの宛先をろくにチェックせず、外部からの言いなりになってしまうことで、攻撃者に「悪質な詐欺サイトへの踏み台」として悪用されてしまうのです。
—
2. 攻撃者はどうやって私たちをだますの?
オープンリダイレクトが厄介なのは、「本物の信頼できるWebサイトのURL」から始まるからなんです。
例えば、あなたが普段からよく使っている安全なショッピングサイトのURLが https://example.com だとします。
攻撃者は、次のような巧妙に仕組まれたリンクをメールやSNSでばらまきます。
https://example.com/login.php?next=https://evil-phishing-site.com
パッと見たとき、URLの最初が https://example.com なので、一般のユーザーは「あ、いつも使ってる公式のページだ安心だな」と信じてクリックしてしまいますよね。これが罠なんです。
裏側の仕組みを少し覗いてみましょう。このサイトのプログラム(PHPなどの動的な処理)が、次のような手抜きコードになっていたとします。
<?php
// 【危険な実装例】受け取ったURLをそのまま無条件で信じて転送してしまう
$next_url = $_GET['next'];
// チェックをせずに、そのままユーザーを別の場所へ飛ばしてしまう!
header("Location: " . $next_url);
exit;
?>
このプログラムは、?next= の後ろに何が書かれていようと、疑うことすらせずにその場所へユーザーを放り出してしまいます。結果として、ユーザーは偽のログイン画面に飛ばされ、IDやパスワードを入力させられてしまう……というわけです。
—
3. 「ホワイトリスト方式」でしっかりお家を守ろう!
「じゃあ、ユーザーを別のページに飛ばす機能なんて使わない方がいいの?」と思われるかもしれませんが、そんなことはありません。ログイン後のリダイレクトなどは便利ですし、どうしても必要です。
そこで登場するのが、今回のテーマである「ホワイトリストベースの検証(身元引受人リスト)」というアプローチです。
先ほどのコンシェルジュの例えに戻りましょう。お人好しだったコンシェルジュに、管理人であるあなたが「絶対に案内していい安全な場所のリスト(ホワイトリスト)」を渡してあげます。
「おい、来客者が行き先を言ってきたら、まずこのリストに名前が載っているか厳しくチェックしなさい。もしリストに載っていない怪しい場所だったら、『ここにはご案内できません!』と追い返しなさい」
これが、プログラミングにおけるホワイトリスト検証の考え方です。
実際に安全なコードを書いてみましょう
PHPを例に、安全なリダイレクト処理の書き方を見てみましょう。実務でもそのまま参考にできるようにコメントを詳しく入れています。
<?php
// 【安全な実装例】ホワイトリストを使ったドメイン検証
// 1. 許可する安全な移動先のリスト(ホワイトリスト)を定義する
$allowed_hosts = [
'example.com',
'shop.example.com',
'help.example.com'
];
// 2. ユーザーからリクエストされた移動先のURLを取得する
$next_url = $_GET['next'] ?? '/dashboard.php'; // 指定がない場合のデフォルト
// 3. URLの構文を解析して、本当に安全な場所を指しているかチェックする
$parsed_url = parse_url($next_url);
$is_safe = false;
// パース結果にホスト名(ドメイン)が含まれているか確認
if (isset($parsed_url['host'])) {
// ホワイトリストに含まれているドメインと完全に一致するかチェック!
if (in_array($parsed_url['host'], $allowed_hosts, true)) {
$is_safe = true;
}
} else {
// ホスト名がない(= /profile.php のような相対パスの場合)は、
// 自社サイト内への移動とみなして安全と判断する
$is_safe = true;
}
// 4. 安全性が確認できた場合のみリダイレクトを実行する
if ($is_safe) {
header("Location: " . $next_url);
exit;
} else {
// 安全が確認できない場合は、エラーとするか安全な初期ページへ飛ばす
header("Location: /error.php?msg=" . urlencode("不正なリダイレクト先です"));
exit;
}
?>
このように、parse_url 関数を使ってドメインを分解し、事前に用意した $allowed_hosts(ホワイトリスト)の中にきっちり含まれているかを確認するのが、実務における王道かつ確実な対策になります。
—
4. 新人の皆さんへ:一歩ずつ安全な開発者になりましょう!
オープンリダイレクトは、直接サーバーのデータをすべて盗まれるような派手なサイバー攻撃ではありません。しかし、「あなたの大切なお客さまを、詐欺の罠に引きずり込むための強力な踏み台」として悪用されてしまう、非常にいやらしい脆弱性です。
「URLのパラメータをそのまま信用しない」
「移動先は必ず自分で作ったリストと照らし合わせる」
この2つの基本さえしっかり頭に入れておけば、あなたの書くプログラムはぐっと安全になります。最初は難しく感じるかもしれませんが、日々のコーディングで「おや、この入力値は信用しても大丈夫かな?」と一度立ち止まるクセをつけることが、最高のセキュリティエンジニアへの第一歩です。
一歩ずつ、焦らず確実に学んでいきましょう!応援しています!
コメント