o [NSE] Added authentication support to MongoDB library and modified existing

scripts to support it. Added the script mongodb-brute to perform password
  brute force guessing. [Patrik]
This commit is contained in:
patrik 2012-03-02 12:28:30 +00:00
parent 8bd550b2fd
commit 43253cea53
6 changed files with 202 additions and 12 deletions

101
scripts/mongodb-brute.nse Normal file
View file

@ -0,0 +1,101 @@
description = [[
Performs brute force password guessing against the MongoDB database.
]]
---
-- @usage
-- nmap -p 27017 <ip> --script mongodb-brute
--
-- @output
-- PORT STATE SERVICE
-- 27017/tcp open mongodb
-- | mongodb-brute:
-- | Accounts
-- | root:Password1 - Valid credentials
-- | Statistics
-- |_ Performed 3542 guesses in 9 seconds, average tps: 393
--
require 'brute'
require 'mongodb'
require 'shortport'
author = "Patrik Karlsson"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"intrusive", "brute"}
local arg_db = stdnse.get_script_args(SCRIPT_NAME .. ".db") or "admin"
portrule = shortport.port_or_service({27017}, {"mongodb"})
Driver = {
new = function(self, host, port, options)
local o = { host = host, port = port, sock = nmap.new_socket() }
setmetatable(o, self)
self.__index = self
return o
end,
connect = function(self)
return self.sock:connect(self.host, self.port)
end,
login = function(self, username, password)
local status, resp = mongodb.login(self.sock, arg_db, username, password)
if ( status ) then
return true, brute.Account:new(username, password, creds.State.VALID)
elseif ( resp ~= "Authentication failed" ) then
local err = brute.Error:new( err )
err:setRetry( true )
return false, err
end
return false, brute.Error:new( "Incorrect password" )
end,
disconnect = function(self)
return self.sock:close()
end,
}
local function needsAuth(host, port)
local socket = nmap.new_socket()
local status, result = socket:connect(host, port)
if ( not(status) ) then
return false, "Failed to connect to server"
end
local packet
status, packet = mongodb.listDbQuery()
if ( not(status) ) then
return false, result
end
--- Send packet
status, result = mongodb.query(socket, packet)
if ( not(status) ) then
return false, result
end
socket:close()
if ( status and result.errmsg ) then
return true
end
return false
end
action = function(host, port)
if ( not(needsAuth(host, port)) ) then
return "No authentication needed"
end
local engine = brute.Engine:new(Driver, host, port )
engine.options.script_name = SCRIPT_NAME
engine.options.firstonly = true
status, result = engine:start()
return result
end

View file

@ -29,18 +29,22 @@ Attempts to get a list of tables from a MongoDB database.
-- | name = admin
-- |_ totalSize = 167772160
-- version 0.1
-- version 0.2
-- Created 01/12/2010 - v0.1 - created by Martin Holst Swende <martin@swende.se>
-- Revised 01/03/2012 - v0.2 - added authentication support <patrik@cqure.net>
author = "Martin Holst Swende"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"default", "discovery", "safe"}
dependencies = {"mongodb-brute"}
require "creds"
require "mongodb"
require "shortport"
portrule = shortport.port_or_service({27017}, {"mongodb"})
function action(host,port)
local socket = nmap.new_socket()
@ -56,6 +60,19 @@ function action(host,port)
try( socket:connect(host, port) )
-- uglyness to allow creds.mongodb to work, as the port is not recognized
-- as mongodb, unless a service scan was run
local ps = port.service
port.service = 'mongodb'
local c = creds.Credentials:new(creds.ALL_DATA, host, port)
for cred in c:getCredentials(creds.State.VALID + creds.State.PARAM) do
local status, err = mongodb.login(socket, "admin", cred.user, cred.pass)
if ( not(status) ) then
return err
end
end
port.service = ps
local req, result, packet, err, status
--Build packet
status, packet = mongodb.listDbQuery()

View file

@ -41,18 +41,25 @@ Attempts to get build info and server status from a MongoDB database.
-- | note = fields vary by platform
-- |_ page_faults = 0
-- version 0.2
-- version 0.3
-- Created 01/12/2010 - v0.1 - created by Martin Holst Swende <martin@swende.se>
-- Revised 01/03/2012 - v0.3 - added authentication support <patrik@cqure.net>
author = "Martin Holst Swende"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"default", "discovery", "safe"}
dependencies = {"mongodb-brute"}
require "creds"
require "mongodb"
require "shortport"
local arg_db = stdnse.get_script_args(SCRIPT_NAME .. ".db") or "admin"
portrule = shortport.port_or_service({27017}, {"mongodb"})
function action(host,port)
local socket = nmap.new_socket()
@ -68,9 +75,22 @@ function action(host,port)
try( socket:connect(host, port) )
local req, status, statusresponse, buildinfo, packet, err
local req, statusresponse, buildinfo, err
status, packet = mongodb.serverStatusQuery()
-- uglyness to allow creds.mongodb to work, as the port is not recognized
-- as mongodb, unless a service scan was run
local ps = port.service
port.service = 'mongodb'
local c = creds.Credentials:new(creds.ALL_DATA, host, port)
for cred in c:getCredentials(creds.State.VALID + creds.State.PARAM) do
local status, err = mongodb.login(socket, arg_db, cred.user, cred.pass)
if ( not(status) ) then
return err
end
end
port.service = ps
local status, packet = mongodb.serverStatusQuery()
if not status then return packet end
status,statQResult = mongodb.query(socket, packet)

View file

@ -183,6 +183,7 @@ Entry { filename = "membase-http-info.nse", categories = { "discovery", "safe",
Entry { filename = "memcached-info.nse", categories = { "discovery", "safe", } }
Entry { filename = "metasploit-xmlrpc-brute.nse", categories = { "brute", "intrusive", } }
Entry { filename = "modbus-discover.nse", categories = { "discovery", "intrusive", } }
Entry { filename = "mongodb-brute.nse", categories = { "brute", "intrusive", } }
Entry { filename = "mongodb-databases.nse", categories = { "default", "discovery", "safe", } }
Entry { filename = "mongodb-info.nse", categories = { "default", "discovery", "safe", } }
Entry { filename = "ms-sql-brute.nse", categories = { "brute", "intrusive", } }