mirror of
https://github.com/nmap/nmap.git
synced 2025-12-18 13:39:02 +00:00
Add omp2-brute and omp2-enum-targets from Henri Doreau.
This commit is contained in:
@@ -1,5 +1,9 @@
|
|||||||
# Nmap Changelog ($Id$); -*-text-*-
|
# Nmap Changelog ($Id$); -*-text-*-
|
||||||
|
|
||||||
|
o [NSE] Added omp2-brute and omp2-enum-targets, which respectively get
|
||||||
|
authentication credentials and then a list of scanning targets from
|
||||||
|
the OpenVAS Management Protocol. [Henri Doreau]
|
||||||
|
|
||||||
o [NSE] Added backorifice-info from Gorjan Petrovski, which retrieves
|
o [NSE] Added backorifice-info from Gorjan Petrovski, which retrieves
|
||||||
lots of system information from a BackOrifice server.
|
lots of system information from a BackOrifice server.
|
||||||
|
|
||||||
|
|||||||
179
nselib/omp2.lua
Normal file
179
nselib/omp2.lua
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
---
|
||||||
|
-- This library was written to ease interaction with OpenVAS Manager servers
|
||||||
|
-- using OMP (OpenVAS Management Protocol) version 2.
|
||||||
|
--
|
||||||
|
-- A very small subset of the protocol is implemented.
|
||||||
|
-- * Connection/authentication
|
||||||
|
-- * Targets enumeration
|
||||||
|
--
|
||||||
|
-- The library can also store accounts in the registry to share them between
|
||||||
|
-- scripts.
|
||||||
|
--
|
||||||
|
-- The complete protocol documentation is available on the official OpenVAS
|
||||||
|
-- website: http://www.openvas.org/omp-2-0.html
|
||||||
|
--
|
||||||
|
-- Sample use:
|
||||||
|
-- <code>
|
||||||
|
-- local session = omp2.Session:new()
|
||||||
|
-- local status, err = session:connect(host, port)
|
||||||
|
-- local status, err = session:authenticate(username, password)
|
||||||
|
-- ...
|
||||||
|
-- session:close()
|
||||||
|
-- </code>
|
||||||
|
--
|
||||||
|
-- @author Henri Doreau
|
||||||
|
-- @copyright Same as Nmap -- See http://nmap.org/book/man-legal.html
|
||||||
|
--
|
||||||
|
-- @args omp2.username The username to use for authentication.
|
||||||
|
-- @args omp2.password The password to use for authentication.
|
||||||
|
--
|
||||||
|
|
||||||
|
module(... or "omp2", package.seeall)
|
||||||
|
|
||||||
|
require("stdnse")
|
||||||
|
require("nmap")
|
||||||
|
|
||||||
|
local HAVE_SSL = false
|
||||||
|
|
||||||
|
if pcall(require,'openssl') then
|
||||||
|
HAVE_SSL = true
|
||||||
|
end
|
||||||
|
|
||||||
|
--- A Session class holds connection and interaction with the server
|
||||||
|
Session = {
|
||||||
|
|
||||||
|
--- Creates a new session object
|
||||||
|
new = function(self, o)
|
||||||
|
|
||||||
|
o = o or {}
|
||||||
|
setmetatable(o, self)
|
||||||
|
self.__index = self
|
||||||
|
|
||||||
|
o.username = nmap.registry.args["omp2.username"]
|
||||||
|
o.password = nmap.registry.args["omp2.password"]
|
||||||
|
o.socket = nmap.new_socket()
|
||||||
|
|
||||||
|
return o
|
||||||
|
end,
|
||||||
|
|
||||||
|
--- Establishes the (SSL) connection to the remote server
|
||||||
|
connect = function(self, host, port)
|
||||||
|
if not HAVE_SSL then
|
||||||
|
return false, "The OMP2 module requires OpenSSL support"
|
||||||
|
end
|
||||||
|
|
||||||
|
return self.socket:connect(host, port, "ssl")
|
||||||
|
end,
|
||||||
|
|
||||||
|
--- Closes connection
|
||||||
|
close = function(self)
|
||||||
|
return self.socket:close()
|
||||||
|
end,
|
||||||
|
|
||||||
|
--- Attempts to authenticate on the current connection
|
||||||
|
authenticate = function(self, username, password)
|
||||||
|
local status, err, xmldata
|
||||||
|
|
||||||
|
-- TODO escape credentials
|
||||||
|
status, err = self.socket:send("<authenticate><credentials>"
|
||||||
|
.. "<username>" .. username .. "</username>"
|
||||||
|
.. "<password>" .. password .. "</password>"
|
||||||
|
.. "</credentials></authenticate>")
|
||||||
|
|
||||||
|
if not status then
|
||||||
|
stdnse.print_debug("ERROR: %s", err)
|
||||||
|
return false, err
|
||||||
|
end
|
||||||
|
|
||||||
|
status, xmldata = self.socket:receive()
|
||||||
|
if not status then
|
||||||
|
stdnse.print_debug("ERROR: %s", xmldata)
|
||||||
|
return false, xmldata
|
||||||
|
end
|
||||||
|
|
||||||
|
return xmldata:match('status="200"')
|
||||||
|
end,
|
||||||
|
|
||||||
|
--- Lists targets defined on the remote server
|
||||||
|
ls_targets = function(self)
|
||||||
|
local status, err, xmldata
|
||||||
|
local res, target_names, target_hosts = {}, {}, {}
|
||||||
|
|
||||||
|
status, err = self.socket:send("<get_targets/>")
|
||||||
|
|
||||||
|
if not status then
|
||||||
|
stdnse.print_debug("ERROR: %s", err)
|
||||||
|
return false, err
|
||||||
|
end
|
||||||
|
|
||||||
|
status, xmldata = self.socket:receive()
|
||||||
|
if not status then
|
||||||
|
stdnse.print_debug("ERROR: %s", xmldata)
|
||||||
|
return false, xmldata
|
||||||
|
end
|
||||||
|
|
||||||
|
-- As NSE has no XML parser yet, we use regexp to extract the data from the
|
||||||
|
-- XML output. Targets are defined as a name and the corresponding host(s).
|
||||||
|
-- Thus we gather both and return an associative array, using names as keys
|
||||||
|
-- and hosts as values.
|
||||||
|
|
||||||
|
local i = 0
|
||||||
|
for name in xmldata:gmatch("<name>(.-)</name>") do
|
||||||
|
-- XXX this is hackish: skip the second and third "<name>" tags, as they
|
||||||
|
-- describe other components than the targets.
|
||||||
|
-- see: http://www.openvas.org/omp-2-0.html#command_get_targets
|
||||||
|
if i % 3 == 0 then
|
||||||
|
table.insert(target_names, name)
|
||||||
|
end
|
||||||
|
i = i + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
for hosts in xmldata:gmatch("<hosts>(.-)</hosts>") do
|
||||||
|
table.insert(target_hosts, hosts)
|
||||||
|
end
|
||||||
|
|
||||||
|
for i, _ in ipairs(target_names) do
|
||||||
|
res[target_names[i]] = target_hosts[i]
|
||||||
|
end
|
||||||
|
|
||||||
|
return res
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
|
--- Registers OMP2 credentials for a given host
|
||||||
|
function add_account(host, username, password)
|
||||||
|
if not nmap.registry[host.ip] then
|
||||||
|
nmap.registry[host.ip] = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
if not nmap.registry[host.ip]["omp2accounts"] then
|
||||||
|
nmap.registry[host.ip]["omp2accounts"] = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(nmap.registry[host.ip]["omp2accounts"], {["username"] = username, ["password"] = password})
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Retrieves the list of accounts for a given host
|
||||||
|
function get_accounts(host)
|
||||||
|
local accounts = {}
|
||||||
|
local username, password
|
||||||
|
|
||||||
|
username = nmap.registry.args["omp2.username"]
|
||||||
|
password = nmap.registry.args["omp2.password"]
|
||||||
|
|
||||||
|
if username and password then
|
||||||
|
table.insert(accounts, {["username"] = username, ["password"] = password})
|
||||||
|
end
|
||||||
|
|
||||||
|
if nmap.registry[host.ip] and nmap.registry[host.ip]["omp2accounts"] then
|
||||||
|
for _, account in pairs(nmap.registry[host.ip]["omp2accounts"]) do
|
||||||
|
table.insert(accounts, account)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if #accounts > 0 then
|
||||||
|
return accounts
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
83
scripts/omp2-brute.nse
Normal file
83
scripts/omp2-brute.nse
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
description = [[
|
||||||
|
Performs brute force password auditing against the OpenVAS manager using OMPv2.
|
||||||
|
]]
|
||||||
|
|
||||||
|
---
|
||||||
|
-- @usage
|
||||||
|
-- nmap -p 9390 --script omp2-brute <target>
|
||||||
|
--
|
||||||
|
-- @output
|
||||||
|
-- PORT STATE SERVICE REASON
|
||||||
|
-- 9390/tcp open openvas syn-ack
|
||||||
|
-- | svn-brute:
|
||||||
|
-- | Accounts
|
||||||
|
-- |_ admin:secret => Login correct
|
||||||
|
--
|
||||||
|
|
||||||
|
author = "Henri Doreau"
|
||||||
|
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
|
||||||
|
categories = {"auth", "intrusive"}
|
||||||
|
|
||||||
|
require("omp2")
|
||||||
|
require("nmap")
|
||||||
|
require("brute")
|
||||||
|
require("shortport")
|
||||||
|
|
||||||
|
|
||||||
|
portrule = shortport.port_or_service(9390, "openvas")
|
||||||
|
|
||||||
|
|
||||||
|
Driver = {
|
||||||
|
new = function(self, host, port)
|
||||||
|
local o = {}
|
||||||
|
setmetatable(o, self)
|
||||||
|
self.__index = self
|
||||||
|
o.host = host
|
||||||
|
o.port = port
|
||||||
|
o.session = omp2.Session:new()
|
||||||
|
return o
|
||||||
|
end,
|
||||||
|
|
||||||
|
--- Connects to the OpenVAS Manager
|
||||||
|
--
|
||||||
|
-- @return status boolean for connection success/failure
|
||||||
|
-- @return err string describing the error on failure
|
||||||
|
connect = function(self)
|
||||||
|
return self.session:connect(self.host, self.port)
|
||||||
|
end,
|
||||||
|
|
||||||
|
--- Closes connection
|
||||||
|
--
|
||||||
|
-- @return status boolean for closing success/failure
|
||||||
|
disconnect = function(self)
|
||||||
|
return self.session:close()
|
||||||
|
end,
|
||||||
|
|
||||||
|
--- Attempts to login the the OpenVAS Manager using a given username/password
|
||||||
|
-- couple. Store the credentials in the registry on success.
|
||||||
|
--
|
||||||
|
-- @param username string containing the login username
|
||||||
|
-- @param password string containing the login password
|
||||||
|
-- @return status boolean for login success/failure
|
||||||
|
-- @return err string describing the error on failure
|
||||||
|
login = function(self, username, password)
|
||||||
|
if self.session:authenticate(username, password) then
|
||||||
|
-- store the account for possible future use
|
||||||
|
omp2.add_account(self.host, username, password)
|
||||||
|
return true, brute.Account:new(username, password, "OPEN")
|
||||||
|
else
|
||||||
|
return false, brute.Error:new("login failed")
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
|
--- Deprecated
|
||||||
|
check = function(self)
|
||||||
|
return true
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
|
action = function(host, port)
|
||||||
|
local status, result = brute.Engine:new(Driver, host, port):start()
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
125
scripts/omp2-enum-targets.nse
Normal file
125
scripts/omp2-enum-targets.nse
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
description = [[
|
||||||
|
Attempts to get the list of targets from an OpenVAS Manager server.
|
||||||
|
|
||||||
|
The script authenticates on the manager using provided or previously cracked
|
||||||
|
credentials and gets the list of defined targets for each account.
|
||||||
|
|
||||||
|
These targets will be added to the scanning queue in case
|
||||||
|
<code>newtargets</code> global variable is set.
|
||||||
|
]]
|
||||||
|
|
||||||
|
---
|
||||||
|
-- @usage
|
||||||
|
-- nmap -p 9390 --script omp2-brute,omp2-enum-targets <target>
|
||||||
|
--
|
||||||
|
-- @usage
|
||||||
|
-- nmap -p 9390 --script omp2-enum-targets --script-args omp2.username=admin,omp2.password=secret <target>
|
||||||
|
--
|
||||||
|
-- @output
|
||||||
|
-- PORT STATE SERVICE
|
||||||
|
-- 9390/tcp open openvas
|
||||||
|
-- | omp2-enum-targets:
|
||||||
|
-- |
|
||||||
|
-- | Targets for account admin:
|
||||||
|
-- | TARGET HOSTS
|
||||||
|
-- | Sales network 192.168.20.0/24
|
||||||
|
-- | Production network 192.168.30.0/24
|
||||||
|
-- |_ Firewall 192.168.1.254
|
||||||
|
--
|
||||||
|
|
||||||
|
|
||||||
|
author = "Henri Doreau"
|
||||||
|
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
|
||||||
|
categories = {"discovery", "safe"}
|
||||||
|
dependencies = {"omp2-brute"}
|
||||||
|
|
||||||
|
|
||||||
|
require("tab")
|
||||||
|
require("omp2")
|
||||||
|
require("target")
|
||||||
|
require("stdnse")
|
||||||
|
require("shortport")
|
||||||
|
|
||||||
|
|
||||||
|
portrule = shortport.port_or_service(9390, "openvas")
|
||||||
|
|
||||||
|
|
||||||
|
--- Return the list of targets defined for a given user
|
||||||
|
--
|
||||||
|
-- @param host the target host table
|
||||||
|
-- @param port the targetted OMP port
|
||||||
|
-- @param username the username to use to login
|
||||||
|
-- @param password the password to use to login
|
||||||
|
-- @return the list of targets for this user or nil
|
||||||
|
local function account_enum_targets(host, port, username, password)
|
||||||
|
local targets
|
||||||
|
local session = omp2.Session:new()
|
||||||
|
|
||||||
|
local status, err = session:connect(host, port)
|
||||||
|
|
||||||
|
if not status then
|
||||||
|
stdnse.print_debug("%s: connection failure (%s)", SCRIPT_NAME, err)
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
if session:authenticate(username, password) then
|
||||||
|
targets = session:ls_targets()
|
||||||
|
else
|
||||||
|
stdnse.print_debug("%s: authentication failure (%s:%s)", SCRIPT_NAME, username, password)
|
||||||
|
end
|
||||||
|
|
||||||
|
session:close()
|
||||||
|
|
||||||
|
return targets
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Generate the output string representing the list of discovered targets
|
||||||
|
--
|
||||||
|
-- @param targets the list of targets as a name->hosts mapping
|
||||||
|
-- @return the array as a formatted string
|
||||||
|
local function report(targets)
|
||||||
|
local outtab = tab.new()
|
||||||
|
|
||||||
|
tab.add(outtab, 1, "TARGET")
|
||||||
|
tab.add(outtab, 2, "HOSTS")
|
||||||
|
tab.nextrow(outtab)
|
||||||
|
|
||||||
|
for name, hosts in pairs(targets) do
|
||||||
|
tab.addrow(outtab, name, hosts)
|
||||||
|
end
|
||||||
|
|
||||||
|
return tab.dump(outtab)
|
||||||
|
end
|
||||||
|
|
||||||
|
action = function(host, port)
|
||||||
|
local results = {}
|
||||||
|
local credentials = omp2.get_accounts(host)
|
||||||
|
|
||||||
|
if not credentials then
|
||||||
|
-- unable to authenticate on the server
|
||||||
|
return "No valid account available!"
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, account in pairs(credentials) do
|
||||||
|
|
||||||
|
local username, password = account.username, account.password
|
||||||
|
|
||||||
|
local targets = account_enum_targets(host, port, username, password)
|
||||||
|
|
||||||
|
if targets ~= nil then
|
||||||
|
table.insert(results, "\nTargets for account " .. username .. ":")
|
||||||
|
table.insert(results, report(targets))
|
||||||
|
else
|
||||||
|
table.insert(results, "\nNo targets found for account " .. username)
|
||||||
|
end
|
||||||
|
|
||||||
|
if target.ALLOW_NEW_TARGETS and targets ~= nil then
|
||||||
|
stdnse.print_debug("%s: adding new targets %s", SCRIPT_NAME, stdnse.strjoin(", ", targets))
|
||||||
|
target.add(unpack(targets))
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return stdnse.format_output(true, results)
|
||||||
|
end
|
||||||
|
|
||||||
@@ -119,6 +119,8 @@ Entry { filename = "nping-brute.nse", categories = { "auth", "intrusive", } }
|
|||||||
Entry { filename = "nrpe-enum.nse", categories = { "discovery", "intrusive", } }
|
Entry { filename = "nrpe-enum.nse", categories = { "discovery", "intrusive", } }
|
||||||
Entry { filename = "ntp-info.nse", categories = { "default", "discovery", "safe", } }
|
Entry { filename = "ntp-info.nse", categories = { "default", "discovery", "safe", } }
|
||||||
Entry { filename = "ntp-monlist.nse", categories = { "discovery", "intrusive", } }
|
Entry { filename = "ntp-monlist.nse", categories = { "discovery", "intrusive", } }
|
||||||
|
Entry { filename = "omp2-brute.nse", categories = { "auth", "intrusive", } }
|
||||||
|
Entry { filename = "omp2-enum-targets.nse", categories = { "discovery", "safe", } }
|
||||||
Entry { filename = "oracle-brute.nse", categories = { "auth", "intrusive", } }
|
Entry { filename = "oracle-brute.nse", categories = { "auth", "intrusive", } }
|
||||||
Entry { filename = "oracle-enum-users.nse", categories = { "auth", "intrusive", } }
|
Entry { filename = "oracle-enum-users.nse", categories = { "auth", "intrusive", } }
|
||||||
Entry { filename = "oracle-sid-brute.nse", categories = { "auth", "intrusive", } }
|
Entry { filename = "oracle-sid-brute.nse", categories = { "auth", "intrusive", } }
|
||||||
|
|||||||
Reference in New Issue
Block a user