How to Find and Fix Insecure MongoDB Instances

Unprotected MongoDB databases on the Internet have resulted in over 3.5 billion records stolen in the last 6 months. We wrote a scanner to help you find insecure MongoDB instances in your organization. Let’s have a deeper look at this.

Since last September, when Veeam revealed a massive data breach of 445 million records, MongoDB has been getting the kind of attention you don’t want. Lax default security settings, and a security team that didn’t bother tightening them up, resulted in the Veeam database being left wide open on a publicly-facing IP. Security researchers, namely Bob Diachenko, and undoubtedly a swarm of bad actors, keyed in on the idea that if Veeam’s MongoDB instance was left in the open, maybe there were others. Boy howdy, there were.

Since then, we’ve seen a slew of wide open MongoDB databases that have resulted in over 3.5 billion records stolen of personal and private data. Examples include:

  • 200 million records containing resume information from Chinese job-seekers
  • 763 million records from an unprotected, public MongoDB database from Verifications.io
  • 2.19 billion records, total from the colossal Collections #1 – #5 breaches
  • 364 million records of Chinese social media profiles

In this post, we show you how to use a MongoDB security scanner we wrote to find unprotected MongoDB instances in your organization.  Once you’ve identified open databases, we’ll outline how to apply minimal security to the database so you can make recommendations to the database owners, or fix it yourself, depending on your environment.

Scanning for Insecure MongoDB Instances

We created a scanner to find open MongoDB instances, which you can find on our Github. This scanner takes as input a list of IP addresses, and attempts to connect to MongoDB on each one. It tries to execute a database listing in each instance, an operation that will be denied if Authentication is enabled and things are even moderately secure.

Here is an example of running the scanner:

python mscan.py iplist outfile

The output will enumerate each open MongoDB instance found:

Preparing to scan 7 IP addresses
SUCCESS -- Connected to open MongoDB at IP 192.241.229.61
SUCCESS -- Connected to open MongoDB at IP 160.16.238.21
SUCCESS -- Connected to open MongoDB at IP 13.59.2.52
SUCCESS -- Connected to open MongoDB at IP 52.199.158.48

The scanner writes each successful IP to an output file, which can then be used to diagnose further each MongoDB instance.

The scanner also supports a DEBUG mode in which MongoDB system info is written to stdout, as well as a listing of the databases found in the instance.

WARNING: Our intention with this utility is to provide a very simple way to scan for insecure MongoDB instances in your own environment, with minimal dependencies. Don’t scan IP’s that aren’t yours!

MongoDB Security: From Zero to Something

A default installation of MongoDB implements nearly zero security. No authentication, no default passwords, no user accounts, no SSL, etc. It’s no wonder these databases find themselves wide open.

If you find a database in this state, which you can use the scanner to find, alert the application or database owner immediately, using the verbose debug logging from the utility.

MongoDB provides a recommended security checklist, which should be followed, particularly for production and/or Internet-facing databases.

As an example of basic safeguard for MongoDB, we’ll show how to add basic user authentication, which is more security than the databases that resulted in 3 billion records stolen had.

(note these steps are for Ubuntu platforms)

Add an Administrator User

We’re going to add an administrative user, then grant to that user.

Connect to the MongoDB shell:

$ mongo

You’ll see output similar to the following. Note that we are warned that access control is not enabled for this database.

Preparing to scan 7 IP addresses
MongoDB shell version v3.4.20
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.4.20
Server has startup warnings:
2019-03-12T17:16:49.591-0700 I STORAGE [initandlisten]
2019-03-12T17:16:49.591-0700 I STORAGE [initandlisten] ** WARNING: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine
2019-03-12T17:16:49.591-0700 I STORAGE [initandlisten] ** See http://dochub.mongodb.org/core/prodnotes-filesystem
2019-03-12T17:16:49.644-0700 I CONTROL [initandlisten]
2019-03-12T17:16:49.644-0700 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database.
2019-03-12T17:16:49.644-0700 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted.
2019-03-12T17:16:49.644-0700 I CONTROL [initandlisten]
2019-03-12T17:16:49.645-0700 I CONTROL [initandlisten]
2019-03-12T17:16:49.645-0700 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
2019-03-12T17:16:49.645-0700 I CONTROL [initandlisten] ** We suggest setting it to 'never'
2019-03-12T17:16:49.645-0700 I CONTROL [initandlisten]

Our example admin user can be named anything we want. The assignment of the role userAdminAnyDatabase gives our admin it’s permissions.

Set the username by typing the following into the mongo shell:

> use admin
> db.createUser(
> {
> user: "mAdmin",
> pwd: "5BTq8%jQ",
> roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
> }
< )

You should see output similar to this:

 > use admin
switched to db admin
> db.createUser(
... {
... user: "Admin",
... pwd: "password",
... roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
... }
... )
Successfully added user: {
"user" : "Admin",
"roles" : [
{
"role" : "userAdminAnyDatabase",
"db" : "admin"
}
]
}
>

Enter “exit” and press ENTER or press CTRL+C to leave the shell.

WARNING: Adding a user with access control privileges, as we have done, is great, and while this user may now enter credentials to log in to the database, they are not required to. Authentication enforcement must be manually enabled. Do not stop after just creating a user with access controls.

User Authentication

Open the MongoDB configuration file:

$ sudo vi /etc/mongod.conf

In the #security section there are several commented settings that an administrator would merely need to uncomment to enable. Not authentication! An addtional parameter must be added, so your security section should look like this:

. . .

security:

authorization: "enabled"

. . .

Ensure that “#security” has no spaces in front of it, and that the “authorization” line is indented with two spaces.

Save, exit, and restart the mongodb daemon:

$ sudo systemctl restart mongod

Ensure the daemon started correctly (if there’s an error in the conf file, it won’t start):

$ sudo systemctl status mongod

You should see active (running) if the daemon is running correctly.

At this point, you’ve added user authentication and access control to MongoDB.

Verifying Your Work

Check the security of the MongoDB instance by re-running the scanner.

$ python mscan.py local.txt out
Preparing to scan 1 IP addresses
not authorized on admin to execute command { listDatabases: 1, nameOnly: true }

You can learn more about Authentication, Role-Based Access Control, and other security controls from the MongoDB security configuration checklist.

By | 2019-03-18T15:34:48+00:00 March 13th, 2019|Data Breach, Database, How-To|0 Comments