mirror of
https://github.com/nmap/nmap.git
synced 2025-12-06 04:31:29 +00:00
Change how ms-sql NSE scripts run
MS SQL NSE scripts run on database instances, which can be TCP or named pipes. With this change, all TCP instances on scanned ports will have script output attached under the port as a portrule script. Named pipe instances and TCP instances on unscanned ports will be displayed in the hostrule script output at the end of the host's output. Utility function mssql.Helper.InitScript makes it easy to write scripts that just work on a per-instance basis, without bothering where to put the output. Discovery will be done once per host, regardless of how many scripts are run, and can be guaranteed to be done before the script's action takes place.
This commit is contained in:
284
nselib/mssql.lua
284
nselib/mssql.lua
@@ -74,12 +74,19 @@
|
|||||||
-- argument is not given but <code>mssql.username</code>, a blank password
|
-- argument is not given but <code>mssql.username</code>, a blank password
|
||||||
-- is used.
|
-- is used.
|
||||||
--
|
--
|
||||||
-- @args mssql.instance-name The name of the instance to connect to.
|
-- @args mssql.instance-name In addition to instances discovered via port
|
||||||
|
-- scanning and version detection, run scripts on
|
||||||
|
-- these named instances (string or list of strings)
|
||||||
--
|
--
|
||||||
-- @args mssql.instance-port The port of the instance to connect to.
|
-- @args mssql.instance-port In addition to instances discovered via port
|
||||||
|
-- scanning and version detection, run scripts on
|
||||||
|
-- the instances running on these ports (number or list of numbers)
|
||||||
--
|
--
|
||||||
-- @args mssql.instance-all Targets all SQL server instances discovered
|
-- @args mssql.instance-all In addition to instances discovered via port
|
||||||
-- through the browser service.
|
-- scanning and version detection, run scripts on all
|
||||||
|
-- discovered instances. These include named-pipe
|
||||||
|
-- instances via SMB and those discovered via the
|
||||||
|
-- browser service.
|
||||||
--
|
--
|
||||||
-- @args mssql.domain The domain against which to perform integrated
|
-- @args mssql.domain The domain against which to perform integrated
|
||||||
-- authentication. When set, the scripts assume integrated authentication
|
-- authentication. When set, the scripts assume integrated authentication
|
||||||
@@ -107,13 +114,14 @@ local math = require "math"
|
|||||||
local match = require "match"
|
local match = require "match"
|
||||||
local nmap = require "nmap"
|
local nmap = require "nmap"
|
||||||
local datetime = require "datetime"
|
local datetime = require "datetime"
|
||||||
local shortport = require "shortport"
|
local outlib = require "outlib"
|
||||||
local smb = require "smb"
|
local smb = require "smb"
|
||||||
local smbauth = require "smbauth"
|
local smbauth = require "smbauth"
|
||||||
local stdnse = require "stdnse"
|
local stdnse = require "stdnse"
|
||||||
local strbuf = require "strbuf"
|
local strbuf = require "strbuf"
|
||||||
local string = require "string"
|
local string = require "string"
|
||||||
local table = require "table"
|
local table = require "table"
|
||||||
|
local tableaux = require "tableaux"
|
||||||
local unicode = require "unicode"
|
local unicode = require "unicode"
|
||||||
_ENV = stdnse.module("mssql", stdnse.seeall)
|
_ENV = stdnse.module("mssql", stdnse.seeall)
|
||||||
|
|
||||||
@@ -150,11 +158,24 @@ do
|
|||||||
end
|
end
|
||||||
MSSQL_TIMEOUT = timeout
|
MSSQL_TIMEOUT = timeout
|
||||||
|
|
||||||
SCANNED_PORTS_ONLY = false
|
|
||||||
if ( stdnse.get_script_args( "mssql.scanned-ports-only" ) ) then
|
|
||||||
SCANNED_PORTS_ONLY = true
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Make args either a list or nil
|
||||||
|
local function list_of (input, transform)
|
||||||
|
if not input then return nil end
|
||||||
|
if type(input) ~= "table" then
|
||||||
|
return {transform(input)}
|
||||||
end
|
end
|
||||||
|
for i, v in ipairs(input) do
|
||||||
|
input[i] = transform(v)
|
||||||
|
end
|
||||||
|
return input
|
||||||
|
end
|
||||||
|
|
||||||
|
local SCANNED_PORTS_ONLY = not not stdnse.get_script_args("mssql.scanned-ports-only")
|
||||||
|
local targetInstanceNames = list_of(stdnse.get_script_args("mssql.instance-name"), string.upper)
|
||||||
|
local targetInstancePorts = list_of(stdnse.get_script_args("mssql.instance-port"), tonumber)
|
||||||
|
local targetAllInstances = not not stdnse.get_script_args("mssql.instance-all")
|
||||||
|
|
||||||
-- This constant is number of seconds from 1900-01-01 to 1970-01-01
|
-- This constant is number of seconds from 1900-01-01 to 1970-01-01
|
||||||
local tds_offset_seconds = -2208988800 - datetime.utc_offset()
|
local tds_offset_seconds = -2208988800 - datetime.utc_offset()
|
||||||
@@ -2561,6 +2582,9 @@ Helper =
|
|||||||
--- Gets a table containing SqlServerInstanceInfo objects discovered on
|
--- Gets a table containing SqlServerInstanceInfo objects discovered on
|
||||||
-- the specified host (and port, if specified).
|
-- the specified host (and port, if specified).
|
||||||
--
|
--
|
||||||
|
-- This table is the NSE registry table itself, not a copy, so do not alter
|
||||||
|
-- it unintentionally.
|
||||||
|
--
|
||||||
-- @param host A host table for the target host
|
-- @param host A host table for the target host
|
||||||
-- @param port (Optional) If omitted, all of the instances for the host
|
-- @param port (Optional) If omitted, all of the instances for the host
|
||||||
-- will be returned.
|
-- will be returned.
|
||||||
@@ -2570,12 +2594,12 @@ Helper =
|
|||||||
nmap.registry.mssql.instances = nmap.registry.mssql.instances or {}
|
nmap.registry.mssql.instances = nmap.registry.mssql.instances or {}
|
||||||
nmap.registry.mssql.instances[ host.ip ] = nmap.registry.mssql.instances[ host.ip ] or {}
|
nmap.registry.mssql.instances[ host.ip ] = nmap.registry.mssql.instances[ host.ip ] or {}
|
||||||
|
|
||||||
if ( not port ) then
|
|
||||||
local instances = nmap.registry.mssql.instances[ host.ip ]
|
local instances = nmap.registry.mssql.instances[ host.ip ]
|
||||||
|
if ( not port ) then
|
||||||
if ( instances and #instances == 0 ) then instances = nil end
|
if ( instances and #instances == 0 ) then instances = nil end
|
||||||
return instances
|
return instances
|
||||||
else
|
else
|
||||||
for _, instance in ipairs( nmap.registry.mssql.instances[ host.ip ] ) do
|
for _, instance in ipairs(instances) do
|
||||||
if ( instance.port and instance.port.number == port.number and
|
if ( instance.port and instance.port.number == port.number and
|
||||||
instance.port.protocol == port.protocol ) then
|
instance.port.protocol == port.protocol ) then
|
||||||
return { instance }
|
return { instance }
|
||||||
@@ -2660,15 +2684,20 @@ Helper =
|
|||||||
DiscoverByTcp = function( host, port )
|
DiscoverByTcp = function( host, port )
|
||||||
local version, instance, status
|
local version, instance, status
|
||||||
-- Check to see if we've already discovered an instance on this port
|
-- Check to see if we've already discovered an instance on this port
|
||||||
instance = Helper.GetDiscoveredInstances( host, port )
|
local instance = Helper.GetDiscoveredInstances(host, port)
|
||||||
if ( not instance ) then
|
if instance then
|
||||||
|
return true, {instance}
|
||||||
|
end
|
||||||
instance = SqlServerInstanceInfo:new()
|
instance = SqlServerInstanceInfo:new()
|
||||||
instance.host = host
|
instance.host = host
|
||||||
instance.port = port
|
instance.port = port
|
||||||
|
|
||||||
-- -sV may have gotten a version, but for now, it doesn't extract subBuild.
|
-- -sV may have gotten a version, but for now, it doesn't extract subBuild.
|
||||||
status, version = Helper.GetInstanceVersion( instance )
|
status, version = Helper.GetInstanceVersion( instance )
|
||||||
if ( status ) then
|
if not status then
|
||||||
|
return false, version
|
||||||
|
end
|
||||||
|
|
||||||
Helper.AddOrMergeInstance( instance )
|
Helper.AddOrMergeInstance( instance )
|
||||||
-- The point of this wasn't to get the version, just to use the
|
-- The point of this wasn't to get the version, just to use the
|
||||||
-- pre-login packet to determine whether there was a SQL Server on
|
-- pre-login packet to determine whether there was a SQL Server on
|
||||||
@@ -2679,10 +2708,8 @@ Helper =
|
|||||||
instance.version:PopulateNmapPortVersion( instance.port )
|
instance.version:PopulateNmapPortVersion( instance.port )
|
||||||
nmap.set_port_version( host, instance.port)
|
nmap.set_port_version( host, instance.port)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return (instance ~= nil), { instance }
|
return true, { instance }
|
||||||
end,
|
end,
|
||||||
|
|
||||||
--- Attempts to discover SQL Server instances listening on default named
|
--- Attempts to discover SQL Server instances listening on default named
|
||||||
@@ -2743,48 +2770,37 @@ Helper =
|
|||||||
end
|
end
|
||||||
nmap.registry.mssql.discovery_performed[ host.ip ] = false
|
nmap.registry.mssql.discovery_performed[ host.ip ] = false
|
||||||
|
|
||||||
-- Check all ports that -sV discovered
|
-- First, do SSRP discovery. Check any open (got response) ports first:
|
||||||
-- First SSRP browser ports, then TCP instances
|
local port = nmap.get_ports(host, nil, "udp", "open")
|
||||||
for _, c in ipairs({
|
|
||||||
{proto="udp", name="ms-sql-m", method="DiscoverBySsrp"},
|
|
||||||
{proto="tcp", name="ms-sql-s", method="DiscoverByTcp"},
|
|
||||||
}) do
|
|
||||||
-- (no need to check open|filtered because -sV marks it as open if it gets a response)
|
|
||||||
local port = nmap.get_ports(host, nil, c.proto, "open")
|
|
||||||
while port do
|
while port do
|
||||||
if port.version and port.version.name == c.name then
|
if port.version and port.version.name == "ms-sql-m" then
|
||||||
Helper[c.method]( host, port )
|
Helper.DiscoverBySsrp(host, port)
|
||||||
end
|
end
|
||||||
port = nmap.get_ports(host, port, c.proto, "open")
|
port = nmap.get_ports(host, port, "udp", "open")
|
||||||
end
|
end
|
||||||
|
-- Then check if default SSRP port hasn't been done yet.
|
||||||
|
port = nmap.get_port_state(host, SSRP.PORT)
|
||||||
|
if not port or port.state == "open|filtered" then
|
||||||
|
-- Either it wasn't scanned or it wasn't strictly "open" so we missed it above
|
||||||
|
Helper.DiscoverBySsrp(host, port)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Next, do TCP discovery. Check any ports with an appropriate service name
|
||||||
|
port = nmap.get_ports(host, nil, "tcp", "open")
|
||||||
|
while port do
|
||||||
|
if port.version and port.version.name == "ms-sql-s" then
|
||||||
|
Helper.DiscoverByTcp(host, port)
|
||||||
|
end
|
||||||
|
port = nmap.get_ports(host, port, "tcp", "open")
|
||||||
end
|
end
|
||||||
|
|
||||||
local sqlDefaultPort = nmap.get_port_state( host, {number = 1433, protocol = "tcp"} ) or {number = 1433, protocol = "tcp"}
|
|
||||||
local sqlBrowserPort = nmap.get_port_state( host, {number = 1434, protocol = "udp"} ) or {number = 1434, protocol = "udp"}
|
|
||||||
local smbPort
|
|
||||||
-- smb.get_port() will return nil if no SMB port was scanned OR if SMB ports were scanned but none was open
|
-- smb.get_port() will return nil if no SMB port was scanned OR if SMB ports were scanned but none was open
|
||||||
local smbPortNumber = smb.get_port( host )
|
if smb.get_port(host) then
|
||||||
if ( smbPortNumber ) then
|
Helper.DiscoverBySmb( host )
|
||||||
smbPort = nmap.get_port_state( host, {number = smbPortNumber, protocol = "tcp"} )
|
|
||||||
-- There's no use in manually setting an SMB port; if no SMB port was
|
|
||||||
-- scanned and found open, the SMB library won't work
|
|
||||||
end
|
end
|
||||||
-- if the user has specified ports, we'll check those too
|
|
||||||
local targetInstancePorts = stdnse.get_script_args( "mssql.instance-port" )
|
|
||||||
|
|
||||||
if ( sqlBrowserPort and sqlBrowserPort.state ~= "closed" ) then
|
-- if the user has specified ports, we'll check those too
|
||||||
Helper.DiscoverBySsrp( host, sqlBrowserPort )
|
|
||||||
end
|
|
||||||
if ( sqlDefaultPort and sqlDefaultPort.state ~= "closed" ) then
|
|
||||||
Helper.DiscoverByTcp( host, sqlDefaultPort )
|
|
||||||
end
|
|
||||||
if ( smbPort ) then
|
|
||||||
Helper.DiscoverBySmb( host, smbPort )
|
|
||||||
end
|
|
||||||
if ( targetInstancePorts ) then
|
if ( targetInstancePorts ) then
|
||||||
if ( type( targetInstancePorts ) == "string" ) then
|
|
||||||
targetInstancePorts = { targetInstancePorts }
|
|
||||||
end
|
|
||||||
for _, portNumber in ipairs( targetInstancePorts ) do
|
for _, portNumber in ipairs( targetInstancePorts ) do
|
||||||
portNumber = tonumber( portNumber )
|
portNumber = tonumber( portNumber )
|
||||||
Helper.DiscoverByTcp( host, {number = portNumber, protocol = "tcp"} )
|
Helper.DiscoverByTcp( host, {number = portNumber, protocol = "tcp"} )
|
||||||
@@ -3142,27 +3158,18 @@ Helper =
|
|||||||
-- more SqlServerInstanceInfo objects. If status is false, this will be
|
-- more SqlServerInstanceInfo objects. If status is false, this will be
|
||||||
-- an error message.
|
-- an error message.
|
||||||
GetTargetInstances = function( host, port )
|
GetTargetInstances = function( host, port )
|
||||||
if ( port ) then
|
-- Perform discovery. This won't do anything if it's already been done.
|
||||||
local status = true
|
-- It's important because otherwise we might miss some ports when not using -sV
|
||||||
local instance = Helper.GetDiscoveredInstances( host, port )
|
Helper.Discover( host )
|
||||||
|
|
||||||
if ( not instance ) then
|
if ( port ) then
|
||||||
status, instance = Helper.DiscoverByTcp( host, port )
|
local status, instances = Helper.GetDiscoveredInstances(host, port)
|
||||||
end
|
if status then
|
||||||
if ( instance ) then
|
return true, instances
|
||||||
return true, instance
|
|
||||||
else
|
else
|
||||||
return false, "No SQL Server instance detected on this port"
|
return false, "No SQL Server instance detected on this port"
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
local targetInstanceNames = stdnse.get_script_args( "mssql.instance-name" )
|
|
||||||
local targetInstancePorts = stdnse.get_script_args( "mssql.instance-port" )
|
|
||||||
local targetAllInstances = stdnse.get_script_args( "mssql.instance-all" )
|
|
||||||
|
|
||||||
if ( targetInstanceNames and targetInstancePorts ) then
|
|
||||||
return false, "Connections can be made either by instance name or port."
|
|
||||||
end
|
|
||||||
|
|
||||||
if ( targetAllInstances and ( targetInstanceNames or targetInstancePorts ) ) then
|
if ( targetAllInstances and ( targetInstanceNames or targetInstancePorts ) ) then
|
||||||
return false, "All instances cannot be specified together with an instance name or port."
|
return false, "All instances cannot be specified together with an instance name or port."
|
||||||
end
|
end
|
||||||
@@ -3171,51 +3178,43 @@ Helper =
|
|||||||
return false, "No instance(s) specified."
|
return false, "No instance(s) specified."
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Perform discovery. This won't do anything if it's already been done.
|
|
||||||
Helper.Discover( host )
|
|
||||||
|
|
||||||
local instanceList = Helper.GetDiscoveredInstances( host )
|
local instanceList = Helper.GetDiscoveredInstances( host )
|
||||||
if ( not instanceList ) then
|
if ( not instanceList ) then
|
||||||
return false, "No instances found on target host"
|
return false, "No instances found on target host"
|
||||||
end
|
end
|
||||||
|
|
||||||
local targetInstances = {}
|
local targetInstances = {}
|
||||||
if ( targetAllInstances ) then
|
|
||||||
targetInstances = instanceList
|
|
||||||
else
|
|
||||||
-- We want an easy way to look up whether an instance's name was
|
|
||||||
-- in our target list. So, we'll make a table of { instanceName = true, ... }
|
|
||||||
local temp = {}
|
|
||||||
if ( targetInstanceNames ) then
|
|
||||||
if ( type( targetInstanceNames ) == "string" ) then
|
|
||||||
targetInstanceNames = { targetInstanceNames }
|
|
||||||
end
|
|
||||||
for _, instanceName in ipairs( targetInstanceNames ) do
|
|
||||||
temp[ string.upper( instanceName ) ] = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
targetInstanceNames = temp
|
|
||||||
|
|
||||||
-- Do the same for the target ports
|
|
||||||
temp = {}
|
|
||||||
if ( targetInstancePorts ) then
|
|
||||||
if ( type( targetInstancePorts ) == "string" ) then
|
|
||||||
targetInstancePorts = { targetInstancePorts }
|
|
||||||
end
|
|
||||||
for _, portNumber in ipairs( targetInstancePorts ) do
|
|
||||||
portNumber = tonumber( portNumber )
|
|
||||||
temp[portNumber] = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
targetInstancePorts = temp
|
|
||||||
|
|
||||||
for _, instance in ipairs( instanceList ) do
|
for _, instance in ipairs( instanceList ) do
|
||||||
if ( instance.instanceName and targetInstanceNames[ string.upper( instance.instanceName ) ] ) then
|
repeat -- just so we can use break
|
||||||
table.insert( targetInstances, instance )
|
if instance.port then
|
||||||
elseif ( instance.port and targetInstancePorts[ tonumber( instance.port.number ) ] ) then
|
local scanport = nmap.get_port_state(host, instance.port)
|
||||||
table.insert( targetInstances, instance )
|
-- If scanned-ports-only and it's on a non-scanned port
|
||||||
|
if (SCANNED_PORTS_ONLY and not scanport)
|
||||||
|
-- or if a portrule script will run on it
|
||||||
|
or (scanport and scanport.state == "open") then
|
||||||
|
break -- not interested
|
||||||
|
end
|
||||||
|
-- If they want everything
|
||||||
|
if targetAllInstances or
|
||||||
|
-- or if it's in the instance-port arg
|
||||||
|
(targetInstancePorts and
|
||||||
|
tableaux.contains(targetInstancePorts, instance.port.number)) then
|
||||||
|
-- keep it and move on
|
||||||
|
targetInstances[#targetInstances+1] = instance
|
||||||
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
-- If they want everything
|
||||||
|
if targetAllInstances or
|
||||||
|
-- or if it's in the instance-name arg
|
||||||
|
(instance.instanceName and targetInstanceNames and
|
||||||
|
tableaux.contains(targetInstanceNames, string.upper(instance.instanceName))) then
|
||||||
|
--keep it and move on
|
||||||
|
targetInstances[#targetInstances+1] = instance
|
||||||
|
break
|
||||||
|
end
|
||||||
|
until false
|
||||||
end
|
end
|
||||||
|
|
||||||
if ( #targetInstances > 0 ) then
|
if ( #targetInstances > 0 ) then
|
||||||
@@ -3232,14 +3231,17 @@ Helper =
|
|||||||
-- the database when normal connection attempts fail, for example, when
|
-- the database when normal connection attempts fail, for example, when
|
||||||
-- the server is hanging, out of memory or other bad states.
|
-- the server is hanging, out of memory or other bad states.
|
||||||
--
|
--
|
||||||
-- @param host Host table as received by the script action function
|
-- @param instance the <code>SqlServerInstanceInfo</code> object to probe for a DAC port
|
||||||
-- @param instanceName the instance name to probe for a DAC port
|
|
||||||
-- @return number containing the DAC port on success or nil on failure
|
-- @return number containing the DAC port on success or nil on failure
|
||||||
DiscoverDACPort = function(host, instanceName)
|
DiscoverDACPort = function(instance)
|
||||||
local socket = nmap.new_socket()
|
local instanceName = instance.instanceName or instance.pipeName
|
||||||
|
if not instanceName then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
local socket = nmap.new_socket("udp")
|
||||||
socket:set_timeout(5000)
|
socket:set_timeout(5000)
|
||||||
|
|
||||||
if ( not(socket:connect(host, 1434, "udp")) ) then
|
if ( not(socket:connect(instance.host, 1434, "udp")) ) then
|
||||||
return false, "Failed to connect to sqlbrowser service"
|
return false, "Failed to connect to sqlbrowser service"
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -3249,11 +3251,10 @@ Helper =
|
|||||||
end
|
end
|
||||||
|
|
||||||
local status, data = socket:receive_buf(match.numbytes(6), true)
|
local status, data = socket:receive_buf(match.numbytes(6), true)
|
||||||
if ( not(status) ) then
|
|
||||||
socket:close()
|
socket:close()
|
||||||
|
if ( not(status) ) then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
socket:close()
|
|
||||||
|
|
||||||
if ( #data < 6 ) then
|
if ( #data < 6 ) then
|
||||||
return nil
|
return nil
|
||||||
@@ -3261,42 +3262,47 @@ Helper =
|
|||||||
return string.unpack("<I2", data, 5)
|
return string.unpack("<I2", data, 5)
|
||||||
end,
|
end,
|
||||||
|
|
||||||
--- Returns a hostrule for standard SQL Server scripts, which will return
|
--- Returns an action, portrule, and hostrule for standard SQL Server scripts
|
||||||
-- true if one or more instances have been targeted with the <code>mssql.instance</code>
|
|
||||||
-- script argument.
|
|
||||||
--
|
--
|
||||||
-- However, if a previous script has failed to find any
|
-- The action function performs discovery if necessary and dispatches the
|
||||||
-- SQL Server instances on the host, the hostrule function will return
|
-- process_instance function on all discovered instances.
|
||||||
-- false to keep further scripts from running unnecessarily on that host.
|
|
||||||
--
|
--
|
||||||
-- @return A hostrule function (use as <code>hostrule = mssql.GetHostrule_Standard()</code>)
|
-- The portrule returns true if the port has been identified as "ms-sql-s" or
|
||||||
GetHostrule_Standard = function()
|
-- discovery has found an instance on that port.
|
||||||
return function( host )
|
--
|
||||||
if ( stdnse.get_script_args( {"mssql.instance-all", "mssql.instance-name", "mssql.instance-port"} ) ~= nil ) then
|
-- The hostrule returns true if any of the <code>mssql.instance-*</code>
|
||||||
if ( Helper.WasDiscoveryPerformed( host ) ) then
|
-- script-args has been set and either a matching instance exists or
|
||||||
return Helper.GetDiscoveredInstances( host ) ~= nil
|
-- discovery has not yet been done.
|
||||||
else
|
-- @usage action, portrule, hostrule = mssql.Helper.InitScript(do_something)
|
||||||
return true
|
--
|
||||||
|
-- @param process_instance A function that takes a single parameter, a
|
||||||
|
-- <code>SqlServerInstanceInfo</code> object, and
|
||||||
|
-- returns output suitable for an action function to
|
||||||
|
-- return.
|
||||||
|
--
|
||||||
|
-- @return An action function
|
||||||
|
-- @return A portrule function
|
||||||
|
-- @return A hostrule function
|
||||||
|
InitScript = function(process_instance)
|
||||||
|
local action = function(host, port)
|
||||||
|
local status, instances = Helper.GetTargetInstances(host, port)
|
||||||
|
if not status then
|
||||||
|
stdnse.debug1("GetTargetInstances: %s", instances)
|
||||||
|
return nil
|
||||||
end
|
end
|
||||||
else
|
local output = {}
|
||||||
return false
|
for _, instance in ipairs(instances) do
|
||||||
|
output[instance:GetName()] = process_instance(instance)
|
||||||
end
|
end
|
||||||
|
if #output > 0 then
|
||||||
|
return outlib.sorted_by_key(output)
|
||||||
|
end
|
||||||
|
return nil
|
||||||
end
|
end
|
||||||
end,
|
|
||||||
|
|
||||||
|
-- GetTargetInstances does the right thing depending on whether port is
|
||||||
--- Returns a portrule for standard SQL Server scripts
|
-- provided, which corresponds to portrule vs hostrule.
|
||||||
--
|
return action, Helper.GetTargetInstances, Helper.GetTargetInstances
|
||||||
-- The portrule return true if BOTH of the following conditions are met:
|
|
||||||
-- * The port has been identified as "ms-sql-s"
|
|
||||||
-- * The <code>mssql.instance</code> script argument has NOT been used
|
|
||||||
--
|
|
||||||
-- @return A portrule function (use as <code>portrule = mssql.GetPortrule_Standard()</code>)
|
|
||||||
GetPortrule_Standard = function()
|
|
||||||
return function( host, port )
|
|
||||||
return ( shortport.service( "ms-sql-s" )(host, port) and
|
|
||||||
stdnse.get_script_args( {"mssql.instance-all", "mssql.instance-name", "mssql.instance-port"} ) == nil)
|
|
||||||
end
|
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3371,11 +3377,11 @@ Auth = {
|
|||||||
Util =
|
Util =
|
||||||
{
|
{
|
||||||
--- Takes a table as returned by Query and does some fancy formatting
|
--- Takes a table as returned by Query and does some fancy formatting
|
||||||
-- better suitable for <code>stdnse.output_result</code>
|
-- better suitable for <code>stdnse.format_output</code>
|
||||||
--
|
--
|
||||||
-- @param tbl as received by <code>Helper.Query</code>
|
-- @param tbl as received by <code>Helper.Query</code>
|
||||||
-- @param with_headers boolean true if output should contain column headers
|
-- @param with_headers boolean true if output should contain column headers
|
||||||
-- @return table suitable for <code>stdnse.output_result</code>
|
-- @return table suitable for <code>stdnse.format_output</code>
|
||||||
FormatOutputTable = function ( tbl, with_headers )
|
FormatOutputTable = function ( tbl, with_headers )
|
||||||
local new_tbl = {}
|
local new_tbl = {}
|
||||||
local col_names = {}
|
local col_names = {}
|
||||||
|
|||||||
@@ -77,13 +77,7 @@ author = "Patrik Karlsson"
|
|||||||
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
|
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
|
||||||
categories = {"brute", "intrusive"}
|
categories = {"brute", "intrusive"}
|
||||||
|
|
||||||
dependencies = {"ms-sql-empty-password"}
|
dependencies = {"broadcast-ms-sql-discover", "ms-sql-empty-password"}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
hostrule = mssql.Helper.GetHostrule_Standard()
|
|
||||||
portrule = mssql.Helper.GetPortrule_Standard()
|
|
||||||
|
|
||||||
|
|
||||||
--- Returns formatted output for the given instance
|
--- Returns formatted output for the given instance
|
||||||
local function create_instance_output_table( instance )
|
local function create_instance_output_table( instance )
|
||||||
@@ -132,7 +126,7 @@ local function create_instance_output_table( instance )
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return instanceOutput
|
return stdnse.format_output(true, instanceOutput)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -199,7 +193,7 @@ local function test_credentials( instance, helper, username, password )
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Processes a single instance, attempting to detect an empty password for "sa"
|
--- Processes a single instance, attempting to detect an empty password for "sa"
|
||||||
local function process_instance( instance )
|
process_instance = function ( instance )
|
||||||
|
|
||||||
-- One of this script's features is that it will report an instance's
|
-- One of this script's features is that it will report an instance's
|
||||||
-- in both the port-script results and the host-script results. In order to
|
-- in both the port-script results and the host-script results. In order to
|
||||||
@@ -275,10 +269,10 @@ local function process_instance( instance )
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local do_action
|
||||||
|
do_action, portrule, hostrule = mssql.Helper.InitScript(process_instance)
|
||||||
|
|
||||||
action = function( host, port )
|
action = function(...)
|
||||||
local scriptOutput = {}
|
|
||||||
local status, instanceList = mssql.Helper.GetTargetInstances( host, port )
|
|
||||||
|
|
||||||
local domain, bruteWindows = stdnse.get_script_args("mssql.domain", "ms-sql-brute.brute-windows-accounts")
|
local domain, bruteWindows = stdnse.get_script_args("mssql.domain", "ms-sql-brute.brute-windows-accounts")
|
||||||
|
|
||||||
@@ -292,16 +286,5 @@ action = function( host, port )
|
|||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
if ( not status ) then
|
return do_action(...)
|
||||||
return stdnse.format_output( false, instanceList )
|
|
||||||
else
|
|
||||||
for _, instance in pairs( instanceList ) do
|
|
||||||
local instanceOutput = process_instance( instance )
|
|
||||||
if instanceOutput then
|
|
||||||
table.insert( scriptOutput, instanceOutput )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return stdnse.format_output( true, scriptOutput )
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -70,12 +70,7 @@ license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
|
|||||||
categories = {"discovery", "safe"}
|
categories = {"discovery", "safe"}
|
||||||
|
|
||||||
|
|
||||||
dependencies = {"ms-sql-brute", "ms-sql-empty-password"}
|
dependencies = {"broadcast-ms-sql-discover", "ms-sql-brute", "ms-sql-empty-password"}
|
||||||
|
|
||||||
|
|
||||||
hostrule = mssql.Helper.GetHostrule_Standard()
|
|
||||||
portrule = mssql.Helper.GetPortrule_Standard()
|
|
||||||
|
|
||||||
|
|
||||||
--- Processes a set of instances
|
--- Processes a set of instances
|
||||||
local function process_instance( instance )
|
local function process_instance( instance )
|
||||||
@@ -130,28 +125,8 @@ local function process_instance( instance )
|
|||||||
|
|
||||||
helper:Disconnect()
|
helper:Disconnect()
|
||||||
|
|
||||||
local instanceOutput = {}
|
-- TODO: structured output instead of format_output
|
||||||
instanceOutput["name"] = string.format( "[%s]", instance:GetName() )
|
return stdnse.format_output(true, result)
|
||||||
table.insert( instanceOutput, result )
|
|
||||||
|
|
||||||
return instanceOutput
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
action, portrule, hostrule = mssql.Helper.InitScript(process_instance)
|
||||||
action = function( host, port )
|
|
||||||
local scriptOutput = {}
|
|
||||||
local status, instanceList = mssql.Helper.GetTargetInstances( host, port )
|
|
||||||
|
|
||||||
if ( not status ) then
|
|
||||||
return stdnse.format_output( false, instanceList )
|
|
||||||
else
|
|
||||||
for _, instance in pairs( instanceList ) do
|
|
||||||
local instanceOutput = process_instance( instance )
|
|
||||||
if instanceOutput then
|
|
||||||
table.insert( scriptOutput, instanceOutput )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return stdnse.format_output( true, scriptOutput )
|
|
||||||
end
|
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
local coroutine = require "coroutine"
|
|
||||||
local mssql = require "mssql"
|
local mssql = require "mssql"
|
||||||
local nmap = require "nmap"
|
local nmap = require "nmap"
|
||||||
local stdnse = require "stdnse"
|
local stdnse = require "stdnse"
|
||||||
local table = require "table"
|
|
||||||
|
|
||||||
description = [[
|
description = [[
|
||||||
Queries the Microsoft SQL Browser service for the DAC (Dedicated Admin
|
Queries the Microsoft SQL Browser service for the DAC (Dedicated Admin
|
||||||
@@ -28,75 +26,60 @@ accessible or not.
|
|||||||
--
|
--
|
||||||
-- @output
|
-- @output
|
||||||
-- | ms-sql-dac:
|
-- | ms-sql-dac:
|
||||||
-- |_ Instance: SQLSERVER; DAC port: 1533
|
-- | SQLSERVER:
|
||||||
|
-- | port: 1533
|
||||||
|
-- |_ state: open
|
||||||
--
|
--
|
||||||
|
|
||||||
author = "Patrik Karlsson"
|
author = "Patrik Karlsson"
|
||||||
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
|
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
|
||||||
categories = {"discovery", "safe"}
|
categories = {"discovery", "safe"}
|
||||||
|
|
||||||
hostrule = function(host)
|
dependencies = {"broadcast-ms-sql-discover"}
|
||||||
if ( mssql.Helper.WasDiscoveryPerformed( host ) ) then
|
|
||||||
return mssql.Helper.GetDiscoveredInstances( host ) ~= nil
|
|
||||||
else
|
|
||||||
local sqlBrowserPort = nmap.get_port_state( host, {number = 1434, protocol = "udp"} )
|
|
||||||
if ( (stdnse.get_script_args( {"mssql.instance-all", "mssql.instance-name", "mssql.instance-port"} ) ~= nil) or
|
|
||||||
(sqlBrowserPort and (sqlBrowserPort.state == "open" or sqlBrowserPort.state == "open|filtered")) ) then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function checkPort(host, port)
|
local function checkPort(host, port)
|
||||||
|
local scanport = nmap.get_port_state(host, {number=port, protocol="tcp"})
|
||||||
|
if scanport then
|
||||||
|
return scanport.state
|
||||||
|
end
|
||||||
local s = nmap.new_socket()
|
local s = nmap.new_socket()
|
||||||
s:set_timeout(5000)
|
s:set_timeout(5000)
|
||||||
local status = s:connect(host, port, "tcp")
|
local status, err = s:connect(host, port, "tcp")
|
||||||
s:close()
|
s:close()
|
||||||
return status
|
return (status and "open" or "closed"), err
|
||||||
end
|
end
|
||||||
|
|
||||||
local function discoverDAC(host, name, result)
|
local function discoverDAC(instance)
|
||||||
local condvar = nmap.condvar(result)
|
stdnse.debug2("Discovering DAC port on instance: %s", instance:GetName())
|
||||||
stdnse.debug2("Discovering DAC port on instance: %s", name)
|
local port = mssql.Helper.DiscoverDACPort(instance)
|
||||||
local port = mssql.Helper.DiscoverDACPort( host, name )
|
if not port then
|
||||||
if ( port ) then
|
return nil
|
||||||
if ( checkPort(host, port) ) then
|
|
||||||
table.insert(result, ("Instance: %s; DAC port: %s"):format(name, port))
|
|
||||||
else
|
|
||||||
table.insert(result, ("Instance: %s; DAC port: %s (connection failed)"):format(name, port))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
condvar "signal"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
action = function( host )
|
local result = stdnse.output_table()
|
||||||
local result, threads = {}, {}
|
result.port = port
|
||||||
local condvar = nmap.condvar(result)
|
local state, err = checkPort(instance.host, port)
|
||||||
|
result.state = state
|
||||||
local status, instanceList = mssql.Helper.GetTargetInstances( host )
|
result.error = err
|
||||||
-- if no instances were targeted, then display info on all
|
return result
|
||||||
if ( not status ) then
|
|
||||||
mssql.Helper.Discover( host )
|
|
||||||
instanceList = mssql.Helper.GetDiscoveredInstances( host )
|
|
||||||
end
|
end
|
||||||
|
|
||||||
for _, instance in ipairs(instanceList or {}) do
|
local lib_portrule, lib_hostrule
|
||||||
local name = instance:GetName():match("^[^\\]*\\(.*)$")
|
action, lib_portrule, lib_hostrule = mssql.Helper.InitScript(discoverDAC)
|
||||||
if ( name ) then
|
|
||||||
local co = stdnse.new_thread(discoverDAC, host, name, result)
|
local function rule_if_browser_open(lib_rule)
|
||||||
threads[co] = true
|
return function (host, ...)
|
||||||
|
if not lib_rule(host, ...) then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local bport = nmap.get_port_state(host, {number=1434, protocol="udp"})
|
||||||
|
-- If port is nil, we don't know the state
|
||||||
|
return bport == nil or (
|
||||||
|
-- we know the state, so it has to be a good one
|
||||||
|
bport.state == "open" or bport.state == "open|filtered"
|
||||||
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
while(next(threads)) do
|
portrule = rule_if_browser_open(lib_portrule)
|
||||||
for t in pairs(threads) do
|
hostrule = rule_if_browser_open(lib_hostrule)
|
||||||
threads[t] = ( coroutine.status(t) ~= "dead" ) and true or nil
|
|
||||||
end
|
|
||||||
if ( next(threads) ) then
|
|
||||||
condvar "wait"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return stdnse.format_output( true, result )
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|||||||
@@ -40,29 +40,19 @@ author = "Patrik Karlsson"
|
|||||||
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
|
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
|
||||||
categories = {"auth", "discovery", "safe"}
|
categories = {"auth", "discovery", "safe"}
|
||||||
|
|
||||||
|
dependencies = {"broadcast-ms-sql-discover", "ms-sql-brute", "ms-sql-empty-password"}
|
||||||
dependencies = {"ms-sql-brute", "ms-sql-empty-password"}
|
|
||||||
|
|
||||||
hostrule = mssql.Helper.GetHostrule_Standard()
|
|
||||||
portrule = mssql.Helper.GetPortrule_Standard()
|
|
||||||
|
|
||||||
local function process_instance(instance)
|
local function process_instance(instance)
|
||||||
|
|
||||||
local helper = mssql.Helper:new()
|
local helper = mssql.Helper:new()
|
||||||
local status, errorMessage = helper:ConnectEx( instance )
|
local status, errorMessage = helper:ConnectEx( instance )
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return false, {
|
return "ERROR: " .. errorMessage
|
||||||
['name'] = string.format( "[%s]", instance:GetName() ),
|
|
||||||
"ERROR: " .. errorMessage
|
|
||||||
}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
status, errorMessage = helper:LoginEx( instance )
|
status, errorMessage = helper:LoginEx( instance )
|
||||||
if ( not(status) ) then
|
if ( not(status) ) then
|
||||||
return false, {
|
return "ERROR: " .. errorMessage
|
||||||
['name'] = string.format( "[%s]", instance:GetName() ),
|
|
||||||
"ERROR: " .. errorMessage
|
|
||||||
}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local result
|
local result
|
||||||
@@ -83,12 +73,7 @@ local function process_instance(instance)
|
|||||||
end
|
end
|
||||||
|
|
||||||
helper:Disconnect()
|
helper:Disconnect()
|
||||||
local instanceOutput = {}
|
return output
|
||||||
instanceOutput["name"] = string.format( "[%s]", instance:GetName() )
|
|
||||||
table.insert( instanceOutput, output )
|
|
||||||
|
|
||||||
return true, instanceOutput
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Saves the hashes to file
|
-- Saves the hashes to file
|
||||||
@@ -110,31 +95,19 @@ local function saveToFile(filename, response)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
action = function( host, port )
|
|
||||||
local dir = stdnse.get_script_args("ms-sql-dump-hashes.dir")
|
local dir = stdnse.get_script_args("ms-sql-dump-hashes.dir")
|
||||||
local scriptOutput = {}
|
|
||||||
local status, instanceList = mssql.Helper.GetTargetInstances( host, port )
|
|
||||||
|
|
||||||
if ( not status ) then
|
local function process_and_save (instance)
|
||||||
return stdnse.format_output( false, instanceList )
|
local instanceOutput = process_instance( instance )
|
||||||
else
|
if type(instanceOutput) == "table" then
|
||||||
for _, instance in pairs( instanceList ) do
|
local inst = instance:GetName():gsub(".*\\", "")
|
||||||
local status, instanceOutput = process_instance( instance )
|
local filename = dir .. "/" .. stringaux.filename_escape(
|
||||||
if ( status ) then
|
("%s_%s_ms-sql_hashes.txt"):format(instance.host.ip, inst))
|
||||||
local filename
|
saveToFile(filename, instanceOutput)
|
||||||
if ( dir ) then
|
|
||||||
local instance = instance:GetName():match("%\\+(.+)$") or instance:GetName()
|
|
||||||
filename = dir .. "/" .. stringaux.filename_escape(("%s_%s_ms-sql_hashes.txt"):format(host.ip, instance))
|
|
||||||
saveToFile(filename, instanceOutput[1])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
table.insert( scriptOutput, instanceOutput )
|
|
||||||
end
|
end
|
||||||
|
return instanceOutput
|
||||||
end
|
end
|
||||||
|
|
||||||
if ( #scriptOutput == 0 ) then return end
|
local do_instance = dir and process_and_save or process_instance
|
||||||
|
|
||||||
local output = ( #scriptOutput > 1 and scriptOutput or scriptOutput[1] )
|
action, portrule, hostrule = mssql.Helper.InitScript(do_instance)
|
||||||
|
|
||||||
return stdnse.format_output( true, output )
|
|
||||||
end
|
|
||||||
|
|||||||
@@ -59,9 +59,7 @@ author = "Patrik Karlsson"
|
|||||||
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
|
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
|
||||||
categories = {"auth","intrusive"}
|
categories = {"auth","intrusive"}
|
||||||
|
|
||||||
|
dependencies = {"broadcast-ms-sql-discover"}
|
||||||
hostrule = mssql.Helper.GetHostrule_Standard()
|
|
||||||
portrule = mssql.Helper.GetPortrule_Standard()
|
|
||||||
|
|
||||||
local function test_credentials( instance, helper, username, password )
|
local function test_credentials( instance, helper, username, password )
|
||||||
local database = "tempdb"
|
local database = "tempdb"
|
||||||
@@ -150,7 +148,6 @@ local function process_instance( instance )
|
|||||||
local instanceOutput
|
local instanceOutput
|
||||||
if ( instance.ms_sql_empty ) then
|
if ( instance.ms_sql_empty ) then
|
||||||
instanceOutput = {}
|
instanceOutput = {}
|
||||||
instanceOutput["name"] = string.format( "[%s]", instance:GetName() )
|
|
||||||
for _, message in ipairs( instance.ms_sql_empty ) do
|
for _, message in ipairs( instance.ms_sql_empty ) do
|
||||||
table.insert( instanceOutput, message )
|
table.insert( instanceOutput, message )
|
||||||
end
|
end
|
||||||
@@ -163,21 +160,4 @@ local function process_instance( instance )
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
action, portrule, hostrule = mssql.Helper.InitScript(process_instance)
|
||||||
action = function( host, port )
|
|
||||||
local scriptOutput = {}
|
|
||||||
local status, instanceList = mssql.Helper.GetTargetInstances( host, port )
|
|
||||||
|
|
||||||
if ( not status ) then
|
|
||||||
return stdnse.format_output( false, instanceList )
|
|
||||||
else
|
|
||||||
for _, instance in pairs( instanceList ) do
|
|
||||||
local instanceOutput = process_instance( instance )
|
|
||||||
if instanceOutput then
|
|
||||||
table.insert( scriptOutput, instanceOutput )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return stdnse.format_output( true, scriptOutput )
|
|
||||||
end
|
|
||||||
|
|||||||
@@ -73,11 +73,7 @@ license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
|
|||||||
categories = {"auth", "discovery","safe"}
|
categories = {"auth", "discovery","safe"}
|
||||||
|
|
||||||
|
|
||||||
dependencies = {"ms-sql-brute", "ms-sql-empty-password"}
|
dependencies = {"broadcast-ms-sql-discover", "ms-sql-brute", "ms-sql-empty-password"}
|
||||||
|
|
||||||
|
|
||||||
hostrule = mssql.Helper.GetHostrule_Standard()
|
|
||||||
portrule = mssql.Helper.GetPortrule_Standard()
|
|
||||||
|
|
||||||
|
|
||||||
local function process_instance( instance )
|
local function process_instance( instance )
|
||||||
@@ -146,30 +142,9 @@ local function process_instance( instance )
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- TODO: structured output, not format_output
|
||||||
local instanceOutput = {}
|
return stdnse.format_output(true, output)
|
||||||
instanceOutput["name"] = string.format( "[%s]", instance:GetName() )
|
|
||||||
table.insert( instanceOutput, output )
|
|
||||||
|
|
||||||
return instanceOutput
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
action = function( host, port )
|
action, portrule, hostrule = mssql.Helper.InitScript(process_instance)
|
||||||
local scriptOutput = {}
|
|
||||||
local status, instanceList = mssql.Helper.GetTargetInstances( host, port )
|
|
||||||
|
|
||||||
if ( not status ) then
|
|
||||||
return stdnse.format_output( false, instanceList )
|
|
||||||
else
|
|
||||||
for _, instance in pairs( instanceList ) do
|
|
||||||
local instanceOutput = process_instance( instance )
|
|
||||||
if instanceOutput then
|
|
||||||
table.insert( scriptOutput, instanceOutput )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return stdnse.format_output( true, scriptOutput )
|
|
||||||
end
|
|
||||||
|
|||||||
@@ -150,25 +150,7 @@ license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
|
|||||||
|
|
||||||
categories = {"default", "discovery", "safe"}
|
categories = {"default", "discovery", "safe"}
|
||||||
|
|
||||||
|
dependencies = {"broadcast-ms-sql-discover"}
|
||||||
hostrule = function(host)
|
|
||||||
if ( mssql.Helper.WasDiscoveryPerformed( host ) ) then
|
|
||||||
return mssql.Helper.GetDiscoveredInstances( host ) ~= nil
|
|
||||||
else
|
|
||||||
local sqlDefaultPort = nmap.get_port_state( host, {number = 1433, protocol = "tcp"} )
|
|
||||||
local sqlBrowserPort = nmap.get_port_state( host, {number = 1434, protocol = "udp"} )
|
|
||||||
-- smb.get_port() will return nil if no SMB port was scanned OR if SMB ports were scanned but none was open
|
|
||||||
local smbPortNumber = smb.get_port( host )
|
|
||||||
|
|
||||||
if ( (stdnse.get_script_args( {"mssql.instance-all", "mssql.instance-name", "mssql.instance-port"} ) ~= nil) or
|
|
||||||
(sqlBrowserPort and (sqlBrowserPort.state == "open" or sqlBrowserPort.state == "open|filtered")) or
|
|
||||||
(sqlDefaultPort and (sqlDefaultPort.state == "open" or sqlDefaultPort.state == "open|filtered")) or
|
|
||||||
(smbPortNumber ~= nil) ) then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Returns formatted output for the given version data
|
--- Returns formatted output for the given version data
|
||||||
local function create_version_output_table( versionInfo )
|
local function create_version_output_table( versionInfo )
|
||||||
@@ -247,33 +229,9 @@ local function process_instance( instance )
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function do_instance (instance)
|
||||||
action = function( host )
|
|
||||||
local scriptOutput = stdnse.output_table()
|
|
||||||
|
|
||||||
local status, instanceList = mssql.Helper.GetTargetInstances( host )
|
|
||||||
-- if no instances were targeted, then display info on all
|
|
||||||
if ( not status ) then
|
|
||||||
mssql.Helper.Discover( host )
|
|
||||||
instanceList = mssql.Helper.GetDiscoveredInstances( host )
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
if ( not instanceList ) then
|
|
||||||
return stdnse.format_output( false, instanceList or "" )
|
|
||||||
else
|
|
||||||
for _, instance in ipairs( instanceList ) do
|
|
||||||
if instance.serverName then
|
|
||||||
scriptOutput["Windows server name"] = instance.serverName
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
for _, instance in pairs( instanceList ) do
|
|
||||||
process_instance( instance )
|
process_instance( instance )
|
||||||
scriptOutput[instance:GetName()] = create_instance_output_table( instance )
|
return create_instance_output_table( instance )
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return scriptOutput
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
action, portrule, hostrule = mssql.Helper.InitScript(do_instance)
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
local os = require "os"
|
local os = require "os"
|
||||||
local datetime = require "datetime"
|
local datetime = require "datetime"
|
||||||
local mssql = require "mssql"
|
local mssql = require "mssql"
|
||||||
local shortport = require "shortport"
|
|
||||||
local stdnse = require "stdnse"
|
local stdnse = require "stdnse"
|
||||||
local smbauth = require "smbauth"
|
local smbauth = require "smbauth"
|
||||||
local string = require "string"
|
local string = require "string"
|
||||||
@@ -46,9 +45,9 @@ author = "Justin Cacak"
|
|||||||
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
|
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
|
||||||
categories = {"default", "discovery", "safe"}
|
categories = {"default", "discovery", "safe"}
|
||||||
|
|
||||||
portrule = shortport.port_or_service(1433, "ms-sql-s")
|
dependencies = {"broadcast-ms-sql-discover"}
|
||||||
|
|
||||||
action = function(host, port)
|
local do_action = function(host, port)
|
||||||
|
|
||||||
local output = stdnse.output_table()
|
local output = stdnse.output_table()
|
||||||
|
|
||||||
@@ -127,3 +126,9 @@ action = function(host, port)
|
|||||||
return output
|
return output
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function process_instance(instance)
|
||||||
|
return do_action(instance.host, instance.port)
|
||||||
|
end
|
||||||
|
|
||||||
|
action, portrule = mssql.Helper.InitScript(process_instance)
|
||||||
|
|||||||
@@ -60,10 +60,7 @@ license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
|
|||||||
categories = {"discovery", "safe"}
|
categories = {"discovery", "safe"}
|
||||||
|
|
||||||
|
|
||||||
dependencies = {"ms-sql-brute", "ms-sql-empty-password"}
|
dependencies = {"broadcast-ms-sql-discover", "ms-sql-brute", "ms-sql-empty-password"}
|
||||||
|
|
||||||
hostrule = mssql.Helper.GetHostrule_Standard()
|
|
||||||
portrule = mssql.Helper.GetPortrule_Standard()
|
|
||||||
|
|
||||||
---
|
---
|
||||||
local function process_instance( instance )
|
local function process_instance( instance )
|
||||||
@@ -92,31 +89,19 @@ local function process_instance( instance )
|
|||||||
result = mssql.Util.FormatOutputTable( result, true )
|
result = mssql.Util.FormatOutputTable( result, true )
|
||||||
result["name"] = string.format( "Query: %s", query )
|
result["name"] = string.format( "Query: %s", query )
|
||||||
end
|
end
|
||||||
local instanceOutput = {}
|
|
||||||
instanceOutput["name"] = string.format( "[%s]", instance:GetName() )
|
|
||||||
table.insert( instanceOutput, result )
|
|
||||||
|
|
||||||
return instanceOutput
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local do_action
|
||||||
|
do_action, portrule, hostrule = mssql.Helper.InitScript(process_instance)
|
||||||
|
|
||||||
action = function( host, port )
|
action = function(...)
|
||||||
local scriptOutput = {}
|
local scriptOutput = do_action(...)
|
||||||
local status, instanceList = mssql.Helper.GetTargetInstances( host, port )
|
|
||||||
|
|
||||||
if ( not status ) then
|
|
||||||
return stdnse.format_output( false, instanceList )
|
|
||||||
else
|
|
||||||
for _, instance in pairs( instanceList ) do
|
|
||||||
local instanceOutput = process_instance( instance )
|
|
||||||
if instanceOutput then
|
|
||||||
table.insert( scriptOutput, instanceOutput )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if ( not( stdnse.get_script_args( {'ms-sql-query.query', 'mssql-query.query' } ) ) ) then
|
if ( not( stdnse.get_script_args( {'ms-sql-query.query', 'mssql-query.query' } ) ) ) then
|
||||||
table.insert(scriptOutput, 1, "(Use --script-args=ms-sql-query.query='<QUERY>' to change query.)")
|
table.insert(scriptOutput, 1, "(Use --script-args=ms-sql-query.query='<QUERY>' to change query.)")
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
return stdnse.format_output( true, scriptOutput )
|
return stdnse.format_output( true, scriptOutput )
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -98,10 +98,7 @@ license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
|
|||||||
categories = {"discovery", "safe"}
|
categories = {"discovery", "safe"}
|
||||||
|
|
||||||
|
|
||||||
dependencies = {"ms-sql-brute", "ms-sql-empty-password"}
|
dependencies = {"broadcast-ms-sql-discover", "ms-sql-brute", "ms-sql-empty-password"}
|
||||||
|
|
||||||
hostrule = mssql.Helper.GetHostrule_Standard()
|
|
||||||
portrule = mssql.Helper.GetPortrule_Standard()
|
|
||||||
|
|
||||||
local function process_instance( instance )
|
local function process_instance( instance )
|
||||||
|
|
||||||
@@ -248,25 +245,9 @@ local function process_instance( instance )
|
|||||||
instanceOutput["name"] = string.format( "[%s]", instance:GetName() )
|
instanceOutput["name"] = string.format( "[%s]", instance:GetName() )
|
||||||
table.insert( instanceOutput, output )
|
table.insert( instanceOutput, output )
|
||||||
|
|
||||||
return instanceOutput
|
return stdnse.format_ouptut(true, instanceOutput)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
action = function( host, port )
|
action, portrule, hostrule = mssql.Helper.InitScript(process_instance)
|
||||||
local scriptOutput = {}
|
|
||||||
local status, instanceList = mssql.Helper.GetTargetInstances( host, port )
|
|
||||||
|
|
||||||
if ( not status ) then
|
|
||||||
return stdnse.format_output( false, instanceList )
|
|
||||||
else
|
|
||||||
for _, instance in pairs( instanceList ) do
|
|
||||||
local instanceOutput = process_instance( instance )
|
|
||||||
if instanceOutput then
|
|
||||||
table.insert( scriptOutput, instanceOutput )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return stdnse.format_output( true, scriptOutput )
|
|
||||||
end
|
|
||||||
|
|||||||
@@ -86,10 +86,7 @@ license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
|
|||||||
categories = {"intrusive"}
|
categories = {"intrusive"}
|
||||||
|
|
||||||
|
|
||||||
dependencies = {"ms-sql-brute", "ms-sql-empty-password"}
|
dependencies = {"broadcast-ms-sql-discover", "ms-sql-brute", "ms-sql-empty-password"}
|
||||||
|
|
||||||
hostrule = mssql.Helper.GetHostrule_Standard()
|
|
||||||
portrule = mssql.Helper.GetPortrule_Standard()
|
|
||||||
|
|
||||||
|
|
||||||
local function process_instance( instance )
|
local function process_instance( instance )
|
||||||
@@ -143,24 +140,14 @@ local function process_instance( instance )
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
action = function( host, port )
|
local do_action
|
||||||
local scriptOutput = {}
|
do_action, portrule, hostrule = mssql.Helper.InitScript(process_instance)
|
||||||
local status, instanceList = mssql.Helper.GetTargetInstances( host, port )
|
|
||||||
|
|
||||||
if ( not status ) then
|
|
||||||
return stdnse.format_output( false, instanceList )
|
|
||||||
else
|
|
||||||
for _, instance in pairs( instanceList ) do
|
|
||||||
local instanceOutput = process_instance( instance )
|
|
||||||
if instanceOutput then
|
|
||||||
table.insert( scriptOutput, instanceOutput )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
action = function(...)
|
||||||
|
local scriptOutput = do_action(...)
|
||||||
if ( not(stdnse.get_script_args( {'ms-sql-xp-cmdshell.cmd', 'mssql-xp-cmdshell.cmd'} ) ) ) then
|
if ( not(stdnse.get_script_args( {'ms-sql-xp-cmdshell.cmd', 'mssql-xp-cmdshell.cmd'} ) ) ) then
|
||||||
table.insert(scriptOutput, 1, "(Use --script-args=ms-sql-xp-cmdshell.cmd='<CMD>' to change command.)")
|
table.insert(scriptOutput, 1, "(Use --script-args=ms-sql-xp-cmdshell.cmd='<CMD>' to change command.)")
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
return stdnse.format_output( true, scriptOutput )
|
return stdnse.format_output( true, scriptOutput )
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user