mirror of
https://github.com/nmap/nmap.git
synced 2026-01-29 09:39:03 +00:00
Merge from /nmap-exp/ron/ms08-067-test
This commit is contained in:
187
nselib/msrpc.lua
187
nselib/msrpc.lua
@@ -1016,6 +1016,193 @@ function srvsvc_netservergetstatistics(smbstate, server)
|
||||
end
|
||||
|
||||
|
||||
---This calls NetPathCanonicalize(), which was the target of ms08-067. I haven't gotten this
|
||||
-- working, yet, I trigger it indirectly through NetPathCompare().
|
||||
--function srvsvc_netpathcanonicalize(smbstate, server, prefix, path)
|
||||
-- local i, j
|
||||
-- local status, result
|
||||
-- local arguments
|
||||
-- local pos, align
|
||||
--
|
||||
-- local response = {}
|
||||
--
|
||||
-- stdnse.print_debug(2, "MSRPC: Calling NetPathCanonicalize(%s) [%s]", path, smbstate['ip'])
|
||||
--
|
||||
---- [in] [string,charset(UTF16)] uint16 *server_unc,
|
||||
-- arguments = bin.pack("<IIIIA",
|
||||
-- REFERENT_ID, -- Referent ID
|
||||
-- string.len(server) + 1, -- Max count
|
||||
-- 0, -- Offset
|
||||
-- string.len(server) + 1, -- Actual count
|
||||
-- string_to_unicode(server, true, true)
|
||||
-- )
|
||||
--
|
||||
---- [in] [string,charset(UTF16)] uint16 path[],
|
||||
-- arguments = arguments .. bin.pack("<IIIA",
|
||||
-- string.len(path) + 1, -- Max count
|
||||
-- 0, -- Offset
|
||||
-- string.len(path) + 1, -- Actual count
|
||||
-- string_to_unicode(path, true, true)
|
||||
-- )
|
||||
--
|
||||
---- [out] [size_is(maxbuf)] uint8 can_path[],
|
||||
---- [in] uint32 maxbuf,
|
||||
-- arguments = arguments .. bin.pack("<I", 3)
|
||||
--
|
||||
---- [in] [string,charset(UTF16)] uint16 prefix[],
|
||||
-- arguments = arguments .. bin.pack("<IIIA",
|
||||
-- string.len(prefix) + 1, -- Max count
|
||||
-- 0, -- Offset
|
||||
-- string.len(prefix) + 1, -- Actual count
|
||||
-- string_to_unicode(prefix, true, true)
|
||||
-- )
|
||||
--
|
||||
---- [in,out] uint32 pathtype,
|
||||
-- arguments = arguments .. bin.pack("<I", 1)
|
||||
--
|
||||
---- [in] uint32 pathflags
|
||||
-- arguments = arguments .. bin.pack("<I", 0)
|
||||
--
|
||||
--
|
||||
--
|
||||
-- -- Do the call
|
||||
-- status, result = call_function(smbstate, 0x1F, arguments)
|
||||
-- if(status ~= true) then
|
||||
-- return false, result
|
||||
-- end
|
||||
--
|
||||
-- stdnse.print_debug(3, "MSRPC: NetPathCanonicalize() returned successfully")
|
||||
--
|
||||
-- -- Make arguments easier to use
|
||||
-- arguments = result['arguments']
|
||||
-- pos = 1
|
||||
--
|
||||
---- [in] [string,charset(UTF16)] uint16 *server_unc,
|
||||
---- [in] [string,charset(UTF16)] uint16 path[],
|
||||
-- [out] [size_is(maxbuf)] uint8 can_path[],
|
||||
-- pos, test = bin.unpack("<I", arguments, pos)
|
||||
-- io.write(string.format("test = %08x\n\n", test))
|
||||
-- pos, path = bin.unpack(string.format("<A%d", test), arguments, pos)
|
||||
-- io.write(string.format("test = %s\n\n", path))
|
||||
---- [in] uint32 maxbuf,
|
||||
---- [in] [string,charset(UTF16)] uint16 prefix[],
|
||||
---- [in,out] uint32 pathtype,
|
||||
-- pos, pathtype = bin.unpack("<I", arguments, pos)
|
||||
-- io.write(string.format("pathtype = %08x\n", pathtype))
|
||||
---- [in] uint32 pathflags
|
||||
--
|
||||
--
|
||||
-- pos, response['return'] = bin.unpack("<I", arguments, pos)
|
||||
-- io.write(string.format("return = %08x\n", response['return']))
|
||||
-- if(response['return'] == nil) then
|
||||
-- return false, "Read off the end of the packet (winreg.openkey)"
|
||||
-- end
|
||||
-- if(response['return'] ~= 0) then
|
||||
-- return false, smb.get_status_name(response['return']) .. " (winreg.openkey)"
|
||||
-- end
|
||||
--
|
||||
-- return true, response
|
||||
--
|
||||
--end
|
||||
|
||||
|
||||
|
||||
|
||||
---Call the NetPathCompare() function, which indirectly calls NetPathCanonicalize(),
|
||||
-- the target of ms08-067. I'm currently only using this to trigger ms08-067.
|
||||
--
|
||||
-- The string used by Metasploit and other free tools to check for this vulnerability is
|
||||
-- '\AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\..\n'. On vulnerable systems, this will be
|
||||
-- accepted and this function will return '0'. On patched systems, this will be rejected
|
||||
-- and return <code>ERROR_INVALID_PARAMETER</code>.
|
||||
--
|
||||
-- Note that the srvsvc.exe process occasionally crashes when attempting this.
|
||||
--
|
||||
--@param smbstate The SMB state table
|
||||
--@param server The IP or Hostname of the server (seems to be ignored but it's a good idea to have it)
|
||||
--@param path1 The first path to compare
|
||||
--@param path2 The second path to compare
|
||||
--@param pathtype The pathtype to pass to the function (I always use '1')
|
||||
--@param pathflags The pathflags to pass to the function (I always use '0')
|
||||
--@return (status, result) If status is false, result is an error message. Otherwise, result is a table of values containing
|
||||
-- 'return'.
|
||||
function srvsvc_netpathcompare(smbstate, server, path1, path2, pathtype, pathflags)
|
||||
local i, j
|
||||
local status, result
|
||||
local arguments
|
||||
local pos, align
|
||||
|
||||
local response = {}
|
||||
|
||||
stdnse.print_debug(2, "MSRPC: Calling NetPathCompare(%s, %s) [%s]", path1, path2, smbstate['ip'])
|
||||
|
||||
-- [in] [string,charset(UTF16)] uint16 *server_unc,
|
||||
arguments = bin.pack("<IIIIA",
|
||||
REFERENT_ID, -- Referent ID
|
||||
string.len(server) + 1, -- Max count
|
||||
0, -- Offset
|
||||
string.len(server) + 1, -- Actual count
|
||||
string_to_unicode(server, true, true)
|
||||
)
|
||||
|
||||
-- [in] [string,charset(UTF16)] uint16 path1[],
|
||||
arguments = arguments .. bin.pack("<IIIA",
|
||||
string.len(path1) + 1, -- Max count
|
||||
0, -- Offset
|
||||
string.len(path1) + 1, -- Actual count
|
||||
string_to_unicode(path1, true, true)
|
||||
)
|
||||
|
||||
|
||||
-- [in] [string,charset(UTF16)] uint16 path2[],
|
||||
arguments = arguments .. bin.pack("<IIIA",
|
||||
string.len(path2) + 1, -- Max count
|
||||
0, -- Offset
|
||||
string.len(path2) + 1, -- Actual count
|
||||
string_to_unicode(path2, true, true)
|
||||
)
|
||||
|
||||
-- [in] uint32 pathtype,
|
||||
arguments = arguments .. bin.pack("<I", pathtype)
|
||||
|
||||
-- [in] uint32 pathflags
|
||||
arguments = arguments .. bin.pack("<I", pathflags)
|
||||
|
||||
|
||||
-- Do the call
|
||||
status, result = call_function(smbstate, 0x20, arguments)
|
||||
if(status ~= true) then
|
||||
return false, result
|
||||
end
|
||||
|
||||
stdnse.print_debug(3, "MSRPC: NetPathCompare() returned successfully")
|
||||
|
||||
-- Make arguments easier to use
|
||||
arguments = result['arguments']
|
||||
pos = 1
|
||||
|
||||
|
||||
-- [in] [string,charset(UTF16)] uint16 *server_unc,
|
||||
-- [in] [string,charset(UTF16)] uint16 path1[],
|
||||
-- [in] [string,charset(UTF16)] uint16 path2[],
|
||||
-- [in] uint32 pathtype,
|
||||
-- [in] uint32 pathflags
|
||||
|
||||
pos, response['return'] = bin.unpack("<I", arguments, pos)
|
||||
|
||||
if(response['return'] == nil) then
|
||||
return false, "Read off the end of the packet (srvsvc.netpathcompare)"
|
||||
end
|
||||
if(response['return'] ~= 0) then
|
||||
return false, smb.get_status_name(response['return']) .. " (srvsvc.netpathcompare)"
|
||||
end
|
||||
|
||||
return true, response
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
---Call the <code>connect4</code> function, to obtain a "connect handle". This must be done before calling many
|
||||
-- of the SAMR functions.
|
||||
--
|
||||
|
||||
129
nselib/smb.lua
129
nselib/smb.lua
@@ -248,7 +248,7 @@ function start(host)
|
||||
stdnse.print_debug(2, "SMB: Starting SMB session for %s (%s)", host.name, host.ip)
|
||||
|
||||
if(port == nil) then
|
||||
return false, "Couldn't find a valid port to check"
|
||||
return false, "SMB: Couldn't find a valid port to check"
|
||||
end
|
||||
|
||||
stdnse.print_debug(3, "SMB: Attempting to lock SMB mutex")
|
||||
@@ -261,7 +261,7 @@ function start(host)
|
||||
if(status == false) then
|
||||
stdnse.print_debug(3, "SMB: Attempting to release SMB mutex (1)")
|
||||
mutex "done"
|
||||
stdnse.print_debug(3, "SMB: SMB mutex released (1)")
|
||||
stdnse.print_debug(3, "SMB: mutex released (1)")
|
||||
end
|
||||
|
||||
return status, state
|
||||
@@ -281,7 +281,7 @@ function start(host)
|
||||
mutex "done"
|
||||
stdnse.print_debug(3, "SMB: SMB mutex released (3)")
|
||||
|
||||
return false, "Couldn't find a valid port to check"
|
||||
return false, "SMB: Couldn't find a valid port to check"
|
||||
end
|
||||
|
||||
--- Kills the SMB connection, closes the socket, and releases the mutex. Because of the mutex
|
||||
@@ -312,7 +312,7 @@ function stop(smb)
|
||||
local status, err = smb['socket']:close()
|
||||
|
||||
if(status == false) then
|
||||
return false, "Failed to close socket: " .. err
|
||||
return false, "SMB: Failed to close socket: " .. err
|
||||
end
|
||||
end
|
||||
|
||||
@@ -333,7 +333,7 @@ function start_raw(host, port)
|
||||
status, err = socket:connect(host.ip, port, "tcp")
|
||||
|
||||
if(status == false) then
|
||||
return false, "Failed to connect to host: " .. err
|
||||
return false, "SMB: Failed to connect to host: " .. err
|
||||
end
|
||||
|
||||
return true, socket
|
||||
@@ -439,7 +439,7 @@ function start_netbios(host, port, name)
|
||||
status, err = socket:connect(host.ip, port, "tcp")
|
||||
if(status == false) then
|
||||
socket:close()
|
||||
return false, "Failed to connect: " .. err
|
||||
return false, "SMB: Failed to connect: " .. err
|
||||
end
|
||||
|
||||
-- Send the session request
|
||||
@@ -447,7 +447,7 @@ function start_netbios(host, port, name)
|
||||
status, err = socket:send(session_request)
|
||||
if(status == false) then
|
||||
socket:close()
|
||||
return false, "Failed to send: " .. err
|
||||
return false, "SMB: Failed to send: " .. err
|
||||
end
|
||||
socket:set_timeout(5000)
|
||||
|
||||
@@ -456,7 +456,7 @@ function start_netbios(host, port, name)
|
||||
status, result = socket:receive_bytes(4);
|
||||
if(status == false) then
|
||||
socket:close()
|
||||
return false, "Failed to close socket: " .. result
|
||||
return false, "SMB: Failed to close socket: " .. result
|
||||
end
|
||||
pos, result, flags, length = bin.unpack(">CCS", result)
|
||||
|
||||
@@ -477,7 +477,7 @@ function start_netbios(host, port, name)
|
||||
|
||||
-- We reached the end of our names list
|
||||
stdnse.print_debug(1, "SMB: None of the NetBIOS names worked!")
|
||||
return false, "Couldn't find a NetBIOS name that works for the server. Sorry!"
|
||||
return false, "SMB: Couldn't find a NetBIOS name that works for the server. Sorry!"
|
||||
end
|
||||
|
||||
---Generate the Lanman v1 hash (LMv1). The generated hash is incredibly easy to reverse, because the input
|
||||
@@ -489,7 +489,7 @@ end
|
||||
--@return (status, hash) If status is true, the hash is returned; otherwise, an error message is returned.
|
||||
function lm_create_hash(password)
|
||||
if(have_ssl ~= true) then
|
||||
return false, "OpenSSL not present"
|
||||
return false, "SMB: OpenSSL not present"
|
||||
end
|
||||
|
||||
local str1, str2
|
||||
@@ -525,7 +525,7 @@ end
|
||||
--@return (status, hash) If status is true, the hash is returned; otherwise, an error message is returned.
|
||||
function ntlm_create_hash(password)
|
||||
if(have_ssl ~= true) then
|
||||
return false, "OpenSSL not present"
|
||||
return false, "SMB: OpenSSL not present"
|
||||
end
|
||||
|
||||
local i
|
||||
@@ -547,7 +547,7 @@ end
|
||||
--@return (status, response) If status is true, the response is returned; otherwise, an error message is returned.
|
||||
function lm_create_response(lanman, challenge)
|
||||
if(have_ssl ~= true) then
|
||||
return false, "OpenSSL not present"
|
||||
return false, "SMB: OpenSSL not present"
|
||||
end
|
||||
|
||||
local str1, str2, str3
|
||||
@@ -593,7 +593,7 @@ end
|
||||
--@return (status, response) If status is true, the response is returned; otherwise, an error message is returned.
|
||||
function ntlmv2_create_hash(ntlm, username, domain)
|
||||
if(have_ssl ~= true) then
|
||||
return false, "OpenSSL not present"
|
||||
return false, "SMB: OpenSSL not present"
|
||||
end
|
||||
|
||||
local unicode = ""
|
||||
@@ -641,7 +641,7 @@ end
|
||||
-- it on every Windows system from Windows 2000 to Windows Vista, and it has always worked.
|
||||
function ntlmv2_create_response(ntlm, username, domain, challenge, client_challenge_length)
|
||||
if(have_ssl ~= true) then
|
||||
return false, "OpenSSL not present"
|
||||
return false, "SMB: OpenSSL not present"
|
||||
end
|
||||
|
||||
local client_challenge = openssl.rand_bytes(client_challenge_length)
|
||||
@@ -785,12 +785,15 @@ function smb_read(smb)
|
||||
|
||||
-- Make sure the connection is still alive
|
||||
if(status ~= true) then
|
||||
return false, "Failed to receive bytes: " .. result
|
||||
return false, "SMB: Failed to receive bytes: " .. result
|
||||
end
|
||||
|
||||
-- The length of the packet is 4 bytes of big endian (for our purposes).
|
||||
-- The NetBIOS header is 4 bytes, big endian
|
||||
pos, netbios_length = bin.unpack(">I", result)
|
||||
if(netbios_length == nil) then
|
||||
return false, "SMB: Malformed packet received"
|
||||
end
|
||||
|
||||
-- The total length is the netbios_length, plus 4 (for the length itself)
|
||||
length = netbios_length + 4
|
||||
@@ -804,7 +807,7 @@ function smb_read(smb)
|
||||
|
||||
-- Make sure the connection is still alive
|
||||
if(status ~= true) then
|
||||
return false, "Failed to receive bytes: " .. result
|
||||
return false, "SMB: Failed to receive bytes: " .. result
|
||||
end
|
||||
|
||||
-- Append the new data to the old stuff
|
||||
@@ -819,14 +822,33 @@ function smb_read(smb)
|
||||
|
||||
-- The header is 32 bytes.
|
||||
pos, header = bin.unpack("<A32", result, pos)
|
||||
if(header == nil) then
|
||||
return false, "SMB: Malformed packet received"
|
||||
end
|
||||
|
||||
-- The parameters length is a 1-byte value.
|
||||
pos, parameter_length = bin.unpack("<C", result, pos)
|
||||
if(parameter_length == nil) then
|
||||
return false, "SMB: Malformed packet received"
|
||||
end
|
||||
|
||||
-- Double the length parameter, since parameters are two-byte values.
|
||||
pos, parameters = bin.unpack(string.format("<A%d", parameter_length*2), result, pos)
|
||||
if(parameters == nil) then
|
||||
return false, "SMB: Malformed packet received"
|
||||
end
|
||||
|
||||
-- The data length is a 2-byte value.
|
||||
pos, data_length = bin.unpack("<S", result, pos)
|
||||
if(data_length == nil) then
|
||||
return false, "SMB: Malformed packet received"
|
||||
end
|
||||
|
||||
-- Read that many bytes of data.
|
||||
pos, data = bin.unpack(string.format("<A%d", data_length), result, pos)
|
||||
if(data == nil) then
|
||||
return false, "SMB: Malformed packet received"
|
||||
end
|
||||
|
||||
stdnse.print_debug(3, "SMB: Received %d bytes", string.len(result))
|
||||
return true, header, parameters, data
|
||||
@@ -891,11 +913,38 @@ function negotiate_protocol(smb)
|
||||
return false, header
|
||||
end
|
||||
|
||||
-- Since this is our first response, parse out the header
|
||||
-- Parse out the header
|
||||
pos, header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid = bin.unpack("<CCCCCICSSlSSSSS", header)
|
||||
|
||||
-- Check if we fell off the packet (if that happened, the last parameter will be nil)
|
||||
if(mid == nil) then
|
||||
return false, "SMB: Malformed packet received"
|
||||
end
|
||||
|
||||
-- Parse the parameter section
|
||||
pos, dialect, security_mode, max_mpx, max_vc, max_buffer, max_raw_buffer, session_key, capabilities, time, timezone, key_length = bin.unpack("<SCSSIIIILsC", parameters)
|
||||
pos, dialect = bin.unpack("<S", parameters)
|
||||
|
||||
-- Check if we ran off the packet
|
||||
if(dialect == nil) then
|
||||
return false, "SMB: Malformed packet received"
|
||||
end
|
||||
-- Check if the server didn't like our requested protocol
|
||||
if(dialect ~= 0) then
|
||||
return false, string.format("Server negotiated an unknown protocol (#%d) -- aborting", dialect)
|
||||
end
|
||||
|
||||
pos, security_mode, max_mpx, max_vc, max_buffer, max_raw_buffer, session_key, capabilities, time, timezone, key_length = bin.unpack("<CSSIIIILsC", parameters, pos)
|
||||
|
||||
-- Some broken implementations of SMB don't send these variables
|
||||
if(time == nil) then
|
||||
time = 0
|
||||
end
|
||||
if(timezone == nil) then
|
||||
timezone = 0
|
||||
end
|
||||
if(key_length == nil) then
|
||||
key_length = 0
|
||||
end
|
||||
|
||||
-- Convert the time and timezone to more useful values
|
||||
time = (time / 10000000) - 11644473600
|
||||
@@ -916,16 +965,17 @@ function negotiate_protocol(smb)
|
||||
-- Get the domain as a Unicode string
|
||||
local ch, dummy
|
||||
domain = ""
|
||||
server = ""
|
||||
|
||||
pos, ch, dummy = bin.unpack("<CC", data, pos)
|
||||
while ch ~= 0 do
|
||||
while ch ~= nil and ch ~= 0 do
|
||||
domain = domain .. string.char(ch)
|
||||
pos, ch, dummy = bin.unpack("<CC", data, pos)
|
||||
end
|
||||
|
||||
-- Get the server name as a Unicode string
|
||||
server = ""
|
||||
pos, ch, dummy = bin.unpack("<CC", data, pos)
|
||||
while ch do
|
||||
while ch ~= nil and ch ~= 0 do
|
||||
server = server .. string.char(ch)
|
||||
pos, ch, dummy = bin.unpack("<CC", data, pos)
|
||||
end
|
||||
@@ -1296,11 +1346,18 @@ function start_session(smb, username, domain, password, password_hash, hash_type
|
||||
-- Check if we were allowed in
|
||||
pos, header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid = bin.unpack("<CCCCCICSSlSSSSS", header)
|
||||
|
||||
if(mid == nil) then
|
||||
return false, "SMB: Malformed packet received"
|
||||
end
|
||||
|
||||
-- Check if we're successful
|
||||
if(status == 0) then
|
||||
|
||||
-- Parse the parameters
|
||||
pos, andx_command, andx_reserved, andx_offset, action = bin.unpack("<CCSS", parameters)
|
||||
if(action == nil) then
|
||||
return false, "SMB: Malformed packet received"
|
||||
end
|
||||
|
||||
-- Parse the data
|
||||
pos, os, lanmanager, domain = bin.unpack("<zzz", data)
|
||||
@@ -1312,8 +1369,10 @@ function start_session(smb, username, domain, password, password_hash, hash_type
|
||||
smb['lanmanager'] = lanmanager
|
||||
|
||||
-- Check if they're using an un-supported system [TODO: once I sort this out, remove the warning]
|
||||
if(os == "Unix" or string.sub(lanmanager, 1, 5) == "Samba") then
|
||||
stdnse.print_debug(1, "SMB: Warning: the server apperas to be running a non-Microsoft operating system. Since these scripts are primarily Microsoft checks, your mileage may vary.")
|
||||
if(os == nil or lanmanager == nil or domain == nil) then
|
||||
stdnse.print_debug(1, "SMB: Warning: the server is using a non-standard SMB implementation; your mileage may vary (%s)", smb['ip'])
|
||||
elseif(os == "Unix" or string.sub(lanmanager, 1, 5) == "Samba") then
|
||||
stdnse.print_debug(1, "SMB: Warning: the server apperas to be Unix; your mileage may vary.")
|
||||
end
|
||||
|
||||
-- Check if they were logged in as a guest
|
||||
@@ -1385,6 +1444,10 @@ function tree_connect(smb, path)
|
||||
|
||||
-- Check if we were allowed in
|
||||
pos, header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid = bin.unpack("<CCCCCICSSlSSSSS", header)
|
||||
if(mid == nil) then
|
||||
return false, "SMB: Malformed packet received"
|
||||
end
|
||||
|
||||
if(status ~= 0) then
|
||||
return false, get_status_name(status)
|
||||
end
|
||||
@@ -1420,6 +1483,9 @@ function tree_disconnect(smb)
|
||||
|
||||
-- Check if there was an error
|
||||
pos, header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid = bin.unpack("<CCCCCICSSlSSSSS", header)
|
||||
if(mid == nil) then
|
||||
return false, "SMB: Malformed packet received"
|
||||
end
|
||||
if(status ~= 0) then
|
||||
return false, get_status_name(status)
|
||||
end
|
||||
@@ -1463,6 +1529,9 @@ function logoff(smb)
|
||||
|
||||
-- Check if there was an error
|
||||
pos, header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid = bin.unpack("<CCCCCICSSlSSSSS", header)
|
||||
if(mid == nil) then
|
||||
return false, "SMB: Malformed packet received"
|
||||
end
|
||||
if(status ~= 0) then
|
||||
return false, get_status_name(status)
|
||||
end
|
||||
@@ -1524,12 +1593,18 @@ function create_file(smb, path)
|
||||
|
||||
-- Check if we were allowed in
|
||||
pos, header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid = bin.unpack("<CCCCCICSSlSSSSS", header)
|
||||
if(mid == nil) then
|
||||
return false, "SMB: Malformed packet received"
|
||||
end
|
||||
if(status ~= 0) then
|
||||
return false, get_status_name(status)
|
||||
end
|
||||
|
||||
-- Parse the parameters
|
||||
pos, andx_command, andx_reserved, andx_offset, oplock_level, fid, create_action, created, last_access, last_write, last_change, attributes, allocation_size, end_of_file, filetype, ipc_state, is_directory = bin.unpack("<CCSCSILLLLILLSSC", parameters)
|
||||
if(is_directory == nil) then
|
||||
return false, "SMB: Malformed packet received"
|
||||
end
|
||||
|
||||
-- Fill in the smb string
|
||||
smb['oplock_level'] = oplock_level
|
||||
@@ -1619,12 +1694,19 @@ function send_transaction(smb, func, function_parameters, function_data)
|
||||
|
||||
-- Check if it worked
|
||||
pos, header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid = bin.unpack("<CCCCCICSSlSSSSS", header)
|
||||
if(mid == nil) then
|
||||
return false, "SMB: Malformed packet received"
|
||||
end
|
||||
if(status ~= 0) then
|
||||
io.write(string.format("Status = %08x\n\n", status))
|
||||
return false, status_codes[status]
|
||||
end
|
||||
|
||||
-- Parse the parameters
|
||||
pos, total_word_count, total_data_count, reserved1, parameter_count, parameter_offset, parameter_displacement, data_count, data_offset, data_displacement, setup_count, reserved2 = bin.unpack("<SSSSSSSSSCC", parameters)
|
||||
if(reserved2 == nil) then
|
||||
return "SMB: Malformed packet received"
|
||||
end
|
||||
|
||||
-- Convert the parameter/data offsets into something more useful (the offset into the data section)
|
||||
-- - 0x20 for the header, - 0x01 for the length.
|
||||
@@ -1734,6 +1816,7 @@ status_names =
|
||||
NT_STATUS_OK = 0x0000,
|
||||
NT_STATUS_WERR_BADFILE = 0x00000002,
|
||||
NT_STATUS_WERR_ACCESS_DENIED = 0x00000005,
|
||||
NT_STATUS_WERR_INVALID_NAME = 0x0000007b,
|
||||
NT_STATUS_NO_MORE_ITEMS = 0x00000103,
|
||||
NT_STATUS_MORE_ENTRIES = 0x00000105,
|
||||
NT_STATUS_SOME_NOT_MAPPED = 0x00000107,
|
||||
|
||||
140
scripts/smb-checkvulns.nse
Normal file
140
scripts/smb-checkvulns.nse
Normal file
@@ -0,0 +1,140 @@
|
||||
id = "MSRPC: Check vulns()"
|
||||
description = [[
|
||||
Currently, this script checks if a host is vulnerable to ms08-067. I'd like to add
|
||||
checks for more vulnerabilities, but I'm worried about licensing/copyright issues
|
||||
(since I'd be basing them on non-free tools).
|
||||
|
||||
Checking for the ms08-067 vulnerability is very dangerous, as the check is likely
|
||||
to crash systems. On a fairly wide scan conducted by Brandon Enright, we determined
|
||||
that a vulnerable on average, is about 50% more likely to crash than to survive
|
||||
the check. Out of 82 vulnerable systems, 52 crashed. As such, great care should be
|
||||
taken when using this check.
|
||||
|
||||
You have the option to supply a username/password when performing this check, but
|
||||
it shouldn't be necessary for a default configuration.
|
||||
]]
|
||||
|
||||
---
|
||||
--@usage
|
||||
-- nmap --script smb-checkvulns.nse -p445 <host>
|
||||
-- sudo nmap -sU -sS --script smb-checkvulns.nse -p U:137,T:139 <host>
|
||||
--
|
||||
--@output
|
||||
-- Host script results:
|
||||
-- |_ smb-checkvulns: This host is vulnerable to ms08-067
|
||||
--
|
||||
-- @args smb* This script supports the <code>smbusername</code>,
|
||||
-- <code>smbpassword</code>, <code>smbhash</code>, <code>smbguest</code>, and
|
||||
-- <code>smbtype</code> script arguments of the <code>smb</code> module.
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
author = "Ron Bowes"
|
||||
copyright = "Ron Bowes"
|
||||
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
|
||||
categories = {"discovery","intrusive"}
|
||||
|
||||
require 'msrpc'
|
||||
require 'smb'
|
||||
require 'stdnse'
|
||||
|
||||
hostrule = function(host)
|
||||
|
||||
local port = smb.get_port(host)
|
||||
|
||||
if(port == nil) then
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
---Check if the server is patched for ms08-067. This is done by calling NetPathCompare() with an
|
||||
-- illegal string. If the string is accepted, then the server is vulnerable; if it's rejected, then
|
||||
-- you're safe (for now).
|
||||
--
|
||||
-- Based on a packet cap of this script, thanks go out to the author:
|
||||
-- http://labs.portcullis.co.uk/download/ms08-067_check.py
|
||||
--
|
||||
-- If there's a licensing issue, please let me (Ron Bowes) know so I can
|
||||
--
|
||||
-- NOTE: This CAN crash stuff (ie, crash svchost.exe and force a reboot), so beware! In about 20
|
||||
-- tests I did, it crashed once. This is not a guarantee.
|
||||
--
|
||||
--@param host The hose object.
|
||||
--@return (status, result) If status if alse, result is an error code; otherwise, result is either
|
||||
-- <code>VULNERABLE</code> for vulnerable, <code>PATCHED</code> for not vulnerable, or
|
||||
-- <code>UNKNOWN</code> if there was an error (likey vulnerable).
|
||||
local VULNERABLE = 1
|
||||
local PATCHED = 2
|
||||
local UNKNOWN = 3
|
||||
function check_ms08_067(host)
|
||||
local status, smbstate
|
||||
local bind_result, netpathcompare_result
|
||||
|
||||
-- Create the SMB session
|
||||
status, smbstate = msrpc.start_smb(host, "\\\\BROWSER")
|
||||
if(status == false) then
|
||||
return false, smbstate
|
||||
end
|
||||
|
||||
-- Bind to SRVSVC service
|
||||
status, bind_result = msrpc.bind(smbstate, msrpc.SRVSVC_UUID, msrpc.SRVSVC_VERSION, nil)
|
||||
if(status == false) then
|
||||
msrpc.stop_smb(smbstate)
|
||||
return false, bind_result
|
||||
end
|
||||
|
||||
-- Call netpathcanonicalize
|
||||
-- status, netpathcanonicalize_result = msrpc.srvsvc_netpathcanonicalize(smbstate, host.ip, "\\a", "\\test\\")
|
||||
|
||||
local path1 = "\\AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\..\\n"
|
||||
local path2 = "\\n"
|
||||
status, netpathcompare_result = msrpc.srvsvc_netpathcompare(smbstate, host.ip, path1, path2, 1, 0)
|
||||
|
||||
-- Stop the SMB session
|
||||
msrpc.stop_smb(smbstate)
|
||||
|
||||
if(status == false) then
|
||||
if(string.find(netpathcompare_result, "INVALID_NAME") == nil) then
|
||||
return true, UNKNOWN
|
||||
else
|
||||
return true, PATCHED
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return true, VULNERABLE
|
||||
end
|
||||
|
||||
|
||||
action = function(host)
|
||||
local status, result
|
||||
|
||||
status, result = check_ms08_067(host)
|
||||
|
||||
if(status == false) then
|
||||
if(nmap.debugging() > 0) then
|
||||
return "ERROR: " .. result
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
if(result == VULNERABLE) then
|
||||
response = "This host is vulnerable to ms08-067"
|
||||
elseif(result == UNKNOWN) then
|
||||
response = "This host is likely vulnerable to ms08-067 (it stopped responding during the test)"
|
||||
else
|
||||
if(nmap.verbosity() > 0) then
|
||||
response = "This host is patched for ms08-067"
|
||||
else
|
||||
response = nil
|
||||
end
|
||||
end
|
||||
|
||||
return response
|
||||
end
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user