There are SQL injections! Is NoSQL injection possible? Yes! Redis, MongoDB, memcached - all these software products belong to the class of non-relational DBMSs, the opposite of the popular MySQL, Oracle Database and MSSQL. Since the interest in the listed databases has recently increased significantly, hackers of all stripes simply could not pass them.

What is NoSQL?
I think you are familiar with the relational model of the DBMS, according to which the database consists of entities (tables) related to each other. Data access is carried out using SQL - structured query language. There is no need to go far for examples of relational DBMS: MySQL, Oracle, Microsoft SQL Server. All other DBMS, the architecture of which differs from the classical relational model, can be safely attributed to the class NoSQL solutions:
- various options for hash tables (Redis, BigTable, memcached);
- document-oriented databases (MongoDB, CouchDB);
- database based on graphs (Neo4j, Sones GraphDB);
- object-oriented databases (db4o, Cache, Jade);
- XML-oriented database (eXist, BaseX).
The main difference between NoSQL-DBMS and their SQL-oriented competitors is the lack of a single, unified query language. For example, MongoDB uses BSON as its query language, eXist uses XQuery, and Sonic GraphDB requires the developer to have knowledge of GraphQL, a query language for data that is graph-like. The popularity of NoSQL-DBMS is growing every day, which can not but affect us with you. Very soon, literally tomorrow, you will have to look not for SQL injections, but for NoSQL injections in the next project. Let's not waste time and talk about potential vulnerabilities.
')
Are NoSQL DBMS Safe?
Quite often, I hear a statement that non-relational DBMSs are safe, since they do not use SQL and the attacker cannot conduct attacks like SQL-injection on them. To some extent, this is true: no SQL - no SQL injection. But, if it is impossible to embed SQL code in the system, this does not mean that it is safe. NoSQL closes one potential vulnerability, while opening a dozen others that allow you to perform a variety of malicious actions:
- manipulate the REST interface and forge cross-site requests (CSRF);
- use regular expressions in query parameters;
- run scripts on the server if NoSQL-DBMS is installed on it (for example, MongoDB allows you to run JavaScript code);
- access data through a special interface supported by the DBMS (SQL in relational databases, BSON in MongoDB, etc.), and, if the query language is used, “correct” these queries.
Consider the typical application architecture with access to the NoSQL data store. Usually it consists of three levels:
- attachment;
- NoSQL database API;
- NoSQL DBMS.
An attacker can attack each of these levels. Let's start from the bottom level, that is, directly from the DBMS. Like any application, the DBMS can be subject to buffer overflow attacks or have a vulnerable authentication scheme. Attacking this level is quite difficult, because the community formed around the product, and the developer company itself, try to correct errors as they are discovered. But you have a very big advantage: most software products come with source code, which means you can completely analyze it and, perhaps, find something worthwhile. If you are lucky, then in your hands will be the key to almost any database! The next level is the client API. Most NoSQL-DBMS have a zoo of various libraries to access data. It is worth noting that most libraries are open source projects, but some of them are no longer supported. The probability of detecting a vulnerability in the client library is much higher than directly in the DBMS itself. And even if you are not lucky enough to find the only vulnerability that will open access to all applications built on the basis of this API, you will be able to imagine how the dialogue between client code and database server takes place, what protocol is used and whether the session can be intercepted.
Finally, the top level is an application that you are going to hack. Here, you first need to find the places where the programmer forgot to check the input data, and try to exploit them. In this case, you need to use the same approach as when searching for SQL injections, that is, to analyze the code and error messages, only this time you will have to deal with JSON, JavaScript, or something like that.
So, it's time for hacking! Today, our goal will be MongoDB - one of the most common NoSQL-DBMS.
NoSQL-injections in MongoDB
We will crack a small web application. Here is its
source code (the installation process is described in detail in the README.RU.txt file). If the installation is successful, the application should be available at http://127.0.0.1:371337. The main attacks, which will be discussed today:
- regular expression injections;
- JSON injection;
- manipulations with the REST interface;
- Javascript injection
Let's start with hacking with errors in using regular expressions.

MongoDB Web Interface
Regular expression injections
MongoDB, like many other NoSQL-DBMS, allows you to search using regular expressions. This is a very powerful, but at the same time, dangerous tool that can cause significant harm if used improperly.
MongoDB uses $ regex operator to search using regular expressions. For example, the request “give me back all users whose login begins with“ ro ”” will look like this:
db.users.find({ login: { $regex: "^ro" } })
By the way, if you are not familiar with the MongoDB query language, then I recommend starting it with
the developer’s guide . But back to our application. Open the test website and select “Injections in regular expressions” in the MongoDB menu.

User Authentication page in test application
Let's see how this page is arranged. Open the mongodb.js file in the lib folder. It implements the MongoDbController class, which is responsible for the operation of all pages in the application. Now we are interested in the regexp method:
var regexpPwd = new RegExp("^" + password, "i"); var loginParam = { login: login, password: regexpPwd };
As you can see, user authentication occurs through a request that specifies a regular expression as a password. At the same time, the password variable is not filtered in any way, which gives us complete freedom of action. Here you can specify the username root and regular expression instead of a password, for example [\ s \ S] *. As a result, MongoDB will execute the following query: “db.users.findOne ({login: 'root', password: / ^ [\ s \ S] * / i})”, and you will successfully enter the vulnerable site with the login root (this technique resembles the classic SQL injection "1 'or 1 = 1 -"). To defend against such an attack is quite simple. First, always check the input data, wherever it comes from - directly from the user, or from an external file, or from a database. Before using the data in the program they should be checked. Secondly, use regular expressions only when it’s really necessary. For example, the above query can be rewritten like this:
db.users.findOne({ login: 'root', password: 'p@ssw0rd' })
As you can see, it is safer and at the same time runs faster.
Json injection
Yes, MongoDB does not support SQL, but a DBMS cannot do without a query language. The MongoDB developers decided to use instead of SQL the most popular text data exchange format JSON (BSON). Thus, you can try to implement all sorts of attacks, injection (of course, if the input data is not filtered). Such attacks are usually called JSON injections.
So, open our application again and go to the “JSON injection” page. As in the previous example, you will see a field for entering a username and password. Let's look at the code responsible for the authentication process on this page. It is contained in the MongoDbController json-injection method:
var loginParam = eval("({ login: '" + login + "', password: '" + password + "' })");
The above code converts the textual representation of a JavaScript object (request to MongoDB) into an object. After the transfer of this object to the database server, the user is authenticated. In this piece of code there is one very weak point - the input data is not controlled at all, so you can form almost any query to the database! For example, enter the user name “root '}) //” (it is not necessary to enter the password) and click on the “Login” button. Congratulations, you are logged in again! How did that happen? Everything is very simple. You specified the username “root '}) //”, and the following focus occurred in the eval function:
In fact, this script is even more dangerous, since with its help you can execute any JavaScript code on a web server. For example, the user name "'+ process.execPath}) //" will form a query like
db.users.findOne({ login: 'C:\\node.exe' })
This type of vulnerability is called Server Side JavaScript Injections, or simply SSJI.
How to protect against such attacks?
- Check all data from external sources. For example, a login must match the regular expression "^ [a-zA-Z] + $".
- Never use the eval function to work with JSON. JSON.parse is available in Node.js, which parses the input string and creates an object based on it.

