mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
smb/dce-rpc: Cleanup DCE-RPC analyzers when fid is closed and limit them
This patch does two things: 1) For SMB close requests, tear down any associated DCE-RPC analyzer if one exists. 2) Protect from fid_to_analyzer_map growing unbounded by introducing a new SMB::max_dce_rpc_analyzers limit and forcefully wipe the analyzers if exceeded. Propagate this to script land as event smb_discarded_dce_rpc_analyzers() for additional cleanup. This is mostly to fix how the binpac SMB analyzer tracks individual DCE-RPC analyzers per open fid. Connections that re-open the same or different pipe may currently allocate unbounded number of analyzers. Closes #3145.
This commit is contained in:
parent
1c9038f38d
commit
6517ed94f2
7 changed files with 61 additions and 1 deletions
|
@ -211,6 +211,7 @@ export {
|
||||||
["spontaneous_RST"] = ACTION_IGNORE,
|
["spontaneous_RST"] = ACTION_IGNORE,
|
||||||
["SMB_parsing_error"] = ACTION_LOG,
|
["SMB_parsing_error"] = ACTION_LOG,
|
||||||
["SMB_discarded_messages_state"] = ACTION_LOG,
|
["SMB_discarded_messages_state"] = ACTION_LOG,
|
||||||
|
["SMB_discarded_dce_rpc_analyzers"] = ACTION_LOG,
|
||||||
["no_smb_session_using_parsesambamsg"] = ACTION_LOG,
|
["no_smb_session_using_parsesambamsg"] = ACTION_LOG,
|
||||||
["smb_andx_command_failed_to_parse"] = ACTION_LOG,
|
["smb_andx_command_failed_to_parse"] = ACTION_LOG,
|
||||||
["smb_tree_connect_andx_response_without_tree"] = ACTION_LOG_PER_CONN,
|
["smb_tree_connect_andx_response_without_tree"] = ACTION_LOG_PER_CONN,
|
||||||
|
|
|
@ -3054,6 +3054,12 @@ export {
|
||||||
##
|
##
|
||||||
## .. zeek:see:: smb2_discarded_messages_state
|
## .. zeek:see:: smb2_discarded_messages_state
|
||||||
const SMB::max_pending_messages = 1000 &redef;
|
const SMB::max_pending_messages = 1000 &redef;
|
||||||
|
|
||||||
|
## Maximum number of DCE-RPC analyzers per connection
|
||||||
|
## before discarding them to avoid unbounded state growth.
|
||||||
|
##
|
||||||
|
## .. zeek:see:: smb_discarded_dce_rpc_analyzers
|
||||||
|
const max_dce_rpc_analyzers = 1000 &redef;
|
||||||
}
|
}
|
||||||
|
|
||||||
module SMB1;
|
module SMB1;
|
||||||
|
|
|
@ -216,6 +216,15 @@ event dce_rpc_response(c: connection, fid: count, ctx_id: count, opnum: count, s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
event smb_discarded_dce_rpc_analyzers(c: connection)
|
||||||
|
{
|
||||||
|
# This event is raised when the DCE-RPC analyzers table
|
||||||
|
# grew too large. Assume things are broken and wipe
|
||||||
|
# the backing table.
|
||||||
|
delete c$dce_rpc_backing;
|
||||||
|
Reporter::conn_weird("SMB_discarded_dce_rpc_analyzers", c, "", "SMB");
|
||||||
|
}
|
||||||
|
|
||||||
hook finalize_dce_rpc(c: connection)
|
hook finalize_dce_rpc(c: connection)
|
||||||
{
|
{
|
||||||
if ( ! c?$dce_rpc )
|
if ( ! c?$dce_rpc )
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
const SMB::pipe_filenames: string_set;
|
const SMB::pipe_filenames: string_set;
|
||||||
const SMB::max_pending_messages: count;
|
const SMB::max_pending_messages: count;
|
||||||
|
const SMB::max_dce_rpc_analyzers: count;
|
||||||
|
|
|
@ -8,3 +8,13 @@
|
||||||
##
|
##
|
||||||
## c: The connection.
|
## c: The connection.
|
||||||
event smb_pipe_connect_heuristic%(c: connection%);
|
event smb_pipe_connect_heuristic%(c: connection%);
|
||||||
|
|
||||||
|
## Generated for :abbr:`SMB (Server Message Block)` when the number of
|
||||||
|
## :abbr:`DCE-RPC (Distributed Computing Environment/Remote Procedure Calls)`
|
||||||
|
## analyzers exceeds :zeek:see:`SMB::max_dce_rpc_analyzers`.
|
||||||
|
## Occurrence of this event may indicate traffic loss, traffic load-balancing
|
||||||
|
## issues or abnormal SMB protocol usage.
|
||||||
|
##
|
||||||
|
## c: The connection.
|
||||||
|
##
|
||||||
|
event smb_discarded_dce_rpc_analyzers%(c: connection%);
|
||||||
|
|
|
@ -10,7 +10,7 @@ refine connection SMB_Conn += {
|
||||||
|
|
||||||
%cleanup{
|
%cleanup{
|
||||||
// Iterate all of the analyzers and destroy them.
|
// Iterate all of the analyzers and destroy them.
|
||||||
for ( auto kv : fid_to_analyzer_map )
|
for ( const auto& kv : fid_to_analyzer_map )
|
||||||
{
|
{
|
||||||
if ( kv.second )
|
if ( kv.second )
|
||||||
{
|
{
|
||||||
|
@ -49,6 +49,22 @@ refine connection SMB_Conn += {
|
||||||
|
|
||||||
if ( it == fid_to_analyzer_map.end() )
|
if ( it == fid_to_analyzer_map.end() )
|
||||||
{
|
{
|
||||||
|
// Too many analyzers?
|
||||||
|
if ( zeek::BifConst::SMB::max_dce_rpc_analyzers > 0 &&
|
||||||
|
fid_to_analyzer_map.size() >= zeek::BifConst::SMB::max_dce_rpc_analyzers )
|
||||||
|
{
|
||||||
|
if ( smb_discarded_dce_rpc_analyzers )
|
||||||
|
zeek::BifEvent::enqueue_smb_discarded_dce_rpc_analyzers(zeek_analyzer(), zeek_analyzer()->Conn());
|
||||||
|
|
||||||
|
for ( const auto& kv : fid_to_analyzer_map )
|
||||||
|
{
|
||||||
|
kv.second->Done();
|
||||||
|
delete kv.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
fid_to_analyzer_map.clear();
|
||||||
|
}
|
||||||
|
|
||||||
auto tmp_analyzer = zeek::analyzer_mgr->InstantiateAnalyzer("DCE_RPC", zeek_analyzer()->Conn());
|
auto tmp_analyzer = zeek::analyzer_mgr->InstantiateAnalyzer("DCE_RPC", zeek_analyzer()->Conn());
|
||||||
pipe_dcerpc = static_cast<zeek::analyzer::dce_rpc::DCE_RPC_Analyzer *>(tmp_analyzer);
|
pipe_dcerpc = static_cast<zeek::analyzer::dce_rpc::DCE_RPC_Analyzer *>(tmp_analyzer);
|
||||||
|
|
||||||
|
@ -68,4 +84,19 @@ refine connection SMB_Conn += {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
function forward_dce_rpc_close(fid: uint64): bool
|
||||||
|
%{
|
||||||
|
auto it = fid_to_analyzer_map.find(fid);
|
||||||
|
|
||||||
|
if ( it != fid_to_analyzer_map.end() )
|
||||||
|
{
|
||||||
|
it->second->Done();
|
||||||
|
delete it->second;
|
||||||
|
fid_to_analyzer_map.erase(it);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
%}
|
||||||
};
|
};
|
||||||
|
|
|
@ -46,7 +46,9 @@ type SMB2_close_request(header: SMB2_Header) = record {
|
||||||
reserved : uint32;
|
reserved : uint32;
|
||||||
file_id : SMB2_guid;
|
file_id : SMB2_guid;
|
||||||
} &let {
|
} &let {
|
||||||
|
fid: uint64 = file_id.persistent + file_id._volatile;
|
||||||
proc: bool = $context.connection.proc_smb2_close_request(header, this);
|
proc: bool = $context.connection.proc_smb2_close_request(header, this);
|
||||||
|
maybe_pipe_close: bool = $context.connection.forward_dce_rpc_close(fid);
|
||||||
};
|
};
|
||||||
|
|
||||||
type SMB2_close_response(header: SMB2_Header) = record {
|
type SMB2_close_response(header: SMB2_Header) = record {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue