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

changeOwnPassword privilege action should not allow users to list collections in the databases that they don't have read access to

    • Type: Icon: Bug Bug
    • Resolution: Works as Designed
    • Priority: Icon: Minor - P4 Minor - P4
    • None
    • Affects Version/s: None
    • Component/s: Security
    • Labels:
      None
    • ALL
    • Hide

      The following commands can be used to reproduce this issue in a MongoDB with auth enabled:

       

      changeOwnPasswordROLE and user333

       

      db.createRole(
      {
       role: "changeOwnPasswordROLE",
       privileges: [
         { resource: { db: "", collection: "" }, actions: [ "changeOwnPassword" ] }
       ],
       roles: [
       ]
      },
      { w: "majority" , wtimeout: 5000 }
      )use admindb.createUser(
      {
       "user" : "user333",
       "pwd" : "user333",
       "roles" : [
         { "role" : "changeOwnPasswordROLE", "db" : "admin" },
         { "role" : "read", "db" : "test" }
       ]
      }
      )db.system.roles.find( {role:"changeOwnPasswordROLE"} ).pretty()
      db.system.users.find({user:"user333"}).pretty()use admin
      db.auth('user333', 'user333')
      use db_xyz
      show collections
      

       


      readOnlyTestDBRole and user4444

       

       
      use admin
      db.createRole(
      {
       role: "readOnlyTestDBRole",
       privileges: [
       { resource: { db: "test", collection: "" }, actions: [ "find" ] }
       ],
       roles: [
       ]
      },
      { w: "majority" , wtimeout: 5000 }
      )
       
      db.createUser(
      {
       "user" : "user4444",
       "pwd" : "user4444",
       "roles" : [
       { "role" : "readOnlyTestDBRole", "db" : "admin" }
       ]
      }
      )
      db.system.roles.find( {role:"readOnlyTestDBRole"} ).pretty()
      
      db.system.users.find({user:"user4444"}).pretty()
       
      use admin
      db.auth('user4444', 'user4444')
      
      use db_xyz
      show collections
      

       

       

      Show
      The following commands can be used to reproduce this issue in a MongoDB with auth enabled:   changeOwnPasswordROLE and user333   db.createRole( { role: "changeOwnPasswordROLE" , privileges: [ { resource: { db: "", collection: " " }, actions: [ " changeOwnPassword" ] } ], roles: [ ] }, { w: "majority" , wtimeout: 5000 } )use admindb.createUser( { "user" : "user333" , "pwd" : "user333" , "roles" : [ { "role" : "changeOwnPasswordROLE" , "db" : "admin" }, { "role" : "read" , "db" : "test" } ] } )db.system.roles.find( {role: "changeOwnPasswordROLE" } ).pretty() db.system.users.find({user: "user333" }).pretty()use admin db.auth( 'user333' , 'user333' ) use db_xyz show collections   readOnlyTestDBRole   and user4444     use admin db.createRole( { role: "readOnlyTestDBRole" , privileges: [ { resource: { db: "test" , collection: "" }, actions: [ " find" ] } ], roles: [ ] }, { w: "majority" , wtimeout: 5000 } )   db.createUser( { "user" : "user4444" , "pwd" : "user4444" , "roles" : [ { "role" : "readOnlyTestDBRole" , "db" : "admin" } ] } ) db.system.roles.find( {role: "readOnlyTestDBRole" } ).pretty() db.system.users.find({user: "user4444" }).pretty()   use admin db.auth( 'user4444' , 'user4444' ) use db_xyz show collections    
    • Security 2019-11-04, Security 2019-11-18, Security 2019-12-02, Security 2019-12-16, Security 2019-12-30, Security 2019-01-13, Security 2019-01-27, Security 2020-02-24, Security 2020-03-09, Security 2020-03-23, Security 2020-04-06, Security 2020-04-20, Security 2020-05-04, Security 2020-05-18, Security 2020-06-01, Security 2020-06-15, Security 2020-07-13, Security 2020-10-05, Security 2020-11-02, Security 2021-01-11, Security 2021-01-25, Security 2021-02-08

      Currently, the changeOwnPassword privilege action allows users to list collections in the databases that they don't have read access to. I can demonstrate this with the help of the example below.


      Scenario#1:

      Consider the following role which has changeOwnPassword privilege action:

       

      > db.system.roles.find( {role:"changeOwnPasswordROLE"} ).pretty()
      { "_id" : "admin.changeOwnPasswordROLE", "role" : "changeOwnPasswordROLE", "db" : "admin", "privileges" : [ { "resource" :
      { "db" : "", "collection" : "" }
      , "actions" : [ "changeOwnPassword" ] } ], "roles" : [ ]}
       
      

      The user333 is assigned the above role, and has only read privileges on the test database:

      > db.system.users.find({user:"user333"}).pretty()
       
      { "_id" : "admin.user333", "user" : "user333", "db" : "admin", "credentials" : { "SCRAM-SHA-1" :
      { "iterationCount" : 10000, "salt" : "2m7Ka+0EbSS477cUD3R3pw==", "storedKey" : "vVpnmUgkO4PniimByVN/Npw8aLc=", "serverKey" : "b83ec/ifKvFKeU7TfSSsXxWwafA=" }
      , "SCRAM-SHA-256" : { "iterationCount" : 15000, "salt" : "cf2Bp7NwOF7p45IvynIq+TSY9j2wEVWuqAhMKQ==", "storedKey" : "WDsN8fX8S9Bmg3a/igVNNU50hRWrtc8RnLPs2g7poqk=", "serverKey" : "i1ggY39wbxLbYlVRSkyrJ2q/IwvQlFY4Umy+vqo1hyw=" } }, 
      "roles" : [ { 
      "role" : "changeOwnPasswordROLE", "db" : "admin" }, 
      { "role" : "read", "db" : "test" } 
      ]}
       
      

      When I authenticate as user333, switch to db_xyz and run show collections, it lists the collections:

       

      > use admin
      switched to db admin
      > db.auth('user333', 'user333')1
       
      > use db_xyz
      switched to db db_xyz
       > show collections
      test_collectionXYZ
      

       

       


      Scenario#2 

      Now, consider another role which has only find privilege action on the test database, with no changeOwnPassword privilege action:

       

      > db.system.roles.find( {role:"readOnlyTestDBRole"} ).pretty()
      { "_id" : "admin.readOnlyTestDBRole", "role" : "readOnlyTestDBRole", "db" : "admin", "privileges" : [ { "resource" :
      { "db" : "test", "collection" : "" }
      , "actions" : [ "find" ] } ], "roles" : [ ]}
      

       

      user4444 is assigned the above readOnlyTestDBRole role:

      > db.system.users.find({user:"user4444"}).pretty()
      { "_id" : "admin.user4444", "user" : "user4444", "db" : "admin", "credentials" : { "SCRAM-SHA-1" :
      { "iterationCount" : 10000, "salt" : "Ym4ZJL1+6HtXnq+IHI+kpg==", "storedKey" : "5lznucBoNy4OW6z4egMTwTK4K/s=", "serverKey" : "neUgsD0+AEAlFpaJAuw+1DU+Gt8=" }
      , "SCRAM-SHA-256" : { "iterationCount" : 15000, "salt" : "6J5NUB0VIW2wpud6EpQxsxcclyBO5mbLs2IA7w==", "storedKey" : "o2PYCZDS5NNMzq0E1v3k9vJGaAbyPnlYdPMONM2ZsuM=", "serverKey" : "cAJ3gjby9eC4KModk42ydHCemPjiMqyI33qeWAUjlmw=" } },
      "roles" : [ { "role" : "readOnlyTestDBRole", "db" : "admin" } ]}
      

       

      Now, if I authenticate as user4444, switch to db_xyz and run show collections, then it does not list the collections:

       

      > use admin
      switched to db admin
      > db.auth('user4444', 'user4444')1
       
      > use db_xyz
      switched to db db_xyz
       > show collections
      Warning: unable to run listCollections, attempting to approximate collection names by parsing connectionStatus
      

       


       

      Therefore, ideally a user who has changeOwnPassword privilege action should not be able to run show collections on a database that the user does not have read access to; such an action should fail with the above warning: "Warning: unable to run listCollections...". 

            Assignee:
            spencer.jackson@mongodb.com Spencer Jackson
            Reporter:
            harshad.dhavale@mongodb.com Harshad Dhavale
            Votes:
            1 Vote for this issue
            Watchers:
            9 Start watching this issue

              Created:
              Updated:
              Resolved: