1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
local smb = require "smb"
local smb2 = require "smb2"
local stdnse = require "stdnse"
local table = require "table"
local nmap = require "nmap"
description = [[
Attempts to list the supported capabilities in a SMBv2 server for each
enabled dialect.
The script sends a SMB2_COM_NEGOTIATE command and parses the response
using the SMB dialects:
* 2.0.2
* 2.1
* 3.0
* 3.0.2
* 3.1.1
References:
* https://msdn.microsoft.com/en-us/library/cc246561.aspx
]]
---
-- @usage nmap -p 445 --script smb2-capabilities <target>
-- @usage nmap -p 139 --script smb2-capabilities <target>
--
-- @output
-- | smb2-capabilities:
-- | 2.0.2:
-- | Distributed File System
-- | 2.1:
-- | Distributed File System
-- | Leasing
-- | Multi-credit operations
--
-- @xmloutput
-- <table key="2.0.2">
-- <elem>Distributed File System</elem>
-- </table>
-- <table key="2.1">
-- <elem>Distributed File System</elem>
-- <elem>Leasing</elem>
-- <elem>Multi-credit operations</elem>
-- </table>
---
author = "Paulino Calderon"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"safe", "discovery"}
hostrule = function(host)
return smb.get_port(host) ~= nil
end
action = function(host,port)
local status, smbstate, overrides
local output = stdnse.output_table()
overrides = {}
-- Checking if SMB 2+ is supported in general
status, smbstate = smb.start(host)
if(status == false) then
return false, smbstate
end
local max_dialect
status, max_dialect = smb2.negotiate_v2(smbstate)
smb.stop(smbstate)
if not status then -- None of SMB2 dialects accepted by the target
return false, "SMB 2+ not supported"
end
stdnse.debug2("SMB2: Dialect '%s' is the highest supported", smb2.dialect_name(max_dialect))
for i, dialect in pairs(smb2.dialects()) do
-- we need a clean connection for each negotiate request
status, smbstate = smb.start(host)
if(status == false) then
stdnse.debug1("Could not establish a connection.")
return nil
end
-- We set our overrides Dialects table with the dialect we are testing
overrides['Dialects'] = {dialect}
status = smb2.negotiate_v2(smbstate, overrides)
if status then
local capabilities = {}
stdnse.debug2("SMB2: Server capabilities: '%s'", smbstate['capabilities'])
-- We check the capabilities flags. Not all of them are supported by
-- every dialect but we dumb check anyway.
if smbstate['capabilities'] & 0x01 == 0x01 then
table.insert(capabilities, "Distributed File System")
end
if smbstate['capabilities'] & 0x02 == 0x02 then
table.insert(capabilities, "Leasing")
end
if smbstate['capabilities'] & 0x04 == 0x04 then
table.insert(capabilities, "Multi-credit operations")
end
if smbstate['capabilities'] & 0x08 == 0x08 then
table.insert(capabilities, "Multiple Channel support")
end
if smbstate['capabilities'] & 0x10 == 0x10 then
table.insert(capabilities, "Persistent handles")
end
if smbstate['capabilities'] & 0x20 == 0x20 then
table.insert(capabilities, "Directory Leasing")
end
if smbstate['capabilities'] & 0x40 == 0x40 then
table.insert(capabilities, "Encryption")
end
if #capabilities<1 then
table.insert(capabilities, "All capabilities are disabled")
end
output[smb2.dialect_name(dialect)] = capabilities
end
smb.stop(smbstate)
if dialect == max_dialect then
break
end
end
if #output>0 then
return output
else
stdnse.debug1("No dialects were accepted.")
if nmap.verbosity()>1 then
return "Couldn't establish a SMBv2 connection."
end
end
end
|