From 9236196d422a25a44ee179b8df34bd593f6cbbc8 Mon Sep 17 00:00:00 2001 From: patrik Date: Tue, 10 Jul 2012 09:50:51 +0000 Subject: [PATCH] o [NSE] Added ms-sql-dac script which queries the Microsoft SQL Browser service for the DAC (Dedicated Admin Connection) port. [Patrik Karlsson] --- CHANGELOG | 10 +++-- nselib/mssql.lua | 34 +++++++++++++++++ scripts/ms-sql-dac.nse | 83 ++++++++++++++++++++++++++++++++++++++++++ scripts/script.db | 1 + 4 files changed, 125 insertions(+), 3 deletions(-) create mode 100644 scripts/ms-sql-dac.nse diff --git a/CHANGELOG b/CHANGELOG index 7567305c4..65eada8eb 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,7 +1,11 @@ # Nmap Changelog ($Id$); -*-text-*- -o [NSE] Added irc-sasl-brute script which performs brute force password auditing - against IRC (Internet Relay Chat) servers supporting SASL authentication. - [Piotr Olma] + +o [NSE] Added ms-sql-dac script which queries the Microsoft SQL Browser service + for the DAC (Dedicated Admin Connection) port. [Patrik Karlsson] + +o [NSE] Added irc-sasl-brute script which performs brute force password + auditing against IRC (Internet Relay Chat) servers supporting SASL + authentication. [Piotr Olma] o [NSE] Added sip-methods script which enumerates a SIP server's allowed methods. [Hani Benhabiles] diff --git a/nselib/mssql.lua b/nselib/mssql.lua index 198bfbb21..74a321fc2 100644 --- a/nselib/mssql.lua +++ b/nselib/mssql.lua @@ -105,6 +105,7 @@ local bin = require "bin" local bit = require "bit" local math = require "math" +local match = require "match" local nmap = require "nmap" local openssl = require "openssl" local os = require "os" @@ -2588,6 +2589,39 @@ Helper = end end, + --- Queries the SQL Browser service for the DAC port of the specified instance + -- The DAC (Dedicated Admin Connection) port allows DBA's to connect to + -- the database when normal connection attempts fail, for example, when + -- the server is hanging, out of memory or other bad states. + -- + -- @param host Host table as received by the script action function + -- @param instanceName the instance name to probe for a DAC port + -- @return number containing the DAC port on success or nil on failure + DiscoverDACPort = function(host, instanceName) + local socket = nmap.new_socket() + socket:set_timeout(5000) + + if ( not(socket:connect(host, 1434, "udp")) ) then + return false, "Failed to connect to sqlbrowser service" + end + + if ( not(socket:send(bin.pack("Hz", "0F01", instanceName))) ) then + socket:close() + return false, "Failed to send request to sqlbrowser service" + end + + local status, data = socket:receive_buf(match.numbytes(6), true) + if ( not(status) ) then + socket:close() + return nil + end + socket:close() + + if ( #data < 6 ) then + return nil + end + return select(2, bin.unpack("mssql.instance diff --git a/scripts/ms-sql-dac.nse b/scripts/ms-sql-dac.nse new file mode 100644 index 000000000..5205da760 --- /dev/null +++ b/scripts/ms-sql-dac.nse @@ -0,0 +1,83 @@ +local mssql = require "mssql" +local nmap = require "nmap" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + +description = [[ +Queries the Microsoft SQL Browser service for the DAC (Dedicated Admin Connection) port +of a given, or all SQL Server instances. The DAC port is used to connect to the database +instance when normal connection attempts fail, for example, when server is hanging, out +of memory or in other bad states. In addition, the DAC port provides an admin with +access to system objects otherwise not accessible over normal connections. + +The DAC feature is accessible on the loopback adapter per default, but can be activated +for remote access by setting the 'remote admin connection' configuration value to 1. In +some cases, when DAC has been remotely enabled but later disabled, the sql browser +service may incorrectly report it as available. The script therefore attempts to connect +to the reported port in order to verify whether it's accessible or not. +]] + +--- +-- @usage +-- sudo nmap -sU -p 1434 --script ms-sql-dac +-- +-- @output +-- | ms-sql-dac: +-- |_ Instance: SQLSERVER; DAC port: 1533 +-- + +author = "Patrik Karlsson" +license = "Same as Nmap--See http://nmap.org/book/man-legal.html" +categories = {"default", "discovery", "safe"} + +hostrule = function(host) + 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 s = nmap.new_socket() + s:set_timeout(5000) + local status = s:connect(host, port, "tcp") + s:close() + return status +end + +action = function( host ) + local result = {} + + local status, instanceList = mssql.Helper.GetTargetInstances( host ) + -- if no instances were targeted, then display info on all + if ( not status ) then + if ( not mssql.Helper.WasDiscoveryPerformed( host ) ) then + mssql.Helper.Discover( host ) + end + instanceList = mssql.Helper.GetDiscoveredInstances( host ) + end + + for _, instance in ipairs(instanceList) do + local name = instance:GetName():match("^[^\\]*\\(.*)$") + if ( name ) then + stdnse.print_debug(2, "Discovering DAC port on instance: %s", name) + local port = mssql.Helper.DiscoverDACPort( host, name ) + if ( port ) then + 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 + end + end + + return stdnse.format_output( true, result ) +end + diff --git a/scripts/script.db b/scripts/script.db index 32320ef7f..1982d09f0 100644 --- a/scripts/script.db +++ b/scripts/script.db @@ -240,6 +240,7 @@ Entry { filename = "mongodb-databases.nse", categories = { "default", "discovery Entry { filename = "mongodb-info.nse", categories = { "default", "discovery", "safe", } } Entry { filename = "ms-sql-brute.nse", categories = { "brute", "intrusive", } } Entry { filename = "ms-sql-config.nse", categories = { "discovery", "safe", } } +Entry { filename = "ms-sql-dac.nse", categories = { "default", "discovery", "safe", } } Entry { filename = "ms-sql-dump-hashes.nse", categories = { "auth", "discovery", "safe", } } Entry { filename = "ms-sql-empty-password.nse", categories = { "auth", "intrusive", } } Entry { filename = "ms-sql-hasdbaccess.nse", categories = { "auth", "discovery", "safe", } }