SMB fixes and cleanup.

SMB error handling improved. The analyzer isn't destroyed when a problem
is encoutered anymore.  The flowbuffer in the parser is now flushed and
the analyzer is set to resync against an SMB command.  This was needed
because there is some state about open files that is kept within the
parser itself which was being destroyed and that was causing analysis
after content gaps or parse errors to be faulty.  The new mechanism
doesn't detroy the parser so parsing after gaps is improved.

DCE_RPC handling in SMB is improved in the edge case where a drive
mapping isn't seen. There is a new const named SMB::pipe_filenames
which is used as a heuristic for identifying "files" opened on named
pipe shares.  If the share mapping type isn't known and a filename
in this set is found, the share type will change to "PIPE" by
generating an event named "smb_pipe_connect_heuristic".  Reads and
writes to that file will be sent to the DCE_RPC analyzer instead of
to the files framework.

The concept of "unknown" share types has been removed due to the new
heuristic detection of share types.

Some general clean up of how the SMB cmd log is written and when.
This commit is contained in:
Seth Hall 2016-10-31 13:35:47 -04:00
parent a836ece4e6
commit 4f3fe047f4
24 changed files with 126 additions and 125 deletions

View file

@ -2535,6 +2535,13 @@ export {
## The time when the file was last modified.
changed : time &log;
} &log;
## A set of file names used as named pipes over SMB. This
## only comes into play as a heuristic to identify named
## pipes when the drive mapping wasn't seen by Bro.
##
## .. bro:see::smb_pipe_connect_heuristic
const SMB::pipe_filenames: set[string] &redef;
}
module SMB1;

View file

@ -160,7 +160,8 @@ event dce_rpc_response(c: connection, fid: count, opnum: count, stub_len: count)
{
# If there is not an endpoint, there isn't much reason to log.
# This can happen if the request isn't seen.
if ( (c$dce_rpc?$endpoint && c$dce_rpc$endpoint !in ignored_operations)
if ( (c$dce_rpc?$endpoint && c$dce_rpc?$operation &&
c$dce_rpc$endpoint !in ignored_operations)
||
(c$dce_rpc?$endpoint && c$dce_rpc?$operation &&
c$dce_rpc$operation !in ignored_operations[c$dce_rpc$endpoint] &&
@ -195,7 +196,8 @@ event connection_state_remove(c: connection)
}
}
if ( (c$dce_rpc?$endpoint && c$dce_rpc$endpoint !in ignored_operations)
if ( (c$dce_rpc?$endpoint && c$dce_rpc?$operation &&
c$dce_rpc$endpoint !in ignored_operations)
||
(c$dce_rpc?$endpoint && c$dce_rpc?$operation &&
c$dce_rpc$operation !in ignored_operations[c$dce_rpc$endpoint] &&

View file

@ -10,20 +10,18 @@ export {
[0x00000000] = [$id="SUCCESS", $desc="The operation completed successfully."],
} &redef &default=function(i: count):StatusCode { local unknown=fmt("unknown-%d", i); return [$id=unknown, $desc=unknown]; };
## These are files names that are used for special
## cases by the file system and would not be
## considered "normal" files.
const pipe_names: set[string] = {
"\\netdfs",
"\\spoolss",
"\\NETLOGON",
"\\winreg",
"\\lsarpc",
"\\samr",
"\\srvsvc",
## Heuristic detection of named pipes when the pipe
## mapping isn't seen. This variable is defined in
## init-bare.bro.
redef SMB::pipe_filenames = {
"spoolss",
"winreg",
"samr",
"srvsvc",
"netdfs",
"lsarpc",
"wkssvc",
"MsFteWds",
"\\wkssvc",
};
## The UUIDs used by the various RPC endpoints

View file

@ -28,11 +28,6 @@ export {
PRINT_WRITE,
PRINT_OPEN,
PRINT_CLOSE,
UNKNOWN_READ,
UNKNOWN_WRITE,
UNKNOWN_OPEN,
UNKNOWN_CLOSE,
};
## The file actions which are logged.
@ -43,8 +38,6 @@ export {
PRINT_OPEN,
PRINT_CLOSE,
UNKNOWN_OPEN,
} &redef;
## The server response statuses which are *not* logged.
@ -225,7 +218,6 @@ function write_file_log(state: State)
{
local f = state$current_file;
if ( f?$name &&
f$name !in pipe_names &&
f$action in logged_file_actions )
{
# Everything in this if statement is to avoid overlogging
@ -252,6 +244,12 @@ function write_file_log(state: State)
}
}
event smb_pipe_connect_heuristic(c: connection) &priority=5
{
c$smb_state$current_tree$path = "<unknown>";
c$smb_state$current_tree$share_type = "PIPE";
}
event file_state_remove(f: fa_file) &priority=-5
{
if ( f$source != "SMB" )

View file

@ -108,11 +108,6 @@ event smb1_negotiate_response(c: connection, hdr: SMB1::Header, response: SMB1::
event smb1_negotiate_response(c: connection, hdr: SMB1::Header, response: SMB1::NegotiateResponse) &priority=-5
{
if ( SMB::write_cmd_log &&
c$smb_state$current_cmd$status !in SMB::ignored_command_statuses )
{
Log::write(SMB::CMD_LOG, c$smb_state$current_cmd);
}
}
event smb1_tree_connect_andx_request(c: connection, hdr: SMB1::Header, path: string, service: string) &priority=5
@ -141,12 +136,6 @@ event smb1_tree_connect_andx_response(c: connection, hdr: SMB1::Header, service:
event smb1_tree_connect_andx_response(c: connection, hdr: SMB1::Header, service: string, native_file_system: string) &priority=-5
{
Log::write(SMB::MAPPING_LOG, c$smb_state$current_tree);
if ( SMB::write_cmd_log &&
c$smb_state$current_cmd$status !in SMB::ignored_command_statuses )
{
Log::write(SMB::CMD_LOG, c$smb_state$current_cmd);
}
}
event smb1_nt_create_andx_request(c: connection, hdr: SMB1::Header, name: string) &priority=5
@ -192,17 +181,7 @@ event smb1_read_andx_request(c: connection, hdr: SMB1::Header, file_id: count, o
if ( c$smb_state$current_tree?$path && !c$smb_state$current_file?$path )
c$smb_state$current_file$path = c$smb_state$current_tree$path;
# We don't even try to log reads and writes to the files log.
#write_file_log(c$smb_state);
}
event smb1_read_andx_response(c: connection, hdr: SMB1::Header, data_len: count) &priority=5
{
if ( SMB::write_cmd_log &&
c$smb_state$current_cmd$status !in SMB::ignored_command_statuses )
{
Log::write(SMB::CMD_LOG, c$smb_state$current_cmd);
}
SMB::write_file_log(c$smb_state);
}
event smb1_write_andx_request(c: connection, hdr: SMB1::Header, file_id: count, offset: count, data_len: count) &priority=5
@ -281,11 +260,7 @@ event smb1_session_setup_andx_request(c: connection, hdr: SMB1::Header, request:
event smb1_session_setup_andx_response(c: connection, hdr: SMB1::Header, response: SMB1::SessionSetupAndXResponse) &priority=-5
{
if ( SMB::write_cmd_log &&
c$smb_state$current_cmd$status !in SMB::ignored_command_statuses )
{
Log::write(SMB::CMD_LOG, c$smb_state$current_cmd);
}
# No behavior yet.
}
event smb1_transaction_request(c: connection, hdr: SMB1::Header, name: string, sub_cmd: count)

View file

@ -101,13 +101,9 @@ event smb2_negotiate_response(c: connection, hdr: SMB2::Header, response: SMB2::
event smb2_negotiate_response(c: connection, hdr: SMB2::Header, response: SMB2::NegotiateResponse) &priority=5
{
if ( SMB::write_cmd_log &&
c$smb_state$current_cmd$status !in SMB::ignored_command_statuses )
{
Log::write(SMB::CMD_LOG, c$smb_state$current_cmd);
}
# No behavior yet.
}
event smb2_tree_connect_request(c: connection, hdr: SMB2::Header, path: string) &priority=5
{
c$smb_state$current_tree$path = path;
@ -142,7 +138,6 @@ event smb2_create_request(c: connection, hdr: SMB2::Header, name: string) &prior
c$smb_state$current_file$action = SMB::PRINT_OPEN;
break;
default:
#c$smb_state$current_file$action = SMB::UNKNOWN_OPEN;
c$smb_state$current_file$action = SMB::FILE_OPEN;
break;
}
@ -150,6 +145,8 @@ event smb2_create_request(c: connection, hdr: SMB2::Header, name: string) &prior
event smb2_create_response(c: connection, hdr: SMB2::Header, file_id: SMB2::GUID, file_size: count, times: SMB::MACTimes, attrs: SMB2::FileAttrs) &priority=5
{
SMB::set_current_file(c$smb_state, file_id$persistent+file_id$volatile);
c$smb_state$current_file$fid = file_id$persistent+file_id$volatile;
c$smb_state$current_file$size = file_size;
@ -188,13 +185,14 @@ event smb2_read_request(c: connection, hdr: SMB2::Header, file_id: SMB2::GUID, o
c$smb_state$current_file$action = SMB::PRINT_READ;
break;
default:
c$smb_state$current_file$action = SMB::FILE_OPEN;
c$smb_state$current_file$action = SMB::FILE_READ;
break;
}
}
event smb2_read_request(c: connection, hdr: SMB2::Header, file_id: SMB2::GUID, offset: count, length: count) &priority=-5
{
SMB::write_file_log(c$smb_state);
}
event smb2_write_request(c: connection, hdr: SMB2::Header, file_id: SMB2::GUID, offset: count, length: count) &priority=5
@ -213,7 +211,6 @@ event smb2_write_request(c: connection, hdr: SMB2::Header, file_id: SMB2::GUID,
c$smb_state$current_file$action = SMB::PRINT_WRITE;
break;
default:
#c$smb_state$current_file$action = SMB::UNKNOWN_WRITE;
c$smb_state$current_file$action = SMB::FILE_WRITE;
break;
}
@ -221,6 +218,7 @@ event smb2_write_request(c: connection, hdr: SMB2::Header, file_id: SMB2::GUID,
event smb2_write_request(c: connection, hdr: SMB2::Header, file_id: SMB2::GUID, offset: count, length: count) &priority=-5
{
SMB::write_file_log(c$smb_state);
}
event smb2_file_rename(c: connection, hdr: SMB2::Header, file_id: SMB2::GUID, dst_filename: string) &priority=5
@ -254,7 +252,9 @@ event smb2_file_delete(c: connection, hdr: SMB2::Header, file_id: SMB2::GUID, de
if ( ! delete_pending )
{
print "huh...";
# This is weird beause it would mean that someone didn't
# set the delete bit in a delete request.
return;
}
switch ( c$smb_state$current_tree$share_type )
@ -289,7 +289,6 @@ event smb2_close_request(c: connection, hdr: SMB2::Header, file_id: SMB2::GUID)
c$smb_state$current_file$action = SMB::PRINT_CLOSE;
break;
default:
#c$smb_state$current_file$action = SMB::UNKNOWN_CLOSE;
c$smb_state$current_file$action = SMB::FILE_CLOSE;
break;
}