Successful test application authentication
Manipulations with a REST interface
Due to the rapid development of the Internet and service-oriented architecture (SOA), REST solutions are gaining increasing popularity. Since most modern non-relational DBMSs are organized in accordance with the latest industry trends, many of these systems either implement REST themselves or use third-party products to access data using RESTful architecture. MongoDB is no exception: this DBMS includes a simple REST interface that allows you to access data in read-only mode. In addition, there is a project called Sleepy Mongoose, which implements full support for REST.
Let's see how the REST interface built into MongoDB works. The DBMS server must be started with the "--rest" parameter. The REST service is available at http://127.0.0.1:28017/. This is a very simple web application that displays information about the current state of the DBMS and allows you to form queries to databases. Here are some interesting links:
- / listDatabases? text = 1 - list of databases;
- / serverStatus? text = 1 - the current state of the server.
In general, the following URL is used to form a REST request to the database:
http://127.0.0.1:28017/_//?filter_=
On the Manipulations with REST interface page of our web application, the user is authenticated using the MongoDB REST interface. It is implemented in the rest method of the MongoDbController class:
var restQry = "/secure_nosql/users/?filter_login=" + login + "&filter_password=" + password; var hash = restQry.indexOf("#"); if (hash > -1) { restQry = restQry.substring(0, hash); }
The script forms a REST request, ignoring all the data after the "#" symbol. When the REST request is ready, the script generates an HTTP request to the server and waits for the result in JSON format. For example, a request for information about the root user in the secure_nosql database is as follows: http://127.0.0.1:28017/secure_nosql/users/?filter_login=root&filter_password=p@ssw0rd. Everything is good, but there is an error in the code that manifests itself when processing the "#" symbol. If you try to log in as “root #”, you will be logged in to the system. The problem is due to the formation of the following URL: http: // localhost: 28017 / secure_nosql / users /? Filter_login = root # & filter_password =. consists in the fact that the filter_password parameter was ignored and authentication took place via the request http: // localhost: 28017 / secure_nosql / users /? filter_login = root.
It should be noted that most REST interfaces are also vulnerable to cross-site request forgery (CSRF):
<img src="http://localhost:28017/secure_nosql/users/" />
Frankly, I am quite skeptical about the RESTful architecture, as it opens up great opportunities for intruders. Try not to use REST. But if without it in any way, then first read the article
Robust Defenses for Cross-Site Request Forgery , in which all aspects of REST security are described in great detail.
Javascript injection
Most modern relational DBMSs allow you to create stored procedures. Let's take a look at Microsoft SQL Server, which extends the capabilities of ANSI SQL and allows you to comply with virtually any requirements of business applications. If you lack T-SQL capabilities (this is the SQL dialect implemented in SQL Server), then you can write a stored procedure in C # or any other .NET-compatible language.
MongoDB has no less rich features, including server-side JavaScript. In fact, you can execute almost any code on the database server. On the one hand, it allows you to write very complex data processing applications, on the other - it makes your application more vulnerable.
Where can I use JavaScript in MongoDB?
- Queries with the $ where operator . For example, the query db.orders.find ({$ where: “this.amount> 3”}) will return you a list of orders, the number of points in which is more than three.
- Db.eval command For example, db.eval (“function (x) {return x * x;}”, 2) returns four.
- Functions to save to the database . MongoDB allows you to save functions written in JavaScript, in the database. For this, the system.js special system collection is used. To create a new stored function foo (x), run the following code:
db.system.js.save( { _id: "foo", value: function (x) { return x * x; }})
Now you can try calling it like this: db.eval (“foo (2)”). - Map / Reduce . Map / Reduce is a software framework developed by Google for parallel computing over large amounts of data. It contains two operations: map, used for preprocessing data, and reduce, which searches for a result.
MongoDB allows you to run map / reduce operations on a database server. The DBMS takes over the operations of parallelizing processes and aggregation; the developer only needs to specify the source data and functions that implement the map and reduce commands. Additional information is available in the MongoDB documentation.
In our test application, there is a javascript injection in the $ where statement and a similar vulnerability in the db.eval command.
Let's start with the $ where operator. Open the application and select the $ where option in the JavaScript Injection menu. Page authentication is implemented in the MongoDbController ssji-where method:
var js = "this.login === '" + login + "' && this.password === '" + password + "'"; var loginParam = { "$where" : js };
First, a script is generated that checks the user name and password. Unfortunately, the data in the password and login variables are not checked in any way, which allows you to run any script on the server.
Now let's try logging in as root. Enter the username "root '//" and try to log in. Once again you successfully log in! This is possible due to the fact that the following request to MongoDB was formed on the server:
{ '$where': 'this.login === \'root\' //\' && this.password === \'\'' }
"//" is a comment in JavaScript, so the resulting query will look like "this.login === 'root'".
Fortunately, at the time the query is executed, the database is in read-only mode, so the attacker will not be able to write a script that modifies your data. But this does not mean that such an attack is impossible. Open the JavaScript Injection - db.eval (...) page. This time authentication occurs by calling the eval function on the database server:
var js = "function () { return db.users.findOne ({ login: '" + login + "', password: '" + password + "' }); }" db.eval(js);
As you can see, you have the opportunity to execute any code on the database server. Try to create a new user pen_test with the password pen_test. To do this, enter the following login:
'}), db.users.insert({login: 'pen_test', password: 'pen_test'}), 1 } //
First, you are logged in. Secondly, a new user pen_test appeared in the database. :-)
Server-side JavaScript has great potential and at the same time carries many dangers. One small error in the code, and the attacker gains access to your database server. I strongly recommend not using server scripts: 85% of requests can be written without them.

