ExportXMLWordPrintableJSON

    • Type: Bug
    • Resolution: Fixed
    • Priority: Major - P3
    • 4.18.3
    • Affects Version/s: None
    • Component/s: BSON, Security
    • None
    • None
    • Python Drivers
    • Not Needed
    • Hide

      1. What would you like to communicate to the user about this feature?
      2. Would you like the user to see examples of the syntax and/or executable code and its output?
      3. Which versions of the driver/connector does this apply to?

      Show
      1. What would you like to communicate to the user about this feature? 2. Would you like the user to see examples of the syntax and/or executable code and its output? 3. Which versions of the driver/connector does this apply to?
    • None
    • None
    • None
    • None
    • None
    • None

      Detailed steps to reproduce the problem?

      The C extension's BSON decoder reads past the end of the caller's buffer when it decodes a truncated Regex element. On buffers without a NUL sentinel, such as mmap, the read can cross into unmapped memory and kill the process with SIGSEGV. The pure-Python decoder is not affected because it copies the input before decoding.

      The crafted document is 8 bytes, 080000000b610000: total length 8, type 0x0b (Regex), field name "a". The regex value is truncated. The pattern terminator is the document's last byte, so the flags string begins one byte past the document.

      • bson.decode of this document as bytes returns a document with Regex('', 0). The out-of-bounds read executes and lands on the NUL sentinel CPython appends to bytes. A conforming decoder must reject the document.
      • Write the document followed by 0xFF padding to 1 MiB into a file, mmap it read-only, and pass it to bson.decode_all. The flags strlen scans the padding to the end of the mapping and reads into unmapped memory.
      Fatal Python error: Segmentation fault
      
      Current thread 0x00000001f8556180 (most recent call first):
        File ".../bson/__init__.py", line 1164 in decode_all
      

      Root cause: in get_value (bson/_cbsonmodule.c), case 11 calls strlen twice on the element value before any check against max. For the document above, the second strlen starts one byte past the document. The read is allocator-dependent: bytes, bytearray, and memoryview slices of a bytearray carry a sentinel, while mmap and array do not.

      Reachability and impact:

      • bson.decode and bson.decode_all document data as "any bytes-like object that implements the buffer protocol", and the _ReadableBuffer type includes mmap and array. An application that decodes an untrusted BSON file from an mmap is using the documented API correctly, and a malformed document kills the process. A SIGSEGV cannot be caught or handled, so the failure is unrecoverable, unlike InvalidBSON on sentinel-backed buffers.
      • Impact is availability only. The out-of-bounds bytes never reach the caller as content. The pattern cannot cross the document's terminator, and the flags bytes only map onto six regex flag bits.
      • Not reachable from the driver's wire path today. The transport decodes from a bytearray, which carries the same sentinel. The crash needs an application-supplied non-sentinel buffer.

      Definition of done: what must be done to consider the task complete?

      • Decoding a malformed Regex element raises InvalidBSON on every accepted buffer type. Valid documents decode unchanged.
      • Regression tests add the crafted input in both bytes and mmap form. A bytes-only test passes with or without the fix, so it does not cover the defect.
      • Security assessment: CWE-125 in bson.decode and bson.decode_all, reachable through the documented public API. Proposed for a CVE. Impact is availability only.

      The exact Python version used, with patch level:

      3.11.9. Any interpreter that loads the C extension is affected; the decoder C code is interpreter-independent. The bug was introduced in PyMongo 0.10.3 (2009).

      The exact version of PyMongo used, with patch level:

      4.18.0.dev0 at master, C extension in use (pymongo.has_c() returns True).

      Describe how MongoDB is set up. Local vs Hosted, version, topology, load balanced, etc.

      Not applicable. The failure needs no server; it triggers on decoding a crafted document.

      The operating system and version (e.g. Windows 7, OSX 10.8, ...)

      Reproduced on macOS 15 (arm64). The defect is in platform-independent C code.

      Web framework or asynchronous network library used, if any, with version (e.g. Django 1.7, mod_wsgi 4.3.0, gevent 1.0.1, Tornado 4.0.2, ...)

      None.

      Security Vulnerabilities

      Found internally during the fuzzing audit in PYTHON-5848. A type-code audit of get_value found that only cases 8 and 11 read value data without checking max first. Case 8's read lands on the document terminator and is harmless. Case 11 is the defect described above.

            Assignee:
            Steve Silvester
            Reporter:
            Steve Silvester
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: