ExportXMLWordPrintableJSON

    • None
    • 0.2
    • Minor Change
    • Dotnet Drivers
    • Not Needed
    • None
    • None
    • None
    • None
    • None
    • None

      Summary

      Someone who can hand an app a raw binary document can smuggle extra fields into, or delete fields from, the database commands the app sends.

      Impact

      Structural injection into MongoDB commands built by the application — added or removed query conditions, command options, and update/insert fields — enabling scope-filter bypass (cross-tenant reads), unauthorized writes, and persistent data corruption.
      Severity: high (upper bound critical)
      Exploitability: likely_exploitable — The attacker controls every byte of the slice including the length prefix; the driver-side chain is fully open, and exploitation only needs an app that forwards external BSON bytes via the raw/lazy document types.
      Customer data: customer_content, customer_metadata (api_response)

      Location

      • src/MongoDB.Bson/IO/BsonBinaryWriter.cs:518 in WriteRawBsonDocument
      • src/MongoDB.Bson/IO/BsonBinaryWriter.cs:496 in WriteRawBsonArray
      • src/MongoDB.Bson/IO/BsonStreamExtensions.cs:298 in WriteSlice
      • src/MongoDB.Bson/ObjectModel/RawBsonDocument.cs:61 in RawBsonDocument(byte[])
      • src/MongoDB.Bson/ObjectModel/LazyBsonDocument.cs:60 in LazyBsonDocument(byte[])
      • src/MongoDB.Bson/ObjectModel/RawBsonArray.cs:47 in RawBsonArray(IByteBuffer)
      • src/MongoDB.Bson/Serialization/Serializers/RawBsonDocumentSerializer.cs:70 in SerializeValue

      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 raw slice bytes: the declared inner length, and all element types/names/values, letting the attacker choose exactly which sibling fields appear in or disappear from the enclosing command document.

      1. (source) src/MongoDB.Bson/ObjectModel/RawBsonDocument.cs:61 in RawBsonDocument(byte[]) — Attacker-supplied byte blob is wrapped with no validation of the embedded length prefix against bytes.Length (delegates to the IByteBuffer ctor at :47-55 which only null-checks).
      2. (hop) src/MongoDB.Bson/Serialization/Serializers/RawBsonDocumentSerializer.cs:70 in SerializeValue — When the app embeds the raw document in a filter/update/insert, serialization hands value.Slice directly to the binary writer.
      3. (hop) src/MongoDB.Bson/IO/BsonBinaryWriter.cs:518 in WriteRawBsonDocument — Slice is written verbatim; no context is pushed so BackpatchSize and the MaxDocumentSize check are skipped (lines 520-533), and the inner prefix is never checked against slice.Length.
      4. (sink) src/MongoDB.Bson/IO/BsonStreamExtensions.cs:316 in WriteSlice — stream.WriteBytes emits the attacker bytes unmodified into the outbound OP_MSG; the server parses the enclosing command using the attacker's inner length prefix, shifting element boundaries (injection or absorption of sibling fields).

      Root cause

      • The public constructors RawBsonDocument(byte[]) (src/MongoDB.Bson/ObjectModel/RawBsonDocument.cs:61, delegating to :47-55), LazyBsonDocument(byte[]) (src/MongoDB.Bson/ObjectModel/LazyBsonDocument.cs:60), and RawBsonArray (src/MongoDB.Bson/ObjectModel/RawBsonArray.cs:47) accept arbitrary bytes and never compare the embedded int32 length prefix to the actual byte count.
      • Their serializers pass the slice straight to the writer (src/MongoDB.Bson/Serialization/Serializers/RawBsonDocumentSerializer.cs:70, LazyBsonDocumentSerializer.cs:63).
      • BsonBinaryWriter.WriteRawBsonDocument (src/MongoDB.Bson/IO/BsonBinaryWriter.cs:518) and WriteRawBsonArray (:496) copy the slice verbatim; no context is pushed, so BackpatchSize and the MaxDocumentSize check never run (:520-533).
      • WriteSlice (src/MongoDB.Bson/IO/BsonStreamExtensions.cs:298-320) only null-checks and emits slice.Length bytes at :316; the enclosing document's size is backpatched from actual stream position, so the outer OP_MSG stays wire-valid while the inner prefix decides where the server ends the subdocument — a short prefix injects the trailing bytes as sibling elements of the enclosing command, a long prefix absorbs subsequent app/driver-written fields into the attacker's subdocument.

      Ownership

      Assigned teams: @mongodb/dbx-csharp-dotnet


      Filed from Aegis finding 2d0a8fa0e921 (scan scan-e837ccfa32ab) · primitive: Attacker-chosen inner length prefix shifts element boundaries in the enclosing command, injecting sibling fields or absorbing following fields into the attacker's subdocument. · categories: NoSQL Injection, Data Corruption, Cross-Tenant Access

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

            Assignee:
            Ferdinando Papale
            Reporter:
            Boris Dogadov
            None
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: