【実務・中級編】NoSQLインジェクションのメカニズム(MongoDBを例に) – アプリケーションセキュリティ & 安全な開発防御ガイド

NoSQLインジェクション:MongoDBに潜む「型」の罠と、設計思想から変える防御術

現場でコードレビューをしていると、未だに「NoSQLだからSQLインジェクションとは無縁」と本気で信じているエンジニアに出くわすことがある。はっきり言おう。それは致命的な誤解だ。

SQLが文字列結合の隙を突くのに対し、MongoDBのようなドキュメント指向データベースに対する攻撃――NoSQLインジェクションは、アプリケーションが受け取る「JSONオブジェクトの構造」そのものを悪用する。今回は、MongoDBを例に、なぜ彼らが認証をいとも簡単にバイパスできるのか、そしてそれを現場でどう根絶すべきか、実務的な視点で解説する。

—

1. なぜ「型」の混入が危険なのか(PoCのメカニズム)

MongoDBのクエリはJSON(実際にはBSON)で構築される。例えば、ログイン機能でユーザー名とパスワードを照合する際、バックエンドでは以下のような処理が行われがちだ。

// 脆弱な実装例(Node.js/Express)
db.collection(‘users’).findOne({
username: req.body.username,
password: req.body.password
});

正常な入力であれば、usernameとpasswordは文字列として扱われる。しかし、攻撃者はここに「オブジェクト」を送り込む。req.body.passwordに {"$ne": null} を仕込むのだ。

すると、生成されるクエリはこうなる。
{ "username": "admin", "password": { "$ne": null } }

$ne は「Not Equal(〜と等しくない)」を意味するクエリ演算子だ。つまり、「パスワードがnullではないユーザーを探せ」という命令にすり替わり、パスワードを知らなくてもログインが成立してしまう。これが認証バイパスの典型的なメカニズムだ。

—

2. 現場で今すぐ使える防御アプローチ

この脆弱性を防ぐためのアプローチは、大きく分けて「バリデーションによる型固定」と「クエリ構築の抽象化」の2点に集約される。

① 型の強制(Input Validation)

一番の基本は、ユーザー入力を「信頼できる型」に強制することだ。JSONとして送られてきたデータであっても、必ずサーバーサイドでデータ型をバリデーションする。

Node.jsでの実装例(Joiなどのバリデーターライブラリを使用)

const Joi = require(‘joi’);

// スキーマで型を厳密に定義する
const loginSchema = Joi.object({
username: Joi.string().alphanum().min(3).max(30).required(),
// ここでpasswordを確実に「string」に制限する。オブジェクトの混入を許さない。
password: Joi.string().required()
});

// リクエストを検証
const { error, value } = loginSchema.validate(req.body);

if (error) {
return res.status(400).send(‘不正な入力形式です’);
}

// 検証済みの値のみを使用する
db.collection(‘users’).findOne({ username: value.username, password: value.password });

② ODM(Object Document Mapper)の活用

生のドライバを直接叩くのではなく、MongooseのようなODMを使うのが今の標準だ。ODMは内部的にスキーマ定義に基づいて型変換を行うため、意図しないクエリ演算子の混入を防ぐ安全装置として機能する。

—

3. セキュリティチーフとしての「推奨設定」

アプリケーションレベルの防御に加えて、インフラ層での多層防御も怠ってはならない。MongoDBの設定ファイル(mongod.conf)やネットワーク構成で以下のガードレールを引くことが重要だ。

MongoDBのセキュリティ設定(抜粋)

セキュリティ設定例
security:
# 認証を必ず有効化する(デフォルトだが稀に無効なケースがある)
authorization: enabled

net:
# 外部からの直接アクセスを遮断し、VPC内からの通信のみ許可する
bindIp: 127.0.0.1, <内部IPアドレス>

WAFでのリクエスト監視

WAF(AWS WAFなど)を利用している場合、JSON内に含まれるクエリ演算子($ne, $gt, $whereなど)をシグネチャとして検知するルールを追加する。

AWS WAF JSON Matchルール例:

  • 検査対象: JSON body
  • マッチ条件: {"$ne":} や {"$gt":} を含むリクエストをBlockする。

—

最後に:エンジニアへのアドバイス

NoSQLインジェクションを防ぐために最も重要なのは、「入力をそのままクエリのパーツとして扱わない」というSQLインジェクション時代からの教訓を、JSONの世界でも徹底することだ。

「MongoDBだから大丈夫」という慢心は、脆弱性の最大の温床になる。コードを書くときは常に、「この値に配列やオブジェクトを突っ込まれたら、クエリの構造はどう変化するか?」を想像してほしい。

セキュリティは「魔法のツール」を導入して終わりではない。開発プロセスの中に、型チェックやバリデーションという「泥臭い習慣」を組み込めるか。それこそが、堅牢なシステムを作る唯一の道だ。

次のリリースでは、まずログイン画面と検索フォームのバリデーション定義を確認してほしい。もし「型」が放置されている場所があれば、そこが攻撃者の入り口だ。戦いは、コードの細部から始まっている。

コメント

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