mirror of
https://github.com/nmap/nmap.git
synced 2025-12-07 13:11:28 +00:00
If you ran the (fortunately non-default) http-domino-enum-passwords script with the (fortunately also non-default) domino-enum-passwords.idpath parameter against a malicious server, it could cause an arbitrarily named file to to be written to the client system. Thanks to Trustwave researcher Piotr Duszynski for discovering and reporting the problem. We've fixed that script, and also updated several other scripts to use a new stdnse.filename_escape function for extra safety. This breaks our record of never having a vulnerability in the 16 years that Nmap has existed, but that's still a fairly good run. [David, Fyodor]
136 lines
3.9 KiB
Lua
136 lines
3.9 KiB
Lua
local io = require "io"
|
|
local mssql = require "mssql"
|
|
local stdnse = require "stdnse"
|
|
local string = require "string"
|
|
local table = require "table"
|
|
|
|
description = [[
|
|
Dumps the password hashes from an MS-SQL server in a format suitable for
|
|
cracking by tools such as John-the-ripper. In order to do so the user
|
|
needs to have the appropriate DB privileges.
|
|
|
|
Credentials passed as script arguments take precedence over credentials
|
|
discovered by other scripts.
|
|
]]
|
|
|
|
---
|
|
-- @usage
|
|
-- nmap -p 1433 <ip> --script ms-sql-dump-hashes
|
|
--
|
|
-- @output
|
|
-- PORT STATE SERVICE
|
|
-- 1433/tcp open ms-sql-s
|
|
-- | ms-sql-dump-hashes:
|
|
-- | nmap_test:0x01001234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF0123
|
|
-- | sa:0x01001234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF0123
|
|
-- |_ webshop_dbo:0x01001234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF0123
|
|
|
|
--
|
|
--
|
|
-- Version 0.1
|
|
-- Created 08/03/2011 - v0.1 - created by Patrik Karlsson <patrik@cqure.net>
|
|
--
|
|
|
|
author = "Patrik Karlsson"
|
|
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
|
|
categories = {"auth", "discovery", "safe"}
|
|
|
|
|
|
dependencies = {"ms-sql-brute", "ms-sql-empty-password"}
|
|
|
|
hostrule = mssql.Helper.GetHostrule_Standard()
|
|
portrule = mssql.Helper.GetPortrule_Standard()
|
|
|
|
local function process_instance(instance)
|
|
|
|
local helper = mssql.Helper:new()
|
|
local status, errorMessage = helper:ConnectEx( instance )
|
|
if ( not(status) ) then
|
|
return false, {
|
|
['name'] = string.format( "[%s]", instance:GetName() ),
|
|
"ERROR: " .. errorMessage
|
|
}
|
|
end
|
|
|
|
status, errorMessage = helper:LoginEx( instance )
|
|
if ( not(status) ) then
|
|
return false, {
|
|
['name'] = string.format( "[%s]", instance:GetName() ),
|
|
"ERROR: " .. errorMessage
|
|
}
|
|
end
|
|
|
|
local result
|
|
local query = [[
|
|
IF ( OBJECT_ID('master..sysxlogins' ) ) <> 0
|
|
SELECT name, password FROM master..sysxlogins WHERE password IS NOT NULL
|
|
ELSE IF ( OBJECT_ID('master.sys.sql_logins') ) <> 0
|
|
SELECT name, password_hash FROM master.sys.sql_logins
|
|
]]
|
|
status, result = helper:Query( query )
|
|
|
|
local output = {}
|
|
|
|
if ( status ) then
|
|
for _, row in ipairs( result.rows ) do
|
|
table.insert(output, ("%s:%s"):format(row[1] or "",row[2] or "") )
|
|
end
|
|
end
|
|
|
|
helper:Disconnect()
|
|
local instanceOutput = {}
|
|
instanceOutput["name"] = string.format( "[%s]", instance:GetName() )
|
|
table.insert( instanceOutput, output )
|
|
|
|
return true, instanceOutput
|
|
|
|
end
|
|
|
|
-- Saves the hashes to file
|
|
-- @param filename string name of the file
|
|
-- @param response table containing the resultset
|
|
-- @return status true on success, false on failure
|
|
-- @return err string containing the error if status is false
|
|
local function saveToFile(filename, response)
|
|
local f = io.open( filename, "w")
|
|
if ( not(f) ) then
|
|
return false, ("Failed to open file (%s)"):format(filename)
|
|
end
|
|
for _, row in ipairs(response) do
|
|
if ( not(f:write(row .."\n" ) ) ) then
|
|
return false, ("Failed to write file (%s)"):format(filename)
|
|
end
|
|
end
|
|
f:close()
|
|
return true
|
|
end
|
|
|
|
action = function( host, port )
|
|
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
|
|
return stdnse.format_output( false, instanceList )
|
|
else
|
|
for _, instance in pairs( instanceList ) do
|
|
local status, instanceOutput = process_instance( instance )
|
|
if ( status ) then
|
|
local filename
|
|
if ( dir ) then
|
|
local instance = instance:GetName():match("%\\+(.+)$") or instance:GetName()
|
|
filename = dir .. "/" .. stdnse.filename_escape(("%s_%s_ms-sql_hashes.txt"):format(host.ip, instance))
|
|
saveToFile(filename, instanceOutput[1])
|
|
end
|
|
end
|
|
table.insert( scriptOutput, instanceOutput )
|
|
end
|
|
end
|
|
|
|
if ( #scriptOutput == 0 ) then return end
|
|
|
|
local output = ( #scriptOutput > 1 and scriptOutput or scriptOutput[1] )
|
|
|
|
return stdnse.format_output( true, output )
|
|
end
|