このページでは、MongoDB クライアント ライブラリを使用する場合のアプリケーション開発のベストプラクティスについて説明します。これらの推奨事項に従うことで、アプリケーションが信頼できない入力を取り扱う際に発生する可能性のあるインジェクション攻撃やその他のセキュリティ問題のリスクを軽減できます。
SRV 接続文字列を使用する
配置がサポートしている場合は、標準の mongodb:// 形式の代わりに mongodb+srv:// 接続文字列形式を使用します。+srv 形式は、接続のためにトランスポート レイヤー セキュリティ (TLS) を自動的に有効にし、デフォルトでアプリケーションと MongoDB 配置の間のトラフィックを暗号化された状態にします。標準形式では、明示的に設定しない限り TLS は有効になりません。
+srv 形式は、DNS SRV レコードからシードホストするの完全なリストを解決します。基礎のホストするが変更されても、接続文字列を更新する必要はありません。
警告
ドライバーは、元のシードホスト名と同じ親ドメインを共有するSRVルックアップ結果を信頼します。例として、foo.example.comのルックアップはnode1.foo.example.comを返す場合があります。また、foo.example.comの下にはありませんが、example.com親ドメインを共有するnode1.example.comを返す場合もあります。
悪意のある DNS サーバーまたは侵害された DNS サーバーは、接続設定中にアプリケーションを攻撃者に制御されたホストへリダイレクトしようとすることができます。親ドメイン制約により、このリスクは制限㌥れます。シードホスト名の親ドメインが、クラスター内のホストのみに解決されるか、または、同じ信頼できるエンティティによって制御されるクラスターに解決されることを確認してください。
To learn more, see SRV Connection Format and Connection Strings in the MongoDB Server manual.
JSONをBSONに変換する前に信頼できない入力を検証する
多くのクライアント ライブラリは、JSON string を BSON ドキュメントに変換する便利なメソッドを提供しています。例、Extended JSON を介してです。アプリケーションが、結果のドキュメントを検証なしでクエリ、更新、またはコマンドに渡す場合、攻撃者はその操作の意味を変更できます。
API エンドポイントとなる接続されたデバイスについて考えてみましょう。このエンドポイントは JSON リクエスト本文を受け付け、string 値を含む name フィールドを想定しています。エンドポイントとなる接続されたデバイスがリクエストボディを BSON に変換し、その結果を検証なしでクエリフィルターで使用すると仮定します。攻撃者は、次の例に示すように、予期される string の代わりにオブジェクトを提出できます。
{"name": {"$ne": null}}
MongoDBは、$neフィールドをリテラル値ではなくクエリ演算子として評価します。このフィルターは、名前で単一のドキュメントを照合するのではなく、null以外のnameフィールドを持つすべてのドキュメントを照合するため、意図したよりも多くのデータが公開されます。
信頼できない入力を BSON に変換する前に JSON string に連結すると、同様のリスクが発生します。次の C++ の例では、string 連結を使用してユーザーが提供した値を JSON string 内に挿入することで、クエリフィルターをビルドする。
std::string json_query = "{ \"name\": \"" + user_supplied_name + "\" }"; bsoncxx::document::value filter = bsoncxx::from_json(json_query); mongocxx::cursor cursor = collection.find(filter.view());
user_supplied_name に double quote または JSON 演算子が含まれている場合、結果の string は意図したフィールド値をエスケープし、任意のクエリ構文を挿入する可能性があります。
このリスクは、JSON string がユーザー、API リクエスト、またはアプリケーションが制御しない別のソースから提供される場合に適用されます。このリスクを軽減するために、信頼できない入力を BSON に変換する前に、型チェックと検証を行ってください。多くのドライバーは、型付きドキュメントAPI またはクエリビルダを提供しており、これらを使用してクエリをビルドすることができます。また、変換のために JSON 入力を受け入れる前に、アプリケーション内で JSON schema またはそれに類似する検証レイヤーを適用することができます。
次の例では、前の連結例と同じフィルターをビルドしますが、型指定されたドキュメント ビルダを使用します:
bsoncxx::builder::basic::document filter_builder; filter_builder.append( bsoncxx::builder::basic::kvp("name", user_supplied_name)); mongocxx::cursor cursor = collection.find(filter_builder.view());
ビルダは user_supplied_name を解析対象の string の一部ではなく値として扱うため、その値によってクエリの構造が変更されることはありません。
Building queries as BSON documents instead of strings avoids traditional SQL injection, since attackers have no query string to manipulate. To learn more, see FAQ: MongoDB Fundamentals in the MongoDB Server manual. To learn more about Extended JSON types and conversions, see MongoDB Extended JSON in the MongoDB Server manual.
サーバーサイドJavaScriptの実行を制限する
MongoDB supports operators and commands that execute JavaScript, including $where, $function, $accumulator, and mapReduce. When your application builds one of these expressions from user input, the server executes that input as code. This behavior creates the same class of risk as passing untrusted input to an eval function in application code.
このリスクを軽減するために、次の推奨事項に従ってください。
string 連結を避ける: JavaScript string に信頼できない入力を連結または補間することにより、
$where式、$function本文、$accumulator関数をビルドするようなことをしないでください。MongoDB は JavaScript を実行せずにそれらを評価するため、代わりに標準クエリ演算子を使用してください。Disable server-side scripting: Disable server-side scripting if your application doesn't use
$where,$function,$accumulator, ormapReduce. Set thesecurity.javascriptEnabledconfiguration option tofalse, or start themongodormongosprocess and pass the--noscriptingoption.
To learn more about securing server-side JavaScript execution, see Run MongoDB with Secure Configuration Options.
To learn more about the $where operator, see $where in the MongoDB Server manual.
詳細情報
For a list of best practices on securing self-managed deployments, see the Security Checklist in the MongoDB Server manual.