Shikata Ga Nai

Private? There is no such things.

NoSQLインジェクションの種類と攻撃手法 ― MongoDBを中心とした実践的な攻略法

Hello there, ('ω')ノ

🧩 NoSQLインジェクションの2つのタイプ

NoSQLインジェクションには大きく分けて以下の2種類が存在します:


① 構文インジェクション(Syntax Injection)

概要:

  • NoSQLのクエリ構文そのものを壊して、意図的に攻撃用の構文を注入する。
  • SQLインジェクションに近い発想だが、NoSQLではJSON形式などが用いられるため攻撃方法が異なる。

例(MongoDB)

{"username": "admin", "password": {"$ne": null}}

この入力により、パスワードが空でなければ認証を通すという条件に改ざんできる。

特徴:

  • 多くのNoSQLがJSON形式の構文を採用しており、クエリにJSONオブジェクトを直接挿入できるケースが多い。
  • 構文が破壊されてもエラーが出ず、静かに意図しない動作をする場合がある。

② 演算子インジェクション(Operator Injection)

概要:

  • $ne, $or, $gt などのMongoDB固有の演算子をパラメータに挿入して、条件の意味そのものを変える攻撃。

例(MongoDB)

{"username": {"$ne": ""}, "password": {"$ne": ""}}
  • どんなユーザーでも、空でさえなければ認証が通ってしまう。
  • $or, $and を使えばさらに複雑な条件も作成可能。

🧪 テスト方法と注意点

テスト方法 解説
ログイン画面で JSON を試す パラメータを {"$ne": null} などに変更してみる
パスワードなしで通るか試す password={"$gt":""} などの条件で通過するか確認
異常な構文でエラーを確認 クエリエラーが返るかチェック(エラーメッセージにヒントあり)
入力値に ${} が使えるか クエリ構築時にそのまま使われるかどうか確認する

🧠 攻撃ポイント(MongoDB)

狙いどころ
$ne, $gt, $lt を使った比較のすり抜け password: {"$ne": null}
$or を使った条件の分岐 {"$or": [{"username":"admin"}, {"username": {"$ne": null}}]}
$where によるJavaScriptの挿入 "$where": "this.password.length < 100"
$regex を使ったパターンマッチ username: {"$regex": ".*"}(全一致)

🛡 対策

対策 内容
JSON構造のバリデーション パラメータが文字列であることを厳密にチェック
${} のフィルタリング クライアント入力に含まれていないか検査・除去
OR条件などを組めないように設計 クエリ構築ロジックを一元管理し、テンプレート化する
ORMや公式ドライバの利用 手動で文字列結合せず、正規の手段でクエリを構築する

✅ まとめ

  • NoSQLインジェクションは構文ベースの操作か、演算子の悪用のどちらかで分類できる。
  • 特にMongoDBでは、JSON構文の柔軟性を逆手に取った高度な改ざんが可能
  • 安易な入力値の埋め込みは厳禁。型チェックと構造検証が防御の要

🔐 柔軟なデータ構造は、攻撃者にとっても柔軟な武器になる。開発者側の制限がなければ、セキュリティは成立しない。

Best regards, (^^ゞ