I recently setup my first MongoDB database in an production environment. I looked up some guides for deployment and followed them.
I had the following in my config:
# Where and how to store data. storage: dbPath: /var/lib/mongodb journal: enabled: true # engine: # mmapv1: # wiredTiger: # where to write logging data. systemLog: destination: file logAppend: true path: /var/log/mongodb/mongod.log # network interfaces net: port: 27017 bindIp: 127.0.0.1 # how the process runs processManagement: timeZoneInfo: /usr/share/zoneinfo security: authorization: "enabled"
And I created an admin user (the only user) that looks like this:
{ "_id" : "admin.admin", "userId" : UUID("6dfe010f-1e62-4801-9c07-5a408b8c75c6"), "user" : "admin", "db" : "admin", "credentials" : { [omitted, but contains SCRAM-SHA-1 and SCRAM-SHA-256 hashes] }, "roles" : [ { "role" : "userAdminAnyDatabase", "db" : "admin" }, { "role" : "readWriteAnyDatabase", "db" : "admin" }, { "role" : "dbAdminAnyDatabase", "db" : "admin" } ]
I also switched the outward facing port for the database (through nginx) to a nearby port that wasn’t the default.
With all of that, I still got hacked and I was greeted with this when I got onto nosqlbooster.
Fortunately for me, I wasn’t storing any sensitive information (just an aggregation of data pulled from a variety of other services) and all of the data can easily be regenerated. However, I’d rather not have this type of thing happen again.
I did some digging in the logs and found the moment they connected:
{ "t": { "$date": "2021-02-04T22:10:38.614+00:00" }, "s": "I", "c": "ACCESS", "id": 20250, "ctx": "conn75191", "msg": "Successful authentication", "attr": { "mechanism": "SCRAM-SHA-256", "principalName": "admin", "authenticationDatabase": "admin", "client": "127.0.0.1:39722" } }{ "t": { "$date": "2021-02-04T22:11:21.521+00:00" }, "s": "I", "c": "NETWORK", "id": 51800, "ctx": "conn75192", "msg": "client metadata", "attr": { "remote": "127.0.0.1:39918", "client": "conn75192", "doc": { "driver": { "name": "PyMongo", "version": "3.11.2" }, "os": { "type": "Linux", "name": "Linux", "architecture": "x86_64", "version": "5.8.0-41-generic" }, "platform": "CPython 3.8.6.final.0" } } }
Shortly after that login, I can see them drop my database and insert the note. Funny enough, it looks like they never saved the data, so the whole thing is obviously a scam. I also checked the auth.log
for the server to ensure that nobody logged into the server itself, so I’m pretty sure they haven’t tampered with the filesystem unless they did some magic through nginx.
I did some testing with authentication off and found that you can have an “authenticated” connection with the incorrect password if authentication is off. At this point, my question is: Are there any ways to get in without knowing the password if my config is set as specified above and my mongo server has been restarted since the last configuration change? Or is the only possibility that they have my password? I’m completely stumped. Around a week before the attack, I tried logging in with incorrect passwords to ensure that authorization was enabled correctly. I got denied as expected.
In case it’s relevant, here’s the rule for my MongoDB port in Nginx:
stream { server { listen 27018; proxy_connect_timeout 1s; proxy_timeout 3s; proxy_pass stream_mongo_backend; } upstream stream_mongo_backend { server 0.0.0.0:27017; } }
Advertisement
Answer
Yes, when authentication is enabled you can connect to the Mongo database without any credentials. However, apart from harmless commands like db.help(), db.getMongo(), db.listCommands(), db.version()
, etc. you can’t execute anything.
Obviously the hacker connected from localhost with valid credentials, so it looks like he got access to your machine. Maybe he read your application python script which has the password.
NB, you write only the admin
user was created. You should use the admin account only for administrative task and keep the password private. The application should not run under such admin account, it should use a dedicated account having only the permissions which are required to run the application.