Updates smb.lua and msrpc.lua to support fully qualified path names as share names and updates match for OID. Modern Windows versions require FQPN and older version work the same. The level of information requested with the call NetShareGetInfo was reduced to support newer versions of Windows. This closes #266, closes #704, closes #238, and closes #883.

This commit is contained in:
paulino 2017-05-27 07:28:44 +00:00
parent c3bf58b2f2
commit b0228a212b
4 changed files with 46 additions and 10 deletions

View file

@ -1,5 +1,9 @@
# Nmap Changelog ($Id$); -*-text-*-
o [NSE][GH#266][GH#704][GH#238][GH#883] NSE libraries smb and msrpc now use
fully qualified paths. SMB scripts now work against all modern versions
of Microsoft Windows. [Paulino Calderon]
o New service probes and matches for Apache HBase and Hadoop MapReduce.
[Paulino Calderon]

View file

@ -200,8 +200,10 @@ local UUID2EXE = {
--@return status true or false
--@return smbstate if status is true, or an error message.
function start_smb(host, path, disable_extended, overrides)
local sharename
overrides = overrides or {}
return smb.start_ex(host, true, true, "IPC$", path, disable_extended, overrides)
_, sharename = smb.get_fqpn(host, "IPC$")
return smb.start_ex(host, true, true, sharename, path, disable_extended, overrides)
end
--- A wrapper around the <code>smb.stop</code> function.
@ -663,10 +665,17 @@ end
--@return (status, result) If status is false, result is an error message. Otherwise, result is a table of values, the most
-- useful one being 'shares', which is a list of the system's shares.
function srvsvc_netsharegetinfo(smbstate, server, share, level)
local status, result
stdnse.debug2("Calling NetShareGetInfo(%s, %s, %d)", server, share, level)
local status, result, sharename
local arguments
local pos, align
--NetGetShareInfo seems to reject FQPN and reads the server value from the request
--If any function called this function using a FQPN, this should take care of it.
_, _, sharename = string.find(share, "\\\\.*\\(.*)")
if sharename then
share = sharename
end
-- [in] [string,charset(UTF16)] uint16 *server_unc,
arguments = msrpctypes.marshall_unicode_ptr("\\\\" .. server, true)
@ -4705,7 +4714,8 @@ function get_share_info(host, name)
end
-- Call NetShareGetInfo
local status, netsharegetinfo_result = srvsvc_netsharegetinfo(smbstate, host.ip, name, 2)
local status, netsharegetinfo_result = srvsvc_netsharegetinfo(smbstate, host.ip, name, 1)
if(status == false) then
smb.stop(smbstate)
return false, netsharegetinfo_result

View file

@ -1316,7 +1316,7 @@ local function start_session_extended(smb, log_errors, overrides)
local sp_nego = false
if ( smb['security_blob'] and #smb['security_blob'] > 11 ) then
local pos, oid = bin.unpack(">A6", smb['security_blob'], 5)
sp_nego = ( oid == "\x2b\x06\x01\x05\x05\x02" ) -- check for SPNEGO OID 1.3.6.1.5.5.2
sp_nego = ( oid == "\x2b\x06\x01\x05\x05\x02" or oid == "\x06\x06\x2b\x06\x01\x05" ) -- check for SPNEGO OID 1.3.6.1.5.5.2
end
local ntlm_challenge_accepted = false
@ -3075,6 +3075,12 @@ function share_get_details(host, share)
local i
local details = {}
--Transform name to FQPN form
status, share = get_fqpn(host, share)
if not status then
stdnse.debug1("SMB:Couldn't obtain FQPN share name. Trying with '%s'", share)
end
-- Save the name
details['name'] = share
@ -3442,7 +3448,7 @@ end
-- 'false' is simply returned.
function is_admin(host, username, domain, password, password_hash, hash_type)
local msrpc = require "msrpc" -- avoid require cycle
local status, smbstate, err, result
local status, smbstate, err, result, fqpn_share
local overrides = get_overrides(username, domain, password, password_hash, hash_type)
stdnse.debug1("SMB: Checking if %s is an administrator", username)
@ -3467,8 +3473,9 @@ function is_admin(host, username, domain, password, password_hash, hash_type)
stop(smbstate)
return false
end
status, err = tree_connect(smbstate, "IPC$", overrides)
_, fqpn_share = get_fqpn(host, "IPC$")
status, err = tree_connect(smbstate, fqpn_share, overrides)
if(status == false) then
stdnse.debug1("SMB; is_admin: Failed to connect tree: %s [%s]", err, username)
stop(smbstate)
@ -3502,6 +3509,19 @@ function is_admin(host, username, domain, password, password_hash, hash_type)
return true
end
---
-- Returns the fully qualified path name (FQPN) for shares.
-- This is required for modern versions of Windows.
-- Returns \\<ip>\<sharename> when successful. Otherwise, returns the same share name.
---
function get_fqpn(host, sharename)
if host.ip and sharename then
return true, string.format("\\\\%s\\%s", host.ip, sharename)
end
stdnse.debug1("SMB: get_fqpn: Couldn't determine server IP address")
return false, sharename
end
command_codes =
{
SMB_COM_CREATE_DIRECTORY = 0x00,
@ -4213,10 +4233,11 @@ namedpipes =
self.name = namedpipes.make_pipe_name( self._host.ip, self._pipeSubPath )
stdnse.debug2("%s: Connecting to named pipe: %s", NP_LIBRARY_NAME, self.name )
local status, result, errorMessage
local status, result, errorMessage, fqpn_share
local bool_negotiate_protocol, bool_start_session, bool_disable_extended = true, true, false
_, fqpn_share = get_fqpn(host, "IPC$")
status, result = start_ex( self._host, bool_negotiate_protocol, bool_start_session,
"IPC$", self._pipeSubPath, bool_disable_extended, self._overrides )
fqpn_share, self._pipeSubPath, bool_disable_extended, self._overrides )
if status then
self._smbstate = result

View file

@ -181,6 +181,7 @@ action = function(host)
local output = ls.new_listing()
for _, share in ipairs(arg_shares) do
stdnse.debug1("Share name:%s", share)
local status, smbstate = smb.start_ex(host, true, true, share,
nil, nil, nil)
if ( not(status) ) then
@ -199,7 +200,7 @@ action = function(host)
ls.new_vol(
output,
'\\\\' .. stdnse.get_hostname(host) .. '\\' .. share .. path,
share .. path,
false)
continue = list_files(host, share, smbstate, path, options,
output, ls.config('maxdepth'))