Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-12223

cleanupOrphaned command grants authentication of internal __system user to current connection

    XMLWordPrintableJSON

Details

    • Icon: Bug Bug
    • Resolution: Done
    • Icon: Critical - P2 Critical - P2
    • 2.5.5
    • 2.5.4
    • Security, Sharding
    • ALL
    • Hide

      function assertUnauthorized(res){
          if (res.ok == 0 && res.errmsg.startsWith('not authorized'))
              return;
       
          var finalMsg = "command worked when it should have been unauthorized: " + tojson(res);
          doassert(finalMsg);
      }
       
      var st = new ShardingTest({
          auth: true,
          keyFile: 'jstests/libs/key1'
      });
       
      st.stopBalancer();
       
      var mongos = st.s0;
      var mongosAdmin = mongos.getDB('admin');
      var coll = mongos.getCollection('foo.bar');
       
      assert.commandWorked(mongosAdmin.runCommand({
          enableSharding: coll.getDB().getName()
      }));
       
      assert.commandWorked(mongosAdmin.runCommand({
          shardCollection: coll.getFullName(),
          key: {_id: 'hashed'}
      }));
       
       
      var shardAdmin = st.shard0.getDB('admin');
      shardAdmin.createUser({'user':'admin', 'pwd': 'x', 'roles': ['clusterAdmin']});
       
      // the first attempt fails as expected
      assertUnauthorized(shardAdmin.runCommand({cleanupOrphaned: 'foo.bar'}));
       
      // authenticate
      shardAdmin.auth('admin', 'x');
       
      printjson(shardAdmin.runCommand('connectionStatus')); // Shows you are auth'd as admin@admin
       
      // the second attempt succeeds after authenticating (as expected)
      assert.commandWorked(shardAdmin.runCommand({cleanupOrphaned: 'foo.bar'}));
       
      printjson(shardAdmin.runCommand('connectionStatus')); // Shows you are auth'd as admin@admin AND __system@local
       
      // logging out seems to succeed
      assert.commandWorked(shardAdmin.logout());
       
      printjson(shardAdmin.runCommand('connectionStatus')); // Shows you are auth'd as __system@local
       
      // the third attempt does not fail after logging out (hence the assertion failure)
      assertUnauthorized(shardAdmin.runCommand({cleanupOrphaned: 'foo.bar'}));

      Show
      function assertUnauthorized(res){ if (res.ok == 0 && res.errmsg.startsWith('not authorized')) return;   var finalMsg = "command worked when it should have been unauthorized: " + tojson(res); doassert(finalMsg); }   var st = new ShardingTest({ auth: true, keyFile: 'jstests/libs/key1' });   st.stopBalancer();   var mongos = st.s0; var mongosAdmin = mongos.getDB('admin'); var coll = mongos.getCollection('foo.bar');   assert.commandWorked(mongosAdmin.runCommand({ enableSharding: coll.getDB().getName() }));   assert.commandWorked(mongosAdmin.runCommand({ shardCollection: coll.getFullName(), key: {_id: 'hashed'} }));     var shardAdmin = st.shard0.getDB('admin'); shardAdmin.createUser({'user':'admin', 'pwd': 'x', 'roles': ['clusterAdmin']});   // the first attempt fails as expected assertUnauthorized(shardAdmin.runCommand({cleanupOrphaned: 'foo.bar'}));   // authenticate shardAdmin.auth('admin', 'x');   printjson(shardAdmin.runCommand('connectionStatus')); // Shows you are auth'd as admin@admin   // the second attempt succeeds after authenticating (as expected) assert.commandWorked(shardAdmin.runCommand({cleanupOrphaned: 'foo.bar'}));   printjson(shardAdmin.runCommand('connectionStatus')); // Shows you are auth'd as admin@admin AND __system@local   // logging out seems to succeed assert.commandWorked(shardAdmin.logout());   printjson(shardAdmin.runCommand('connectionStatus')); // Shows you are auth'd as __system@local   // the third attempt does not fail after logging out (hence the assertion failure) assertUnauthorized(shardAdmin.runCommand({cleanupOrphaned: 'foo.bar'}));

    Description

      The cleanupOrphaned command calls into RangeDeleterDBEnv::deleteRange, which calls cc().getAuthorizationSession()->grantInternalAuthorization().

      This means that anyone with permission to run cleanupOrphaned can get privilege escalation because all they need to do is run cleanupOrphaned and now they are authenticated as the internal user, with full access to the system.

      Attachments

        Activity

          People

            randolph@mongodb.com Randolph Tan
            kamran.khan Kamran K.
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: