NoSQL injection alphabet

    There are SQL injections! Are NoSQL injections possible? Yes! Redis, MongoDB, memcached - all these software products belong to the class of non-relational DBMS, the opposite of the popular MySQL, Oracle Database and MSSQL. Since interest in these databases has recently grown significantly, hackers of all stripes simply could not get past 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), interconnected. Data is accessed using SQL, a structured query language. You don’t have to go far for examples of relational DBMSs: MySQL, Oracle, Microsoft SQL Server. All other DBMSs, the architecture of which differs from the classical relational model, can be safely attributed to the class of NoSQL solutions:
    • various hash table options (Redis, BigTable, memcached);
    • document-oriented databases (MongoDB, CouchDB);
    • graph-based databases (Neo4j, Sones GraphDB);
    • object-oriented databases (db4o, Cache, Jade);
    • XML-oriented databases (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 the query language, eXist uses XQuery, and Sonic GraphDB requires the developer to know GraphQL, a language for querying data in the form of graphs. The popularity of NoSQL-DBMS is growing every day, which cannot but affect you and me. Very soon, literally tomorrow, you will not have to look for SQL injections, but NoSQL injections in the next project. We will not waste time and talk about potential vulnerabilities.

    Are NoSQL DBMSs Safe?

    Quite often, I hear the statement that non-relational DBMSs are safe, because they do not use SQL and an 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 inject SQL code into the system, this does not mean that it is safe. NoSQL closes one potential vulnerability, while opening up a dozen others that allow you to perform a variety of malicious actions:
    • manipulate with a REST interface and fake cross-site requests (CSRF);
    • Use regular expressions in query parameters
    • execute 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 a typical application architecture with access to a NoSQL data warehouse. 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 lowest level, that is, directly from the DBMS. Like any application, the DBMS may be susceptible to buffer overflow attacks or have a vulnerable authentication scheme. Attacking this level is quite difficult, because the community that has formed around the product and the development company themselves are trying 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 fully analyze it and possibly 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 DBMSs have a whole zoo of different libraries for accessing 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 would allow access to all applications built on the basis of this API, you will imagine how the dialogue between the client code and the database server occurs, what protocol is used and whether it is possible to intercept the session.
    And finally, the top level is the application that you are going to hack. Here you first of all need to find those places where the programmer forgot to check the input data, and try to exploit it. In this case, you need to use the same approach as when searching for SQL injections, that is, analyze the code and error messages, only this time you have to deal with JSON, JavaScript, or something similar.
    So, it's time for a hack! Today, our goal will be MongoDB, one of the most common NoSQL DBMSs.

    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, then the application should be available at{1337. The main attacks that will be discussed today:
    • regular expression injections;
    • JSON injection
    • manipulations with the REST interface;
    • JavaScript injections.

    Let's start by hacking with errors in using regular expressions.

    MongoDB Web Interface

    Regular Expressions

    MongoDB, like many other NoSQL DBMSs, allows you to search using regular expressions. This is a very powerful, but at the same time dangerous remedy that can cause significant harm if used improperly.
    MongoDB uses the $ regex operator to search using regular expressions. For example, the query “return to me 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, I recommend that you start learning 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 works. Open the mongodb.js file in the Lib folder. It implements the MongoDbController class, which is responsible for the functioning 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 the 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 root username and regular expression instead of a password, for example [\ s \ S] *. As a result, MongoDB will execute the following request: “db.users.findOne ({login: 'root', password: / ^ [\ s \ S] * / i})”, and you will successfully log in to the vulnerable site as root (this the technique resembles the classic SQL injection "1 'or 1 = 1 -"). Protecting yourself from such an attack is quite simple. First, always check the input data, no matter where it comes from - directly from the user, or from an external file, or from the database. Before using the data in the program, it should be checked. Secondly, use regular expressions only when really needed. 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 also faster.

    Json injection

    Yes, MongoDB does not support SQL, but the DBMS cannot do without a query language. MongoDB developers decided to use the popular JSON text exchange format (BSON) instead of SQL. Thus, you can try to carry out various kinds of injection attacks (of course, if the input data are not filtered). Such attacks are commonly 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 json-injection method of the MongoDbController class:

    var loginParam = eval("({ login: '" + login + "',
                           password: '" + password + "' })");

    The above code converts the textual representation of a JavaScript object (MongoDB query) into an object. After the transfer of this object to the database server, user authentication occurs. There is one very weak spot in this piece of code - the input data is not controlled in any way, so you can generate almost any query to the database! For example, specify the username “root '}) //” (password is optional) and click on the “Login” button. Congratulations, you are logged in again! How did it happen? Everything is very simple. You specified the username “root '}) //”, and the following trick occurred in the eval function:

    //Переданное значение
    ({ login: 'root'})//', password: '' })
    //Получившийся запрос
    db.users.findOne({ login: 'root' })

    In fact, this script is even more dangerous, because with it you can execute any JavaScript code on a web server. For example, the username "'+ process.execPath}) //" will form a query of the form

    db.users.findOne({ login: 'C:\\node.exe' })

    Vulnerabilities of this type are called Server Side JavaScript Injections or simply SSJI.
    How to protect yourself from such attacks?
    1. Check all data from external sources. For example, the login must match the regular expression "^ [a-zA-Z] + $".
    2. Never use the eval function to work with JSON. In Node.js, the JSON.parse function is available, which parses the input string and creates an object based on it.

    Successful authentication in a test application

    REST interface manipulations

    Due to the rapid development of the Internet and service-oriented architecture (SOA), REST solutions are gaining more and more 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 the 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 that implements full REST support.
    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 This is a very simple web-application that displays information about the current state of the DBMS and allows you to generate database queries. Here are some interesting links:
    • / listDatabases? text = 1 - list of databases;
    • / serverStatus? text = 1 - current state of the server.

    In general, a URL of the following type is used to generate a REST request to the database:база_данных/коллекция/?filter_поле=значение

    On the Manipulation with REST interface page of our web application, user authentication is performed 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 generates a REST request, ignoring all the data after the "#" character. When the REST request is ready, the script generates an HTTP request to the server and expects the result in JSON format. For example, a request for root user information in the secure_nosql database is as follows: Everything would be fine, but there is an error in the code that manifests itself when processing the "#" symbol. If you try to log in with the name “root #”, you will be logged in to the system. The problem is caused by 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 was performed through the request http: // localhost:
    It is worth noting that most REST interfaces are also vulnerable to cross-site request forgery (CSRF):

    Honestly, I am rather skeptical about the RESTful architecture, as it opens up great opportunities for attackers. Try not to use REST. But if there is nothing without it, then first read the article Robust Defenses for Cross-Site Request Forgery , which describes in detail all aspects of REST security.

    Javascript injections

    Most modern relational DBMSs allow you to create stored procedures. Let's look at Microsoft SQL Server, which extends the capabilities of ANSI SQL and allows you to comply with almost any business application requirements. If you lack the capabilities of T-SQL (this is a dialect of SQL implemented in SQL Server), then you can write a stored procedure in C # or any other .NET-compatible language.
    MongoDB has equally rich features, including server-side JavaScript. In fact, you can execute almost any code on the database server. On the one hand, this allows you to write very complex data processing applications, on the other hand, it makes your application more vulnerable.
    Where can I use JavaScript in MongoDB?
    1. Queries with the $ where operator . For example, the query db.orders.find ({$ where: "this.amount> 3"}) will return you a list of orders with more than three items.
    2. Db.eval team . For example, db.eval ("function (x) {return x * x;}", 2) will return four.
    3. Functions to save to the database . MongoDB allows you to store functions written in JavaScript in a database. For this, a special system collection system.js is used. To create a new stored function foo (x), execute the following code: { _id: "foo", value: function (x) { return x * x; }})

      Now you can try calling it like this: db.eval ("foo (2)").
    4. 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 data preprocessing, and reduce, which searches for the result.
      MongoDB allows you to run map / reduce operations on a database server. The DBMS takes care of the processes parallelization and aggregation; the developer only needs to specify the initial data and functions that implement the map and reduce commands. Additional information is available in the MongoDB documentation .

    Our test application has JavaScript injection in the $ where statement and a similar vulnerability in the db.eval command.
    Let's start with the $ where statement. Open the application and select $ where in the "JavaScript Injection" menu. Authentication on the page is implemented in the ssji-where method of the MongoDbController class:

    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 is not checked in any way, which allows you to execute any script on the server.
    Now let's try logging in as root. Enter the username “root '//” and try logging in. Once again, you are successfully logged in! This is possible due to the following request to MongoDB formed on the server:

    { '$where': 'this.login === \'root\' //\' && this.password === \'\'' }

    "//" is a comment in JavaScript, so the resulting query will take the form "this.login === 'root'".
    Fortunately, at the time the request is executed, the database is in the "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 page "JavaScript injections - db.eval (...)". This time, authentication occurs by calling the eval function on the database server:

    var js = "function () { return db.users.findOne ({ login: '" + login + "', password: '" + password + "' }); }"

    As you can see, you have the ability to execute any code on the database server. Try creating a new pen_test user with the pen_test password. 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 has appeared in the database. :-)
    Server-side JavaScript has great potential and at the same time carries many dangers. One small mistake in the code, and the attacker gains access to your database server. I highly recommend not using server-side scripts: 85% of requests can be written without them.

    Access to the test application is denied


    In conclusion, I would like to talk about how I see the present and future of the NoSQL community. First, you made sure that NoSQL DBMSs are not mainstream yet, but are pretty close to this: new non-relational DBMSs and projects that use them appear. It seems to me that in the near future NoSQL solutions will occupy a relatively large market share in highly 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 many more potential vulnerabilities. If, when working with relational databases, it was enough to learn SQL injections and how to deal with them (at the same time, you could apply existing knowledge both in MySQL, and in Oracle or SQL Server), then with non-relational databases everything is not so simple. First, you have to figure out what query language is used in your DBMS, how to access data 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 how to fix them. how 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 how to fix them. how 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 how to fix them.

    I really hope that in the near future the situation will change: more information will appear in the public domain and to protect against threats associated with the use of NoSQL-DBMS will be as simple as from ordinary SQL injections.


    Q: What is the origin of the term NoSQL?
    A: NoSQL is translated not as “No SQL” (No SQL at all), but as “Not only SQL” (Not only SQL). This term originated in 1998: that is what Carlo Strozzi called his non-relational database management system. He received his rebirth in 2009, when Eric Evans at a conference on free distributed databases used it to refer to non-relational DBMSs and data warehouses. We can assume that this particular conference laid the foundation for the NoSQL solutions boom.

    Q: What is MongoDB?
    A:MongoDB is an open source document management database system developed by 10gen since October 2007. The first MongoDB release was released in February 2009. The DBMS is positioned as a solution for storing data in highly loaded 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, there are world-famous companies such as Disney, SAP, Forbes and others among MongoDB users.

    Q: Why NoSQL?
    A: Let's look at the main advantages of NoSQL databases compared to their relational counterparts.
    1. Производительность.Разработчики большинства NoSQL-решений посвящают очень много времени оптимизации своих проектов. MongoDB позволяет добиться порядка 20000 вставок и 4800 выборок в секунду.
    2. Простая настройка репликации баз данных. MongoDB позволяет настроить репликацию всего лишь с помощью нескольких команд, то есть гораздо проще, чем в том же Oracle.
    3. Множество «плюшек», облегчающих жизнь программистам. Например, MongoDB имеет встроенную поддержку Map/Reduce и сложных структур данных.
    4. Масштабируемость. Это один из главных козырей NoSQL-СУБД. Большинство из них поддерживает горизонтальное масштабирование, что способствует существенной экономии средств на оборудовании, ведь дешевле купить еще один недорогой сервер для кластера, чем добавить в корпоративный сервер дополнительную пару процессоров и оперативную память.
    5. They are cheaper! Most NoSQL solutions are open source projects. You can download them right now and start using them. A large and close-knit community has formed around many projects, which 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 expenses for database administrators, since non-relational DBMSs are much simpler than relational ones and in most cases they do not require a special employee to support them.

    Q: Who uses NoSQL?
    A: As you can see, NoSQL DBMSs have a number of undeniable advantages. Let's consider who uses them:
    • "Cloud" services, namely Google, Amazon and even Windows Azure from Microsoft.
    • Portals and social networks: Facebook, Twitter, LinkedIn - I think you can continue the list yourself.
    • SaaS. A growing number of companies are choosing Software-as-Service solutions as the main platform for doing business in those industries where infrastructure loads are constantly growing. Many SaaS solution providers are switching to NoSQL. So, for example, did - the leader in the field of SaaS CRM.
    • Startups This is a separate category of projects that are launched with a minimum budget with the expectation of super profits in the future. Such projects often choose NoSQL solutions, because, firstly, they are cheap, and secondly, they represent an excellent reserve for the future if the project becomes popular.

    Hacker Magazine, February (02) 157
    Ilya Verbitsky ( )

    Subscribe to Hacker

    Also popular now: