何が起きるか

NoSQLインジェクションは、検索する値として受け取った入力をDBの比較演算子や式として扱い、攻撃者に検索条件まで変えさせる問題です。ここではMongoDBのような文書DBへ、サーバーがJSONのオブジェクトで検索条件を渡す構成を扱います。

説明用に、名前欄の値をそのまま{name: 入力値}としてDBへ渡すAPIを考えます。攻撃者が文字列の代わりに{"$ne": null}というオブジェクトを送ると、DBは$neを「等しくない」という比較演算子と解釈し、名前がnullでない利用者を検索します。サーバーが名前とパスワードの両方でこの型の入力を受け付け、該当する利用者がいればログイン成功にする実装なら、攻撃者は正しい資格情報なしに他人としてログインできます。 この不備のある例では、DBへ{name: {"$ne": null}, password: {"$ne": null}}を渡し、条件に最初に一致した利用者をログイン対象にすると仮定しています。どの利用者が返るかはデータと検索順に依存し、常に狙ったアカウントを選べるという意味ではありません。

正常ならどう動くか

名前検索APIでは、サーバーが名前欄を文字列に限定し、{name: 検証済みの文字列}のように検索条件の形を自分で決めます。DBはその名前に一致する文書だけを探します。オブジェクトや配列が名前欄へ届いたら検索前に拒否するため、利用者が比較演算子へ置き換えられません。

ログインでも、名前の検索とパスワードの検証をサーバー側で管理します。HTTPリクエストのJSON全体をDBの検索条件として使わず、受け付ける項目・型を決めます。JSONとして解析できるかと、名前として許可できる値かは別の検査です。

不備と攻撃が成立する流れ

攻撃者が名前欄へ文字列ではなく、DBの比較演算子を含むオブジェクトを送ります。APIが型を確かめず名前欄の値を検索条件へ入れると、DBはそのオブジェクトを名前そのものではなく比較条件として解釈します。受信した値を検査せず比較条件として採用する箇所が不備です。

例えば$neを受け付けるDBで、名前欄へ{"$ne": null}を指定する説明用の例です。その値が無検査で採用されると、「指定した名前と同じ」ではなく「nullでない名前」を探します。名前とパスワードの条件を同様に広げられ、見つかった利用者をそのままログイン成功にする実装なら、正しい資格情報なしでログインするおそれがあります。 たとえば{name: {"$ne": null}, password: {"$ne": null}}で最初に返った利用者を採用する不備なら、その利用者がログイン対象になります。

オブジェクトの演算子を渡す方法とは別に、DBが評価する検索用JavaScriptへ入力を文字列連結する構成もあります。説明用にthis.name == '入力値'という式をサーバーが作るとします。入力中の引用符で値を閉じ、ORで常に真の比較を追加できれば、DBが評価する条件が広がります。使える式、ドライバの変換、アプリのログイン判定によって成立条件は異なります。

起こり得る被害と条件

検索範囲の拡大の例では、本来は自分が指定した顧客だけを返すAPIが、広い条件に一致する顧客をHTTPレスポンスで返します。攻撃者は、返されたレコードの氏名や連絡先などを自分の端末で入手できます。

認証迂回の例では、誤って一致した被害者のアカウントとしてサーバーがセッションを発行します。Cookieを使う例なら、ログイン応答のSet-CookieでセッションIDを攻撃者のブラウザへ保存させます。ブラウザが次のAPIリクエストのCookieヘッダーへそのIDを付け、サーバーが保存した利用者情報と照合すると、被害者本人向けの情報を取得できるおそれがあります。任意のDB更新やOSコード実行まで可能かは、別の機能と条件の根拠が必要です。

防ぎ方と、防げる理由

名前やパスワードを文字列として受け付けるAPIでは、オブジェクト・配列を型検査で拒否してから、サーバーが決めたキーと比較方法で検索条件を作ります。これにより、名前欄へ$neを含むオブジェクトを送っても、比較演算子としてDBへ届く前に止められます。

req.bodyはHTTPリクエストから取り出した本文なので、その全体を検索条件へ展開しません。許可したキーから必要な値だけを取り出します。検索用JavaScriptなどの式へ入力を文字列連結する構成も避け、利用者が式の構造を書き換えず、決めた条件と比較する値だけを渡せるようにします。

よくある誤解

JSON.parseに成功することは、構文として正しいJSONだというだけです。名前として許可できる型や内容とは限りません。またSQLを使わないDBでも、演算子や実行式への注入は起こり得ます。

実装の確認点

ログインや検索でreq.bodyをそのまま検索条件へ使う箇所を調べます。ネストしたオブジェクトや配列も含め、許可しない型・キーがDBへ届く前に拒否されるか確認します。

出典・確認範囲

  1. [1] Web Security Academy: NoSQLインジェクションPortSwigger / 確認日 2026-11-01