【入門編】NoSQLインジェクションの仕組みとMongoDBにおける演算子フィルタリング – アプリケーションセキュリティ & 安全な開発防御ガイド

家の鍵は「数字」だけだと思っていない?NoSQLインジェクションの恐ろしい罠

こんにちは!セキュリティの現場で日々、泥臭い攻防を繰り広げているエンジニアです。

今日は、最近のWeb開発で非常によく使われる「MongoDB」などのNoSQLデータベースを狙った、「NoSQLインジェクション」という攻撃についてお話しします。

「SQLインジェクションは聞いたことあるけど、NoSQLは安全なんでしょ?」なんて思っていたら大間違い。実は、家の鍵の形を巧みに変えて、泥棒が堂々と玄関から入ってくるような攻撃が、このNoSQLの世界にはあるんです。

一歩ずつ、その仕組みと対策を学んでいきましょう!

—

1. 泥棒が「合鍵」を作る仕組み:演算子の悪用

まずは、なぜ攻撃が成功してしまうのか、身近な例で考えてみましょう。

あなたが家主で、玄関の鍵に「暗証番号」を設定しているとします。正しい番号を知っている人だけが入れる仕組みですね。プログラムで書くと、こんな感じです。

// ユーザーが入力したパスワードと、データベース内の値を照合するイメージ
db.users.find({ username: “admin”, password: inputPassword });

ここで、泥棒(攻撃者)は考えます。「パスワードが何かわからないなら、『何でもいいから一致させてしまえ!』」と。

魔法の言葉「$gt」の登場

MongoDBなどのNoSQLには、検索条件を柔軟にするための「演算子」という機能があります。その一つが $gt(Greater Than:より大きい)です。

もし、攻撃者がパスワードの入力欄に、単なる文字列ではなく、{"$gt": ""} という特殊なコマンドを入力したらどうなるでしょうか?

プログラムはこう解釈してしまいます。
「パスワードは、空文字(””)より大きい値であること」

パスワードが何であれ、空文字より大きい値であれば条件は「真(True)」になりますよね。結果として、パスワードを知らなくても、システムは「はい、一致しました!」と判断してログインを許可してしまうのです。これがNoSQLインジェクションの正体です。

—

2. なぜ「型」のチェックが重要なのか

SQLインジェクションは「文字列」を細工してSQL文を壊す攻撃ですが、NoSQLインジェクションは「入力データの型(構造)」を騙す攻撃です。

開発者のみなさんは、入力フォームから送られてくるデータを「ただの文字列」だと信じ切っていませんか?実は、悪意のある攻撃者は、そこに「オブジェクト(構造体)」を送り込んでくることがあります。

対策の基本:入力値を厳格にバリデーション(検証)する

この攻撃を防ぐための第一歩は、「入力されたものが、本当に期待通りの形をしているか?」を厳しくチェックすることです。

例えば、パスワードは必ず「文字列」であるはずですよね。もし入力データが「オブジェクト({})」だったら、それはもう不審な訪問者として追い返すべきです。

実践的な対策コード例(Node.jsの例)

const express = require(‘express’);
const app = express();

app.post(‘/login’, (req, res) => {
const { username, password } = req.body;

// 対策:入力値が「文字列」であることを強制する!
// もし攻撃者が {“$gt”: “”} を送ってきても、typeof は “object” になるため
// このif文で弾くことができます。
if (typeof username !== ‘string’ || typeof password !== ‘string’) {
return res.status(400).send(“不正な入力です。”);
}

// ここで安全にデータベース検索を行う
db.users.find({ username: username, password: password });
});

このように、「型」を厳格にチェックするだけで、泥棒の合鍵は無効化されます。

—

3. 防御の要:セキュリティを強固にする3つのポイント

最後に、現場で今日から意識できる防御のポイントをまとめました。

1. 入力値を盲信しない(Type Checking)
先ほどのコードのように、typeof やライブラリ(JoiやZodなど)を使って、入力値が期待したデータ型(文字列、数値など)であることを必ず確認してください。
2. データベースの権限を最小限に(Least Privilege)
Webサーバーがデータベースに接続する際、DBの全権限を持たせていませんか?読み取り専用のユーザーを作成し、必要なデータ以外には触れないように設定しましょう。
3. フレームワークの機能を活用する
最近のWebフレームワークには、こうしたインジェクションを防ぐためのバリデーション機能が標準で備わっています。自分で泥臭く書くのも大切ですが、まずはフレームワークの公式ドキュメントで「安全な入力処理」を調べてみてください。

—

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

セキュリティは難しい数学のようなものではなく、「相手(攻撃者)がどうやって裏をかこうとしているか」を想像する知恵比べです。

「パスワード欄には文字列が来るはずだ」という性善説を一度捨てて、「もし、ここに命令文が書かれていたら?」と考えてみてください。その小さな疑いが、あなたの作るアプリケーションを、そして大切なユーザーを守る一番の盾になります。

これからも、一緒に安全でかっこいい開発の世界を築いていきましょう!何か不明点があれば、いつでも相談してくださいね。

コメント

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