Securing your MongoDB

Securing MongoDB must be a top priority for system administrators right now as ransom attacks are on the rise.  If you are using MongoDB to storing data on any public facing cloud server running on Linux, then you will need to make sure you lock it down properly to prevent hackers from gaining access to your data.  So, the big question … How do I go about securing my MongoDB from hackers?

Let’s start from the beginning: MongoDB is a free and open-source NoSQL document oriented database server.  Classified as a NoSQL database program, MongoDB uses JSON-like documents with schemas. MongoDB is developed by MongoDB Inc. and is free and open-source, published under a combination of the GNU Affero General Public License and the Apache License.

As of this writing, more than 28,000 MongoDB’s are being held for ransom by hackers demanding between .2 and 1 Bitcoin.

The hackers – with codenames Harak1r1, Kraken0, and 0wn3d – are scanning the web using Shodan for databases connected to the internet without adequate password protection. The dozen, or so, hackers are preying on weak files, extracting the information and demanding crypto-currency in return.  Additionally, like the more traditional form of email-based ransomware attack, messages are being inserted into the file about how to pay the fee.

One reads: “Your database has been pwned because it is publically accessible at port 27017 with no authentication (wtf were you thinking?). Your data has been dumped (with data types preserved), and is easily restoreable.  To get your data back, email the supplied email after sending 0.15BTC to the supplied Bitcoin wallet, do this quickly as after 72 hours your data will be erased (if an email is not sent by then). We will get back to you within 2 days. All of your data will be restored to you upon payment.”

One of the most active culprits, is Kraken0, a hacker who has reportedly compromised over 16,000 victims at the time of writing. This is followed by Harak1r1, who has claimed 4,174 and then 3lix1r who has accessed 3,304.

Securing MongoDB to Prevent a Ransomware Attack

MongoDB configuration assumptions:

  1. The default file is located at /etc/mongodb.conf
  2. The default port is TCP 27017
  3. MongoDB server version: 3.4.1

Limit network exposure

Edit the /etc/mongodb.conf or /usr/local/etc/mongodb.conf file, enter:
$ sudo vi /etc/mongodb.conf
If your web-app and MongoDB (mongod server) are installed on the same machine, set the IP address of MongoDB to 127.0.0.1 as this will cut communication directly from the internet:

# network interfaces
net:
  port: 27017
  bindIp: 127.0.0.1

However, it is possible that you may have a 3 tier model:

 

Securing MongoDB - 3 Tier Application Model Diagram
  • LinkedIn

You need to bind mongod to 192.168.1.7 so that it can be only accessed over VLAN:

  bindIp: 192.168.1.7

The bind_ip directive ensures that MongoDB runs in a trusted network environment and limit the interfaces on which MongoDB instances listen for incoming connections.

Change the default port

The default TCP port used for MongoDB is 27017.  It is recommended that you change the default port. For example set it to 2887:

port: 2887

Save and close the file. You need to restart MongoDB, enter:
$ sudo systemctl restart mongod

Verify open ports with netstat command:
$ netstat -tulpn | grep 2887
Sample outputs:

tcp        0      0 127.0.0.1:2887         0.0.0.0:*               LISTEN      6818/mongod

From this point forward, all commands and output displayed will reference this changed port.  

Setup access control

You need to add a user administrator to a MongoDB instance running without access control and in order to enable access control.  By default anyone can connect to the MongoDB and this is lack of security is one of the mechanisms the hackers are using to access the database.

Connect to the DB instance, create the user administrator, turn on security and then restart mongo:

$ mongo
## or ##
$ mongo --port 2887
MongoDB shell version: 2.6.10
connecting to: test

You need to use admin database. Type the following command at > prompt to create your superuser:
> use admin
switched to db admin

Next create the user administrator in the admin database with the userAdminAnyDatabase role:
> db.createUser({user:"administrator",pwd:"SomethingVerySecure", roles:[{role:"userAdminAnyDatabase",db:"admin"}]})
Sample outputs:

Successfully added user: {
	"user" : "administrator",
	"roles" : [
		{
			"role" : "userAdminAnyDatabase",
			"db" : "admin"
		}
	]
}

Disconnect the mongo shell by typing the following command:
> exit
bye
$

Warning: Create the administrator user with strong password.  For demonstration purposes, the command is using ‘SomethingVerySecure’ but you should use your own strong password.

Note:  the user you defined as the administrator does not have to be called administrator.  It is best practice to obfuscate the administrator account with a random name.

Edit the /etc/mongodb.conf or /usr/local/etc/mongodb.conf file, enter:
$ sudo vi /etc/mongodb.conf
Turn on security:

security:
  authorization: enabled

Save and close the file. Re-start the Mongo instance:
$ sudo systemctl restart mongodb

To authenticate during connection using user administrator and password for the admin database:
$ mongo -u administrator -p SomethingVerySecure --authenticationDatabase admin
Add additional user to your DB. First create a new database called “fortify24x7”:
> use fortify24x7
switched to db fortify24x7

Create a user named ‘jeremy’ with a password named ‘ILoveHockey’ for fortify24x7 database:

db.createUser( 
  { 
    USER: "jeremy", 
    pwd: "ILoveHockey",
    roles: [ { ROLE: "readWrite", db: "fortify24x7" }, { ROLE: "read", db: "reporting" } ] 
  } 
)

Sample output:

Successfully added user: {
	"user" : "jeremy",
	"roles" : [
		{
			"role" : "readWrite",
			"db" : "fortify24x7"
		},
		{
			"role" : "read",
			"db" : "reporting"
		}
	]
}

You can now connect to fortify24x7 databse like this:
$ mongo --port 2887 -u "jeremy" -p "ILoveHockey" --authenticationDatabase "fortify24x7"

Securing MongoDB with the Firewall

Use firewalls to restrict which other entities are allowed to connect to your mongodb server.  In this example, I show how to only allow your web & application servers access to the database using ufw on Ubuntu or Debian Linux:
$ sudo ufw allow proto tcp from 192.168.1.5 to 192.168.1.7 port 2887
$ sudo ufw allow proto tcp from 192.168.1.6 to 192.168.1.7 port 2887

Securing MongoDB with SSL

To ensure the security of your data, we recommend using SSL between your Mongo client and server when connecting to your Mongo server over the internet.  This helps to prevent your session from being vulnerable to the “man in the middle” attack.  Here is an example on how to configure SSL:

  mongodb-server: 127.0.0.1
  mongodb-client: 127.0.0.1
  Common Name (e.g. server FQDN or YOUR name) []: 127.0.0.1
  The PEM pass phrase for server: mongodb_server_test_ssl
  The password/passphrase for client: mongodb_client_test_ssl

Type the following commands for the server certificate:

$ sudo mkdir /etc/ssl/mongodb/
$ cd /etc/ssl/mongodb/
$ sudo openssl req -new -x509 -days 365 -out mongodb-server-cert.crt -keyout mongodb-server-cert.key

Create the server .pem file with both key and certificate:

$ cd /etc/ssl/mongodb/
$ sudo bash -c 'cat mongodb-server-cert.key mongodb-server-cert.crt > mongodb-server.pem'

Type the following commands for the client certificate:

$ cd /etc/ssl/mongodb/
$ sudo openssl req -new -x509 -days 365 -out mongodb-client-cert.crt -keyout mongodb-client-cert.key

Create the client .pem file with both key and certificate:

$ cd /etc/ssl/mongodb/
$ sudo bash -c 'cat mongodb-client-cert.key mongodb-client-cert.crt > mongodb-client.pem'

Configure mongod and mongos for TLS/SSL server

Edit the /etc/mongodb.conf or /usr/local/etc/mongodb.conf file, enter:
$ sudo vi /etc/mongodb.conf
Update the config file as follows:

# network interfaces
 net: 
  port: 27017 
  bindIp: 127.0.0.1 
  ssl: 
     mode: requireSSL
     PEMKeyFile: /etc/ssl/mongodb/mongodb-server.pem
     CAFile: /etc/ssl/mongodb/mongodb-client.pem
     PEMKeyPassword: mongodb_server_test_ssl

Save and close the file. Re-start the Mongo instance:

$ sudo systemctl restart mongodb
OR if you are using FreeBSD Unix:
# service mongod restart

Configure TLS/SSL for Mongo clients:

The syntax is as follows for mongo shell interface:
$ mongo --ssl --sslCAFile /etc/ssl/mongodb/mongodb-server.pem \
--sslPEMKeyFile /etc/ssl/mongodb/mongodb-client.pem \
--sslPEMKeyPassword mongodb_client_test_ssl \
--host 127.0.0.1 --port 2887 \
--u "nixdbuser" -p "myKoolPassowrd" --authenticationDatabase "nixcraft"

And here are two examples for a Python client for connection to an SSL enabled MongoDB:

Example 1:
client = pymongo.MongoClient('127.0.0.1', ssl=True)
Example 2:
client = pymongo.MongoClient('127.0.0.1',
                              ssl=True,
                              ssl_certfile='/etc/ssl/mongodb/mongodb-client.pem',
                              ssl_keyfile='/etc/ssl/mongodb/mongodb-server.pem',
                              ssl_pem_passphrase=mongodb_client_test_ssl)

Don’t Forget …

Always keep your operating system & mongo patching up to date.  If you need assistance with securing your systems or databases, please schedule a free 30 minute discussion with one of your project managers.