4elta / recon

automate the boring stuff!
GNU General Public License v3.0
8 stars 3 forks source link

Analyzer: Add smb analyzer #82

Closed ikstream closed 6 months ago

4elta commented 11 months ago

information about SMB dialects:

4elta commented 11 months ago

this is partly a response to this comment and partly my argument on how to represent the configuration of a server regarding its security mode (i.e. "SMB signing") for SMB2 and CIFS/SMB.

i have consulted the official documentation regarding the SMB2 negotiation message. of particular interest is the section about the SecurityMode field. this field specifies whether SMB signing is enabled and/or required:

this is the relevant section of the Nmap smb2-security-mode script:

local message_signing = {}
-- Signing configuration. SMBv2 servers support two flags:
-- * Message signing enabled
-- * Message signing required
local signing_enabled, signing_required
if smbstate['security_mode'] & 0x01 == 0x01 then
  signing_enabled = true
end
if smbstate['security_mode'] & 0x02 == 0x02 then
  signing_required = true
end
if signing_enabled and signing_required then
  table.insert(message_signing, "Message signing enabled and required")
elseif signing_enabled and not(signing_required) then
  table.insert(message_signing, "Message signing enabled but not required")
elseif not(signing_enabled) and not(signing_required) then
  table.insert(message_signing, "Message signing is disabled and not required!")
elseif not(signing_enabled) and signing_required then
  table.insert(message_signing, "Message signing is disabled!")
end

we can compare the SMB2 negotiation message with the one for CIFS/SMB:

this is the relevant section of the Nmap smb-security-mode script:

-- Message signing supported/required?
if(security_mode & 8) == 8 then
  response.message_signing = "required"
elseif(security_mode & 4) == 4 then
  response.message_signing = "supported"
else
  response.message_signing = "disabled"
  warnings.message_signing = "dangerous, but default"
end

therefore, i suggest the following for representing a CIFS/SMB/SMB2 server's configuration regarding its security mode (i.e. "SMB signing"):

protocol is either CIFS ("An SMB Version 1.0 Protocol implementation MUST implement CIFS") or SMB2 ("Server Message Block (SMB) Protocol Versions 2 and 3")

the recommendations file should then define the state (e.g. signing = {'CIFS' = "required", 'SMB2' = "required") by which an CIFS/SMB/SMB2 server will be rated.

4elta commented 11 months ago

i have slept on it and am revising my proposal based on the following fact (which i didn't think about in my comment yesterday):

A parser maps the result of a particular tool to a tool-agnostic representation of a service's configuration.

--from the architecture documentation

what if some other SMB scanner extracts/displays the values of the signing_enabled and signing_required flags as they are (i.e. not "interpreting" them as the Nmap scripts do)? the tool-agnostic representation of a CIFS/SMB/SMB2 server's configuration is to represent the configuration as it actually is (i.e. without interpretation):

# inside `_parse_smb_security_mode(...)`:

protocol = 'CIFS'
# TODO: parse the script result into `signing_enabled` and `signing_required`

service['signing'][protocol]['enabled'] = signing_enabled
service['signing'][protocol]['required'] = signing_required

# inside `_parse_smb2_security_mode(...)`:

protocol = 'SMB2'
# TODO: parse the script result into `signing_enabled` and `signing_required`

service['signing'][protocol]['enabled'] = signing_enabled
service['signing'][protocol]['required'] = signing_required

interpreting the configuration (based on some recommendations) is the analyzer's job; not that of the parser.

4elta commented 6 months ago

thanks again for your contribution :pray: