-
Type:
Bug
-
Resolution: Fixed
-
Priority:
Major - P3
-
Affects Version/s: None
-
Component/s: None
-
None
-
0.2
-
Dotnet Drivers
-
Not Needed
-
None
-
None
-
None
-
None
-
None
-
None
Summary
A user who can supply extra GeoJSON fields can silently replace a shape's type or coordinates, changing what geo queries match or what gets stored.
Impact
An application user can override the effective geometry type or coordinates of geo queries and stored documents, bypassing application-side validation and geography-based business rules, with the corruption persisted and invisible to driver-side read-back.
Severity: high
Exploitability: exploitable — The attacker fully controls both the injected key name and its BsonValue; a single extra member named 'coordinates' deterministically overrides the geometry with no timing, race, or memory conditions.
Customer data: customer_content, customer_metadata (api_response)
Location
- src/MongoDB.Driver/GeoJsonObjectModel/Serializers/GeoJsonObjectSerializerHelper.cs:180 in SerializeExtraMembers
- src/MongoDB.Driver/GeoJsonObjectModel/GeoJsonObjectArgs.cs:39 in GeoJsonObjectArgs.ExtraMembers
- src/MongoDB.Driver/GeoJsonObjectModel/Serializers/GeoJsonObjectSerializerHelper.cs:121 in SerializeMembers
- src/MongoDB.Driver/FilterDefinitionBuilder.cs:2056 in GeometryOperatorFilterDefinition.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 injected element name and its arbitrary BsonValue for any key the application places in a GeoJSON object's extra members — including the reserved names 'type', 'coordinates', 'bbox', and 'crs'.
- (source) src/MongoDB.Driver/GeoJsonObjectModel/GeoJsonObjectArgs.cs:39 in GeoJsonObjectArgs.ExtraMembers — Application places caller/user-supplied key-value pairs (e.g. GeoJSON foreign members from an untrusted client) into the unvalidated ExtraMembers BsonDocument.
- (hop) src/MongoDB.Driver/GeoJsonObjectModel/GeoJsonObject.cs:45 in GeoJsonObject (constructor) — The attacker-influenced BsonDocument is stored by reference into the GeoJson object; it remains mutable via the getter after construction.
- (hop) src/MongoDB.Driver/GeoJsonObjectModel/Serializers/GeoJsonPointSerializer.cs:97 in SerializeValue — Point serializer (representative of all GeoJson serializers) delegates all member writing to the shared helper.
- (hop) src/MongoDB.Driver/GeoJsonObjectModel/Serializers/GeoJsonObjectSerializerHelper.cs:121 in SerializeMembers — Extra members are written last, after 'type', 'crs', 'bbox', and the legitimate 'coordinates' have already been emitted.
- (sink) src/MongoDB.Driver/GeoJsonObjectModel/Serializers/GeoJsonObjectSerializerHelper.cs:180 in SerializeExtraMembers — Every extra-member name is written verbatim with WriteName — a reserved name becomes a second, later duplicate key that last-wins readers resolve to the attacker's value.
- (hop) src/MongoDB.Driver/FilterDefinitionBuilder.cs:2056 in GeometryOperatorFilterDefinition.Render — Egress: the duplicate-key geometry is embedded under '$geometry' in a geo query filter (or in an inserted document) sent to the MongoDB server, whose query engine interprets it last-wins.
Root cause
- `GeoJsonObjectArgs.ExtraMembers` is a publicly settable BsonDocument with no element-name validation (src/MongoDB.Driver/GeoJsonObjectModel/GeoJsonObjectArgs.cs:39), stored by reference into the immutable-looking GeoJson object (src/MongoDB.Driver/GeoJsonObjectModel/GeoJsonObject.cs:45).
- `SerializeMembers` writes `type`, `crs`, `bbox`, then the derived `coordinates` member, then extra members last (src/MongoDB.Driver/GeoJsonObjectModel/Serializers/GeoJsonObjectSerializerHelper.cs:116-121; coordinates written at src/MongoDB.Driver/GeoJsonObjectModel/Serializers/GeoJsonPointSerializer.cs:108).
- `SerializeExtraMembers` emits every extra-member name verbatim via WriteName with no check against the reserved names already written (src/MongoDB.Driver/GeoJsonObjectModel/Serializers/GeoJsonObjectSerializerHelper.cs:180), producing duplicate-key BSON.
- The poisoned geometry is embedded into `$geoWithin`/`$geoIntersects`/`$near` filters under `$geometry` (src/MongoDB.Driver/FilterDefinitionBuilder.cs:2056) and into inserted/replaced documents; MongoDB's last-wins duplicate-key handling makes the injected value the effective one, and the driver's own deserializer is also last-wins (src/MongoDB.Bson/Serialization/Serializers/SerializerHelper.cs:106), so read-back never reveals the spoof.
Ownership
Assigned teams: @mongodb/dbx-csharp-dotnet
Filed from Aegis finding 3131c6ea3129 (scan scan-4dd77e1a1432) · primitive: Attacker-named extra member serialized as a second reserved key, so last-wins BSON parsing swaps effective geometry type or coordinates in queries and stored documents. · categories: NoSQL Injection, Data Corruption, Silent Data Truncation