From: George Koikara (gkoikara) Date: Tue, 24 Mar 2020 18:18:28 +0000 (+0000) Subject: Merge pull request #1984 in SNORT/snort3 from ~NEHASH4/snort3:CSCvh17903 to master X-Git-Tag: 3.0.0-270~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7b6e5e72e205d449ea4d1847f210b85354628fb3;p=thirdparty%2Fsnort3.git Merge pull request #1984 in SNORT/snort3 from ~NEHASH4/snort3:CSCvh17903 to master Squashed commit of the following: commit fe0e3ebb85728a7ace9022accf90046561a843ce Author: neha sharma Date: Tue Dec 17 05:53:19 2019 -0500 smb: inspect midstream sessions for file inspection --- diff --git a/src/service_inspectors/dce_rpc/dce_common.cc b/src/service_inspectors/dce_rpc/dce_common.cc index 366e763c8..d1469648e 100644 --- a/src/service_inspectors/dce_rpc/dce_common.cc +++ b/src/service_inspectors/dce_rpc/dce_common.cc @@ -85,7 +85,7 @@ static const char* dce2_get_policy_name(DCE2_Policy policy) bool dce2_set_common_config(Value& v, dce2CommonProtoConf& common) { if ( v.is("limit_alerts") ) - common.limit_alerts = v.get_bool(); + common.limit_alerts = v.get_bool(); else if ( v.is("disable_defrag") ) common.disable_defrag = v.get_bool(); @@ -138,22 +138,14 @@ void print_dce2_co_config(dce2CoProtoConf& co) co.co_reassemble_threshold); } -bool dce2_paf_abort(Flow* flow, DCE2_SsnData* sd) +bool dce2_paf_abort(DCE2_SsnData* sd) { - // FIXIT-L Checking flags from flow is okay here because this is in paf? - if ( (flow->get_session_flags() & SSNFLAG_MIDSTREAM) ) - return true; - - else if ( !(flow->get_session_flags() & SSNFLAG_ESTABLISHED) ) - return true; - if ((sd != nullptr) && DCE2_SsnNoInspect(sd)) return true; return false; } - void DCE2_Detect(DCE2_SsnData* sd) { DceContextData::set_current_ropts(sd); @@ -168,7 +160,7 @@ void DCE2_Detect(DCE2_SsnData* sd) DetectionEngine::detect(top_pkt); dce2_detected = 1; /* Always reset rule option data after detecting */ - DCE2_ResetRopts(sd , top_pkt); + DCE2_ResetRopts(sd, top_pkt); } DCE2_TransType get_dce2_trans_type(const Packet* p) diff --git a/src/service_inspectors/dce_rpc/dce_common.h b/src/service_inspectors/dce_rpc/dce_common.h index 866144118..94f4740be 100644 --- a/src/service_inspectors/dce_rpc/dce_common.h +++ b/src/service_inspectors/dce_rpc/dce_common.h @@ -399,7 +399,7 @@ bool dce2_set_common_config(snort::Value&, dce2CommonProtoConf&); void print_dce2_common_config(dce2CommonProtoConf&); bool dce2_set_co_config(snort::Value&, dce2CoProtoConf&); void print_dce2_co_config(dce2CoProtoConf&); -bool dce2_paf_abort(snort::Flow*, DCE2_SsnData*); +bool dce2_paf_abort(DCE2_SsnData*); void DCE2_Detect(DCE2_SsnData*); snort::Packet* DCE2_GetRpkt(snort::Packet*, DCE2_RpktType, const uint8_t*, uint32_t); uint16_t DCE2_GetRpktMaxData(DCE2_RpktType); diff --git a/src/service_inspectors/dce_rpc/dce_smb.cc b/src/service_inspectors/dce_rpc/dce_smb.cc index 9140ef011..4b165a573 100644 --- a/src/service_inspectors/dce_rpc/dce_smb.cc +++ b/src/service_inspectors/dce_rpc/dce_smb.cc @@ -359,9 +359,6 @@ void Dce2Smb::eval(Packet* p) assert(p->has_tcp_data()); assert(p->flow); - if ( p->test_session_flags(SSNFLAG_MIDSTREAM) ) - return; - dce2_smb_sess = dce2_handle_smb_session(p, &config); if (dce2_smb_sess) diff --git a/src/service_inspectors/dce_rpc/dce_smb2.cc b/src/service_inspectors/dce_rpc/dce_smb2.cc index e5c2cf885..bf6dad521 100644 --- a/src/service_inspectors/dce_rpc/dce_smb2.cc +++ b/src/service_inspectors/dce_rpc/dce_smb2.cc @@ -36,6 +36,7 @@ using namespace snort; #define UNKNOWN_FILE_SIZE ~0 +#define SMB2_MAX_OUTSTANDING_REQUESTS 128 // FIXIT-L port fileCache related code along with // DCE2_Smb2Init, DCE2_Smb2Close and DCE2_Smb2UpdateStats @@ -60,24 +61,19 @@ static int DCE2_Smb2TidCompare(const void* a, const void* b) return -1; } -static inline void DCE2_Smb2InsertTid(DCE2_SmbSsnData* ssd, const uint32_t tid, +static inline DCE2_Ret DCE2_Smb2InsertTid(DCE2_SmbSsnData* ssd, const uint32_t tid, const uint8_t share_type) { - bool is_ipc = (share_type != SMB2_SHARE_TYPE_DISK); + DCE2_Ret ret = DCE2_RET__ERROR; - if ( !is_ipc and - ssd->max_file_depth == -1 and DCE2_ScSmbFileDepth((dce2SmbProtoConf*)ssd->sd.config) == -1 ) + if ( (share_type == SMB2_SHARE_TYPE_DISK)and + (ssd->max_file_depth == + -1 and DCE2_ScSmbFileDepth((dce2SmbProtoConf*)ssd->sd.config) == -1) ) { - trace_logf(dce_smb, "Not inserting TID (%u) because it's " - "not IPC and not inspecting normal file data.\n", tid); - return; - } - - if (is_ipc) - { - trace_logf(dce_smb, "Not inserting TID (%u) " - "because it's IPC and only inspecting normal file data.\n", tid); - return; + trace_logf(dce_smb, "Not inserting TID (%u) for DISK share type" + "as mandatory configuration max_file_depth is not present." + "This will result in non-inspection of file data.\n", tid); + return ret; } if (ssd->tids == nullptr) @@ -87,32 +83,42 @@ static inline void DCE2_Smb2InsertTid(DCE2_SmbSsnData* ssd, const uint32_t tid, if (ssd->tids == nullptr) { - return; + return ret; } } - DCE2_ListInsert(ssd->tids, (void*)(uintptr_t)tid, (void*)(uintptr_t)share_type); + if (ssd->outstanding_requests >= SMB2_MAX_OUTSTANDING_REQUESTS) + { + return ret; + } + + ret = DCE2_ListInsert(ssd->tids, (void*)(uintptr_t)tid, (void*)(uintptr_t)share_type); + if (DCE2_RET__SUCCESS == ret) + { + ssd->outstanding_requests++; + } + + return ret; } -static DCE2_Ret DCE2_Smb2FindTid(DCE2_SmbSsnData* ssd, const Smb2Hdr* smb_hdr) +static inline uint8_t DCE2_Smb2GetShareType(DCE2_SmbSsnData* ssd, const uint32_t tid) { - /* Still process async commands*/ - if (alignedNtohl(&(smb_hdr->flags)) & SMB2_FLAGS_ASYNC_COMMAND) - return DCE2_RET__SUCCESS; + if ( DCE2_RET__SUCCESS == DCE2_ListFindKey(ssd->tids, (void*)(uintptr_t)tid) ) + return ((uint8_t)(uintptr_t)DCE2_ListFind(ssd->tids, (void*)(uintptr_t)tid)); - return DCE2_ListFindKey(ssd->tids, (void*)(uintptr_t)Smb2Tid(smb_hdr)); + return SMB2_SHARE_TYPE_NONE; } static inline void DCE2_Smb2RemoveTid(DCE2_SmbSsnData* ssd, const uint32_t tid) { - DCE2_ListRemove(ssd->tids, (void*)(uintptr_t)tid); + if ( DCE2_RET__SUCCESS == DCE2_ListRemove(ssd->tids, (void*)(uintptr_t)tid) ) + ssd->outstanding_requests--; } static inline void DCE2_Smb2StoreRequest(DCE2_SmbSsnData* ssd, uint64_t message_id, uint64_t offset, uint64_t file_id) { Smb2Request* request = ssd->smb2_requests; - ssd->max_outstanding_requests = 128; /* windows client max */ while (request) { @@ -121,7 +127,7 @@ static inline void DCE2_Smb2StoreRequest(DCE2_SmbSsnData* ssd, request = request->next; } - if ( ssd->outstanding_requests >= (ssd->max_outstanding_requests - 1) ) + if (ssd->outstanding_requests >= SMB2_MAX_OUTSTANDING_REQUESTS) { dce_alert(GID_DCE2, DCE2_SMB_MAX_REQS_EXCEEDED, (dce2CommonStats*)&dce2_smb_stats, ssd->sd); @@ -254,7 +260,8 @@ static void DCE2_Smb2TreeConnect(DCE2_SmbSsnData* ssd, const Smb2Hdr* smb_hdr, { /* Using structure size to decide whether it is response or request*/ uint16_t structure_size; - const Smb2TreeConnectResponseHdr* smb_tree_connect_hdr = (const Smb2TreeConnectResponseHdr*)smb_data; + const Smb2TreeConnectResponseHdr* smb_tree_connect_hdr = + (const Smb2TreeConnectResponseHdr*)smb_data; if ((const uint8_t*)smb_tree_connect_hdr + SMB2_TREE_CONNECT_RESPONSE_STRUC_SIZE > end) return; @@ -336,7 +343,6 @@ static void DCE2_Smb2CreateResponse(DCE2_SmbSsnData* ssd, const Smb2Hdr*, uint64_t fileId_persistent; uint64_t file_size = UNKNOWN_FILE_SIZE; - fileId_persistent = alignedNtohq((const uint64_t*)(&(smb_create_hdr->fileId_persistent))); ssd->ftracker.fid_v2 = fileId_persistent; if (smb_create_hdr->end_of_file) @@ -455,7 +461,8 @@ static void DCE2_Smb2SetInfo(DCE2_SmbSsnData* ssd, const Smb2Hdr*, if (structure_size == SMB2_SET_INFO_REQUEST_STRUC_SIZE) { - const uint8_t* file_data = (const uint8_t*)smb_set_info_hdr + SMB2_SET_INFO_REQUEST_STRUC_SIZE - 1; + const uint8_t* file_data = (const uint8_t*)smb_set_info_hdr + + SMB2_SET_INFO_REQUEST_STRUC_SIZE - 1; if (smb_set_info_hdr->file_info_class == SMB2_FILE_ENDOFFILE_INFO) { uint64_t file_size = alignedNtohq((const uint64_t*)file_data); @@ -617,7 +624,6 @@ static void DCE2_Smb2WriteRequest(DCE2_SmbSsnData* ssd, const Smb2Hdr* smb_hdr, ssd->pdu_state = DCE2_SMB_PDU_STATE__RAW_DATA; } - /******************************************************************** * * Process write command @@ -655,35 +661,49 @@ static void DCE2_Smb2Inspect(DCE2_SmbSsnData* ssd, const Smb2Hdr* smb_hdr, const { const uint8_t* smb_data = (const uint8_t*)smb_hdr + SMB2_HEADER_LENGTH; uint16_t command = alignedNtohs(&(smb_hdr->command)); + uint8_t share_type = DCE2_Smb2GetShareType(ssd, Smb2Tid(smb_hdr)); switch (command) { case SMB2_COM_CREATE: dce2_smb_stats.smb2_create++; - if (DCE2_Smb2FindTid(ssd, smb_hdr) != DCE2_RET__SUCCESS) - return; - DCE2_Smb2Create(ssd, smb_hdr, smb_data, end); + + if ( SMB2_SHARE_TYPE_NONE == share_type ) + { + if ( DCE2_RET__SUCCESS == + DCE2_Smb2InsertTid(ssd, Smb2Tid(smb_hdr), SMB2_SHARE_TYPE_DISK) ) + DCE2_Smb2Create(ssd, smb_hdr, smb_data, end); + } + else if ( SMB2_SHARE_TYPE_DISK == share_type ) + { + DCE2_Smb2Create(ssd, smb_hdr, smb_data, end); + } + else + { + trace_logf(dce_smb, "Not handling create request for IPC with TID (%u)\n", + Smb2Tid(smb_hdr)); + } break; case SMB2_COM_READ: dce2_smb_stats.smb2_read++; - if (DCE2_Smb2FindTid(ssd, smb_hdr) != DCE2_RET__SUCCESS) + if ( SMB2_SHARE_TYPE_DISK != share_type ) return; DCE2_Smb2Read(ssd, smb_hdr, smb_data, end); break; case SMB2_COM_WRITE: dce2_smb_stats.smb2_write++; - if (DCE2_Smb2FindTid(ssd, smb_hdr) != DCE2_RET__SUCCESS) + if ( SMB2_SHARE_TYPE_DISK != share_type ) return; DCE2_Smb2Write(ssd, smb_hdr, smb_data, end); break; case SMB2_COM_SET_INFO: dce2_smb_stats.smb2_set_info++; - if (DCE2_Smb2FindTid(ssd, smb_hdr) != DCE2_RET__SUCCESS) + if ( SMB2_SHARE_TYPE_DISK != share_type ) return; DCE2_Smb2SetInfo(ssd, smb_hdr, smb_data, end); break; case SMB2_COM_CLOSE: dce2_smb_stats.smb2_close++; - if (DCE2_Smb2FindTid(ssd, smb_hdr) != DCE2_RET__SUCCESS) + if ( SMB2_SHARE_TYPE_DISK != share_type ) return; DCE2_Smb2CloseCmd(ssd, smb_hdr, smb_data, end); break; @@ -734,18 +754,19 @@ void DCE2_Smb2Process(DCE2_SmbSsnData* ssd) DCE2_Smb2Inspect(ssd, smb_hdr, data_ptr + data_len); /* In case of message compounding, find the offset of the next smb command */ next_command_offset = alignedNtohl(&(smb_hdr->next_command)); - if (next_command_offset + (const uint8_t *)smb_hdr > (data_ptr + data_len)) + if (next_command_offset + (const uint8_t*)smb_hdr > (data_ptr + data_len)) { dce_alert(GID_DCE2, DCE2_SMB_BAD_NEXT_COMMAND_OFFSET, - (dce2CommonStats*)&dce2_smb_stats, ssd->sd); + (dce2CommonStats*)&dce2_smb_stats, ssd->sd); return; } if (next_command_offset) { - smb_hdr = (const Smb2Hdr *)((const uint8_t *)smb_hdr + next_command_offset); + smb_hdr = (const Smb2Hdr*)((const uint8_t*)smb_hdr + next_command_offset); } - } while (next_command_offset && smb_hdr); + } + while (next_command_offset && smb_hdr); } else if (ssd->pdu_state == DCE2_SMB_PDU_STATE__RAW_DATA) { @@ -780,7 +801,7 @@ DCE2_SmbVersion DCE2_Smb2Version(const Packet* p) { /* Only check reassembled SMB2 packet*/ if ( p->has_paf_payload() and - (p->dsize > sizeof(NbssHdr) + DCE2_SMB_ID_SIZE) ) // DCE2_SMB_ID is u32 + (p->dsize > sizeof(NbssHdr) + DCE2_SMB_ID_SIZE) ) // DCE2_SMB_ID is u32 { const Smb2Hdr* smb_hdr = (const Smb2Hdr*)(p->data + sizeof(NbssHdr)); uint32_t smb_version_id = SmbId((const SmbNtHdr*)smb_hdr); diff --git a/src/service_inspectors/dce_rpc/dce_smb2.h b/src/service_inspectors/dce_rpc/dce_smb2.h index 6009f889a..8bc2fdb28 100644 --- a/src/service_inspectors/dce_rpc/dce_smb2.h +++ b/src/service_inspectors/dce_rpc/dce_smb2.h @@ -164,7 +164,7 @@ struct Smb2SetInfoRequestHdr uint16_t buffer_offset; /* buffer offset */ uint16_t reserved; /* reserved */ uint32_t additional_info; /* additional information */ - uint64_t fileId_persistent;/* fileId that is persistent */ + uint64_t fileId_persistent; /* fileId that is persistent */ uint64_t fileId_volatile; /* fileId that is volatile */ }; @@ -216,6 +216,7 @@ struct Smb2CloseRequestHdr uint64_t fileId_volatile; /* fileId that is volatile */ }; +#define SMB2_SHARE_TYPE_NONE 0x00 #define SMB2_SHARE_TYPE_DISK 0x01 #define SMB2_SHARE_TYPE_PIPE 0x02 #define SMB2_SHARE_TYPE_PRINT 0x03 diff --git a/src/service_inspectors/dce_rpc/dce_smb_paf.cc b/src/service_inspectors/dce_rpc/dce_smb_paf.cc index 84e09a420..730458de5 100644 --- a/src/service_inspectors/dce_rpc/dce_smb_paf.cc +++ b/src/service_inspectors/dce_rpc/dce_smb_paf.cc @@ -32,7 +32,7 @@ namespace inline void DCE2_SMB_PAF_SHIFT(uint64_t& x64, const uint8_t& x8) { x64 <<= 8; - x64 |= (uint64_t) x8; + x64 |= (uint64_t)x8; } } @@ -45,7 +45,8 @@ using namespace snort; * junk states, header type must be Session Message. * *********************************************************************/ -static inline bool DCE2_PafSmbIsValidNetbiosHdr(uint32_t nb_hdr, bool junk, const SmbNtHdr *nt_hdr, uint32_t *nb_len) +static inline bool DCE2_PafSmbIsValidNetbiosHdr(uint32_t nb_hdr, bool junk, const SmbNtHdr* nt_hdr, + uint32_t* nb_len) { uint8_t type = (uint8_t)(nb_hdr >> 24); uint8_t bit = (uint8_t)((nb_hdr & 0x00ff0000) >> 16); @@ -72,19 +73,20 @@ static inline bool DCE2_PafSmbIsValidNetbiosHdr(uint32_t nb_hdr, bool junk, cons return false; } } - //The bit should be checked only for SMB1, because the length in NetBIOS header should not exceed 0x1FFFF. + //The bit should be checked only for SMB1, because the length in NetBIOS header should not + // exceed 0x1FFFF. //See [MS-SMB] 2.1 Transport. There is no such limit for SMB2 or SMB3 - if(is_smb1) + if (is_smb1) { if ((bit != 0x00) && (bit != 0x01)) return false; } nbs_hdr = htonl(nb_hdr); - if(is_smb1) - *nb_len = NbssLen((const NbssHdr *)&nbs_hdr); + if (is_smb1) + *nb_len = NbssLen((const NbssHdr*)&nbs_hdr); else - *nb_len = NbssLen2((const NbssHdr *)&nbs_hdr); + *nb_len = NbssLen2((const NbssHdr*)&nbs_hdr); return true; } @@ -109,12 +111,12 @@ static StreamSplitter::Status dce2_smb_paf(DCE2_PafSmbData* ss, Flow* flow, cons { uint32_t n = 0; StreamSplitter::Status ps = StreamSplitter::SEARCH; - const SmbNtHdr *nt_hdr = nullptr; + const SmbNtHdr* nt_hdr = nullptr; uint32_t nb_len = 0; DCE2_SmbSsnData* sd = get_dce2_smb_session_data(flow); - if (dce2_paf_abort(flow, (DCE2_SsnData*)sd)) + if ( dce2_paf_abort((DCE2_SsnData*)sd) ) { return StreamSplitter::ABORT; } @@ -131,7 +133,7 @@ static StreamSplitter::Status dce2_smb_paf(DCE2_PafSmbData* ss, Flow* flow, cons DCE2_SMB_PAF_SHIFT(ss->nb_hdr, data[n]); //(data + n + 1) points to the SMB header protocol identifier //(0xFF,'SMB' or 0xFE,'SMB'), which follows the NetBIOS header - nt_hdr = (const SmbNtHdr *)(data + n + 1); + nt_hdr = (const SmbNtHdr*)(data + n + 1); if (DCE2_PafSmbIsValidNetbiosHdr((uint32_t)ss->nb_hdr, false, nt_hdr, &nb_len)) { *fp = (nb_len + sizeof(NbssHdr) + n) - ss->paf_state; @@ -146,9 +148,10 @@ static StreamSplitter::Status dce2_smb_paf(DCE2_PafSmbData* ss, Flow* flow, cons //(data + n - sizeof(DCE2_SMB_ID) + 1) points to the smb_idf field //in SmbNtHdr (0xFF,'SMB' or 0xFE,'SMB'), which follows the NetBIOS header - nt_hdr = (const SmbNtHdr *)(data + n - DCE2_SMB_ID_SIZE + 1); + nt_hdr = (const SmbNtHdr*)(data + n - DCE2_SMB_ID_SIZE + 1); //ss->nb_hdr is the value to 4 bytes of NetBIOS header + 4 bytes of - //SMB header protocol identifier . Right shift by 32 bits to get the value of NetBIOS header + //SMB header protocol identifier . Right shift by 32 bits to get the value of NetBIOS + // header if (!DCE2_PafSmbIsValidNetbiosHdr((uint32_t)(ss->nb_hdr >> 32), true, nt_hdr, &nb_len)) { break; diff --git a/src/service_inspectors/dce_rpc/dce_tcp_paf.cc b/src/service_inspectors/dce_rpc/dce_tcp_paf.cc index 1d04b7763..374816ef3 100644 --- a/src/service_inspectors/dce_rpc/dce_tcp_paf.cc +++ b/src/service_inspectors/dce_rpc/dce_tcp_paf.cc @@ -51,7 +51,7 @@ static StreamSplitter::Status dce2_tcp_paf(DCE2_PafTcpData* ds, Flow* flow, cons int num_requests = 0; - if (dce2_paf_abort(flow, (DCE2_SsnData*)sd)) + if ( dce2_paf_abort((DCE2_SsnData*)sd) ) { return StreamSplitter::ABORT; } @@ -66,9 +66,9 @@ static StreamSplitter::Status dce2_tcp_paf(DCE2_PafTcpData* ds, Flow* flow, cons if ((DceRpcCoVersMaj(co_hdr) == DCERPC_PROTO_MAJOR_VERS__5) && (DceRpcCoVersMin(co_hdr) == DCERPC_PROTO_MINOR_VERS__0) && (((flags & PKT_FROM_CLIENT) - && DceRpcCoPduType(co_hdr) == DCERPC_PDU_TYPE__BIND) - || ((flags & PKT_FROM_SERVER) - && DceRpcCoPduType(co_hdr) == DCERPC_PDU_TYPE__BIND_ACK)) + && DceRpcCoPduType(co_hdr) == DCERPC_PDU_TYPE__BIND) + || ((flags & PKT_FROM_SERVER) + && DceRpcCoPduType(co_hdr) == DCERPC_PDU_TYPE__BIND_ACK)) && (DceRpcCoFragLen(co_hdr) >= sizeof(DceRpcCoHdr))) { autodetected = true;