mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00
Merge branch 'smb3-negotiate-response' of https://github.com/mauropalumbo75/zeek
* 'smb3-negotiate-response' of https://github.com/mauropalumbo75/zeek: added test and pcap files for smb 3.1.1 negotiate-response smb3.1.1 additions to negotiate-response command I made several modifications: - Code format, style, naming changes - For completeness/correctness, I added parsing support for the remaining context type structures. - Moved the optional padding before the NegotiateContextList field to also require the 0x0311 dialect version (some failures in pre-existing unit tests pointed this out as an issue)
This commit is contained in:
commit
1b76d92e97
11 changed files with 264 additions and 26 deletions
4
CHANGES
4
CHANGES
|
@ -1,4 +1,8 @@
|
|||
|
||||
2.6-178 | 2019-03-21 14:10:44 -0700
|
||||
|
||||
* Add support for parsing SMB 3.1.1 NegotiateContextList response values (Mauro Palumbo)
|
||||
|
||||
2.6-175 | 2019-03-20 19:25:11 -0700
|
||||
|
||||
* Parse SMB2 TRANSFORM_HEADER messages and generate new smb2_transform_header event (Mauro Palumbo)
|
||||
|
|
10
NEWS
10
NEWS
|
@ -51,6 +51,16 @@ New Functionality
|
|||
|
||||
- Support for NFLOG link-layer type.
|
||||
|
||||
- Support for some SMB 3.x features
|
||||
|
||||
- An ``smb2_transform_header`` event is raised after parsing
|
||||
TRANSFORM_HEADER structures associated with encrypted messages.
|
||||
|
||||
- The ``SMB2::NegotiateResponse`` record now contains
|
||||
``negotiate_context_count`` and ``negotiate_context_values`` fields
|
||||
containing capability information found in an SMB 3.1.1 dialect's
|
||||
negotiation message.
|
||||
|
||||
Changed Functionality
|
||||
---------------------
|
||||
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
2.6-175
|
||||
2.6-178
|
||||
|
|
2
doc
2
doc
|
@ -1 +1 @@
|
|||
Subproject commit 79d4293fb0a7b03b7c3ae84c633b14f51c836a8d
|
||||
Subproject commit ee040c581f8a4e1ea82a7ec5f17d5f36f1184324
|
|
@ -3226,6 +3226,64 @@ export {
|
|||
attrs : SMB2::FileAttrs;
|
||||
};
|
||||
|
||||
## Preauthentication information as defined in SMB v. 3.1.1
|
||||
##
|
||||
## For more information, see MS-SMB2:2.3.1.1
|
||||
##
|
||||
type SMB2::PreAuthIntegrityCapabilities: record {
|
||||
## The number of hash algorithms.
|
||||
hash_alg_count : count;
|
||||
## The salt length.
|
||||
salt_length : count;
|
||||
## An array of hash algorithms (counts).
|
||||
hash_alg : vector of count;
|
||||
## The salt.
|
||||
salt : string;
|
||||
};
|
||||
|
||||
## Encryption information as defined in SMB v. 3.1.1
|
||||
##
|
||||
## For more information, see MS-SMB2:2.3.1.2
|
||||
##
|
||||
type SMB2::EncryptionCapabilities: record {
|
||||
## The number of ciphers.
|
||||
cipher_count : count;
|
||||
## An array of ciphers.
|
||||
ciphers : vector of count;
|
||||
};
|
||||
|
||||
## Compression information as defined in SMB v. 3.1.1
|
||||
##
|
||||
## For more information, see MS-SMB2:2.3.1.3
|
||||
##
|
||||
type SMB2::CompressionCapabilities: record {
|
||||
## The number of algorithms.
|
||||
alg_count : count;
|
||||
## An array of compression algorithms.
|
||||
algs : vector of count;
|
||||
};
|
||||
|
||||
## The context type information as defined in SMB v. 3.1.1
|
||||
##
|
||||
## For more information, see MS-SMB2:2.3.1
|
||||
##
|
||||
type SMB2::NegotiateContextValue: record {
|
||||
## Specifies the type of context (preauth or encryption).
|
||||
context_type : count;
|
||||
## The length in byte of the data field.
|
||||
data_length : count;
|
||||
## The preauthentication information.
|
||||
preauth_info : SMB2::PreAuthIntegrityCapabilities &optional;
|
||||
## The encryption information.
|
||||
encryption_info : SMB2::EncryptionCapabilities &optional;
|
||||
## The compression information.
|
||||
compression_info : SMB2::CompressionCapabilities &optional;
|
||||
## Indicates the server name the client must connect to.
|
||||
netname: string &optional;
|
||||
};
|
||||
|
||||
type SMB2::NegotiateContextValues: vector of SMB2::NegotiateContextValue;
|
||||
|
||||
## The response to an SMB2 *negotiate* request, which is used by tghe client to notify the server
|
||||
## what dialects of the SMB2 protocol the client understands.
|
||||
##
|
||||
|
@ -3244,6 +3302,11 @@ export {
|
|||
system_time : time;
|
||||
## The SMB2 server start time.
|
||||
server_start_time : time;
|
||||
|
||||
## The number of negotiate context values in SMB v. 3.1.1, otherwise reserved to 0.
|
||||
negotiate_context_count : count;
|
||||
## An array of context values in SMB v. 3.1.1.
|
||||
negotiate_context_values : SMB2::NegotiateContextValues;
|
||||
};
|
||||
|
||||
## The request sent by the client to request a new authenticated session
|
||||
|
|
|
@ -1,3 +1,21 @@
|
|||
enum smb3_capabilities {
|
||||
SMB2_GLOBAL_CAP_DFS = 0x00,
|
||||
SMB2_GLOBAL_CAP_LEASING = 0x02,
|
||||
SMB2_GLOBAL_CAP_LARGE_MTU = 0x04,
|
||||
SMB2_GLOBAL_CAP_MULTI_CHANNE = 0x08,
|
||||
SMB2_GLOBAL_CAP_PERSISTENT_HANDLES = 0x10,
|
||||
SMB2_GLOBAL_CAP_DIRECTORY_LEASING = 0x20,
|
||||
SMB2_GLOBAL_CAP_ENCRYPTION = 0x40,
|
||||
};
|
||||
|
||||
enum smb3_context_type {
|
||||
SMB2_PREAUTH_INTEGRITY_CAPABILITIES = 0x0001,
|
||||
SMB2_ENCRYPTION_CAPABILITIES = 0x0002,
|
||||
SMB2_COMPRESSION_CAPABILITIES = 0x0004,
|
||||
SMB2_NETNAME_NEGOTIATE_CONTEXT_ID = 0x0005,
|
||||
};
|
||||
|
||||
|
||||
refine connection SMB_Conn += {
|
||||
|
||||
function proc_smb2_negotiate_request(h: SMB2_Header, val: SMB2_negotiate_request) : bool
|
||||
|
@ -25,9 +43,19 @@ refine connection SMB_Conn += {
|
|||
|
||||
nr->Assign(0, val_mgr->GetCount(${val.dialect_revision}));
|
||||
nr->Assign(1, val_mgr->GetCount(${val.security_mode}));
|
||||
nr->Assign(2, BuildSMB2GUID(${val.server_guid})),
|
||||
nr->Assign(2, BuildSMB2GUID(${val.server_guid}));
|
||||
nr->Assign(3, filetime2brotime(${val.system_time}));
|
||||
nr->Assign(4, filetime2brotime(${val.server_start_time}));
|
||||
nr->Assign(5, val_mgr->GetCount(${val.negotiate_context_count}));
|
||||
|
||||
VectorVal* cv = new VectorVal(BifType::Vector::SMB2::NegotiateContextValues);
|
||||
|
||||
if ( ${val.dialect_revision} == 0x0311 )
|
||||
for ( auto i = 0u; i < ${val.smb3_ncl.vals}->size(); ++i )
|
||||
cv->Assign(i, BuildSMB2ContextVal(${val.smb3_ncl.vals[i]}));
|
||||
|
||||
nr->Assign(6, cv);
|
||||
|
||||
BifEvent::generate_smb2_negotiate_response(bro_analyzer(), bro_analyzer()->Conn(),
|
||||
BuildSMB2HeaderVal(h),
|
||||
nr);
|
||||
|
@ -37,35 +65,81 @@ refine connection SMB_Conn += {
|
|||
%}
|
||||
};
|
||||
|
||||
type SMB3_preauth_integrity_capabilities = record {
|
||||
hash_alg_count : uint16;
|
||||
salt_length : uint16;
|
||||
hash_alg : uint16[hash_alg_count];
|
||||
salt : bytestring &length = salt_length;
|
||||
};
|
||||
|
||||
type SMB3_encryption_capabilities = record {
|
||||
cipher_count : uint16;
|
||||
ciphers : uint16[cipher_count];
|
||||
};
|
||||
|
||||
type SMB3_compression_capabilities = record {
|
||||
alg_count : uint16;
|
||||
pad: uint16;
|
||||
reserved : uint32;
|
||||
algs : uint16[alg_count];
|
||||
};
|
||||
|
||||
type SMB3_netname_negotiate_context_id(len: uint16) = record {
|
||||
net_name: bytestring &length = len;
|
||||
};
|
||||
|
||||
type SMB3_negotiate_context_value = record {
|
||||
context_type : uint16; # specify the type of context
|
||||
data_length : uint16; # the length of the data field
|
||||
reserved : uint32; # ignored
|
||||
data : case context_type of {
|
||||
SMB2_PREAUTH_INTEGRITY_CAPABILITIES -> preauth_integrity_capabilities : SMB3_preauth_integrity_capabilities;
|
||||
SMB2_ENCRYPTION_CAPABILITIES -> encryption_capabilities : SMB3_encryption_capabilities;
|
||||
SMB2_COMPRESSION_CAPABILITIES -> compression_capabilities : SMB3_compression_capabilities;
|
||||
SMB2_NETNAME_NEGOTIATE_CONTEXT_ID -> netname_negotiate_context_id : SMB3_netname_negotiate_context_id(data_length);
|
||||
};
|
||||
pad : padding align 4;
|
||||
};
|
||||
|
||||
type SMB2_negotiate_request(header: SMB2_Header) = record {
|
||||
structure_size : uint16; # client MUST set this to 36
|
||||
dialect_count : uint16; # must be > 0
|
||||
security_mode : uint16; # there is a list of required modes
|
||||
reserved : padding[2]; # must be set to 0
|
||||
capabilities : uint32; # must be set to 0
|
||||
client_guid : SMB2_guid; # guid if client implements SMB 2.1 dialect, otherwise set to 0
|
||||
client_start_time : SMB_timestamp; # must be set to 0
|
||||
structure_size : uint16; # client MUST set this to 36
|
||||
dialect_count : uint16; # must be > 0
|
||||
security_mode : uint16; # there is a list of required modes
|
||||
reserved : padding[2]; # must be set to 0
|
||||
capabilities : uint32; # must be set to 0 if SMB 2.x, otherwise if SMB 3.x one of enum smb2_capabilities
|
||||
client_guid : SMB2_guid; # guid if client implements SMB 2.1 dialect, otherwise set to 0
|
||||
client_start_time : SMB_timestamp;
|
||||
dialects : uint16[dialect_count];
|
||||
} &byteorder=littleendian, &let {
|
||||
proc : bool = $context.connection.proc_smb2_negotiate_request(header, this);
|
||||
};
|
||||
|
||||
type NegotiateContextList(len: uint16) = record {
|
||||
pad : padding align 8;
|
||||
vals : SMB3_negotiate_context_value[len];
|
||||
}
|
||||
|
||||
type SMB2_negotiate_response(header: SMB2_Header) = record {
|
||||
structure_size : uint16;
|
||||
security_mode : uint16;
|
||||
dialect_revision : uint16;
|
||||
reserved : padding[2];
|
||||
server_guid : SMB2_guid;
|
||||
capabilities : uint32;
|
||||
max_transact_size : uint32;
|
||||
max_read_size : uint32;
|
||||
max_write_size : uint32;
|
||||
system_time : SMB_timestamp;
|
||||
server_start_time : SMB_timestamp;
|
||||
security_offset : uint16;
|
||||
security_length : uint16;
|
||||
pad1 : padding to security_offset - header.head_length;
|
||||
security_blob : bytestring &length=security_length;
|
||||
structure_size : uint16;
|
||||
security_mode : uint16;
|
||||
dialect_revision : uint16;
|
||||
negotiate_context_count : uint16; # reserved to 0 if not smb 3.1.1
|
||||
server_guid : SMB2_guid;
|
||||
capabilities : uint32;
|
||||
max_transact_size : uint32;
|
||||
max_read_size : uint32;
|
||||
max_write_size : uint32;
|
||||
system_time : SMB_timestamp;
|
||||
server_start_time : SMB_timestamp;
|
||||
security_offset : uint16;
|
||||
security_length : uint16;
|
||||
negotiate_context_offset : uint32;
|
||||
pad1 : padding to security_offset - header.head_length;
|
||||
security_blob : bytestring &length=security_length;
|
||||
negotiate_context_list : case dialect_revision of {
|
||||
0x0311 -> smb3_ncl : NegotiateContextList(negotiate_context_count);
|
||||
default -> unknown : empty;
|
||||
};
|
||||
} &byteorder=littleendian, &let {
|
||||
proc : bool = $context.connection.proc_smb2_negotiate_response(header, this);
|
||||
gssapi_proc : bool = $context.connection.forward_gssapi(security_blob, false);
|
||||
|
|
|
@ -100,6 +100,74 @@ refine connection SMB_Conn += {
|
|||
std::map<uint64,uint64> smb2_request_tree_id;
|
||||
%}
|
||||
|
||||
function BuildSMB2ContextVal(ncv: SMB3_negotiate_context_value): BroVal
|
||||
%{
|
||||
RecordVal* r = new RecordVal(BifType::Record::SMB2::NegotiateContextValue);
|
||||
|
||||
r->Assign(0, val_mgr->GetCount(${ncv.context_type}));
|
||||
r->Assign(1, val_mgr->GetCount(${ncv.data_length}));
|
||||
|
||||
switch ( ${ncv.context_type} ) {
|
||||
case SMB2_PREAUTH_INTEGRITY_CAPABILITIES:
|
||||
{
|
||||
RecordVal* rpreauth = new RecordVal(BifType::Record::SMB2::PreAuthIntegrityCapabilities);
|
||||
rpreauth->Assign(0, val_mgr->GetCount(${ncv.preauth_integrity_capabilities.hash_alg_count}));
|
||||
rpreauth->Assign(1, val_mgr->GetCount(${ncv.preauth_integrity_capabilities.salt_length}));
|
||||
|
||||
VectorVal* ha = new VectorVal(internal_type("index_vec")->AsVectorType());
|
||||
|
||||
for ( int i = 0; i < (${ncv.preauth_integrity_capabilities.hash_alg_count}); ++i )
|
||||
ha->Assign(i, val_mgr->GetCount(${ncv.preauth_integrity_capabilities.hash_alg[i]}));
|
||||
|
||||
rpreauth->Assign(2, ha);
|
||||
rpreauth->Assign(3, bytestring_to_val(${ncv.preauth_integrity_capabilities.salt}));
|
||||
r->Assign(2, rpreauth);
|
||||
}
|
||||
break;
|
||||
|
||||
case SMB2_ENCRYPTION_CAPABILITIES:
|
||||
{
|
||||
RecordVal* rencr = new RecordVal(BifType::Record::SMB2::EncryptionCapabilities);
|
||||
rencr->Assign(0, val_mgr->GetCount(${ncv.encryption_capabilities.cipher_count}));
|
||||
|
||||
VectorVal* c = new VectorVal(internal_type("index_vec")->AsVectorType());
|
||||
|
||||
for ( int i = 0; i < (${ncv.encryption_capabilities.cipher_count}); ++i )
|
||||
c->Assign(i, val_mgr->GetCount(${ncv.encryption_capabilities.ciphers[i]}));
|
||||
|
||||
rencr->Assign(1, c);
|
||||
r->Assign(3, rencr);
|
||||
}
|
||||
break;
|
||||
|
||||
case SMB2_COMPRESSION_CAPABILITIES:
|
||||
{
|
||||
RecordVal* rcomp = new RecordVal(BifType::Record::SMB2::CompressionCapabilities);
|
||||
rcomp->Assign(0, val_mgr->GetCount(${ncv.compression_capabilities.alg_count}));
|
||||
|
||||
VectorVal* c = new VectorVal(internal_type("index_vec")->AsVectorType());
|
||||
|
||||
for ( int i = 0; i < (${ncv.compression_capabilities.alg_count}); ++i )
|
||||
c->Assign(i, val_mgr->GetCount(${ncv.compression_capabilities.algs[i]}));
|
||||
|
||||
rcomp->Assign(1, c);
|
||||
r->Assign(4, rcomp);
|
||||
}
|
||||
break;
|
||||
|
||||
case SMB2_NETNAME_NEGOTIATE_CONTEXT_ID:
|
||||
{
|
||||
r->Assign(5, bytestring_to_val(${ncv.netname_negotiate_context_id.net_name}));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return r;
|
||||
%}
|
||||
|
||||
function BuildSMB2HeaderVal(hdr: SMB2_Header): BroVal
|
||||
%{
|
||||
RecordVal* r = new RecordVal(BifType::Record::SMB2::Header);
|
||||
|
|
|
@ -5,3 +5,9 @@ type SMB1::Header: record;
|
|||
type SMB2::Header: record;
|
||||
type SMB2::GUID: record;
|
||||
type SMB2::FileAttrs: record;
|
||||
|
||||
type SMB2::PreAuthIntegrityCapabilities: record;
|
||||
type SMB2::EncryptionCapabilities: record;
|
||||
type SMB2::CompressionCapabilities: record;
|
||||
type SMB2::NegotiateContextValue: record;
|
||||
type SMB2::NegotiateContextValues: vector;
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
smb2_negotiate_response 192.168.100.168 -> 10.160.67.244:445 [dialect_revision=785, security_mode=3, server_guid=[persistent=5167561042355431755, volatile=7583560952700542861], system_time=1547145849.626981, server_start_time=1540586308.948775, negotiate_context_count=2, negotiate_context_values=[[context_type=1, data_length=38, preauth_info=[hash_alg_count=1, salt_length=32, hash_alg=[1], salt=\x17\xa3\x95(\x0d\x0dt\xecZ\xe5\x0e\x1a\xef\x85\x07]U\x99\x86B\xd0\xeb\xc8\x08\xe0\x0a\xad\x01p\x9a/\xb7], encryption_info=<uninitialized>, compression_info=<uninitialized>, netname=<uninitialized>], [context_type=2, data_length=4, preauth_info=<uninitialized>, encryption_info=[cipher_count=1, ciphers=[1]], compression_info=<uninitialized>, netname=<uninitialized>]]]
|
BIN
testing/btest/Traces/smb/smb311.pcap
Normal file
BIN
testing/btest/Traces/smb/smb311.pcap
Normal file
Binary file not shown.
12
testing/btest/scripts/base/protocols/smb/smb311.test
Normal file
12
testing/btest/scripts/base/protocols/smb/smb311.test
Normal file
|
@ -0,0 +1,12 @@
|
|||
# @TEST-EXEC: bro -b -C -r $TRACES/smb/smb311.pcap %INPUT
|
||||
# @TEST-EXEC: test ! -f dpd.log
|
||||
# @TEST-EXEC: test ! -f weird.log
|
||||
# @TEST-EXEC: btest-diff .stdout
|
||||
|
||||
@load base/protocols/smb
|
||||
|
||||
# Add some tests for SMB3
|
||||
event smb2_negotiate_response(c: connection, hdr: SMB2::Header, nr: SMB2::NegotiateResponse)
|
||||
{
|
||||
print fmt("smb2_negotiate_response %s -> %s:%d %s", c$id$orig_h, c$id$resp_h, c$id$resp_p, nr);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue