From 8276c250bd931062b921a5d635945d27812fc19b Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Tue, 25 Oct 2016 02:52:09 -0400 Subject: [PATCH 1/7] Updates for SMB auth handling from Martin van Hensbergen. - Raw NTLM (not in GSSAPI) over SMB is now handled correctly. - The encrypted NTLM session key is now passed into scriptland through the ntlm_authenticate event. --- scripts/base/init-bare.bro | 8 +++--- src/analyzer/protocol/ntlm/ntlm-analyzer.pac | 5 +++- src/analyzer/protocol/ntlm/ntlm-protocol.pac | 2 +- src/analyzer/protocol/smb/smb-gssapi.pac | 27 ++++++++++++++++++-- 4 files changed, 35 insertions(+), 7 deletions(-) diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro index 1f15a3fe81..a898ceb88c 100644 --- a/scripts/base/init-bare.bro +++ b/scripts/base/init-bare.bro @@ -2505,11 +2505,13 @@ export { ## The negotiate flags flags : NTLM::NegotiateFlags; ## The domain or computer name hosting the account - domain_name : string; + domain_name : string &optional; ## The name of the user to be authenticated. - user_name : string; + user_name : string &optional; ## The name of the computer to which the user was logged on. - workstation : string; + workstation : string &optional; + ## The session key + session_key : string &optional; ## The Windows version information, if supplied version : NTLM::Version &optional; }; diff --git a/src/analyzer/protocol/ntlm/ntlm-analyzer.pac b/src/analyzer/protocol/ntlm/ntlm-analyzer.pac index e1850f8b45..55756b61e9 100644 --- a/src/analyzer/protocol/ntlm/ntlm-analyzer.pac +++ b/src/analyzer/protocol/ntlm/ntlm-analyzer.pac @@ -148,8 +148,11 @@ refine connection NTLM_Conn += { if ( ${val}->has_workstation() > 0 ) result->Assign(3, utf16_bytestring_to_utf8_val(bro_analyzer()->Conn(), ${val.workstation.string.data})); + if ( ${val}->has_encrypted_session_key() > 0 ) + result->Assign(4, bytestring_to_val(${val.encrypted_session_key.string.data})); + if ( ${val}->has_version() ) - result->Assign(4, build_version_record(${val.version})); + result->Assign(5, build_version_record(${val.version})); BifEvent::generate_ntlm_authenticate(bro_analyzer(), bro_analyzer()->Conn(), diff --git a/src/analyzer/protocol/ntlm/ntlm-protocol.pac b/src/analyzer/protocol/ntlm/ntlm-protocol.pac index c553330760..8862be1f22 100644 --- a/src/analyzer/protocol/ntlm/ntlm-protocol.pac +++ b/src/analyzer/protocol/ntlm/ntlm-protocol.pac @@ -61,7 +61,7 @@ type NTLM_Authenticate(offset: uint16) = record { domain_name : NTLM_String(domain_name_fields, absolute_offset, flags.negotiate_unicode) withinput payload &if(domain_name_fields.length > 0); user_name : NTLM_String(user_name_fields, absolute_offset, flags.negotiate_unicode) withinput payload &if(user_name_fields.length > 0); workstation : NTLM_String(workstation_fields, absolute_offset , flags.negotiate_unicode) withinput payload &if(workstation_fields.length > 0); - encrypted_session_key : NTLM_String(encrypted_session_key_fields, absolute_offset, flags.negotiate_unicode) withinput payload &if(flags.negotiate_key_exch); + encrypted_session_key : NTLM_String(encrypted_session_key_fields, absolute_offset, flags.negotiate_unicode) withinput payload &if(encrypted_session_key_fields.length > 0); }; type NTLM_Version = record { diff --git a/src/analyzer/protocol/smb/smb-gssapi.pac b/src/analyzer/protocol/smb/smb-gssapi.pac index 0a933e8286..2bde6e9e8f 100644 --- a/src/analyzer/protocol/smb/smb-gssapi.pac +++ b/src/analyzer/protocol/smb/smb-gssapi.pac @@ -2,10 +2,12 @@ refine connection SMB_Conn += { %member{ analyzer::Analyzer *gssapi; + analyzer::Analyzer *ntlm; %} %init{ gssapi = 0; + ntlm = 0; %} %cleanup{ @@ -14,6 +16,12 @@ refine connection SMB_Conn += { gssapi->Done(); delete gssapi; } + + if ( ntlm ) + { + ntlm->Done(); + delete ntlm; + } %} function forward_gssapi(data: bytestring, is_orig: bool): bool @@ -21,9 +29,24 @@ refine connection SMB_Conn += { if ( ! gssapi ) gssapi = analyzer_mgr->InstantiateAnalyzer("GSSAPI", bro_analyzer()->Conn()); - if ( gssapi ) - gssapi->DeliverStream(${data}.length(), ${data}.begin(), is_orig); + if ( ! ntlm ) + ntlm = analyzer_mgr->InstantiateAnalyzer("NTLM", bro_analyzer()->Conn()); + // SMB allows raw NTLM instead of GSSAPI in certain messages. + // We check if this is the case and run the NTLM analyzer directly. + if ( ${data}.length() >= 8 ) + { + if ( strncmp((const char*)${data}.begin(), "NTLMSSP",7) == 0 ) + { + if ( ntlm ) + ntlm->DeliverStream(${data}.length(), ${data}.begin(), is_orig); + } + else + { + if ( gssapi ) + gssapi->DeliverStream(${data}.length(), ${data}.begin(), is_orig); + } + } return true; %} }; From a836ece4e634181f28d966b0695e8072b8b79dea Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Wed, 26 Oct 2016 10:41:08 -0400 Subject: [PATCH 2/7] Including a test for raw NTLM in SMB --- .../scripts.base.protocols.smb.raw-ntlm/.stdout | 1 + testing/btest/Traces/smb/raw_ntlm_in_smb.pcap | Bin 0 -> 27214 bytes .../scripts/base/protocols/smb/raw-ntlm.test | 14 ++++++++++++++ 3 files changed, 15 insertions(+) create mode 100644 testing/btest/Baseline/scripts.base.protocols.smb.raw-ntlm/.stdout create mode 100644 testing/btest/Traces/smb/raw_ntlm_in_smb.pcap create mode 100644 testing/btest/scripts/base/protocols/smb/raw-ntlm.test diff --git a/testing/btest/Baseline/scripts.base.protocols.smb.raw-ntlm/.stdout b/testing/btest/Baseline/scripts.base.protocols.smb.raw-ntlm/.stdout new file mode 100644 index 0000000000..054c38f738 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.smb.raw-ntlm/.stdout @@ -0,0 +1 @@ +\xebr\x96\x86\xfc\xaa\xcf\xad\xb14\x18\xfaIG`\xde diff --git a/testing/btest/Traces/smb/raw_ntlm_in_smb.pcap b/testing/btest/Traces/smb/raw_ntlm_in_smb.pcap new file mode 100644 index 0000000000000000000000000000000000000000..8a40175db43205065dfbccfc3d006cf7146778de GIT binary patch literal 27214 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 PH_u1DLe^5pnQi<(yueRy literal 0 HcmV?d00001 diff --git a/testing/btest/scripts/base/protocols/smb/raw-ntlm.test b/testing/btest/scripts/base/protocols/smb/raw-ntlm.test new file mode 100644 index 0000000000..6e09ef7ded --- /dev/null +++ b/testing/btest/scripts/base/protocols/smb/raw-ntlm.test @@ -0,0 +1,14 @@ +#@TEST-EXEC: bro -b -C -r $TRACES/smb/raw_ntlm_in_smb.pcap %INPUT +#@TEST-EXEC: btest-diff .stdout + +@load base/protocols/ntlm +@load policy/protocols/smb + +# Just verify that the session key is grabbed correctly from NTLM +# carried raw over SMB. + +event ntlm_authenticate(c: connection, request: NTLM::Authenticate) + { + if ( request?$session_key ) + print request$session_key; + } \ No newline at end of file From 4f3fe047f4638adf09797ccb5d6737437fe27ff7 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Mon, 31 Oct 2016 13:35:47 -0400 Subject: [PATCH 3/7] 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. --- scripts/base/init-bare.bro | 7 +++++ scripts/base/protocols/dce-rpc/main.bro | 6 ++-- scripts/base/protocols/smb/consts.bro | 22 +++++++------- scripts/policy/protocols/smb/main.bro | 14 ++++----- scripts/policy/protocols/smb/smb1-main.bro | 29 ++----------------- scripts/policy/protocols/smb/smb2-main.bro | 21 +++++++------- src/analyzer/protocol/smb/CMakeLists.txt | 3 ++ src/analyzer/protocol/smb/SMB.cc | 25 +++++++++------- src/analyzer/protocol/smb/SMB.h | 7 ++--- src/analyzer/protocol/smb/consts.bif | 1 + src/analyzer/protocol/smb/events.bif | 10 +++++++ src/analyzer/protocol/smb/smb-pipe.pac | 8 ++--- src/analyzer/protocol/smb/smb.pac | 2 ++ src/analyzer/protocol/smb/smb1-com-close.pac | 10 ++----- .../protocol/smb/smb1-com-nt-create-andx.pac | 24 +++++++++------ .../protocol/smb/smb1-com-read-andx.pac | 5 ++-- .../protocol/smb/smb1-com-write-andx.pac | 5 ++-- src/analyzer/protocol/smb/smb1-protocol.pac | 3 +- src/analyzer/protocol/smb/smb2-com-close.pac | 3 ++ src/analyzer/protocol/smb/smb2-com-create.pac | 23 +++++++++------ src/analyzer/protocol/smb/smb2-com-read.pac | 5 ++-- src/analyzer/protocol/smb/smb2-com-write.pac | 5 ++-- src/analyzer/protocol/smb/smb2-protocol.pac | 7 +++-- .../scripts.base.protocols.smb.smb2/files.log | 6 ++-- 24 files changed, 126 insertions(+), 125 deletions(-) create mode 100644 src/analyzer/protocol/smb/consts.bif create mode 100644 src/analyzer/protocol/smb/events.bif diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro index a898ceb88c..b8ebb9677e 100644 --- a/scripts/base/init-bare.bro +++ b/scripts/base/init-bare.bro @@ -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; diff --git a/scripts/base/protocols/dce-rpc/main.bro b/scripts/base/protocols/dce-rpc/main.bro index 5ec5ded2d8..c0e36624d2 100644 --- a/scripts/base/protocols/dce-rpc/main.bro +++ b/scripts/base/protocols/dce-rpc/main.bro @@ -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] && diff --git a/scripts/base/protocols/smb/consts.bro b/scripts/base/protocols/smb/consts.bro index 86c470024c..b74b75fb37 100644 --- a/scripts/base/protocols/smb/consts.bro +++ b/scripts/base/protocols/smb/consts.bro @@ -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 diff --git a/scripts/policy/protocols/smb/main.bro b/scripts/policy/protocols/smb/main.bro index 0399e92a9a..61a2548f6c 100644 --- a/scripts/policy/protocols/smb/main.bro +++ b/scripts/policy/protocols/smb/main.bro @@ -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 = ""; + c$smb_state$current_tree$share_type = "PIPE"; + } + event file_state_remove(f: fa_file) &priority=-5 { if ( f$source != "SMB" ) diff --git a/scripts/policy/protocols/smb/smb1-main.bro b/scripts/policy/protocols/smb/smb1-main.bro index c1b8ead509..3e7f43cf45 100644 --- a/scripts/policy/protocols/smb/smb1-main.bro +++ b/scripts/policy/protocols/smb/smb1-main.bro @@ -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) diff --git a/scripts/policy/protocols/smb/smb2-main.bro b/scripts/policy/protocols/smb/smb2-main.bro index 31b3abf0db..041813b99e 100644 --- a/scripts/policy/protocols/smb/smb2-main.bro +++ b/scripts/policy/protocols/smb/smb2-main.bro @@ -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; } diff --git a/src/analyzer/protocol/smb/CMakeLists.txt b/src/analyzer/protocol/smb/CMakeLists.txt index 2ea745d51d..844eca4cd4 100644 --- a/src/analyzer/protocol/smb/CMakeLists.txt +++ b/src/analyzer/protocol/smb/CMakeLists.txt @@ -37,6 +37,9 @@ bro_plugin_bif( smb2_com_write.bif smb2_events.bif + events.bif + consts.bif + types.bif) bro_plugin_pac( smb.pac diff --git a/src/analyzer/protocol/smb/SMB.cc b/src/analyzer/protocol/smb/SMB.cc index da202f5269..d886421906 100644 --- a/src/analyzer/protocol/smb/SMB.cc +++ b/src/analyzer/protocol/smb/SMB.cc @@ -10,7 +10,8 @@ SMB_Analyzer::SMB_Analyzer(Connection *conn) : tcp::TCP_ApplicationAnalyzer("SMB", conn) { chunks=0; - interp=0; + interp = new binpac::SMB::SMB_Conn(this); + need_sync=true; } SMB_Analyzer::~SMB_Analyzer() @@ -54,24 +55,28 @@ bool SMB_Analyzer::HasSMBHeader(int len, const u_char* data) strncmp((const char*) data+4, "\xfeSMB", 4) == 0); } +void SMB_Analyzer::NeedResync() + { + interp->upflow()->flow_buffer()->DiscardData(); + interp->downflow()->flow_buffer()->DiscardData(); + need_sync=true; + } + void SMB_Analyzer::DeliverStream(int len, const u_char* data, bool orig) { TCP_ApplicationAnalyzer::DeliverStream(len, data, orig); assert(TCP()); - // Either instantiate an interpreter or bail. - if ( ! interp ) - { - if ( HasSMBHeader(len, data) ) - interp = new binpac::SMB::SMB_Conn(this); - else - return; - } + // It we need to resync and we don't have an SMB header, bail! + if ( need_sync && ! HasSMBHeader(len, data) ) + return; + else + need_sync=false; try { - // If we get here, it means we have an interpreter. + // If we get here, it means we have an SMB header in the message. interp->NewData(orig, data, data + len); // Let's assume that if there are no binpac exceptions after diff --git a/src/analyzer/protocol/smb/SMB.h b/src/analyzer/protocol/smb/SMB.h index 2edeecf506..ea9ec2e6a5 100644 --- a/src/analyzer/protocol/smb/SMB.h +++ b/src/analyzer/protocol/smb/SMB.h @@ -17,10 +17,7 @@ public: void EndpointEOF(bool is_orig) override; bool HasSMBHeader(int len, const u_char* data); - void NeedResync() { - delete interp; - interp = 0; - } + void NeedResync(); static analyzer::Analyzer* Instantiate(Connection* conn) { return new SMB_Analyzer(conn); } @@ -31,6 +28,8 @@ protected: // Count the number of chunks received by the analyzer // but only used to count the first few. uint8 chunks; + + bool need_sync; }; } } // namespace analyzer::* diff --git a/src/analyzer/protocol/smb/consts.bif b/src/analyzer/protocol/smb/consts.bif new file mode 100644 index 0000000000..321875b43d --- /dev/null +++ b/src/analyzer/protocol/smb/consts.bif @@ -0,0 +1 @@ +const SMB::pipe_filenames: string_set; \ No newline at end of file diff --git a/src/analyzer/protocol/smb/events.bif b/src/analyzer/protocol/smb/events.bif new file mode 100644 index 0000000000..0ecf6e91c7 --- /dev/null +++ b/src/analyzer/protocol/smb/events.bif @@ -0,0 +1,10 @@ +## Generated for :abbr:`SMB (Server Message Block)` connections when a +## named pipe has been detected heuristically. The case when this comes +## up is when the drive mapping isn't seen so the analyzer is not able +## to determine whether to send the data to the files framework or to +## the DCE_RPC analyzer. This heuristic can be tuned by adding or +## removing "named pipe" names from the :bro:see:`SMB::pipe_filenames` +## const. +## +## c: The connection. +event smb_pipe_connect_heuristic%(c: connection%); diff --git a/src/analyzer/protocol/smb/smb-pipe.pac b/src/analyzer/protocol/smb/smb-pipe.pac index 5c32f1f17c..bcc910e19a 100644 --- a/src/analyzer/protocol/smb/smb-pipe.pac +++ b/src/analyzer/protocol/smb/smb-pipe.pac @@ -5,7 +5,7 @@ refine connection SMB_Conn += { %member{ map tree_is_pipe_map; - map fid_to_analyzer_map;; + map fid_to_analyzer_map; %} %cleanup{ @@ -20,13 +20,9 @@ refine connection SMB_Conn += { } %} - function get_tree_is_pipe(tree_id: uint16): bool %{ - if ( tree_is_pipe_map.count(tree_id) > 0 ) - return tree_is_pipe_map.at(tree_id); - else - return false; + return ( tree_is_pipe_map.count(tree_id) > 0 ); %} function set_tree_is_pipe(tree_id: uint16, is_pipe: bool): bool diff --git a/src/analyzer/protocol/smb/smb.pac b/src/analyzer/protocol/smb/smb.pac index e0dffd2484..cdb0f04236 100644 --- a/src/analyzer/protocol/smb/smb.pac +++ b/src/analyzer/protocol/smb/smb.pac @@ -9,6 +9,8 @@ #include "smb2_events.bif.h" #include "types.bif.h" +#include "events.bif.h" +#include "consts.bif.h" #include "smb1_com_check_directory.bif.h" #include "smb1_com_close.bif.h" diff --git a/src/analyzer/protocol/smb/smb1-com-close.pac b/src/analyzer/protocol/smb/smb1-com-close.pac index 4aa6c5c3a0..092f8f4020 100644 --- a/src/analyzer/protocol/smb/smb1-com-close.pac +++ b/src/analyzer/protocol/smb/smb1-com-close.pac @@ -8,14 +8,8 @@ refine connection SMB_Conn += { BuildHeaderVal(h), ${val.file_id}); - // This is commented out for the moment because it caused problems - // with extraction because the file kept having the same name due - // to repeatedly having the same file uid. This results in files - // effectively falling of SMB solely by expiration instead of - // manually being closed. - - //file_mgr->EndOfFile(bro_analyzer()->GetAnalyzerTag(), - // bro_analyzer()->Conn(), h->is_orig()); + file_mgr->EndOfFile(bro_analyzer()->GetAnalyzerTag(), + bro_analyzer()->Conn(), h->is_orig()); return true; %} diff --git a/src/analyzer/protocol/smb/smb1-com-nt-create-andx.pac b/src/analyzer/protocol/smb/smb1-com-nt-create-andx.pac index 36a583696e..d71086a44b 100644 --- a/src/analyzer/protocol/smb/smb1-com-nt-create-andx.pac +++ b/src/analyzer/protocol/smb/smb1-com-nt-create-andx.pac @@ -1,13 +1,27 @@ refine connection SMB_Conn += { function proc_smb1_nt_create_andx_request(header: SMB_Header, val: SMB1_nt_create_andx_request): bool %{ + StringVal *filename = smb_string2stringval(${val.filename}); + if ( ! ${header.is_pipe} && + BifConst::SMB::pipe_filenames->AsTable()->Lookup(filename->CheckString()) ) + { + set_tree_is_pipe(${header.tid}, true); + BifEvent::generate_smb_pipe_connect_heuristic(bro_analyzer(), + bro_analyzer()->Conn()); + } + if ( smb1_nt_create_andx_request ) { BifEvent::generate_smb1_nt_create_andx_request(bro_analyzer(), bro_analyzer()->Conn(), BuildHeaderVal(header), - smb_string2stringval(${val.filename})); + filename); } + else + { + delete filename; + } + return true; %} @@ -26,14 +40,6 @@ refine connection SMB_Conn += { ${val.last_change_time})); } - if ( ${val.end_of_file} > 0 ) - { - //file_mgr->SetSize(${val.end_of_file}, - // bro_analyzer()->GetAnalyzerTag(), - // bro_analyzer()->Conn(), - // header->is_orig()); - } - return true; %} diff --git a/src/analyzer/protocol/smb/smb1-com-read-andx.pac b/src/analyzer/protocol/smb/smb1-com-read-andx.pac index 89e367206d..712ad8948b 100644 --- a/src/analyzer/protocol/smb/smb1-com-read-andx.pac +++ b/src/analyzer/protocol/smb/smb1-com-read-andx.pac @@ -28,7 +28,7 @@ refine connection SMB_Conn += { BuildHeaderVal(h), ${val.data_len}); - if ( ! ${val.is_pipe} && ${val.data_len} > 0 ) + if ( ! ${h.is_pipe} && ${val.data_len} > 0 ) { uint64 offset = read_offsets[${h.mid}]; read_offsets.erase(${h.mid}); @@ -93,8 +93,7 @@ type SMB1_read_andx_response(header: SMB_Header, offset: uint16) = record { andx_command : SMB_andx_command(header, 0, offset+offsetof(andx_command), andx.command); } &let { - is_pipe : bool = $context.connection.get_tree_is_pipe(header.tid); - pipe_proc : bool = $context.connection.forward_dce_rpc(data, 0, false) &if(is_pipe); + pipe_proc : bool = $context.connection.forward_dce_rpc(data, 0, false) &if(header.is_pipe); padding_len : uint8 = (header.unicode == 1) ? 1 : 0; data_len : uint32 = (data_len_high << 16) + data_len_low; diff --git a/src/analyzer/protocol/smb/smb1-com-write-andx.pac b/src/analyzer/protocol/smb/smb1-com-write-andx.pac index 79d36c52b5..8b4eed7056 100644 --- a/src/analyzer/protocol/smb/smb1-com-write-andx.pac +++ b/src/analyzer/protocol/smb/smb1-com-write-andx.pac @@ -10,7 +10,7 @@ refine connection SMB_Conn += { ${val.write_offset}, ${val.data_len}); - if ( ! ${val.is_pipe} && ${val.data}.length() > 0 ) + if ( ! ${h.is_pipe} && ${val.data}.length() > 0 ) { file_mgr->DataIn(${val.data}.begin(), ${val.data}.length(), ${val.write_offset}, @@ -58,8 +58,7 @@ type SMB1_write_andx_request(header: SMB_Header, offset: uint16) = record { andx_command : SMB_andx_command(header, 1, offset+offsetof(andx_command), andx.command); } &let { - is_pipe : bool = $context.connection.get_tree_is_pipe(header.tid); - pipe_proc : bool = $context.connection.forward_dce_rpc(data, 0, true) &if(is_pipe); + pipe_proc : bool = $context.connection.forward_dce_rpc(data, 0, true) &if(header.is_pipe); data_len : uint32 = (data_len_high << 16) + data_len_low; offset_high : uint32 = (word_count == 0x0E) ? offset_high_tmp : 0; diff --git a/src/analyzer/protocol/smb/smb1-protocol.pac b/src/analyzer/protocol/smb/smb1-protocol.pac index b7ad6af140..985e67c068 100644 --- a/src/analyzer/protocol/smb/smb1-protocol.pac +++ b/src/analyzer/protocol/smb/smb1-protocol.pac @@ -298,7 +298,8 @@ type SMB_Header(is_orig: bool) = record { err_status_type = (flags2 >> 14) & 1; unicode = (flags2 >> 15) & 1; pid = (pid_high * 0x10000) + pid_low; - proc : bool = $context.connection.proc_smb_message(this, is_orig); + is_pipe: bool = $context.connection.get_tree_is_pipe(tid); + proc : bool = $context.connection.proc_smb_message(this, is_orig); } &byteorder=littleendian; # TODO: compute this as diff --git a/src/analyzer/protocol/smb/smb2-com-close.pac b/src/analyzer/protocol/smb/smb2-com-close.pac index bb3b1bab49..0c90897d84 100644 --- a/src/analyzer/protocol/smb/smb2-com-close.pac +++ b/src/analyzer/protocol/smb/smb2-com-close.pac @@ -10,6 +10,9 @@ refine connection SMB_Conn += { BuildSMB2GUID(${val.file_id})); } + file_mgr->EndOfFile(bro_analyzer()->GetAnalyzerTag(), + bro_analyzer()->Conn(), h->is_orig()); + return true; %} diff --git a/src/analyzer/protocol/smb/smb2-com-create.pac b/src/analyzer/protocol/smb/smb2-com-create.pac index 0072e75adf..5e35d8e975 100644 --- a/src/analyzer/protocol/smb/smb2-com-create.pac +++ b/src/analyzer/protocol/smb/smb2-com-create.pac @@ -2,12 +2,25 @@ refine connection SMB_Conn += { function proc_smb2_create_request(h: SMB2_Header, val: SMB2_create_request): bool %{ + StringVal *filename = smb2_string2stringval(${val.filename}); + if ( ! ${h.is_pipe} && + BifConst::SMB::pipe_filenames->AsTable()->Lookup(filename->CheckString()) ) + { + set_tree_is_pipe(${h.tree_id}, true); + BifEvent::generate_smb_pipe_connect_heuristic(bro_analyzer(), + bro_analyzer()->Conn()); + } + if ( smb2_create_request ) { BifEvent::generate_smb2_create_request(bro_analyzer(), bro_analyzer()->Conn(), BuildSMB2HeaderVal(h), - smb2_string2stringval(${val.filename})); + filename); + } + else + { + delete filename; } return true; @@ -29,14 +42,6 @@ refine connection SMB_Conn += { smb2_file_attrs_to_bro(${val.file_attrs})); } - if ( ${val.eof} > 0 ) - { - //file_mgr->SetSize(${val.eof}, - // bro_analyzer()->GetAnalyzerTag(), - // bro_analyzer()->Conn(), - // h->is_orig()); - } - return true; %} }; diff --git a/src/analyzer/protocol/smb/smb2-com-read.pac b/src/analyzer/protocol/smb/smb2-com-read.pac index 1fa409a5f0..cf5d2ae065 100644 --- a/src/analyzer/protocol/smb/smb2-com-read.pac +++ b/src/analyzer/protocol/smb/smb2-com-read.pac @@ -42,7 +42,7 @@ refine connection SMB_Conn += { uint64 offset = smb2_read_offsets[${h.message_id}]; smb2_read_offsets.erase(${h.message_id}); - if ( ! ${val.is_pipe} && ${val.data_len} > 0 ) + if ( ! ${h.is_pipe} && ${val.data_len} > 0 ) { file_mgr->DataIn(${val.data}.begin(), ${val.data_len}, offset, bro_analyzer()->GetAnalyzerTag(), @@ -83,9 +83,8 @@ type SMB2_read_response(header: SMB2_Header) = record { pad : padding to data_offset - header.head_length; data : bytestring &length=data_len; } &let { - is_pipe : bool = $context.connection.get_tree_is_pipe(header.tree_id); fid : uint64 = $context.connection.get_file_id(header.message_id); - pipe_proc : bool = $context.connection.forward_dce_rpc(data, fid, false) &if(is_pipe); + pipe_proc : bool = $context.connection.forward_dce_rpc(data, fid, false) &if(header.is_pipe); proc: bool = $context.connection.proc_smb2_read_response(header, this); }; diff --git a/src/analyzer/protocol/smb/smb2-com-write.pac b/src/analyzer/protocol/smb/smb2-com-write.pac index f463afc767..177a3a84bd 100644 --- a/src/analyzer/protocol/smb/smb2-com-write.pac +++ b/src/analyzer/protocol/smb/smb2-com-write.pac @@ -12,7 +12,7 @@ refine connection SMB_Conn += { ${val.data_len}); } - if ( ! ${val.is_pipe} && ${val.data}.length() > 0 ) + if ( ! ${h.is_pipe} && ${val.data}.length() > 0 ) { file_mgr->DataIn(${val.data}.begin(), ${val.data_len}, ${val.offset}, bro_analyzer()->GetAnalyzerTag(), @@ -44,8 +44,7 @@ type SMB2_write_request(header: SMB2_Header) = record { pad : padding to data_offset - header.head_length; data : bytestring &length=data_len; } &let { - is_pipe: bool = $context.connection.get_tree_is_pipe(header.tree_id); - pipe_proc : bool = $context.connection.forward_dce_rpc(data, file_id.persistent+file_id._volatile, true) &if(is_pipe); + pipe_proc : bool = $context.connection.forward_dce_rpc(data, file_id.persistent+file_id._volatile, true) &if(header.is_pipe); proc : bool = $context.connection.proc_smb2_write_request(header, this); }; diff --git a/src/analyzer/protocol/smb/smb2-protocol.pac b/src/analyzer/protocol/smb/smb2-protocol.pac index 523ab3b890..dd31559126 100644 --- a/src/analyzer/protocol/smb/smb2-protocol.pac +++ b/src/analyzer/protocol/smb/smb2-protocol.pac @@ -35,10 +35,10 @@ type SMB2_PDU(is_orig: bool) = record { # Status 0 indicates success. In the case of a # request this should just happen to work out due to # how the fields are set. - 0 -> msg : SMB2_Message(header, is_orig); - STATUS_BUFFER_OVERFLOW -> buffer_overflow : SMB2_Message(header, is_orig); + 0 -> msg : SMB2_Message(header, is_orig); + STATUS_BUFFER_OVERFLOW -> buffer_overflow : SMB2_Message(header, is_orig); STATUS_MORE_PROCESSING_REQUIRED -> more_processing_required : SMB2_Message(header, is_orig); - default -> err : SMB2_error_response(header); + default -> err : SMB2_error_response(header); }; }; @@ -199,6 +199,7 @@ type SMB2_Header(is_orig: bool) = record { related = (flags >> 26) & 1; msigned = (flags >> 27) & 1; dfs = (flags) & 1; + is_pipe: bool = $context.connection.get_tree_is_pipe(tree_id); proc : bool = $context.connection.proc_smb2_message(this, is_orig); } &byteorder=littleendian; diff --git a/testing/btest/Baseline/scripts.base.protocols.smb.smb2/files.log b/testing/btest/Baseline/scripts.base.protocols.smb.smb2/files.log index 66e632e0cb..9dc925e4dc 100644 --- a/testing/btest/Baseline/scripts.base.protocols.smb.smb2/files.log +++ b/testing/btest/Baseline/scripts.base.protocols.smb.smb2/files.log @@ -3,8 +3,8 @@ #empty_field (empty) #unset_field - #path files -#open 2016-08-16-23-02-30 +#open 2016-10-27-17-16-27 #fields ts fuid tx_hosts rx_hosts conn_uids source depth analyzers mime_type filename duration local_orig is_orig seen_bytes total_bytes missing_bytes overflow_bytes timedout parent_fuid md5 sha1 sha256 extracted #types time string set[addr] set[addr] set[string] string count set[string] string string interval bool bool count count count count bool string string string string string -1323202695.515890 Fg6wjp3BAYahIGAEf7 10.0.0.11 10.0.0.12 CHhAvVGS1DHFjwGM9 SMB 0 (empty) application/pdf WP_SMBPlugin.pdf 0.073970 - T 1508939 - 0 0 T - - - - - -#close 2016-08-16-23-02-30 +1323202695.515890 Fg6wjp3BAYahIGAEf7 10.0.0.11 10.0.0.12 CHhAvVGS1DHFjwGM9 SMB 0 (empty) application/pdf WP_SMBPlugin.pdf 0.073970 - T 1508939 - 0 0 F - - - - - +#close 2016-10-27-17-16-27 From 19a4376a9afde816af899a9f0d6854a6d7365c82 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Tue, 1 Nov 2016 03:13:04 -0400 Subject: [PATCH 4/7] Fix a small issue where DCE_RPC commands were improperly being logged. --- scripts/base/protocols/dce-rpc/main.bro | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/scripts/base/protocols/dce-rpc/main.bro b/scripts/base/protocols/dce-rpc/main.bro index c0e36624d2..b6de70cb78 100644 --- a/scripts/base/protocols/dce-rpc/main.bro +++ b/scripts/base/protocols/dce-rpc/main.bro @@ -160,12 +160,12 @@ 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?$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] && - "*" !in ignored_operations[c$dce_rpc$endpoint]) ) + 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] && + "*" !in ignored_operations[c$dce_rpc$endpoint]) ) ) { Log::write(LOG, c$dce_rpc); } @@ -196,12 +196,12 @@ event connection_state_remove(c: connection) } } - 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] && - "*" !in ignored_operations[c$dce_rpc$endpoint]) ) + 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] && + "*" !in ignored_operations[c$dce_rpc$endpoint]) ) ) { Log::write(LOG, c$dce_rpc); } From bb5c2c94ec8adb60e8157cbd73cae4bc33f0f6b7 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Tue, 1 Nov 2016 03:14:15 -0400 Subject: [PATCH 5/7] Fix SMB tree connect handling. It was misidentifying share mappings as FILE shares sometimes when they were actually PIPE shares. --- src/analyzer/protocol/smb/smb-pipe.pac | 4 ++-- src/analyzer/protocol/smb/smb1-com-nt-create-andx.pac | 2 +- src/analyzer/protocol/smb/smb1-com-tree-connect-andx.pac | 6 +++++- src/analyzer/protocol/smb/smb2-com-create.pac | 2 +- src/analyzer/protocol/smb/smb2-com-tree-connect.pac | 3 ++- 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/analyzer/protocol/smb/smb-pipe.pac b/src/analyzer/protocol/smb/smb-pipe.pac index bcc910e19a..1183618b8a 100644 --- a/src/analyzer/protocol/smb/smb-pipe.pac +++ b/src/analyzer/protocol/smb/smb-pipe.pac @@ -25,9 +25,9 @@ refine connection SMB_Conn += { return ( tree_is_pipe_map.count(tree_id) > 0 ); %} - function set_tree_is_pipe(tree_id: uint16, is_pipe: bool): bool + function set_tree_is_pipe(tree_id: uint16): bool %{ - tree_is_pipe_map[tree_id] = is_pipe; + tree_is_pipe_map[tree_id] = true; return true; %} diff --git a/src/analyzer/protocol/smb/smb1-com-nt-create-andx.pac b/src/analyzer/protocol/smb/smb1-com-nt-create-andx.pac index d71086a44b..0cdae1cefb 100644 --- a/src/analyzer/protocol/smb/smb1-com-nt-create-andx.pac +++ b/src/analyzer/protocol/smb/smb1-com-nt-create-andx.pac @@ -5,7 +5,7 @@ refine connection SMB_Conn += { if ( ! ${header.is_pipe} && BifConst::SMB::pipe_filenames->AsTable()->Lookup(filename->CheckString()) ) { - set_tree_is_pipe(${header.tid}, true); + set_tree_is_pipe(${header.tid}); BifEvent::generate_smb_pipe_connect_heuristic(bro_analyzer(), bro_analyzer()->Conn()); } diff --git a/src/analyzer/protocol/smb/smb1-com-tree-connect-andx.pac b/src/analyzer/protocol/smb/smb1-com-tree-connect-andx.pac index 756a28bc96..0b8802b2fb 100644 --- a/src/analyzer/protocol/smb/smb1-com-tree-connect-andx.pac +++ b/src/analyzer/protocol/smb/smb1-com-tree-connect-andx.pac @@ -13,7 +13,11 @@ refine connection SMB_Conn += { function proc_smb1_tree_connect_andx_response(header: SMB_Header, val: SMB1_tree_connect_andx_response): bool %{ - set_tree_is_pipe(${header.tid}, strncmp((const char*) smb_string2stringval(${val.service})->Bytes(), "IPC", 3) == 0); + if ( strncmp((const char*) smb_string2stringval(${val.service})->Bytes(), + "IPC", 3) == 0 ) + { + set_tree_is_pipe(${header.tid}); + } if ( smb1_tree_connect_andx_response ) { diff --git a/src/analyzer/protocol/smb/smb2-com-create.pac b/src/analyzer/protocol/smb/smb2-com-create.pac index 5e35d8e975..174c201f27 100644 --- a/src/analyzer/protocol/smb/smb2-com-create.pac +++ b/src/analyzer/protocol/smb/smb2-com-create.pac @@ -6,7 +6,7 @@ refine connection SMB_Conn += { if ( ! ${h.is_pipe} && BifConst::SMB::pipe_filenames->AsTable()->Lookup(filename->CheckString()) ) { - set_tree_is_pipe(${h.tree_id}, true); + set_tree_is_pipe(${h.tree_id}); BifEvent::generate_smb_pipe_connect_heuristic(bro_analyzer(), bro_analyzer()->Conn()); } diff --git a/src/analyzer/protocol/smb/smb2-com-tree-connect.pac b/src/analyzer/protocol/smb/smb2-com-tree-connect.pac index 1c8b4d5978..fe59ecb74d 100644 --- a/src/analyzer/protocol/smb/smb2-com-tree-connect.pac +++ b/src/analyzer/protocol/smb/smb2-com-tree-connect.pac @@ -13,7 +13,8 @@ refine connection SMB_Conn += { function proc_smb2_tree_connect_response(header: SMB2_Header, val: SMB2_tree_connect_response): bool %{ - set_tree_is_pipe(${header.tree_id}, ${val.share_type} == SMB2_SHARE_TYPE_PIPE); + if ( ${val.share_type} == SMB2_SHARE_TYPE_PIPE ) + set_tree_is_pipe(${header.tree_id}); if ( smb2_tree_connect_response ) { From 5832b872c2f387f564833634df41ef614fd1298d Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Tue, 1 Nov 2016 15:56:15 -0400 Subject: [PATCH 6/7] Removed some files that aren't being used. - I went ahead and finished implementing smb2 tree_disconnect. This made it possible to address an edge case when packet loss occurs. - Fixes BIT-1721 --- scripts/policy/protocols/smb/smb2-main.bro | 10 +++ src/analyzer/protocol/smb/CMakeLists.txt | 4 +- src/analyzer/protocol/smb/smb-pipe.pac | 6 ++ src/analyzer/protocol/smb/smb.pac | 4 +- .../protocol/smb/smb1-com-open-andx.pac | 85 ------------------- src/analyzer/protocol/smb/smb1-protocol.pac | 4 +- .../protocol/smb/smb1_com_open_andx.bif | 41 --------- src/analyzer/protocol/smb/smb2-com-lock.pac | 2 +- .../protocol/smb/smb2-com-tree-disconnect.pac | 36 ++++++++ src/analyzer/protocol/smb/smb2_com_ioctl.bif | 1 - src/analyzer/protocol/smb/smb2_com_lock.bif | 1 - .../protocol/smb/smb2_com_tree_disconnect.bif | 23 ++++- 12 files changed, 79 insertions(+), 138 deletions(-) delete mode 100644 src/analyzer/protocol/smb/smb1-com-open-andx.pac delete mode 100644 src/analyzer/protocol/smb/smb1_com_open_andx.bif delete mode 100644 src/analyzer/protocol/smb/smb2_com_ioctl.bif delete mode 100644 src/analyzer/protocol/smb/smb2_com_lock.bif diff --git a/scripts/policy/protocols/smb/smb2-main.bro b/scripts/policy/protocols/smb/smb2-main.bro index 041813b99e..726851dee4 100644 --- a/scripts/policy/protocols/smb/smb2-main.bro +++ b/scripts/policy/protocols/smb/smb2-main.bro @@ -119,6 +119,16 @@ event smb2_tree_connect_response(c: connection, hdr: SMB2::Header, response: SMB Log::write(SMB::MAPPING_LOG, c$smb_state$current_tree); } +event smb2_tree_disconnect_request(c: connection, hdr: SMB2::Header) &priority=5 + { + if ( hdr$tree_id in c$smb_state$tid_map ) + { + delete c$smb_state$tid_map[hdr$tree_id]; + delete c$smb_state$current_tree; + delete c$smb_state$current_cmd$referenced_tree; + } + } + event smb2_create_request(c: connection, hdr: SMB2::Header, name: string) &priority=5 { if ( name == "") diff --git a/src/analyzer/protocol/smb/CMakeLists.txt b/src/analyzer/protocol/smb/CMakeLists.txt index 844eca4cd4..bf44501b96 100644 --- a/src/analyzer/protocol/smb/CMakeLists.txt +++ b/src/analyzer/protocol/smb/CMakeLists.txt @@ -26,14 +26,12 @@ bro_plugin_bif( smb2_com_close.bif smb2_com_create.bif - #smb2_com_ioctl.bif - #smb2_com_lock.bif smb2_com_negotiate.bif smb2_com_read.bif smb2_com_session_setup.bif smb2_com_set_info.bif smb2_com_tree_connect.bif - #smb2_com_tree_disconnect.bif + smb2_com_tree_disconnect.bif smb2_com_write.bif smb2_events.bif diff --git a/src/analyzer/protocol/smb/smb-pipe.pac b/src/analyzer/protocol/smb/smb-pipe.pac index 1183618b8a..2407c63dd3 100644 --- a/src/analyzer/protocol/smb/smb-pipe.pac +++ b/src/analyzer/protocol/smb/smb-pipe.pac @@ -25,6 +25,12 @@ refine connection SMB_Conn += { return ( tree_is_pipe_map.count(tree_id) > 0 ); %} + function unset_tree_is_pipe(tree_id: uint16): bool + %{ + tree_is_pipe_map.erase(tree_id); + return true; + %} + function set_tree_is_pipe(tree_id: uint16): bool %{ tree_is_pipe_map[tree_id] = true; diff --git a/src/analyzer/protocol/smb/smb.pac b/src/analyzer/protocol/smb/smb.pac index cdb0f04236..156037f614 100644 --- a/src/analyzer/protocol/smb/smb.pac +++ b/src/analyzer/protocol/smb/smb.pac @@ -31,14 +31,12 @@ #include "smb2_com_close.bif.h" #include "smb2_com_create.bif.h" -//#include "smb2_com_ioctl.bif.h" -//#include "smb2_com_lock.bif.h" #include "smb2_com_negotiate.bif.h" #include "smb2_com_read.bif.h" #include "smb2_com_session_setup.bif.h" #include "smb2_com_set_info.bif.h" #include "smb2_com_tree_connect.bif.h" -//#include "smb2_com_tree_disconnect.bif.h" +#include "smb2_com_tree_disconnect.bif.h" #include "smb2_com_write.bif.h" %} diff --git a/src/analyzer/protocol/smb/smb1-com-open-andx.pac b/src/analyzer/protocol/smb/smb1-com-open-andx.pac deleted file mode 100644 index c7e7bea03a..0000000000 --- a/src/analyzer/protocol/smb/smb1-com-open-andx.pac +++ /dev/null @@ -1,85 +0,0 @@ -refine connection SMB_Conn += { - - function proc_smb1_open_andx_request(h: SMB_Header, val: SMB1_open_andx_request): bool - %{ - if ( smb1_open_andx_request ) - BifEvent::generate_smb1_open_andx_request(bro_analyzer(), - bro_analyzer()->Conn(), - BuildHeaderVal(h), - ${val.flags}, - ${val.access_mode}, - ${val.search_attrs}, - ${val.file_attrs}, - ${val.creation_time}, - ${val.open_mode}, - ${val.allocation_size}, - ${val.timeout}, - smb_string2stringval(${val.filename})); - - return true; - %} - - function proc_smb1_open_andx_response(h: SMB_Header, val: SMB1_open_andx_response): bool - %{ - if ( smb1_open_andx_response ) - BifEvent::generate_smb1_open_andx_response(bro_analyzer(), - bro_analyzer()->Conn(), - BuildHeaderVal(h), - ${val.fid}, - ${val.file_attrs}, - ${val.last_write_time}, - ${val.file_data_size}, - ${val.access_rights}, - ${val.resource_type}, - ${val.nm_pipe_status}, - ${val.open_results}); - - return true; - %} - -}; - - - -type SMB1_open_andx_request(header: SMB_Header, offset: uint16) = record { - word_count : uint8; - andx : SMB_andx; - flags : uint16; - access_mode : uint16; - search_attrs : uint16; - file_attrs : uint16; - creation_time : uint32; - open_mode : uint16; - allocation_size : uint32; - timeout : uint32; - reserved : padding[4]; - byte_count : uint16; - filename : SMB_string(header.unicode, offsetof(filename); - - extra_byte_parameters : bytestring &transient &length=(andx.offset == 0 || andx.offset >= (offset+offsetof(extra_byte_parameters))+2) ? 0 : (andx.offset-(offset+offsetof(extra_byte_parameters))); - - andx_command : SMB_andx_command(header, 1, offset+offsetof(andx_command), andx.command); -} &let { - proc : bool = $context.connection.proc_smb1_open_andx_request(header, this); -} &byteorder=littleendian; - -type SMB1_open_andx_response(header: SMB_Header, offset: uint16) = record { - word_count : uint8; - andx : SMB_andx; - fid : uint16; - file_attrs : uint16; - last_write_time : uint32; - file_data_size : uint32; - access_rights : uint16; - resource_type : uint16; - nm_pipe_status : uint16; - open_results : uint16; - reserved : padding[6]; - byte_count : uint16; - - extra_byte_parameters : bytestring &transient &length=(andx.offset == 0 || andx.offset >= (offset+offsetof(extra_byte_parameters))+2) ? 0 : (andx.offset-(offset+offsetof(extra_byte_parameters))); - - andx_command : SMB_andx_command(header, 0, offset+offsetof(andx_command), andx.command); -} &let { - proc : bool = $context.connection.proc_smb1_open_andx_response(header, this); -} &byteorder=littleendian; diff --git a/src/analyzer/protocol/smb/smb1-protocol.pac b/src/analyzer/protocol/smb/smb1-protocol.pac index 985e67c068..4b38feefcb 100644 --- a/src/analyzer/protocol/smb/smb1-protocol.pac +++ b/src/analyzer/protocol/smb/smb1-protocol.pac @@ -127,7 +127,7 @@ type SMB_andx_command(header: SMB_Header, is_orig: bool, offset: uint16, command type SMB_Message_Request(header: SMB_Header, offset: uint16, command: uint8, is_orig: bool) = case command of { # SMB1 Command Extensions - #SMB_COM_OPEN_ANDX -> open_andx : SMB_open_andx_request(header); + #SMB_COM_OPEN_ANDX -> open_andx : SMB1_open_andx_request(header); SMB_COM_READ_ANDX -> read_andx : SMB1_read_andx_request(header, offset); SMB_COM_WRITE_ANDX -> write_andx : SMB1_write_andx_request(header, offset); SMB_COM_TRANSACTION2 -> transaction2 : SMB1_transaction2_request(header); @@ -205,7 +205,7 @@ type SMB_Message_Request(header: SMB_Header, offset: uint16, command: uint8, is_ type SMB_Message_Response(header: SMB_Header, offset: uint16, command: uint8, is_orig: bool) = case command of { # SMB1 Command Extensions - #SMB_COM_OPEN_ANDX -> open_andx : SMB_open_andx_response(header, offset); + #SMB_COM_OPEN_ANDX -> open_andx : SMB1_open_andx_response(header, offset); SMB_COM_READ_ANDX -> read_andx : SMB1_read_andx_response(header, offset); SMB_COM_WRITE_ANDX -> write_andx : SMB1_write_andx_response(header, offset); SMB_COM_TRANSACTION2 -> transaction2 : SMB1_transaction2_response(header); diff --git a/src/analyzer/protocol/smb/smb1_com_open_andx.bif b/src/analyzer/protocol/smb/smb1_com_open_andx.bif deleted file mode 100644 index 1ce418e33a..0000000000 --- a/src/analyzer/protocol/smb/smb1_com_open_andx.bif +++ /dev/null @@ -1,41 +0,0 @@ -## Generated for :abbr:`SMB (Server Message Block)`/:abbr:`CIFS (Common Internet File System)` -## version 1 requests of type *open andx*. This is sent by the client to create and open a new -## file or open an existing regular file and chain additional messages along with the request. -## -## For more information, see MS-CIFS:2.2.4.41 -## -## c: The connection. -## -## hdr: The parsed header of the :abbr:`SMB (Server Message Block)` version 1 message. -## -## flags: Flags requesting attribute data and locking. -## -## access_mode: The requested access mode. -## -## search_attrs: The set of attributes that the file MUST have in order to be found. -## -## file_attrs: The set of attributes that the file is to have if the file needs to be created. -## -## creation_time: The time of creation if the file is created. -## -## open_mode: The way a file s -## -## length: The number of bytes being requested. -## -## .. bro:see:: smb1_message smb1_open_andx_response -event smb1_open_andx_request%(c: connection, hdr: SMB1::Header, file_id: count, offset: count, length: count%); - -## Generated for :abbr:`SMB (Server Message Block)`/:abbr:`CIFS (Common Internet File System)` -## version 1 responses of type *open andx*. This is the server response to the *open andx* request. -## -## For more information, see MS-CIFS:2.2.4.41 -## -## c: The connection. -## -## hdr: The parsed header of the :abbr:`SMB (Server Message Block)` version 1 message. -## -## data_len: The length of data from the requested file. -## -## .. bro:see:: smb1_message smb1_open_andx_request -event smb1_open_andx_response%(c: connection, hdr: SMB1::Header, data_len: count%); - diff --git a/src/analyzer/protocol/smb/smb2-com-lock.pac b/src/analyzer/protocol/smb/smb2-com-lock.pac index d6b1f5c2c8..3efd5f4e55 100644 --- a/src/analyzer/protocol/smb/smb2-com-lock.pac +++ b/src/analyzer/protocol/smb/smb2-com-lock.pac @@ -1,5 +1,5 @@ refine connection SMB_Conn += { - + # Needs to be implemented. }; type SMB2_lock = record { diff --git a/src/analyzer/protocol/smb/smb2-com-tree-disconnect.pac b/src/analyzer/protocol/smb/smb2-com-tree-disconnect.pac index 4413b56952..cba7b0deb3 100644 --- a/src/analyzer/protocol/smb/smb2-com-tree-disconnect.pac +++ b/src/analyzer/protocol/smb/smb2-com-tree-disconnect.pac @@ -1,9 +1,45 @@ + +refine connection SMB_Conn += { + + function proc_smb2_tree_disconnect_request(header: SMB2_Header): bool + %{ + unset_tree_is_pipe(${header.tree_id}); + + if ( smb2_tree_disconnect_request ) + { + BifEvent::generate_smb2_tree_disconnect_request(bro_analyzer(), + bro_analyzer()->Conn(), + BuildSMB2HeaderVal(header)); + } + + return true; + %} + + function proc_smb2_tree_disconnect_response(header: SMB2_Header): bool + %{ + if ( smb2_tree_disconnect_response ) + { + BifEvent::generate_smb2_tree_disconnect_response(bro_analyzer(), + bro_analyzer()->Conn(), + BuildSMB2HeaderVal(header)); + } + + return true; + %} + +}; + type SMB2_tree_disconnect_request(header: SMB2_Header) = record { structure_size : uint16; reserved : uint16; +} &let { + proc: bool = $context.connection.proc_smb2_tree_disconnect_request(header); + }; type SMB2_tree_disconnect_response(header: SMB2_Header) = record { structure_size : uint16; reserved : uint16; +} &let { + proc: bool = $context.connection.proc_smb2_tree_disconnect_response(header); }; diff --git a/src/analyzer/protocol/smb/smb2_com_ioctl.bif b/src/analyzer/protocol/smb/smb2_com_ioctl.bif deleted file mode 100644 index 996cee9ad8..0000000000 --- a/src/analyzer/protocol/smb/smb2_com_ioctl.bif +++ /dev/null @@ -1 +0,0 @@ -# Empty. diff --git a/src/analyzer/protocol/smb/smb2_com_lock.bif b/src/analyzer/protocol/smb/smb2_com_lock.bif deleted file mode 100644 index b22403cef0..0000000000 --- a/src/analyzer/protocol/smb/smb2_com_lock.bif +++ /dev/null @@ -1 +0,0 @@ -# Empty. \ No newline at end of file diff --git a/src/analyzer/protocol/smb/smb2_com_tree_disconnect.bif b/src/analyzer/protocol/smb/smb2_com_tree_disconnect.bif index 996cee9ad8..fdcd5d9d8b 100644 --- a/src/analyzer/protocol/smb/smb2_com_tree_disconnect.bif +++ b/src/analyzer/protocol/smb/smb2_com_tree_disconnect.bif @@ -1 +1,22 @@ -# Empty. +## Generated for :abbr:`SMB (Server Message Block)`/:abbr:`CIFS (Common Internet File System)` +## version 2 requests of type *tree disconnect*. This is sent by the client to logically disconnect +## client access to a server resource. +## +## c: The connection. +## +## hdr: The parsed header of the :abbr:`SMB (Server Message Block)` version 2 message. +## +## .. bro:see:: smb2_message +event smb2_tree_disconnect_request%(c: connection, hdr: SMB2::Header%); + + +## Generated for :abbr:`SMB (Server Message Block)`/:abbr:`CIFS (Common Internet File System)` +## version 2 requests of type *tree disconnect*. This is sent by the server to logically disconnect +## client access to a server resource. +## +## c: The connection. +## +## hdr: The parsed header of the :abbr:`SMB (Server Message Block)` version 2 message. +## +## .. bro:see:: smb2_message +event smb2_tree_disconnect_response%(c: connection, hdr: SMB2::Header%); From 5e63584b4850d1ff68a9beaf967401a84ba1a8dc Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Tue, 1 Nov 2016 16:03:36 -0400 Subject: [PATCH 7/7] Disable SMB2 error data parsing. It is not implemented correctly and is causing a lot of parse errors. --- src/analyzer/protocol/smb/smb2-protocol.pac | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/analyzer/protocol/smb/smb2-protocol.pac b/src/analyzer/protocol/smb/smb2-protocol.pac index dd31559126..1cad6e130e 100644 --- a/src/analyzer/protocol/smb/smb2-protocol.pac +++ b/src/analyzer/protocol/smb/smb2-protocol.pac @@ -243,7 +243,9 @@ type SMB2_error_response(header: SMB2_Header) = record { structure_size : uint16; reserved : padding[2]; byte_count : uint32; - error_data : SMB2_error_data(header, byte_count); + # This is implemented incorrectly and is disabled for now. + #error_data : SMB2_error_data(header, byte_count); + stuff : bytestring &restofdata &transient; } &byteorder = littleendian; type SMB2_logoff_request(header: SMB2_Header) = record {