Required Skill Level: Intermediate
Reading Time: 15-20 Minutes
MongoDB is a NoSQL, document database that is widely used by companies and individuals. Its popularity and support makes it a contender for one of the best options for database needs. Unfortunately, its popularity makes it a target for experienced and mediocre attackers alike. This article will go over the most common security risks to MongoDB and how to mitigate them. Hopefully by the end of this article, your MongoDB deployment will be impervious to most attacks.
We also assume that you have quite a bit of knowledge when using MongoDB as you have probably created a database and have come here looking to secure it. If you have little knowledge in MongoDB, you can continue to read this post and learn the theory behind securing your database, however we strongly recommend taking a course and learning the syntax and how MongoDB works to gain a better understanding. With that being said, let’s get into it!
Side note: WoTT is a service that checks and audits your node network including MongoDB deployments.
By default, when MongoDB is installed, it does without needing password credentials when accessing the database. It is highly recommended that you add users with login credentials, and an admin user with elevated privelages.
Before doing so, you need to enable Access Control. By enabling access control, you enforce user authentication, requiring users to identify themselves before accessing your MongoDB deployment. Assuming you have the mongodb server running, connect to the server using a terminal as the client by executing the command:
$ mongo
NB: You probably need to add a port--
and host--
after the mongo command depending on how you set up your deployment.
Now that you are in the database as a client, you must switch to the admin database to add a new user. Simply execute the following command:
$ use admin
switched to db admin
Now we need to create an admin user, to do so, run the following commands:
db.createUser(
{
user: "admin",
pwd: "placeholder",
roles [{role: "userAdminAnyDatabase", db: "admin"}, "readWriteANyDatabase"]
}
)
Make sure to replace placeholder with a strong password, you could alternatively use the command:
passwordPrompt()
This creates an admin user that has access to every aspect of any database in your deployment, so be cautious as to who you share that information with. Since MongoDB doesn’t enable authorization/authentication by default, even with the creation of an admin user, users will still have access to all aspects of every database in your deployment without the need to authenticate.
To enable authorization, first disconnect from the mongoshell and stop the mongo server (usually using ^C in the terminal will do the trick). Then access the MongoD configuration file using your favourite editor. We will use $EDITOR for the purpose of this tutorial.
$ sudo $EDITOR mongod.conf
It might be worth mentioning that your configuration file will be by default in the </etc/
directory. If you specified the location yourself please refer to that directory when running the command.
Once in the file, navigate to the section that reads
security:
authorization: "disabled"
Change it to "endabled"
. Save the file and start up your mongodb server. Go back to your terminal and access the mongo client, this time adding the following:
$ mongo --authenticationDatabase -u "admin" -p "placeholder"
You can also authenticate after accessing the mongo client:
$ mongo
> db.auth("admin", "placeholder")
Now that you have connected to the deployment as an admin and enabled authorization, you can now create users for whichever database they need to access. For the purposes of this article, we will assume you have a database named testDB
and would like to add the user tester
. In the client just use the following syntax:
> use testDB
> db.createUser{
user: "tester"
pwd: "default"
roles: [ { role: "read", db: "testDB" } ]
}
This leads us to our next point.
It’s not enough to turn on authentication and create an admin user. You need to create users and give them roles that are specific to their user requirements. There are 2 ways you can do this, you can either utilize MongoDB’s built-in roles, or you can create user-defined roles if you need users to do something specific.
Don’t worry if you created a user with the wrong role, you can always update the role of the user using the method db.updateUser()
. The following is the syntax for the method (bear in mind it can also be used to update other fields for the user and not just the role so be careful):
db.updateUser(
"<username>",
{
customData : { <any information> },
roles : [
{ role: "<role>", db: "<database>" } | "<role>",
...
],
pwd: "<cleartext password>"
},
writeConcern: { <write concern> }
)
An example would be:
> db.updateUser("tester",
{
roles: [
{role: "readWrite", db: "testDB}
]
})
By default, information sent between the mongo client and server is sent in plaintext. The implications of using such a basic method of communication can be devastating when handling sensitive data, especially if an attacker is setting up camp in your lines of communication. We recommend configuring your MongoDB deployment to support TLS/SSL. The Process to enabling TLS/SSL communication is a long one and has a lot to cover, so we recommend going through this page in the MongoDB documentaion. It does assume prior knowledge of TLS/SSL and public key infrastructure, so make sure you are brushed up on that before going through it.
MongoDB Enterprise 3.2 comes with a WiredTiger storage engine. This engine also comes with it’s own Encryption At Rest, which can be used to encrypt data in the storage layer.
If you decide not to go with the WiredTiger’s encryption at rest, please make sure any MongoDB data is encrypted on every host using file-system, device or physical encryption. Be sure if you use any key-based encryption to store the key outside of the MongoDB deployment and somewhere that shouldn’t be easy to find.
A common attack used by attackers looking to earn an easy paycheck is ransomware. Ransomware is a type of malware that either encrypts or whipes your data and threatens to never give you access to the data unless you pay the attacker through bitcoins or some other currency that is difficult to trace. To defend yourself against these attacks, it is best to ensure you keep a regular backup of your data, in the event that this attack occurs, you can simply restore your data from the most recent backup. It sounds simple enough, but it can definitely save you a lot of money as most of these ransomware encryptions use advanced cryptographic algorithms that would either cost too much to break or be almost impossible to break before then end of the Earth. Oh, and don’t forget to make sure you’re backup is encrypted, you don’t want just anybody stumbling upon it and having access to all that data.
This point is security by ambiguity, it isn’t an effective way to stop attackers, but it can certainly slow them down, as most attackers begin attacks by scanning for the standard MongoDB ports and hoping to catch someone with their shields down.
The standard MongoDB ports are:
To change the default port, navigate to the mongod.conf file and locate the lines:
net:
port: 27017
and change the port number to one that is available. When this is done, restart the server.
MongoDB deployments have been at risk of attacks for quite some time now, the most common of them being ransomware attacks. By following this guide, we hoped to cover the more blatant flaws that are overlooked by MongoDB users and secure them. Make sure to stay vigilant when working with other people and know that no system is 100% secure.
But why have to worry about going through all of these points? WoTT is a developer tool to automatically run CVE scans, audit service configurations, manage your firewalls, simplify mTLS, and more. By using WoTT, we can run some checks on your MongoDB deployment and notify you of any fixes we recommend to keep your deployment safe and secure.
Did you know that WoTT gives you free security audits, including CVE scanning, for your first node? Sign up today.