diff --git a/README.md b/README.md index 3fe4146..f69aa31 100644 --- a/README.md +++ b/README.md @@ -3,15 +3,19 @@ NoSQLMap [NoSQLMap](http://www.nosqlmap.net) v0.7 -Introduction -============ - +# Introduction NoSQLMap is an open source Python tool designed to audit for as well as automate injection attacks and exploit default configuration weaknesses in NoSQL databases as well as web applications using NoSQL in order to disclose data from the database. -It is named as a tribute to Bernardo Damele and Miroslav's Stampar's popular SQL injection tool [sqlmap](http://sqlmap.org), and its concepts are based on and extensions of Ming Chow's excellent presentation at Defcon 21, ["Abusing NoSQL Databases"](https://www.defcon.org/images/defcon-21/dc-21-presentations/Chow/DEFCON-21-Chow-Abusing-NoSQL-Databases.pdf). Presently the tool's exploits are focused around MongoDB, but additional support for other NoSQL based platforms such as CouchDB, Redis, and Cassandra are planned in future releases. +## What is NoSQL? +A NoSQL (originally referring to "non SQL", "non relational" or "not only SQL") database provides a mechanism for storage and retrieval of data which is modeled in means other than the tabular relations used in relational databases. Such databases have existed since the late 1960s, but did not obtain the "NoSQL" moniker until a surge of popularity in the early twenty-first century, triggered by the needs of Web 2.0 companies such as Facebook, Google, and Amazon.com. NoSQL databases are increasingly used in big data and real-time web applications. NoSQL systems are also sometimes called "Not only SQL" to emphasize that they may support SQL-like query languages. + +## Credits +NoSQLMap is named as a tribute to Bernardo Damele and Miroslav's Stampar's popular SQL injection tool [sqlmap](http://sqlmap.org), and its concepts are based on and extensions of Ming Chow's excellent presentation at Defcon 21, ["Abusing NoSQL Databases"](https://www.defcon.org/images/defcon-21/dc-21-presentations/Chow/DEFCON-21-Chow-Abusing-NoSQL-Databases.pdf). + +## DBMS Support +Presently the tool's exploits are focused around MongoDB, and CouchDB but additional support for other NoSQL based platforms such as CouchDB, Redis, and Cassandra are planned in future releases. -Requirements -============ +# Requirements On a Debian or Red Hat based system, the setup.sh script may be run as root to automate the installation of NoSQLMap's dependencies. Varies based on features used: @@ -23,11 +27,12 @@ Varies based on features used: There are some various other libraries required that a normal Python installation should have readily available. Your milage may vary, check the script. -Setup -============ -``python setup.py install`` -Usage -===== +# Setup +``` +python setup.py install +``` + +# Usage -Start with @@ -68,8 +73,3 @@ Video NoSQLMap MongoDB Management Attack Demo. NoSQLMap MongoDB Management Attack Demo - -Contribute -========== - -If you'd like to contribute, please create [new issue](https://github.com/tcstool/NoSQLMap/issues) or [pull request](https://github.com/tcstool/NoSQLMap/pulls). diff --git a/nosqlmap.py b/nosqlmap.py index b17dca8..8460457 100755 --- a/nosqlmap.py +++ b/nosqlmap.py @@ -423,6 +423,13 @@ def options(): else: print "unsupported method in request header." + # load the HTTP headers + for line in reqData[1:]: + print(line) + if not line.strip(): break + header = line.split(": "); + requestHeaders[header[0]] = header[1].strip() + victim = reqData[1].split( " ")[1].replace("\r\n","") optionSet[0] = True uri = methodPath[1].replace("\r\n","") diff --git a/nsmweb.py b/nsmweb.py index 21f9013..c619137 100644 --- a/nsmweb.py +++ b/nsmweb.py @@ -43,8 +43,6 @@ def getApps(webPort,victim,uri,https,verb,requestHeaders): possAddrs = [] timeVulnsStr = [] timeVulnsInt = [] - yes_tag = ['y', 'Y'] - no_tag = ['n', 'N'] appUp = False strTbAttack = False intTbAttack = False @@ -58,13 +56,13 @@ def getApps(webPort,victim,uri,https,verb,requestHeaders): int24 = False #Verify app is working. - print "Checking to see if site at " + str(victim) + ":" + str(webPort) + str(uri) + " is up..." + print "Checking to see if site at " + str(victim).strip() + ":" + str(webPort).strip() + str(uri).strip() + " is up..." if https == "OFF": - appURL = "http://" + str(victim) + ":" + str(webPort) + str(uri) + appURL = "http://" + str(victim).strip() + ":" + str(webPort).strip() + str(uri).strip() elif https == "ON": - appURL = "https://" + str(victim) + ":" + str(webPort) + str(uri) + appURL = "https://" + str(victim).strip() + ":" + str(webPort).strip() + str(uri).strip() try: req = urllib2.Request(appURL, None, requestHeaders) appRespCode = urllib2.urlopen(req).getcode() @@ -264,7 +262,7 @@ def getApps(webPort,victim,uri,https,verb,requestHeaders): doTimeAttack = raw_input("Start timing based tests (y/n)? ") - if doTimeAttack in yes_tag: + if doTimeAttack.lower() == "y": print "Starting Javascript string escape time based injection..." req = urllib2.Request(uriArray[18], None, requestHeaders) start = time.time() @@ -306,7 +304,7 @@ def getApps(webPort,victim,uri,https,verb,requestHeaders): if lt24 == True: bfInfo = raw_input("MongoDB < 2.4 detected. Start brute forcing database info (y/n)? ") - if bfInfo in yes_tag: + if bfInfo.lower == "y": getDBInfo() @@ -330,7 +328,7 @@ def getApps(webPort,victim,uri,https,verb,requestHeaders): fileOut = raw_input("Save results to file (y/n)? ") - if fileOut in yes_tag: + if fileOut.lower() == "y": savePath = raw_input("Enter output file name: ") fo = open(savePath, "wb") fo.write ("Vulnerable URLs:\n") @@ -692,7 +690,7 @@ def postApps(victim,webPort,uri,https,verb,postData,requestHeaders): fileOut = raw_input("Save results to file (y/n)? ") - if fileOut in yes_tag: + if fileOut.lower() == "y": savePath = raw_input("Enter output file name: ") fo = open(savePath, "wb") fo.write ("Vulnerable Requests:\n") @@ -759,7 +757,7 @@ def checkResult(baseSize,respSize,testNum,verb,postData): global httpMethod global neDict global gtDict - + delta = abs(respSize - baseSize) if (delta >= 100) and (respSize != 0) : @@ -974,7 +972,6 @@ def buildUri(origUri, randValue): def getDBInfo(): curLen = 0 - yes_tag = ['y', 'Y'] nameLen = 0 gotFullDb = False gotNameLen = False @@ -1039,7 +1036,7 @@ def getDBInfo(): getUserInf = raw_input("Get database users and password hashes (y/n)? ") - if getUserInf in yes_tag: + if getUserInf.lower() == "y": charCounter = 0 nameCounter = 0 #find the total number of users on the database @@ -1189,7 +1186,7 @@ def getDBInfo(): pwdHash = "" crackHash = raw_input("Crack recovered hashes (y/n)?: ") - while crackHash in yes_tag: + while crackHash.lower() == "y": menuItem = 1 for user in users: print str(menuItem) + "-" + user diff --git a/setup.py b/setup.py index a51fbbc..c0d518b 100644 --- a/setup.py +++ b/setup.py @@ -4,9 +4,9 @@ with open("README.md") as f: setup( name = "NoSQLMap", - version = "0.5", + version = "0.7", packages = find_packages(), - scripts = ['nosqlmap.py', 'nsmmongo.py', 'nsmcouch.py'], + scripts = ['nosqlmap.py', 'nsmmongo.py', 'nsmcouch.py','nsmscan.py','nsmweb.py'], entry_points = { "console_scripts": [ @@ -15,10 +15,10 @@ }, install_requires = [ "CouchDB==1.0", "httplib2==0.9", "ipcalc==1.1.3",\ - "NoSQLMap==0.5", "pbkdf2==1.3", "pymongo==2.7.2",\ + "NoSQLMap==0.7", "pbkdf2==1.3", "pymongo==2.7.2",\ "requests==2.5.0"], - author = "tcstools", + author = "tcstool", author_email = "nosqlmap@gmail.com", description = "Automated MongoDB and NoSQL web application exploitation tool", license = "GPLv3", diff --git a/vuln_apps/mongo.nosql b/vuln_apps/mongo.nosql new file mode 100644 index 0000000..45bfcbc --- /dev/null +++ b/vuln_apps/mongo.nosql @@ -0,0 +1,23 @@ +use shop +db.orders.insert({"id":"42","name":"Adrien","item":"Fuzzy pink towel","quantity":"1"}) +db.orders.insert({"id":"99","name":"Justin","item":"Bird supplies","quantity":"4"}) +db.orders.insert({"id":"1","name":"Robin","item":"Music gift cards","quantity":"100"}) +db.orders.insert({"id":"1001","name":"Moses","item":"Miami Heat tickets","quantity":"1000"}) +db.orders.insert({"id":"66","name":"Rick","item":"Black hoodie","quantity":"1"}) +db.orders.insert({"id":"0","name":"Nobody","item":"Nothing","quantity":"0"}) + +use customers +db.paymentinfo.insert({"name":"Adrien","id":"42","cc":"5555123456789999","cvv2":"1234"}) +db.paymentinfo.insert({"name":"Justin","id":"99","cc":"5555123456780000","cvv2":"4321"}) +db.paymentinfo.insert({"name":"Robin","id":"1","cc":"3333444455556666","cvv2":"2222"}) +db.paymentinfo.insert({"name":"Moses","id":"2","cc":"4444555566667777","cvv2":"3333"}) +db.paymentinfo.insert({"name":"Rick","id":"3","cc":"5555666677778888","cvv2":"5678"}) +db.paymentinfo.insert({"name":"Nobody","id":"0","cc":"45009876543215555","cvv2":"9999"}) + +use appUserData +db.users.insert({"name":"Adrien","username":"adrien","email":"adrien@sec642.org"}) +db.users.insert({"name":"Justin","username":"justin","email":"justin@sec642.org"}) +db.users.insert({"name":"Robin","username":"digininja","email":"digininja@sec642.org"}) +db.users.insert({"name":"Moses","username":"adrien","email":"moses@sec642.org"}) +db.users.insert({"name":"Rick","username":"rick","email":"rick@sec642.org"}) +db.users.insert({"name":"Nobody","username":"administrator","email":"root@sec642.org"}) diff --git a/vuln_apps/orderdata.php b/vuln_apps/orderdata.php index 39dfa32..427359f 100644 --- a/vuln_apps/orderdata.php +++ b/vuln_apps/orderdata.php @@ -15,7 +15,7 @@ $db = $conn->shop; $collection = $db->orders; $search = $_GET['ordersearch']; - $js = "function () { var query = '". $ordersearch . "'; return this.id == query;}"; + $js = "function () { var query = '". $search . "'; return this.id == query;}"; //print $js; print '
'; @@ -48,4 +48,4 @@ - \ No newline at end of file + diff --git a/vuln_apps/populate_db.php b/vuln_apps/populate_db.php new file mode 100644 index 0000000..44d2576 --- /dev/null +++ b/vuln_apps/populate_db.php @@ -0,0 +1,107 @@ +shop; + +// Drop the database +$response = $db->drop(); +//print_r($response); + +// select a collection (analogous to a relational database's table) +$collection = $db->orders; + +// add records +$obj = array( "id"=>"1234","name"=>"Russell","item"=>"ManCity Jersey","quantity"=>"2"); +$collection->insert($obj); +$obj = array( "id"=>"42","name"=>"Adrien","item"=>"Fuzzy pink towel","quantity"=>"1"); +$collection->insert($obj); +$obj = array( "id"=>"99","name"=>"Justin","item"=>"Bird supplies","quantity"=>"4"); +$collection->insert($obj); +$obj = array( "id"=>"1","name"=>"Robin","item"=>"Music gift cards","quantity"=>"100"); +$collection->insert($obj); +$obj = array( "id"=>"1001","name"=>"Moses","item"=>"Miami Heat tickets","quantity"=>"1000"); +$collection->insert($obj); +$obj = array( "id"=>"66","name"=>"Rick","item"=>"Black hoodie","quantity"=>"1"); +$collection->insert($obj); +$obj = array( "id"=>"0","name"=>"Nobody","item"=>"Nothing","quantity"=>"0"); +$collection->insert($obj); + +// find everything in the collection +$cursor = $collection->find(); + +// iterate through the results +foreach ($cursor as $obj) { + echo $obj["name"] . "
"; +} + +// select a database +$db = $m->customers; + +// Drop the database +$response = $db->drop(); +//print_r($response); + +// select a collection (analogous to a relational database's table) +$collection = $db->paymentinfo; + +$obj = array( "name"=>"Russell","id"=>"1000","cc"=>"0000000000000000","cvv2"=>"0000"); +$collection->insert($obj); +$obj = array( "name"=>"Adrien","id"=>"42","cc"=>"5555123456789999","cvv2"=>"1234"); +$collection->insert($obj); +$obj = array( "name"=>"Justin","id"=>"99","cc"=>"5555123456780000","cvv2"=>"4321"); +$collection->insert($obj); +$obj = array( "name"=>"Robin","id"=>"1","cc"=>"3333444455556666","cvv2"=>"2222"); +$collection->insert($obj); +$obj = array( "name"=>"Moses","id"=>"2","cc"=>"4444555566667777","cvv2"=>"3333"); +$collection->insert($obj); +$obj = array( "name"=>"Rick","id"=>"3","cc"=>"5555666677778888","cvv2"=>"5678"); +$collection->insert($obj); +$obj = array( "name"=>"Nobody","id"=>"0","cc"=>"4500987654321555","cvv2"=>"9999"); +$collection->insert($obj); + +// find everything in the collection +$cursor = $collection->find(); + +// iterate through the results +foreach ($cursor as $obj) { + echo $obj["cc"] . "
"; +} + + +// select a database +$db = $m->appUserData; + +// Drop the database +$response = $db->drop(); +//print_r($response); + +// select a collection (analogous to a relational database's table) +$collection = $db->users; + +$obj = array( "name"=>"Russell","username"=>"tcstoolHax0r","email"=>"nosqlmap@sec642.org"); +$collection->insert($obj); +$obj = array( "name"=>"Adrien","username"=>"adrien","email"=>"adrien@sec642.org"); +$collection->insert($obj); +$obj = array( "name"=>"Justin","username"=>"justin","email"=>"justin@sec642.org"); +$collection->insert($obj); +$obj = array( "name"=>"Robin","username"=>"digininja","email"=>"digininja@sec642.org"); +$collection->insert($obj); +$obj = array( "name"=>"Moses","username"=>"adrien","email"=>"moses@sec642.org"); +$collection->insert($obj); +$obj = array( "name"=>"Rick","username"=>"rick","email"=>"rick@sec642.org"); +$collection->insert($obj); +$obj = array( "name"=>"Nobody","username"=>"administrator","email"=>"root@sec642.org"); +$collection->insert($obj); + +// find everything in the collection +$cursor = $collection->find(); + +// iterate through the results +foreach ($cursor as $obj) { + echo $obj["email"] . "
"; +} + +?> diff --git a/vuln_apps/userdata.php b/vuln_apps/userdata.php index 303fbef..0fc8165 100644 --- a/vuln_apps/userdata.php +++ b/vuln_apps/userdata.php @@ -11,7 +11,7 @@ if (isset($_GET['usersearch']) && !empty($_GET['usersearch'])) { try { $result = ""; - $conn = new MongoClient('mongodb://192.168.87.157'); + $conn = new MongoClient('mongodb://127.0.0.1'); $db = $conn->appUserData; $collection = $db->users; $search = $_GET['usersearch']; @@ -47,4 +47,4 @@ - \ No newline at end of file +