Integer Overflow in explodeForSort() lets authenticated query trigger mongod OOM denial of service

    • Type: Bug
    • Resolution: Unresolved
    • Priority: Major - P3
    • None
    • Affects Version/s: 8.3.2
    • Component/s: None
    • None
    • Query Optimization
    • ALL
    • Hide

      1. Run MongoDB with the affected code path.
      2. Create or use a collection with compound index

      {a:1,b:1,c:1,d:1,e:1}

      .
      3. Send a normal find({a:{$in:[0..65535]}, b:{$in:[0..65535]}, c:{$in:[0..65535]}, d:{$in:[0..65535]}}).sort(

      {e:1}

      ) query.
      4. Observe planner math 65536^4 = 2^64 wraps to 0 on 64-bit size_t.
      5. Observe bypass of maxScansToExplode safeguard and entry into Cartesian-product materialization.
      6. Observe disconnect and mongod OOM termination.

      Control

      • Restart service and run same shape with 200 values per $in array.
      • Expected: queryPlanner.maxScansToExplodeReached=True and no crash.

      Artifacts

      Show
      1. Run MongoDB with the affected code path. 2. Create or use a collection with compound index {a:1,b:1,c:1,d:1,e:1} . 3. Send a normal find({a:{$in: [0..65535] }, b:{$in: [0..65535] }, c:{$in: [0..65535] }, d:{$in: [0..65535] }}).sort( {e:1} ) query. 4. Observe planner math 65536^4 = 2^64 wraps to 0 on 64-bit size_t. 5. Observe bypass of maxScansToExplode safeguard and entry into Cartesian-product materialization. 6. Observe disconnect and mongod OOM termination. Control Restart service and run same shape with 200 values per $in array. Expected: queryPlanner.maxScansToExplodeReached=True and no crash. Artifacts Report: https://gist.github.com/YLChen-007/88e66ebaf6ef0965937131da5749675c
    • None
    • None
    • None
    • None
    • None
    • None
    • None

      Summary
      A post-auth denial of service vulnerability exists in MongoDB Server's query planner. A user who can issue ordinary find(...).sort(...) queries can supply four large $in predicates against a matching compound index so that QueryPlannerAnalysis::explodeForSort() overflows its scan-count multiplication, bypasses the maxScansToExplode safeguard, and proceeds into Cartesian-product materialization. In practice this can drive mongod into out-of-memory termination.

      Details

      • Bug location: src/mongo/db/query/planner_analysis.cpp inside QueryPlannerAnalysis::explodeForSort()
      • numScans starts at 1 and multiplies interval counts without overflow checking
      • with four fields of 65,536 values each, 65536^4 = 2^64 wraps to 0 on 64-bit size_t
      • wrapped value is accumulated into totalNumScans, so the later safeguard compares a false low value
      • execution proceeds into explodeNode() and makeCartesianProduct(), amplifying memory use

      Impact
      An authenticated user with ordinary query capability can send a specially crafted find().sort() request that terminates the mongod process through memory exhaustion.

      Affected versions
      <= r8.3.2

      Severity
      High (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H)

      Reference
      Private report gist: https://gist.github.com/YLChen-007/88e66ebaf6ef0965937131da5749675c

            Assignee:
            Unassigned
            Reporter:
            芽 菜
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: