Closed ikstream closed 6 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:
SMB2_NEGOTIATE_SIGNING_ENABLED
(0x01
): When set, indicates that security signatures are enabled on the server.SMB2_NEGOTIATE_SIGNING_REQUIRED
(0x02
): When set, indicates that security signatures are required by the server.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:
NEGOTIATE_SECURITY_SIGNATURES_ENABLED
(0x04
): If set, the server supports SMB security signatures for this connection.NEGOTIATE_SECURITY_SIGNATURES_REQUIRED
(0x08
): If set, the server requires security signatures. This bit must be clear if the NEGOTIATE_SECURITY_SIGNATURES_ENABLED
bit is clear.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"):
service['signing'][protocol] = "required"
: message signing requiredservice['signing'][protocol] = "supported"
: message signing supported (i.e. enabled but not required)service['signing'][protocol] = "disabled"
: message signing disabledprotocol
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.
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.
thanks again for your contribution :pray:
information about SMB dialects: