Query filter regex injection via unescaped backslash and bracket in LINQ character-set translation

XMLWordPrintableJSON

    • None
    • 0.2
    • Dotnet Drivers
    • Not Needed
    • None
    • None
    • None
    • None
    • None
    • None

      Summary

      Someone who can feed characters into an app's text filter can rewrite the database query's matching rules, exposing or affecting records the filter was meant to exclude.

      Impact

      The attacker rewrites one predicate of the application's database query — making it match everything, nothing, or a chosen pattern — causing disclosure of records the filter should exclude, mis-scoped updates/deletes executed with the application's database privileges, server-side regex compile errors, or CPU-heavy catastrophic patterns.
      Severity: high (upper bound critical)
      Exploitability: likely_exploitable — Deterministic once the app pattern exists: a char[] containing ']' in a non-first position closes the character class and every following attacker character is raw regex, giving reliable arbitrary sub-pattern injection with no timing or environmental conditions.
      Customer data: customer_content, customer_metadata (api_response)

      Location

      • src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToFilterTranslators/ExpressionTranslators/StringExpressionToRegexFilterTranslator.cs:212 in EscapeCharacterSet
      • src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToFilterTranslators/ExpressionTranslators/StringExpressionToRegexFilterTranslator.cs:593 in TranslateStringIndexOfComparison
      • src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToFilterTranslators/ExpressionTranslators/StringExpressionToRegexFilterTranslator.cs:349 in TranslateGetCharsComparison
      • src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToFilterTranslators/ExpressionTranslators/StringExpressionToRegexFilterTranslator.cs:739 in TranslateTrimEnd
      • src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToFilterTranslators/ExpressionTranslators/StringExpressionToRegexFilterTranslator.cs:755 in TranslateTrimStart
      • src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Filters/AstRegexFilterOperation.cs:46 in 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 control of the character sequence inside the regex character class whenever the application sources the char/char[] from external input; with two or more characters the attacker obtains an arbitrary regex sub-pattern confined to that one $regex predicate (cannot inject BSON operators, other fields, or commands).

      1. (source) src/MongoDB.Driver/Linq/Linq3Implementation/Misc/PartialEvaluator.cs:41 in EvaluatePartially — Application LINQ predicate captures an attacker-influenced char/char[] runtime value; the partial evaluator compiles the parameter-independent subtree into a ConstantExpression carrying the attacker's characters.
      2. (hop) src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToFilterTranslators/ExpressionTranslators/StringExpressionToRegexFilterTranslator.cs:566 in TranslateStringIndexOfComparison — GetConstantValue<char[]> extracts the attacker's character array from the IndexOfAny argument (char overload at line 572; trim chars at line 242; indexer comparand at line 341).
      3. (hop) src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToFilterTranslators/ExpressionTranslators/StringExpressionToRegexFilterTranslator.cs:224 in EscapeCharacterSet — Escape switch handles only space, '.', '-', '^', tab; backslash and ']' fall through the default case unescaped.
      4. (hop) src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToFilterTranslators/ExpressionTranslators/StringExpressionToRegexFilterTranslator.cs:593 in TranslateStringIndexOfComparison — Unescaped set spliced into '[^ {set}]{n}' / '[{set}

        ]' (lines 593, 601) — a ']' closes the class early and remaining attacker chars become raw regex; same splice in TranslateTrimEnd:739, TranslateTrimStart:755, TranslateGetCharsComparison:349.

      5. (sink) src/MongoDB.Driver/Linq/Linq3Implementation/Ast/Filters/AstRegexFilterOperation.cs:46 in Render — Broken/injected pattern emitted verbatim as the $regex value of the filter document and sent to the MongoDB server, whose regex engine compiles and executes it as the query predicate.

      Root cause

      • `EscapeCharacterSet` (StringExpressionToRegexFilterTranslator.cs:212-228) escapes only space, '.', '-', '^', and tab; the `default` case at line 224 passes '
        ' and ']' through unchanged.
      • The unescaped set is spliced into regex character classes: `[^ {escapedSet}]{n}` and `[{escapedSet}

        ]` for IndexOfAny/IndexOf(char) comparisons (lines 593, 597, 601), `[^...]` for char-indexer inequality (line 349), and lookaround/star classes for TrimEnd/TrimStart (lines 739, 755 via GetEscapedTrimChars at line 249).

      • A ']' member in a non-first position terminates the class early, so all subsequent attacker characters are emitted as raw regex syntax; a '
        ' member escapes the closing ']' leaving the class unterminated (server-side compile error) or corrupts the trailing '.*'.
      • `PartialEvaluator.EvaluatePartially` (Misc/PartialEvaluator.cs:41) evaluates captured runtime variables into ConstantExpressions, so attacker-influenced runtime values reach `GetConstantValue<char[]>` (ExpressionExtensions.cs:88 → translator lines 566, 572, 242, 341) exactly like literals; `AstRegexFilterOperation.Render` (AstRegexFilterOperation.cs:46) emits the pattern verbatim as the `$regex` value with no validation anywhere in between.

      Ownership

      Assigned teams: @mongodb/dbx-csharp-dotnet


      Filed from Aegis finding 3f2cf794768d (scan scan-320b0a32a42c) · primitive: Arbitrary regex syntax injection into a MongoDB query filter value via unescaped backslash and bracket characters in LINQ character-set translation. · categories: NoSQL Injection, Data Corruption, Error Information Leak, Resource Exhaustion

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

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

              Created:
              Updated:
              Resolved: