mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +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,
|
||||
["SMB_parsing_error"] = ACTION_LOG,
|
||||
["SMB_discarded_messages_state"] = ACTION_LOG,
|
||||
["SMB_discarded_dce_rpc_analyzers"] = ACTION_LOG,
|
||||
["no_smb_session_using_parsesambamsg"] = ACTION_LOG,
|
||||
["smb_andx_command_failed_to_parse"] = ACTION_LOG,
|
||||
["smb_tree_connect_andx_response_without_tree"] = ACTION_LOG_PER_CONN,
|
||||
|
|
|
@ -3054,6 +3054,12 @@ export {
|
|||
##
|
||||
## .. zeek:see:: smb2_discarded_messages_state
|
||||
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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
if ( ! c?$dce_rpc )
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
const SMB::pipe_filenames: string_set;
|
||||
const SMB::max_pending_messages: count;
|
||||
const SMB::max_dce_rpc_analyzers: count;
|
||||
|
|
|
@ -8,3 +8,13 @@
|
|||
##
|
||||
## c: The 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{
|
||||
// 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 )
|
||||
{
|
||||
|
@ -49,6 +49,22 @@ refine connection SMB_Conn += {
|
|||
|
||||
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());
|
||||
pipe_dcerpc = static_cast<zeek::analyzer::dce_rpc::DCE_RPC_Analyzer *>(tmp_analyzer);
|
||||
|
||||
|
@ -68,4 +84,19 @@ refine connection SMB_Conn += {
|
|||
|
||||
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;
|
||||
file_id : SMB2_guid;
|
||||
} &let {
|
||||
fid: uint64 = file_id.persistent + file_id._volatile;
|
||||
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 {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue