「URLの数字を変えるだけ」で大惨事?IDORの恐怖と、今日からできる「鍵の掛け方」
こんにちは。セキュリティの世界へようこそ。
今日は、開発現場でつい見落とされがちなのに、やられると致命傷になる「IDOR(アイドア:不適切な直接オブジェクト参照)」という脆弱性についてお話しします。
「認証(ログイン)」はしっかり実装したつもりでも、その後の「認可(権限チェック)」が抜けていると、まるで「玄関の鍵は閉めたけど、家の中の金庫は誰でも開けられる状態」になってしまいます。
今回は、この「IDOR」を身近な例えで紐解きながら、どうすれば防げるのか、現場の知見を交えて解説していきますね。
—
1. IDORって何?「泥棒」に例えて解説
想像してみてください。あなたは今、会員制のWebサービスを運営しています。ユーザーはログインすると、自分のプロフィール画面が見られますよね。
その時のURLがこんな感じだとします。
`https://example.com/api/users/12345/profile`
ここで、もしあなたが悪意のあるユーザーだとしたら、どう考えるでしょうか?
「この『12345』っていう数字、もしかして隣の人のIDに変えたら、その人のプロフィールが見えちゃうんじゃない?」
そう、これがIDORの正体です。
サーバー側が「このリクエストを送ってきた人は、本当にID 12345の持ち主かな?」を確認せずに、「言われた通りにID 12345のデータを表示しますよ!」と素直に返してしまう。 これがまさに、鍵の掛かっていない金庫を泥棒に差し出す行為なんです。
—
2. なぜこんなことが起きてしまうのか?
開発現場でよくあるのが、「ログインさえしていれば、その人は信用できるユーザーだ」という思い込みです。
- 認証(Authentication): 「あなたは誰ですか?」を確認すること。(ログイン)
- 認可(Authorization): 「あなたはそのデータに触ってもいい人ですか?」を確認すること。
IDORは、「認証はしたけれど、認可を忘れた」時に発生します。APIを実装する際、「ユーザーIDを受け取ってデータを返す」という機能を作ると、ついつい「動くこと」を優先して、権限チェックという「鍵の確認」をすっ飛ばしてしまうんですよね。
—
3. 実践!IDORを防ぐための「認可ロジック」
では、コードで具体的にどう防ぐべきか見ていきましょう。
悪い例(脆弱な実装)
// ユーザーが自分のプロフィールを取得するAPI
app.get(‘/api/users/:id/profile’, (req, res) => {
// 受け取ったIDを使ってDBからデータを引くだけ(超危険!)
const userData = db.findUserById(req.params.id);
res.json(userData);
});
これだと、誰でもURLのIDを書き換えるだけで他人の情報を盗み見放題です。
良い例(認可ロジックの実装)
必ず「現在ログインしているユーザー」と「要求されたデータ」を照らし合わせる必要があります。
app.get(‘/api/users/:id/profile’, (req, res) => {
// 1. セッション(またはトークン)から現在ログイン中のユーザーIDを取得
const currentUserId = req.session.userId;
// 2. URLで指定されたIDと、ログイン中のIDが一致するかチェック!
if (currentUserId !== req.params.id) {
// 権限がない場合は「403 Forbidden(閲覧禁止)」を返す
return res.status(403).send(“自分のデータ以外は見られません!”);
}
// 3. 一致した場合のみ、データを返す
const userData = db.findUserById(req.params.id);
res.json(userData);
});
シンプルですが、これが鉄則です。「リクエストされたIDをそのまま信用しない」。これがセキュリティの第一歩です。
—
4. プロからのアドバイス:IDを隠す工夫
認可ロジックをしっかり入れるのが大前提ですが、さらに防御を固める手法として「推測しにくいIDを使う」というやり方もあります。
連番(1, 2, 3…)のIDを使っていると、攻撃者は「次は4だ!」と簡単に予測できてしまいます。そこで、UUID(ランダムな文字列)を使うのが世界標準のトレンドです。
- 悪い例: `user/101`
- 良い例: `user/a1b2c3d4-e5f6-7890-abcd-1234567890ef`
URLが複雑になると、攻撃者が他人のIDを推測して片っ端から試す(総当たり攻撃)のが非常に難しくなります。これも立派な防御策の一つです。
—
最後に:セキュリティは「疑うこと」から始まる
セキュリティは、一度設定して終わりというものではありません。日々の開発の中で、「もし自分が意地悪なハッカーだったら、このURLの数値をいじるだろうか?」と、ちょっとだけ立ち止まって考えてみてください。
「ログインしているから大丈夫」ではなく、「ログインしていても、操作する対象が本当にその人のものか確認する」。この泥臭いチェックの積み重ねが、あなたのサービスを、そしてユーザーを守る最強の盾になります。
一歩ずつ、安全な開発を一緒に進めていきましょうね!何か不安なことや疑問があれば、いつでも相談してください。応援しています!

コメント