📄 snort_httpinspect.c
字号:
/* ** Let's print out the global config */ PrintGlobalConf(GlobalConf); } /* ** Server Configuration */ else if(!iGlobal && !strcmp(pcToken, SERVER)) { if((iRet = ProcessUniqueServerConf(GlobalConf, ErrorString, ErrStrLen))) { return iRet; } } /* ** Invalid configuration keyword */ else { if(iGlobal) { snprintf(ErrorString, ErrStrLen, "Invalid configuration token '%s'. " "The first configuration must start with a '%s' " "configuration type.", pcToken, GLOBAL); } else { snprintf(ErrorString, ErrStrLen, "Invalid configuration token '%s'. Must be a '%s' " "configuration.", pcToken, SERVER); } return -1; } return 0;}/*** NAME** LogEvents::*//**** This is the routine that logs HttpInspect alerts through Snort.** ** Every Session gets looked at for any logged events, and if there are** events to be logged then we select the one with the highest priority.** ** We use a generic event structure that we set for each different event** structure. This way we can use the same code for event logging regardless** of what type of event strucure we are dealing with.** ** The important things to know about this function is how to work with** the event queue. The number of unique events is contained in the** stack_count variable. So we loop through all the unique events and** find which one has the highest priority. During this loop, we also** re-initialize the individual event counts for the next iteration, saving** us time in a separate initialization phase.** ** After we've iterated through all the events and found the one with the** highest priority, we then log that event through snort.** ** We've mapped the HttpInspect and the Snort alert IDs together, so we** can access them directly instead of having a more complex mapping** function. It's the only good way to do this.** ** @param Session pointer to Session construct** @param p pointer to the Snort packet construct** @param iInspectMode inspection mode to take event queue from** ** @return integer** ** @retval 0 this function only return success*/static inline int LogEvents(HI_SESSION *hi_ssn, Packet *p, int iInspectMode){ HI_GEN_EVENTS GenEvents; HI_EVENT *OrigEvent; HI_EVENT *HiEvent = NULL; Session *ssn = NULL; u_int32_t uiMask = 0; int iGenerator; int iStackCnt; int iEvent; int iCtr; /* ** Set the session ptr, if applicable */ if(p && p->ssnptr) ssn = (Session *)p->ssnptr; if(iInspectMode == HI_SI_CLIENT_MODE) { GenEvents.stack = hi_ssn->client.event_list.stack; GenEvents.stack_count = &(hi_ssn->client.event_list.stack_count); GenEvents.events = hi_ssn->client.event_list.events; iGenerator = GENERATOR_SPP_HTTP_INSPECT_CLIENT; } else if(iInspectMode == HI_SI_SERVER_MODE) { /* ** We have no server events right now, so we just return. */ return 0; } else { GenEvents.stack = hi_ssn->anom_server.event_list.stack; GenEvents.stack_count = &(hi_ssn->anom_server.event_list.stack_count); GenEvents.events = hi_ssn->anom_server.event_list.events; iGenerator = GENERATOR_SPP_HTTP_INSPECT_ANOM_SERVER; } /* ** Now starts the generic event processing */ iStackCnt = *(GenEvents.stack_count); /* ** IMPORTANT:: ** We have to check the stack count of the event queue before we process ** an log. */ if(iStackCnt == 0) { return 0; } /* ** Cycle through the events and select the event with the highest ** priority. */ for(iCtr = 0; iCtr < iStackCnt; iCtr++) { iEvent = GenEvents.stack[iCtr]; OrigEvent = &(GenEvents.events[iEvent]); /* ** Set the event to start off the comparison */ if(!HiEvent) { HiEvent = OrigEvent; } /* ** This is our "comparison function". Log the event with the highest ** priority. */ if(OrigEvent->event_info->priority < HiEvent->event_info->priority) { HiEvent = OrigEvent; } /* ** IMPORTANT: ** This is how we reset the events in the event queue. ** If you miss this step, you can be really screwed. */ OrigEvent->count = 0; } /* ** We use the iEvent+1 because the event IDs between snort and ** HttpInspect are mapped off-by-one. Don't ask why, drink Bud ** Dry . . . They're mapped off-by one because in the internal ** HttpInspect queue, events are mapped starting at 0. For some ** reason, it appears that the first event can't be zero, so we ** use the internal value and add one for snort. */ iEvent = HiEvent->event_info->alert_id + 1; uiMask = (u_int32_t)(1 << (iEvent & 31)); /* ** If we've already logged this event for this stream, then ** don't log it again. */ if(ssn && (ssn->http_alert_flags & uiMask)) { return 0; } SnortEventqAdd(iGenerator, iEvent, 1, 0, 3, HiEvent->event_info->alert_str,0); /* ** Set the http_flag bit so we don't log the event on a reassembled ** stream. */ if(ssn) ssn->http_alert_flags |= uiMask; /* ** Reset the event queue stack counter, in the case of pipelined ** requests. */ *(GenEvents.stack_count) = 0; return 0;}static inline int SetSiInput(HI_SI_INPUT *SiInput, Packet *p){ Session *ssnptr = NULL; SiInput->sip = p->iph->ip_src.s_addr; SiInput->dip = p->iph->ip_dst.s_addr; SiInput->sport = p->sp; SiInput->dport = p->dp; if(p->ssnptr) { ssnptr = (Session *)p->ssnptr; } /* ** We now set the packet direction */ if(ssnptr && ssnptr->session_flags & SSNFLAG_MIDSTREAM) { SiInput->pdir = HI_SI_NO_MODE; } else if(p->packet_flags & PKT_FROM_SERVER) { SiInput->pdir = HI_SI_SERVER_MODE; } else if(p->packet_flags & PKT_FROM_CLIENT) { SiInput->pdir = HI_SI_CLIENT_MODE; } else { SiInput->pdir = HI_SI_NO_MODE; } return HI_SUCCESS;}/*** NAME** SnortHttpInspect::*//**** This function calls the HttpInspect function that processes an HTTP ** session.**** We need to instantiate a pointer for the HI_SESSION that HttpInspect ** fills in. Right now stateless processing fills in this session, which ** we then normalize, and eventually detect. We'll have to handle ** separately the normalization events, etc.** ** This function is where we can see from the highest level what the** HttpInspect flow looks like.**** @param GlobalConf pointer to the global configuration** @param p pointer to the Packet structure**** @return integer**** @retval 0 function successful** @retval <0 fatal error** @retval >0 non-fatal error*/int SnortHttpInspect(HTTPINSPECT_GLOBAL_CONF *GlobalConf, Packet *p){ extern HttpUri UriBufs[URI_COUNT]; extern int do_detect; extern OptTreeNode *otn_tmp; HI_SESSION *Session; HI_SI_INPUT SiInput; int iInspectMode = 0; int iRet; int iCallDetect = 1; if(!p->iph || !p->tcph) { return 1; } /* ** Set up the HI_SI_INPUT pointer. This is what the session_inspection() ** routines use to determine client and server traffic. Plus, this makes ** the HttpInspect library very independent from snort. */ SetSiInput(&SiInput, p); /* ** HTTPINSPECT PACKET FLOW:: ** ** Session Inspection Module:: ** The Session Inspection Module retrieves the appropriate server ** configuration for sessions, and takes care of the stateless ** vs. stateful processing in order to do this. Once this module ** does it's magic, we're ready for the primetime. ** ** HTTP Inspection Module:: ** This isn't really a module in HttpInspect, but more of a helper ** function that sends the data to the appropriate inspection ** routine (client, server, anomalous server detection). ** ** HTTP Normalization Module:: ** This is where we normalize the data from the HTTP Inspection ** Module. The Normalization module handles what type of normalization ** to do (client, server). ** ** HTTP Detection Module:: ** This isn't being used in the first iteration of HttpInspect, but ** all the HTTP detection components of signatures will be. ** ** HTTP Event Output Module:: ** The Event Ouput Module handles any events that have been logged ** in the inspection, normalization, or detection phases. */ /* ** Session Inspection Module:: */ if((iRet = hi_si_session_inspection(GlobalConf, &Session, &SiInput, &iInspectMode))) { return iRet; } /* ** HTTP Inspection Module:: ** ** This is where we do the client/server inspection and find the ** various HTTP protocol fields. We then normalize these fields and ** call the detection engine. ** ** The reason for the loop is for pipelined requests. Doing pipelined ** requests in this way doesn't require any memory or tracking overhead. ** Instead, we just process each request linearly. */ do { /* ** INIT: ** We set this equal to zero (again) because of the pipelining ** requests. We don't want to bail before we get to setting the ** URI, so we make sure here that this can't happen. */ p->uri_count = 0; UriBufs[0].decode_flags = 0; if(iInspectMode == HI_SI_SERVER_MODE) { /* Don't do server inspection */ if (Session->server_conf->flow_depth == -1) { do_detect = 0; p->preprocessors = 0; p->preprocessors |= PP_PORTSCAN; p->preprocessors |= PP_STREAM4; return 0; } } if((iRet = hi_mi_mode_inspection(Session, iInspectMode, p->data, p->dsize))) { LogEvents(Session,p,iInspectMode); return iRet; } if((iRet = hi_normalization(Session, iInspectMode))) { LogEvents(Session,p,iInspectMode); return iRet; } /* ** Let's setup the pointers for the detection engine, and ** then go for it. */ if(iInspectMode == HI_SI_CLIENT_MODE) { if(!iCallDetect || Session->server_conf->uri_only) { UriBufs[0].decode_flags |= HTTPURI_PIPELINE_REQ; } if(Session->client.request.uri_norm) { UriBufs[0].uri = Session->client.request.uri_norm; UriBufs[0].length = Session->client.request.uri_norm_size; p->uri_count = 1; p->packet_flags |= PKT_HTTP_DECODE; } else if(Session->client.request.uri) { UriBufs[0].uri = Session->client.request.uri; UriBufs[0].length = Session->client.request.uri_size; p->uri_count = 1; p->packet_flags |= PKT_HTTP_DECODE; } } else if(iInspectMode == HI_SI_SERVER_MODE) { /* ** We set the header length and detect the normal way. */ p->dsize = Session->server.header_size; /* ** If dsize is 0, we only get here because dsize was set to 0 ** by the server module by the flow_depth inspection. ** ** We check here to see whether this was a server response ** header or not. If the dsize is 0 then, we know that this ** is not the header and don't do any detection. */ if(p->dsize == 0) { do_detect = 0; p->preprocessors = 0; p->preprocessors |= PP_PORTSCAN; p->preprocessors |= PP_STREAM4; return 0; } } else { /* ** We log events before doing detection because every non-HTTP ** packet is possible an anomalous server. So we still want to ** go through the regular detection engine, and just log any ** alerts here before returning. ** ** Return normally if this isn't either HTTP client or server ** traffic. */ if(Session->anom_server.event_list.stack_count) LogEvents(Session, p, iInspectMode); return 0; } /* ** If we get here we either had a client or server request/response. ** We do the detection here, because we're starting a new paradigm ** about protocol decoders. ** ** Protocol decoders are now their own detection engine, since we are ** going to be moving protocol field detection from the generic ** detection engine into the protocol module. This idea scales much ** better than having all these Packet struct field checks in the ** main detection engine for each protocol field. */ Detect(p); otn_tmp = NULL; /* ** Handle event stuff after we do detection. ** ** Here's the reason why: ** - since snort can only handle one logged event per packet, ** we only log HttpInspect events if there wasn't one in the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -