[SERVER-5985] It sound a loophole on MongoDB Shard Authentication Created: 01/Jun/12  Updated: 15/Aug/12  Resolved: 09/Aug/12

Status: Closed
Project: Core Server
Component/s: Security, Stability
Affects Version/s: 2.0.5
Fix Version/s: None

Type: Question Priority: Critical - P2
Reporter: swordsman Assignee: Spencer Brody (Inactive)
Resolution: Duplicate Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Centos 5.8, MongoDB 2.0.5, php 5.3.11, php mongo driver 1.3 and rockmongo v1.1.1;


Attachments: Zip Archive config.zip    
Issue Links:
Depends
Participants:

 Description   

i use 2 server for setup mongodb.

Server A:
rs_a/shardserv 27001,shardserv 27002,Arbiter 27003
rs_b/shardserv 29001,shardserv 29002,Arbiter 29003
configserv 31001,configserv 31002,configserv 31003

Server B:
mongos 27017
+ Rockmongo

As usual, i use rockmongo to connect to mongodb cluster. I have created a database with 1 normal user and 1 readonly user. When i first connect to mongodb cluster, it is normal and correct which just show 1 database. However, when i try to click on the database (refresh) a lot of times, it suddenly list all the database include admin, and the worst you can add admin user.

Is that anything wrong, it a bugs or setup problem?



 Comments   
Comment by Spencer Brody (Inactive) [ 09/Aug/12 ]

Resolving as a duplicate of PHP-315

Comment by Jeremy Mikola [ 11/Jun/12 ]

Apologies for the delayed response. There are already some issues tracking sharding and authentication, so the engineering team is aware; however, I think your problem is specific to the PHP driver's connection re-use. Please follow up once Derick's rewrite is released (and the problem persists).

Comment by swordsman [ 06/Jun/12 ]

Thanks for replying...

I will take Derick advice on creating Mongodb connection at the moment, and look forward for newer PHP Mongo Driver.

About the readonly access thru mongos, after clean all the 'lock file', problem still appear. Should i report it as bugs? or MongoDB Development team was aware on this issue.

Comment by Derick Rethans [ 05/Jun/12 ]

Just a quick note; we're working on re-doing the connection handling code- including making sure the driver doesn't re-use a connection with a different user. I would however suggest that you don't use

authenticate()

but instead add the username and password to your connection string. That I think might have a good chance of mitigating the problem. So instead of:

$m = new Mongo("mongodb://xxx:27017" );
$db = $m->activitydb;
$a = $db->authenticate('trackingread' , 'xxx');

Use:

$m = new Mongo("mongodb://trackingread:password@xxx:27017/activitydb" );
$db = $m->activitydb;

The new driver code will only allow authentication through this as well.

Comment by Jeremy Mikola [ 05/Jun/12 ]

The first issue definitely looks like a connection caching issue. The extension is re-using connections that it should not. I'd wager it doesn't appear until after you've connected with the admin user at least once through PHP. If you're using lighttpd, are you also using PHP FPM? The cached connections hang around in shared memory for the PHP worker process. Restarting Apache with mod_php would flush that, but I'd expect restarting PHP FPM alone would do the same for something like lighttpd/nginx, since PHP isn't so closely tied to the web server.

Regarding your section question, the two console commands actually differ a bit in their code. You can view the JS on the console by accessing the function itself (without invoking it):

$ mongo
MongoDB shell version: 2.1.0
connecting to: test
> db.serverStatus
function () {
    return this._adminCommand("serverStatus");
}
> db.runCommand
function (obj) {
    if (typeof obj == "string") {
        var n = {};
        n[obj] = 1;
        obj = n;
    }
    return this.getCollection("$cmd").findOne(obj);
}
> db._adminCommand
function (obj) {
    if (this._name == "admin") {
        return this.runCommand(obj);
    }
    return this.getSiblingDB("admin").runCommand(obj);
}
>

Arguably, I think the two should be consistent, but this explains why only db.serverStatus() requires auth credentials.

For your last question, is there any chance you have a stale lock file on disk, which might be retaining lesser auth credentials? See http://stackoverflow.com/questions/9297544/mongo-commandline-admin-auth-fails. Otherwise, that sounds like a bug.

Comment by swordsman [ 05/Jun/12 ]
  • I try both, the PECL 1.2.10 & compile from source 1.3.0dev;
  • After i create a database call activitydb, i create 1 normal user call 'tracking' and 1 readonly user call 'trackingread'
  • I cannot reproduce it via command-line interface connected to mongos, and yes it only appearing through rockmongo and PHP. I believe it is there is some caching problem in the driver.....
    To reproduce...
    Thru rockmongo
  • Login thru rockmongo connected to mongos with normal user. (only can browse the database, looks ok)
  • Logout
  • Login with admin user. (can browse all database, looks ok)
  • Logout
  • Login with normal user again. (if you see 1 database, try to click multiple time, then it suddenly show all database, and able to do admin command)

Thru PHP

  • Sample:
    $m = new Mongo("mongodb://xxx:27017" );
    $db = $m->activitydb;
    $a = $db->authenticate('trackingread' , 'xxx');
    print_r($a );
    $collection = $db->activitydb;
    echo "\n Total Records : ".print_r($collection->count() )."\r\n";
    $obj = array("myid" => 123412412 );
    $a = $collection->insert($obj , array("safe"=>true));
    print_r($a );
  • After u logout from admin user in rockmongo (firefox), open another browser(chrome), browse the similar script, it still able to insert data using readonly access.
  • Only after i restart lighttpd (web server), it only show 'unauthorized' insert.

Others questions:
1st) In normal database user, in command-line, although we cannot execute db.serverStatus(), but we can execute db.runCommand(

{ serverStatus : 1 }

); It should be same behavior rite?
Example:
db.serverStatus()
=> Result:

{ "ok" : 0, "errmsg" : "unauthorized" }

db.runCommand(

{ serverStatus : 1 }

);
=> ......Show status

2nd) When i connect to mongos, i found that readonly user not working even in command-line interface. What i expect is readonly to particular database, but it totally cannot read at all. It that the features not ready yet in mongos?
Example:
[chenlin@shrimp bin]$ ./mongo localhost:27017
MongoDB shell version: 2.0.5
connecting to: localhost:27017/test
> use activitydb
switched to db activitydb
> db.auth('trackingread','xxx');
1
> show collections
Tue Jun 5 10:00:56 uncaught exception: error:

{ "$err" : "unauthorized", "code" : 15845 }

> db.test.find();
error:

{ "$err" : "unauthorized", "code" : 15845 }
Comment by Jeremy Mikola [ 01/Jun/12 ]

I'm going to try to reproduce this locally. In the meantime, can you answer the following?

  • What version of the PECL driver are you using? 1.2.10 is the latest version listed on http://pecl.php.net/package/mongo
  • What are the usernames of the normal and readonly users?
  • Can you reproduce this authentication loophole via the command-line interface connected to `mongos`, or is it only appearing through rockmongo and PHP?
Generated at Thu Feb 08 03:10:26 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.