ExportXMLWordPrintableJSON

    • None
    • 0.1
    • Dotnet Drivers
    • Not Needed
    • None
    • None
    • None
    • None
    • None
    • None

      Summary

      An application user whose input becomes a key or field name in a LINQ query can silently redirect that query or update to different database fields.

      Impact

      Queries and updates silently target different fields, documents, or array elements than the C# expression describes — enabling boolean-oracle probing of unintended fields (including other users' documents in shared collections), broadening of update scope to all array elements, and application-level filter-logic bypass, with no error signaled anywhere.
      Severity: high
      Exploitability: likely_exploitable — Given any application that feeds user strings into these LINQ positions (user-named attribute/metadata lookups are a common pattern), exploitation is deterministic — the attacker fully controls the injected path segment and no check anywhere in the translation or rendering pipeline inspects it.
      Customer data: customer_content, customer_metadata (api_response)

      Location

      • src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Filters/AstFilterField.cs:49 in AstFilterField.SubField
      • src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToFilterTranslators/ToFilterFieldTranslators/GetItemMethodToFilterFieldTranslator.cs:106 in TranslateDictionaryGetItemWithKey
      • src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToFilterTranslators/ToFilterFieldTranslators/GetItemMethodToFilterFieldTranslator.cs:75 in TranslateBsonValueGetItemWithString
      • src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToFilterTranslators/ToFilterFieldTranslators/FieldMethodToFilterFieldTranslator.cs:41 in FieldMethodToFilterFieldTranslator.Translate
      • src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToFilterTranslators/ToFilterFieldTranslators/AllMatchingElementsMethodToFilterFieldTranslator.cs:49 in AllMatchingElementsMethodToFilterFieldTranslator.Translate
      • src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToFilterTranslators/MethodTranslators/ContainsKeyMethodToFilterTranslator.cs:47 in ContainsKeyMethodToFilterTranslator.Translate
      • src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Filters/AstFieldOperationFilter.cs:61 in AstFieldOperationFilter.Render

      Reproduction / trigger path

      Analyzed trigger path from static analysis — not an executed PoC. Confirm with a concrete repro before handing off.

      Attacker controls: Full content of one field-path segment in the rendered filter: '.' splits it into nested traversal ('a.b' queries subdocument b of a instead of a literal key), '$'-prefixed segments enter operator-lookalike positions, ']'/'.' inside an AllMatchingElements identifier restructures the '$[...]' array-filter segment, null identifier silently becomes '$[]' (all array elements), and a null Mql.Field name throws ArgumentNullException instead of a translation error.

      1. (source) src/MongoDB.Driver/Linq/Linq3Implementation/Misc/PartialEvaluator.cs:41 in PartialEvaluator.EvaluatePartially — Attacker-influenced runtime strings captured in the application's LINQ expression (dictionary keys, Mql.Field names, AllMatchingElements identifiers) are folded into ConstantExpressions before translation.
      2. (hop) src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToFilterTranslators/ToFilterFieldTranslators/MethodCallExpressionToFilterFieldTranslator.cs:33 in MethodCallExpressionToFilterFieldTranslator.Translate — Dispatcher routes get_Item / Field / AllMatchingElements calls to the producer translators (lines 28, 30, 33).
      3. (hop) src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToFilterTranslators/ToFilterFieldTranslators/GetItemMethodToFilterFieldTranslator.cs:106 in TranslateDictionaryGetItemWithKey — Serialized dictionary key passes only an 'is not BsonString' type check (line 101); content with '.', '$', or brackets flows through to SubField.
      4. (hop) src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToFilterTranslators/ToFilterFieldTranslators/TranslatedFilterField.cs:37 in TranslatedFilterField.SubField — Forwards the sub-field name unchanged to the AST layer; no validation layer exists between translators and concatenation.
      5. (sink) src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Filters/AstFilterField.cs:49 in AstFilterField.SubField — Raw concatenation _path + "." + subFieldName; Render() (line 53) emits the string, and AstFieldOperationFilter.Render (AstFieldOperationFilter.cs:61) makes it the element name of the wire filter document that the MongoDB server interprets structurally.

      Root cause

      • AstFilterField.SubField (src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Filters/AstFilterField.cs:49) builds field paths by raw concatenation (_path + "." + subFieldName); the only guard is a null check at line 41, and Render() at line 53 emits the raw string.
      • All five producers pass strings through unchecked: dictionary keys (GetItemMethodToFilterFieldTranslator.cs:106, guarded only by an 'is not BsonString' type check at :101), BsonValue keys (:75), Mql.Field names (FieldMethodToFilterFieldTranslator.cs:38-41), ContainsKey arguments (ContainsKeyMethodToFilterTranslator.cs:47), and AllMatchingElements identifiers (AllMatchingElementsMethodToFilterFieldTranslator.cs:38-49, which rejects only "" so null yields '$[]').
      • PartialEvaluator (src/MongoDB.Driver/Linq/Linq3Implementation/Misc/PartialEvaluator.cs:41) folds captured runtime variables into constants, so runtime user input reaches GetConstantValue and then SubField.
      • AstFieldOperationFilter.Render (src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Filters/AstFieldOperationFilter.cs:61) makes the concatenated path the element name of the wire filter document, which the server interprets structurally; by contrast the aggregation side guards exactly this case (AstGetFieldExpression.cs:69 checks for leading '$' and embedded '.' and falls back to a safe $getField form), a guard the filter side lacks.

      Ownership

      Assigned teams: @mongodb/dbx-csharp-dotnet


      Filed from Aegis finding 2fa978de4893 (scan scan-320b0a32a42c) · primitive: Attacker string containing dots, dollars, brackets, or null is concatenated verbatim into the MQL filter field path, redirecting query matching and update targeting. · categories: NoSQL Injection, Data Corruption

      https://docs.google.com/document/d/1osPjSiI-pvMXtrI49QVqwrIK21_nU38fsp7tJlQpDlY/edit?tab=t.0#heading=h.biijq6ke6z0p

            Assignee:
            Damien Guard
            Reporter:
            Boris Dogadov
            None
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: