こんにちは。セキュリティの現場で長年、泥臭いインシデント対応や防御設計の最前線に立っている者です。
今日は、開発者なら誰もが一度は耳にするけれど、実は一番「やらかしやすい」脆弱性、IDOR(Insecure Direct Object Reference:安全でない直接オブジェクト参照)についてお話しします。
「自分はちゃんとしたシステムを作っているから大丈夫」と思っていませんか? 実は、このIDORは世界中の大企業でもいまだに頻発している、まさに「セキュリティの死角」なんです。さあ、一緒に紐解いていきましょう!
—
1. IDORって、結局なに?(泥棒の例え話)
まずは想像してみてください。あなたは今、豪華なマンションの管理システムを作っています。
あるユーザー(太郎くん)が自分のプロフィールを見るために、ブラウザでこんなURLにアクセスしたとします。
https://example.com/api/users/1234
この「1234」が、太郎くんのID番号です。さて、ここで悪い心を持った泥棒がやってきます。泥棒は、このURLの数字を「1235」に書き換えてリクエストを送ってみました。
するとどうでしょう。画面には、見ず知らずの「花子さん」の住所や電話番号がバッチリ表示されてしまいました。
これがIDORの正体です。「数字を一個ずらすだけで、他人の家の中を覗き放題」という、極めてシンプルかつ危険な状態ですね。玄関の鍵は閉まっているのに、窓枠のサイズを調整するだけで隣の部屋に侵入できてしまうようなものです。
2. なぜこんなことが起きるの?
多くの新人エンジニアが陥る罠は、「URLを知っている=本人である」と勘違いしてしまうことです。
システム側が「このリクエストは誰からのものか?」という本人確認(認証)はしていても、「このユーザーは、このデータを見る権限があるのか?」という認可(Authorization)のチェックを忘れてしまうと、一気にセキュリティホールになります。
3. 防御の基本:二重の鍵をかけよう
では、どうすれば防げるのでしょうか。解決策は大きく分けて2つあります。
① 「セッション」と突き合わせる(基本の認可)
リクエストが来たら、URLのIDを信じるのではなく、「今ログインしているユーザー」と「アクセスしようとしているデータの持ち主」が一致するかを必ずコード内で確認します。
// 悪い例:URLのIDをそのまま信じてデータを取ってくる
app.get(‘/api/users/:id’, (req, res) => {
const userData = db.findUser(req.params.id); // 誰でも他人のIDを入れ放題
res.json(userData);
});
// 良い例:セッションのユーザーIDと比較する
app.get(‘/api/users/:id’, (req, res) => {
// ログイン中のユーザーIDと、リクエストされたIDを比較
if (req.session.userId !== req.params.id) {
return res.status(403).send(“自分のデータしか見られません!”);
}
const userData = db.findUser(req.params.id);
res.json(userData);
});
② IDを推測不可能にする(間接参照)
数字の「1234」のような連番は、泥棒に「次は1235だ!」と推測させるヒントになります。これを「UUID(ランダムな文字列)」に変えてみましょう。
https://example.com/api/users/550e8400-e29b-41d4-a716-446655440000
こうなれば、総当たりで推測するのはほぼ不可能です。これを「間接参照」と呼びます。表向きはランダムな文字列を見せておき、裏側でデータベースの連番と紐付ける手法です。
—
4. プロの視点:防御ヘッダーの活用
開発だけでなく、インフラ側でも「念のための保険」をかけておきましょう。
- CSP (Content Security Policy): 予期せぬスクリプトの実行を防ぎます。
- X-Content-Type-Options: nosniff: ブラウザが勝手にファイルを解釈するのを防ぎ、攻撃者が悪意あるファイルをアップロードした際のリスクを減らします。
これらは直接的なIDOR対策ではありませんが、「攻撃者の足元をすくうための防犯カメラ」のようなものです。セキュリティは「一点豪華主義」ではなく、多層防御で守るのがプロの鉄則ですよ。
—
最後に:一歩ずつ、確実に。
IDORを防ぐ鍵は、「すべてのリクエストにおいて、誰が何をしようとしているのかを疑うこと」です。
「面倒だな」と思うかもしれませんが、このひと手間で、あなたの大切なユーザーの個人情報が守られます。最初は難しく感じるかもしれませんが、まずは「自分が書いたコードで、他人のデータが見えてしまわないか?」という視点を持つことから始めてみてください。
もし不安な点があれば、いつでも聞きに来てくださいね。一緒に鉄壁のシステムを作っていきましょう!応援しています。
コメント