-- -*- mode: lua -*-
-- vim: set filetype=lua :
description = [[
Attempts to discover Microsoft SQL Server instances.
SQL Server credentials required: No (will not benefit from
mssql.username
& mssql.password
).
Run criteria:
* Host script: Will always run, unless the mssql.scanned-ports-only
script argument was specified (see mssql.lua for more details); in that case,
the script will run if one or more of the following ports were scanned and
weren't found to be closed: 1434/udp, 1433/tcp, an SMB port (see smb.lua).
* Port script: N/A
The script attempts to discover SQL Server instances. Any instances found are
stored in the Nmap registry for use by any other ms-sql-* scripts that are run
in the same scan.
The script attempts to discover SQL Server instances by the following three
methods:
* Querying the SQL Server Brower service (UDP port 1434): If this service is
available, it will provide detailed information on each of the instances
installed on the host, including an approximate version number (use ms-sql-info
for more accurate and detailed version information). However, this service may
not be running, even if SQL Server instances are present, and it is also possible
for instances to "hide" themselves from the Browser service.
* Connecting to the default SQL Server listening port (TCP port 1433): The script
will attempt to fingerprint the service (if any) listening on TCP port 1433, SQL
Server's default port.
* Connecting via named pipes to the default pipe names: The script will attempt
to connect over SMB to default pipe names for SQL Server.
NOTE: Communication with instances via named pipes depends on the smb
library. To communicate with (and possibly to discover) instances via named pipes,
the host must have at least one SMB port (e.g. TCP 445) that was scanned and
found to be open. Additionally, named pipe connections may require Windows
authentication to connect to the Windows host (via SMB) in addition to the
authentication required to connect to the SQL Server instances itself. See the
documentation and arguments for the smb
library for more information.
NOTE: By default, the ms-sql-* scripts may attempt to connect to and communicate
with ports that were not included in the port list for the Nmap scan. This can
be disabled using the mssql.scanned-ports-only
script argument.
]]
---
-- @usage
-- nmap -p 445 --script ms-sql-discover
--
-- @output
-- | ms-sql-discover:
-- | [192.168.100.128\MSSQLSERVER]
-- | Name: MSSQLSERVER
-- | Product: Microsoft SQL Server 2000
-- | TCP port: 1433
-- | Named pipe: \\192.168.100.128\pipe\sql\query
-- | [192.168.100.128\SQL2K5]
-- | Name: SQL2K5
-- | Product: Microsoft SQL Server 2005
-- |_ Named pipe: \\192.168.100.128\pipe\MSSQL$SQL2K5\sql\query
-- rev 1.0 (2011-02-01) - Initial version (Chris Woodbury)
author = "Chris Woodbury"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"default", "discovery", "safe"}
require("mssql")
require("smb")
hostrule = function(host)
local sqlDefaultPort = nmap.get_port_state( host, {number = 1433, protocol = "tcp"} )
local sqlBrowserPort = nmap.get_port_state( host, {number = 1434, protocol = "udp"} )
local smbPortNumber = smb.get_port( host )
return (not mssql.SCANNED_PORTS_ONLY) or
(sqlDefaultPort and sqlDefaultPort.state ~= "closed") or
(sqlBrowserPort and sqlBrowserPort.state ~= "closed") or
(smbPortNumber ~= nil)
end
--- Adds a label and value to an output table. If the value is a boolean, it is
-- converted to Yes/No; if the value is nil, nothing is added to the table.
local function add_to_output_table( outputTable, outputLabel, outputData )
if outputData ~= nil then
if outputData == true then
outputData = "Yes"
elseif outputData == false then
outputData = "No"
end
table.insert(outputTable, string.format( "%s: %s", outputLabel, outputData ) )
end
end
--- Returns formatted output for the given instance
local function create_instance_output_table( instance )
local instanceOutput = {}
instanceOutput["name"] = string.format( "[%s]", instance:GetName() )
add_to_output_table( instanceOutput, "Name", instance.instanceName )
if instance.version then add_to_output_table( instanceOutput, "Product", instance.version.productName ) end
if instance.port then add_to_output_table( instanceOutput, "TCP port", instance.port.number ) end
add_to_output_table( instanceOutput, "Named pipe", instance.pipeName )
return instanceOutput
end
action = function(host)
mssql.Helper.Discover( host )
local scriptOutput, instancesFound = {}, nil
instancesFound = mssql.Helper.GetDiscoveredInstances( host )
if ( instancesFound ) then
for _, instance in ipairs( instancesFound ) do
local instanceOutput = create_instance_output_table( instance )
table.insert(scriptOutput, instanceOutput)
end
stdnse.print_debug( 1, "%s: Found %d instances for %s.", SCRIPT_NAME, #instancesFound, host.ip )
end
return stdnse.format_output( true, scriptOutput )
end