WP NoSQL SSJI Authentication Bypass | Imperva

NoSQL SSJI Authentication Bypass

NoSQL SSJI Authentication Bypass
Following my previous post on SSJI (Server Side JavaScript Injection), I received many questions requesting more details and techniques on how applications that use a big data back end may be vulnerable and If I could give some viable examples. I figured we could start with an login page authentication bypass that gives a very clear example to the problem.
In order to demonstrate this problem, I wrote a vanilla MongoDB frontend application that basically authenticates users using username and password as you would normally have in any application. The user collection is stored in a MongoDB backend, and I use an apache with PHP as my webserver in order to establish common and familiar ground.
Here is a snapshot from the “myusers” collection on the backend MongoDB:
On the application side, attached is the code snippet that provides the authentication matching mechanism, essentially looking for a user/pass match and allowing a login if a match was found.

To explain the code a little bit, it is important to understand that the MongoDB query requires a JSON format query, which passes as arrays of parameter and values. In my case I called this “criteria” to make it more visible, the MongoDB driver is the component that converts the array format to JSON.
This query populated with values will be translated to MongoDB as the following query:
db.myusers.find( {username: ‘barry’,Password:’jimmypage’})
Now, lets look at manipulating the input to create an injection point. As we can see from the login code, we have two parameters populated with username and password. The login form I created is very simple and looks like this:
A URL that will perform the login will look in my case as follows:
http://Anonymous bypass (any user)
PHP naturally has an interesting way to pass negated parameters, which will help us in the authentication bypass mechanism. Passing paremeters with the [$ne] (negate) operator will help us perform that.
The following URL will implement this negation
http:///mongoapp/login.php?username[$ne]=foo&password[$ne]=bar
This URL will create the following query on the MongoDB side, which will return all the documents in the collection per the query negated match:
db.myusers.find( {username: { $ne: ‘foo’} ,Password: {$ne:’bar’}})
The application will then allow us to bypass the login mechanism and our injection will be successful:
 
Targeted user bypass (a specific user)
This is a very simple adoption of the previous injection, only in this case, we already know the username that we want to target. In this case we will try to get into Mark’s account.
The query that we want to create is: (username = Mark) and (password != bar)
Funny enough, any password that isn’t Mark’s password will work here.
Translated to a URL this input manipulation will look as follows
http:///mongoapp/login.php?username=mark&password[$ne]=bar
And eventually to the MongoDB query:
db.myusers.find( {username: ‘mark’ ,Password: {$ne:’bar’}})
The result injection will allow us to login as Mark

Final thoughts
As demonstrated in this blog, Input manipulation and injection attacks are a real threat in big data driven applications and it becomes more critical as these applications are getting more popular and big data platforms become the data store of choice for emerging applications. It is important for us to raise the awareness around the SSJI (Server Side JavaScript Injection) vector and the need to sanitize input.