Software Security

 

MongoDB: Preventing common vulnerabilities in the MEAN stack

Preventing common mean stack vulnerabilities

MEAN stack applications (MongoDB, ExpressJS, AngularJS, and NodeJS) are becoming increasingly popular as lightweight, easily deployable frameworks due to a vast ecosystem of middleware plugins and dependencies. But just how secure are these technologies?

Let’s examine some common vulnerabilities that are introduced either by using these components in their default configurations or due to common developer mistakes. Throughout this series, we will demonstrate each of these issues using an intentionally vulnerable MEAN Bug application, as well as provide mitigating techniques that developers can use to protect their applications from these issues. These articles focus on the security-related issues and assume that the reader has a basic understanding of the MEAN stack technologies.

Query selector injection (MongoDB)

The first piece of the technology stack that we will examine is the MongoDB database. This NoSQL database is immune to conventional SQL injection attacks, but is vulnerable to a similar attack called Query Selector Injection or NoSQL Injection which uses built-in logic operators to alter queries. To demonstrate, let’s look at the login form for our example application.

MEAN Bug login form

Figure 1: MEAN Bug login form

Using BurpSuite web proxy we have intercepted the login request and changed the POST pass parameter to pass[$ne]= where $ne is the MongoDB query operator ‘not equal to’.

Form parameter modified with HTTP proxy tool BurpSuite

Figure 2: Form parameter modified with HTTP proxy tool BurpSuite

When Express processes the x-www-form-urlencoded request body, this will be parsed into the object {user: ‘admin’, pass: {$ne: null} and passed to the MongoDB query in the code block below.

Preventing Common Vulnerabilities in the MEAN Stack

With the above payload, the query will match the first username that matches ‘admin’ with a password that is not equal to null, allowing us to authenticate to the application as an administrator without providing a valid password.

Bypassed authentication and accessed the application welcome page

Figure 3: Bypassed authentication and accessed the application welcome page

If we attempt the same injection attack on the /secure/query API, we see that the request contains a JSON body which, unlike a simple POST body, is not vulnerable to attribute pollution when parsed by Express.

Initial request contains JSON body

Figure 4: Initial request contains JSON body

However, if we change the Content-Type header to x-www-form-urlencoded and modify the body to contain our payload we can continue to use the Express parser to insert a query selector into the request object. This allows us to execute another Query Selector Injection attack and obtain all the invoices in the database.

Content-Type header and request body are modified to exploit Express parser

Figure 5: Content-Type header and request body are modified to exploit Express parser

Perhaps the simplest way to mitigate query selector injection is to cast the values to a String before running the query. The vulnerable authentication query from the first example has been modified with the code block below.

Preventing common vulnerabilities in the MEAN stack

If we re-submit the malicious request, the password will be matched against the String ‘$ne: null’ rather than evaluating the actual query operator ‘not equal to’. As a result, the authentication bypass attack no longer works.

Query selector injection attack failed after casting input to String

Figure 6: Query selector injection attack failed after casting input to String

Alternatively, an input validation tool such as mongo-sanitize can be used to reject any request key beginning with the $ character used to denote query operators.


What’s hiding in the open source code within your applications?

Insecure configuration (MongoDB)

By default, MongoDB does not enforce authentication, meaning anyone can connect to and directly query the database. To further complicate this issue, MongoDB versions prior to 2.6.0 are bound to all interfaces by default. Whether the result of using an older instance with default configurations or explicitly binding a newer instance to a public interface, MongoDB databases are often exposed to the open internet. As demonstrated with our example application, we can connect directly to the MongoDB users database from an external system without any authentication using the Mongo Shell utility.

Accessing MongoDB users database directly with Mongo Shell

Figure 7: Accessing MongoDB users database directly with Mongo Shell

MongoDB also provides an optional HTTP and REST interface which, if enabled, exposes sensitive information about the databases and the underlying file system. These interfaces may be enabled in the configuration file as shown below or from the command line when starting the MongoDB instance. By default, they will bind to the database port plus 1000 (i.e., 28017).

Preventing common vulnerabilities in the MEAN stack

HTTP interface exposes system and database information

Figure 8: HTTP interface exposes system and database information

Figure 9: Enabling the REST interface allows us to run commands such as ‘listDatabases’

To secure the MongoDB instance, the /etc/mongodb.conf file’s bind_ip, auth, httpinterface, and rest options should be configured to restrict access appropriately as demonstrated in the excerpt below.

As of January 2017, more than 40,000 MongoDB instances have been compromised by ransomware that exploits these servers’ insecure default configuration. You should take a few moments to ensure that your MongoDB instance is properly hardened so that it does not become a statistic.

Part 2 of this series, exploring ExpressJS, will wash up on the Software Security blog on April 20th.

 

Additional Reading

MongoDB ransom attacks continue to plague administrators

MongoDB Configuration Hardening

Enable Auth

Share and Enjoy:
  • Facebook
  • Twitter
  • Google Bookmarks
  • LinkedIn