summaryrefslogtreecommitdiffstats
path: root/scripts/ms-sql-dac.nse
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/ms-sql-dac.nse')
-rw-r--r--scripts/ms-sql-dac.nse85
1 files changed, 85 insertions, 0 deletions
diff --git a/scripts/ms-sql-dac.nse b/scripts/ms-sql-dac.nse
new file mode 100644
index 0000000..ab8ee20
--- /dev/null
+++ b/scripts/ms-sql-dac.nse
@@ -0,0 +1,85 @@
+local mssql = require "mssql"
+local nmap = require "nmap"
+local stdnse = require "stdnse"
+
+description = [[
+Queries the Microsoft SQL Browser service for the DAC (Dedicated Admin
+Connection) port of a given (or all) SQL Server instance. 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 <ip>
+--
+-- @output
+-- | ms-sql-dac:
+-- | SQLSERVER:
+-- | port: 1533
+-- |_ state: open
+--
+
+author = "Patrik Karlsson"
+license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
+categories = {"discovery", "safe"}
+
+dependencies = {"broadcast-ms-sql-discover"}
+
+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()
+ s:set_timeout(5000)
+ local status, err = s:connect(host, port, "tcp")
+ s:close()
+ return (status and "open" or "closed"), err
+end
+
+local function discoverDAC(instance)
+ stdnse.debug2("Discovering DAC port on instance: %s", instance:GetName())
+ local port = mssql.Helper.DiscoverDACPort(instance)
+ if not port then
+ return nil
+ end
+
+ local result = stdnse.output_table()
+ result.port = port
+ local state, err = checkPort(instance.host, port)
+ result.state = state
+ result.error = err
+ return result
+end
+
+local lib_portrule, lib_hostrule
+action, lib_portrule, lib_hostrule = mssql.Helper.InitScript(discoverDAC)
+
+local function rule_if_browser_open(lib_rule)
+ 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
+
+portrule = rule_if_browser_open(lib_portrule)
+hostrule = rule_if_browser_open(lib_hostrule)