Application Security and Hardening
Geekwise Academy
Week 8 - NoSQL Injection and MEAN Stack Vulnerabilities
Instructors:
Corey Shuman
Slack Channel:
Github Repo:
https://github.com/coreyshuman/GeekwiseApplicationSecurity
Lecture Notes:
http://coreyshuman.github.io/GeekwiseApplicationSecurity/LectureNotes
Table of Contents:
NoSQL databases are a type of storage structure that use a mechanism other than the tabular relations used in relational databases. As a result, these types of databases usually are not vulnerable to SQL injection. However that doesn't mean they are inherently more secure. Instead they have their own vulnerabilities to contend with.
MongoDB is one of the more popular NoSQL databases, and is a primary component of MEAN stack. As a result, we will focus on MongoDB for our examples.
To start us off, here is the list of known vulnerabilities in MongoDB:
[MongoDB Vulnerability List](https://www.cvedetails.com/vulnerability-list/vendor_id-12752/product_id-25450/Mongodb-Mongodb.html)
Throughout this lecture, we will be using code and notes created by David Bohannon on the Synopsys.com blog.
[Bohannon: Preventing Common Vulnerabilties: Part 1](https://www.synopsys.com/blogs/software-security/preventing-common-mean-stack-vulnerabilities/)
[Bohannon: Source Code](https://github.com/dbohannon/MEANBug)
Between Christmas 2016 and mid-January 2017, 28,000 public MongoDB installations were hacked due to insecure default settings. MongoDB versions before 2.6.0 would, by default, be open to remote connections without requiring authentication.
[The MongoDB Hack](https://snyk.io/blog/mongodb-hack-and-secure-defaults/)
While MongoDB is not susceptible to SQL injection, it is vulnerable to a similar attack called Query Selector Injection. MongoDB's query language uses special keywords such as `$where` and `$ne`. In a vulnerable implementation, it is possible for an attacker to pass these parameters into API fields and manipulate the result, or worse.
[OWASP: Testing for NoSQL Injection](https://www.owasp.org/index.php/Testing_for_NoSQL_injection)
MongoDB supplies a security checklist which includes the following topics:
[Security Checklist](https://docs.mongodb.com/manual/administration/security-checklist/)
[Mass Assignment Cheatsheet](https://www.owasp.org/index.php/Mass_Assignment_Cheat_Sheet)
Software frameworks sometime allow developers to automatically bind HTTP request parameters into program code variables or objects to make using that framework easier on developers. This can sometimes cause harm. Attackers can sometimes use this methodology to create new parameters that the developer never intended which in turn creates or overwrites new variable or objects in program code that was not intended. This is called a mass assignment vulnerability.
Alternate names:
To defend against this, we should use whitelisting, blacklisting, or a combinantion of the two to make sure sensitive or unintended fields are not editable by external forces.
For MongoDB, we can use a Schema to define the expected structure of our objects. More on that can be found here:
[Mongoose](http://mongoosejs.com/docs/guide.html)
[Bohannon: Preventing Common Vulnerabilties: Part 2](https://www.synopsys.com/blogs/software-security/preventing-common-expressjs-mean-stack-vulnerabilities/)
The order of app middlewares in your Express applications is critical. In our MEANBug app, the `/secure/removeInvoice` endpoint is implemented before the authentication check, therefore an unathenticated user can delete invoices.
When creating access rules based on routes, it is critical that your code is not case-sensitive. In MEANBug, all routes beginning with `/secure` require the user to be logged in. However if I connecte with `/SECURE`, the authentication middleware doesn't match the route, even though the endpoint handling code does!
[Bohannon: Preventing Common Vulnerabilties: Part 3](https://www.synopsys.com/blogs/software-security/preventing-common-expressjs-mean-stack-vulnerabilities-part2/)
It is common in MEAN applications to store the session state client-side. This makes the application simpler and more scalable, but makes it so that we can't invalidate the user's session easily or consistently. This can lead to session replay or hijacking attacks. One way to mitigate this is to also do server-side session invalidation. Look at last week's lecture for ideas on how we can use a security stamp to do this.
We discussed CSRF protection in Week 05. We can use the `Csurf` module to protect our application. By default, the module will not protect `GET`, `HEAD`, or `OPTION` methods. As we have discussed before, we should not put state-modifying actions on `GET` methods. In this case, they would not be protected from CSRF. In MEANBug, the `secure/removeInvoice` endpoint uses a `GET` method, which is insecure. We should consider switching it to use `POST` for more security.
[Bohannon: Preventing Common Vulnerabilties: Part 4](https://www.synopsys.com/blogs/software-security/preventing-common-angularjs-vulnerabilities/)
By default, the SCE service strips malicious HTML tags, attributes, and URI protocols from data rended as HTML with the `ng-bind-html` directive. If this is disabled using `$sceProvider.enabled(false)` it can leave our application susceptible to script injections. It is important to leave the SCE service enabled. We should also use the `ng-bind` directive when rendering data, as this will perform HTML encdoing on all malicious characters.
Angular templates use the double curly braces to denote expressions that are evaluated by the Angular rendering engine. We should make sure that users are not able to inject curly braces into a template. This can be used to circumvent HTML sanitization. For example, on the MEANBug login screen, this url would not allow a script to run:
However, by adding curly braces, we can get our XSS injection to work:
[Angular Security](https://angular.io/guide/security)
For Angular 2+, let's take a look at Angular's own security guide page.
[Bohannon: Preventing Common Vulnerabilties: Part 5](https://www.synopsys.com/blogs/software-security/nodejs-mean-stack-vulnerabilities/)
In development mode, NodeJS returns more rebose error messages which can leak information you don't want the public to have. Make sure to set `NODE_ENV=production` on live servers, and double-check the NodeJS mode after deploying a project. I like to have a page that shows project version and mode for this purpose.
On Unix systems, non-root users cannot bind to low-numbered ports. This means that NodeJS must be run as root to bind to port 80. However, if we sudo to root to start our web server then our application will be running with unnecessary privileges. To remedy this, invoke the process.setgid and process.setuid methods in the callback function after binding to port 80 as shown below.
[Special File Permissions](https://docs.oracle.com/cd/E19683-01/816-4883/secfile-69/index.html)
The Node Security Platform maintains a record of NodeJS plugins with known security issues. It can be installed and ran using the following lines: