This site is the archived OWASP Foundation Wiki and is no longer accepting Account Requests.
To view the new OWASP Foundation website, please visit https://owasp.org

Difference between revisions of "Testing for NoSQL injection"

From OWASP
Jump to: navigation, search
m
m
Line 29: Line 29:
  
 
<code> db.myCollection.find( { $where: function() { return obj.credits - obj.debits < 0; } } ); </code>
 
<code> db.myCollection.find( { $where: function() { return obj.credits - obj.debits < 0; } } ); </code>
 +
 +
===Example 1===
  
 
If an attacker were able to manipulate the data passed into the $where operator, that attacker could include arbitrary JavaScript to be evaluated as part of the MongoDB query. An example vulnerability is exposed in the following code, if user input is passed directly into the MongoDB query without sanitization.
 
If an attacker were able to manipulate the data passed into the $where operator, that attacker could include arbitrary JavaScript to be evaluated as part of the MongoDB query. An example vulnerability is exposed in the following code, if user input is passed directly into the MongoDB query without sanitization.
  
<code>db.myCollection.find("{ $where: 'this.credits > " + userinput + "' }");</code>
+
<code>db.myCollection.find( { active: true, $where: function() { return obj.credits - obj.debits < $userInput; } } );;</code>
 +
 
 +
As with testing other types of injection, one does not need to fully exploit the vulnerability to demonstrate a problem. By injecting special characters relevant to the target API language, and observing the results, a tester can determine if the application correctly sanitized the input. For example within MongoDB, if a string containing any of the following special characters were passed unsanitized, it would trigger a database error.
 +
 
 +
<code>' " \ ; { }</code>
 +
 
 +
With normal SQL injection, a similar vulnerability would allow an attacker to execute arbitrary SQL commands - exposing or manipulating data at will. However, because JavaScript is a fully featured language, not only does this allow an attacker to manipulate data, but also to run arbitrary code. For example, instead of just causing an error when testing, a full exploit would use the special characters to craft valid JavaScript.
 +
 
 +
This input <code>0;var date=new Date(); do{curDate = new Date();}while(curDate-date<10000)</code> inserted into $userInput in the above example code would result in the following JavaScript function being executed. This specific attack string would case the entire MongoDB instance to execute at 100% CPU usage for 10 second.
 +
 
 +
<code>function() { return obj.credits - obj.debits < 0;var date=new Date(); do{curDate = new Date();}while(curDate-date<10000); }</code>
  
With normal SQL injection, a similar vulnerability would allow an attacker to execute arbitrary SQL commands - exposing or manipulating data at will. However, because JavaScript is a fully featured language, not only does this allow an attacker to manipulate data, but also to run arbitrary code.
+
===Example 2===
  
 +
Even if the input used within queries is completely sanitized or parameterized, there is an alternate path in which one might trigger NoSQL injection. Many NoSQL instances have their own reserved variable names, independent of the application programming language.
  
 +
For example within MongoDB, the <code>$where</code> syntax itself is a reserved query operator. It needs to be passed into the query exactly as shown; any alteration would cause a database error. However, because <code>$where</code> is also a valid PHP variable name, it may be possible for an attacker to insert code into the query by creating a PHP variable named <code>$where</code>. The PHP MongoDB documentation explicitly warns developers: <pre>Please make sure that for all special query operators (starting with $) you use single quotes so that PHP doesn't try to replace "$exists" with the value of the variable $exists.</pre>
 +
 +
Even if a query depended on no user input, such as the following example, an attacker could exploit MongoDB by replacing the operator with malicious data.
 +
 +
<code> db.myCollection.find( { $where: function() { return obj.credits - obj.debits < 0; } } ); </code>
 +
 +
One way to potentially assign data to PHP variables is via HTTP Parameter Pollution (see: [[Testing_for_HTTP_Parameter_pollution_(OWASP-DV-004)]]). By creating a variable named <code>$where</code> via parameter pollution, one could trigger a MongoDB error indicating that the query is no longer valid. Any value of <code>$where</code> other than the string "$where" itself, should suffice to demonstrate vulnerability. An attacker would develop a full exploit by inserting the following: <code>"$where: function() { //arbitrary JavaScript here }"</code>
  
  
Line 48: Line 68:
 
http://erlend.oftedal.no/blog/?blogid=110
 
http://erlend.oftedal.no/blog/?blogid=110
  
http://seclists.org/fulldisclosure/2011/Dec/383
+
http://www.syhunt.com/?n=Articles.NoSQLInjection
  
 
https://media.blackhat.com/bh-us-11/Sullivan/BH_US_11_Sullivan_Server_Side_WP.pdf
 
https://media.blackhat.com/bh-us-11/Sullivan/BH_US_11_Sullivan_Server_Side_WP.pdf
  
 
http://docs.mongodb.org/manual/faq/developers/#how-does-mongodb-address-sql-or-query-injection
 
http://docs.mongodb.org/manual/faq/developers/#how-does-mongodb-address-sql-or-query-injection
 +
 +
http://php.net/manual/en/mongocollection.find.php
 
...<br>
 
...<br>
 
'''Tools'''<br>
 
'''Tools'''<br>
 
...<br>
 
...<br>

Revision as of 16:33, 9 August 2013

This article is part of the new OWASP Testing Guide v4.
Back to the OWASP Testing Guide v4 ToC: https://www.owasp.org/index.php/OWASP_Testing_Guide_v4_Table_of_Contents Back to the OWASP Testing Guide Project: https://www.owasp.org/index.php/OWASP_Testing_Project


Brief Summary


NoSQL databases provide looser consistency restrictions than traditional SQL databases. By requiring fewer relational constraints and consistency checks, NoSQL databases often offer performance and scaling benefits. Yet these databases are still potentially vulnerable to injection attacks, even if they aren't using the traditional SQL syntax. Because these NoSQL injection attacks may execute within a procedural[1] language , rather than in the declarative[2] SQL language, the potential impacts are greater than traditional SQL injection.

Description of the Issue


NoSQL database calls are written in the application's programming language, a custom API call, or formatted according to a common convention (such as XML, JSON, LINQ, etc). Malicious input targeting those specifications may not trigger the primarily application sanitization checks. For example, filtering out common HTML special characters such as < > & ; will not prevent attacks against a JSON API, where special characters include / { } : .

There are now over 150 NoSQL databases available[3] for use within an application, providing APIs in a variety of languages and relationship models. Each offers different features and restrictions. Because there is not a common language between them, example injection code will not apply across all NoSQL databases. For this reason, anyone testing for NoSQL injection attacks will need to familiarize themselves with the syntax, data model, and underlying programming language in order to craft specific tests.

NoSQL injection attacks may execute in different areas of an application than traditional SQL injection. Where SQL injection would execute within the database engine, NoSQL variants may execute during within the application layer or the database layer, depending on the NoSQL API used and data model. Typically NoSQL injection attacks will execute where the attack string is parsed, evaluated, or concatenated into a NoSQL API call.

Additional timing attacks may be relevant to the lack of concurrency checks within a NoSQL database. These are not covered under injection testing.

At the time of writing MongoDB is the most widely used NoSQL database, and so all examples will feature MongoDB APIs.

Black Box testing and example

Testing for NoSQL injection vulnerabilities in MongoDB:
The MongoDB API expects BSON (Binary JSON) calls, and includes a secure BSON query assembly tool. However, according to MongoDB documentation - unserialized JSON and JavaScript expressions are permitted in several alternative query parameters.[4] The most commonly used API call allowing arbitrary JavaScript input is the $where operator.

The MongoDB $where operator typically is used as a simple filter or check, as it is within SQL.

db.myCollection.find( { $where: "this.credits == this.debits" } );

Optionally JavaScript is also evaluated to allow more advanced conditions.

db.myCollection.find( { $where: function() { return obj.credits - obj.debits < 0; } } );

Example 1

If an attacker were able to manipulate the data passed into the $where operator, that attacker could include arbitrary JavaScript to be evaluated as part of the MongoDB query. An example vulnerability is exposed in the following code, if user input is passed directly into the MongoDB query without sanitization.

db.myCollection.find( { active: true, $where: function() { return obj.credits - obj.debits < $userInput; } } );;

As with testing other types of injection, one does not need to fully exploit the vulnerability to demonstrate a problem. By injecting special characters relevant to the target API language, and observing the results, a tester can determine if the application correctly sanitized the input. For example within MongoDB, if a string containing any of the following special characters were passed unsanitized, it would trigger a database error.

' " \ ; { }

With normal SQL injection, a similar vulnerability would allow an attacker to execute arbitrary SQL commands - exposing or manipulating data at will. However, because JavaScript is a fully featured language, not only does this allow an attacker to manipulate data, but also to run arbitrary code. For example, instead of just causing an error when testing, a full exploit would use the special characters to craft valid JavaScript.

This input 0;var date=new Date(); do{curDate = new Date();}while(curDate-date<10000) inserted into $userInput in the above example code would result in the following JavaScript function being executed. This specific attack string would case the entire MongoDB instance to execute at 100% CPU usage for 10 second.

function() { return obj.credits - obj.debits < 0;var date=new Date(); do{curDate = new Date();}while(curDate-date<10000); }

Example 2

Even if the input used within queries is completely sanitized or parameterized, there is an alternate path in which one might trigger NoSQL injection. Many NoSQL instances have their own reserved variable names, independent of the application programming language.

For example within MongoDB, the $where syntax itself is a reserved query operator. It needs to be passed into the query exactly as shown; any alteration would cause a database error. However, because $where is also a valid PHP variable name, it may be possible for an attacker to insert code into the query by creating a PHP variable named $where. The PHP MongoDB documentation explicitly warns developers:
Please make sure that for all special query operators (starting with $) you use single quotes so that PHP doesn't try to replace "$exists" with the value of the variable $exists.

Even if a query depended on no user input, such as the following example, an attacker could exploit MongoDB by replacing the operator with malicious data.

db.myCollection.find( { $where: function() { return obj.credits - obj.debits < 0; } } );

One way to potentially assign data to PHP variables is via HTTP Parameter Pollution (see: Testing_for_HTTP_Parameter_pollution_(OWASP-DV-004)). By creating a variable named $where via parameter pollution, one could trigger a MongoDB error indicating that the query is no longer valid. Any value of $where other than the string "$where" itself, should suffice to demonstrate vulnerability. An attacker would develop a full exploit by inserting the following: "$where: function() { //arbitrary JavaScript here }"



Result Expected:
...

References

Whitepapers
http://blogs.adobe.com/asset/files/2011/04/NoSQL-But-Even-Less-Security.pdf

http://erlend.oftedal.no/blog/?blogid=110

http://www.syhunt.com/?n=Articles.NoSQLInjection

https://media.blackhat.com/bh-us-11/Sullivan/BH_US_11_Sullivan_Server_Side_WP.pdf

http://docs.mongodb.org/manual/faq/developers/#how-does-mongodb-address-sql-or-query-injection

http://php.net/manual/en/mongocollection.find.php ...
Tools
...