Access to the test application is denied
Conclusion
In conclusion, I would like to talk about how I see the present and future of the NoSQL community. Firstly, you are convinced that NoSQL-DBMS is not yet mainstream, but rather close to this: new non-relational DBMS and projects that use them appear. It seems to me that in the near future, NoSQL solutions will occupy a relatively large share in the market of high-loaded applications. Secondly, the security of modern NoSQL-DBMS leaves much to be desired. If in the world of relational databases there is one standardized query language - SQL, then in the “non-relational world” everyone implements the query language, as he pleases: JSON, XQuery, REST interfaces. Accordingly, there are much more potential vulnerabilities. While working with relational databases, it was enough to study SQL injections and ways to deal with them (while you could apply existing knowledge in MySQL, as well as in Oracle or SQL Server), then with non-relational databases everything is not so simple. First you have to figure out which query language is used in your DBMS, how the data is accessed and whether there are additional features that can be used for hacking (for example, server-side JavaScript in MongoDB). After collecting the information you have to find potential vulnerabilities in your system and ways to eliminate them.
I very much hope that the situation will change in the near future: more information will appear in the public domain and it will be as easy to protect against the threats associated with the use of NoSQL-DBMS, as well as from conventional SQL injections.
NoSQL FAQ
Q: What is the origin of the term NoSQL?
A: NoSQL is not translated as “No SQL” (No SQL at all), but as “Not only SQL” (Not only SQL). This term originated in 1998: this is how Carlo Strozzi called his non-relational database management system. He was reborn in 2009, when Eric Evans (Eric Evans) at a conference on free distributed databases, used it to refer to non-relational DBMS and data warehousing. We can assume that this particular conference marked the beginning of the boom of NoSQL solutions.
Q: What is MongoDB?
A: MongoDB is an open source document-based database management system developed by 10gen since October 2007. The first release of MongoDB was released in February 2009. The DBMS is positioned as a solution for storing data in high-load projects. Its main advantages include high performance, excellent scalability, fault tolerance and the presence of an extensive community of developers and users. At the moment, among the users of MongoDB there are such world famous companies as Disney, SAP, Forbes and others.
Q: Why NoSQL?
A: Let's take a look at what main advantages NoSQL databases have compared to their relational counterparts.
- Productivity. The developers of most NoSQL solutions devote a lot of time to optimizing their projects. MongoDB allows you to achieve about 20,000 inserts and 4,800 samples per second.
- Easy database replication setup . MongoDB allows you to configure replication with just a few commands, that is much easier than in the same Oracle.
- Many "buns" that make life easier for programmers. For example, MongoDB has built-in support for Map / Reduce and complex data structures.
- Scalable . This is one of the main trump cards NoSQL-DBMS. Most of them support horizontal scaling, which contributes to significant savings in hardware, because it is cheaper to buy another low-cost server for a cluster than to add an extra pair of processors and RAM to a corporate server.
- They are cheaper! Most NoSQL solutions are open source projects. You can download them right now and start using. A large and cohesive community has formed around many projects that is always ready to help and fix the bug you found. In the end, you yourself can fix the bug or write the necessary extension. In addition, you can significantly save on costs for database administrators, since non-relational DBMS is much simpler than relational and in most cases they do not require a special employee to support them.
Q: Who uses NoSQL?
A: As you can see, NoSQL-DBMS has a number of irrefutable advantages. Let's consider who uses them:
- Cloud services, namely Google, Amazon and even Microsoft's Windows Azure.
- Portals and social networks: Facebook, Twitter, LinkedIn - I think you can continue the list yourself.
- SaaS. An increasing number of companies are choosing Software-as-Service solutions as the main platform for doing business in industries where infrastructure loads are constantly growing. Many providers of SaaS solutions are switching to NoSQL. So, for example, entered Salesforce.com - the leader in the field of SaaS CRM.
- Startups This is a separate category of projects that run with a minimum budget with the expectation of super profits in the future. Such projects often choose NoSQL solutions, as they are, firstly, cheap, and secondly, they represent an excellent foundation for the future if the project becomes popular.
Journal Hacker, February (02) 157
Ilya Verbitsky ( blog.chivavas.org )Subscribe to "Hacker"
