MongoDB User-triggerable NULL pointer dereference due to utter plebbery

2013.06.01
Credit: Kurt Seifried
Risk: Medium
Local: Yes
Remote: No
CVE: N/A
CWE: N/A

https://jira.mongodb.org/browse/PYTHON-532 Short summary: Step 1. Use Mongo as WEB SCALE DOCUMENT STORE OF CHOICE LOL Step 2. Assume basic engineering principles applied throughout due to HEAVY MARKETING SUGGESTING AWESOMENESS. Step 3. Spend 6 months fighting plebbery across the spectrum, mostly succeed. Step 4. NIGHT BEFORE INVESTOR DEMO, TRY UPLOADING SOME DATA WITH "{$ref: '#/mongodb/plebtastic'" Step 5. LOL WTF?!?!? PYMONGO CRASH?? :OOO LOOOL WEBSCALE Step 6. It's 4am now. STILL INVESTIGATING b4cb9be0 pymongo/_cbsonmodule.c (Mike Dirolf 2009-11-10 14:54:39 -0500 1196) /* Decoding for DBRefs */ Oh Mike!!! 3. ADD process_dbrefs=False TO ALL THE DRIVERS To reproduce: - in mongo shell: db.python532.insert({x : {"$ref" : "whatever"} }); - in python shell import pymongo pymongo.MongoClient().test.python532.find_one() Fix: https://github.com/mongodb/mongo-python-driver/commit/a060c15ef87e0f0e72974c7c0e57fe811bbd06a2 BTW can someone from 10gen contact me so we can start doing the CVEs for MongoDB properly? Thanks. - -- Kurt Seifried Red Hat Security Response Team (SRT) bson/__init__.py View file @ a060c15 @@ -150,7 +150,7 @@ def _get_object(data, position, as_class, tz_aware, uuid_subtype): object = _elements_to_dict(encoded, as_class, tz_aware, uuid_subtype) position += obj_size if "$ref" in object: - return (DBRef(object.pop("$ref"), object.pop("$id"), + return (DBRef(object.pop("$ref"), object.pop("$id", None), object.pop("$db", None), object), position) return object, position bson/_cbsonmodule.c View file @ a060c15 @@ -1202,8 +1202,14 @@ static PyObject* get_value(PyObject* self, const char* buffer, int* position, Py_INCREF(collection); PyDict_DelItemString(value, "$ref"); - Py_INCREF(id); - PyDict_DelItemString(value, "$id"); + + if (id == NULL) { + id = Py_None; + Py_INCREF(id); + } else { + Py_INCREF(id); + PyDict_DelItemString(value, "$id"); + } if (database == NULL) { database = Py_None; test/test_collection.py View file @ a060c15 @@ -30,6 +30,7 @@ from bson.binary import Binary, UUIDLegacy, OLD_UUID_SUBTYPE, UUID_SUBTYPE from bson.code import Code +from bson.dbref import DBRef from bson.objectid import ObjectId from bson.py3compat import b from bson.son import SON @@ -1675,6 +1676,31 @@ def test_bad_encode(self): self.assertRaises(InvalidDocument, c.save, {"x": c}) warnings.simplefilter("default") + def test_bad_dbref(self): + c = self.db.test + c.drop() + + # Incomplete DBRefs. + self.assertRaises( + InvalidDocument, + c.insert, {'ref': {'$ref': 'collection'}}) + + self.assertRaises( + InvalidDocument, + c.insert, {'ref': {'$id': ObjectId()}}) + + ref_only = {'ref': {'$ref': 'collection'}} + id_only = {'ref': {'$id': ObjectId()}} + + # Force insert of ref without $id. + c.insert(ref_only, check_keys=False) + self.assertEqual(DBRef('collection', id=None), c.find_one()['ref']) + c.drop() + + # DBRef without $ref is decoded as normal subdocument. + c.insert(id_only, check_keys=False) + self.assertEqual(id_only, c.find_one()) + def test_as_class(self): c = self.db.test c.drop()

References:

https://github.com/mongodb/mongo-python-driver/commit/a060c15ef87e0f0e72974c7c0e57fe811bbd06a2
https://jira.mongodb.org/browse/PYTHON-532


Vote for this issue:
100%
0%


 

Thanks for you vote!


 

Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.


(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2024, cxsecurity.com

 

Back to Top