/** * \brief Make the threshold logic for signatures * * \param de_ctx Dectection Context * \param tsh_ptr Threshold element * \param p Packet structure * \param s Signature structure * * \retval 2 silent match (no alert but apply actions) * \retval 1 alert on this event * \retval 0 do not alert on this event */ int PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const DetectThresholdData *td, Packet *p, const Signature *s, PacketAlert *pa) { SCEnter(); int ret = 0; if (td == NULL) { SCReturnInt(0); } if (td->type == TYPE_SUPPRESS) { ret = ThresholdHandlePacketSuppress(p,td,s->id,s->gid); } else if (td->track == TRACK_SRC) { Host *src = HostGetHostFromHash(&p->src); if (src) { ret = ThresholdHandlePacketHost(src,p,td,s->id,s->gid,pa); HostRelease(src); } } else if (td->track == TRACK_DST) { Host *dst = HostGetHostFromHash(&p->dst); if (dst) { ret = ThresholdHandlePacketHost(dst,p,td,s->id,s->gid,pa); HostRelease(dst); } } else if (td->track == TRACK_RULE) { SCMutexLock(&de_ctx->ths_ctx.threshold_table_lock); ret = ThresholdHandlePacketRule(de_ctx,p,td,s,pa); SCMutexUnlock(&de_ctx->ths_ctx.threshold_table_lock); } SCReturnInt(ret); }
/** * \brief Add a tag entry for a host. If it already exist, update it. * * \param tag_ctx Tag context for hosts * \param tde Tag data * \param p packet * * \retval 0 if it was added, 1 if it was updated */ int TagHashAddTag(DetectTagDataEntry *tde, Packet *p) { SCEnter(); uint8_t updated = 0; uint16_t num_tags = 0; Host *host = NULL; /* Lookup host in the hash. If it doesn't exist yet it's * created. */ if (tde->flags & TAG_ENTRY_FLAG_DIR_SRC) { host = HostGetHostFromHash(&p->src); } else if (tde->flags & TAG_ENTRY_FLAG_DIR_DST) { host = HostGetHostFromHash(&p->dst); } /* no host for us */ if (host == NULL) { return -1; } if (host->tag == NULL) { /* get a new tde as the one we have is on the stack */ DetectTagDataEntry *new_tde = DetectTagDataCopy(tde); if (new_tde != NULL) { host->tag = new_tde; (void) SC_ATOMIC_ADD(num_tags, 1); } } else { /* Append the tag to the list of this host */ /* First iterate installed entries searching a duplicated sid/gid */ DetectTagDataEntry *iter = NULL; for (iter = host->tag; iter != NULL; iter = iter->next) { num_tags++; if (iter->sid == tde->sid && iter->gid == tde->gid) { iter->cnt_match++; /* If so, update data, unless the maximum MATCH limit is * reached. This prevents possible DOS attacks */ if (iter->cnt_match < DETECT_TAG_MATCH_LIMIT) { /* Reset time and counters */ iter->first_ts = iter->last_ts = tde->first_ts; iter->packets = 0; iter->bytes = 0; } updated = 1; break; } } /* If there was no entry of this rule, append the new tde */ if (updated == 0 && num_tags < DETECT_TAG_MAX_TAGS) { /* get a new tde as the one we have is on the stack */ DetectTagDataEntry *new_tde = DetectTagDataCopy(tde); if (new_tde != NULL) { (void) SC_ATOMIC_ADD(num_tags, 1); new_tde->next = host->tag; host->tag = new_tde; } } else if (num_tags == DETECT_TAG_MAX_TAGS) { SCLogDebug("Max tags for sessions reached (%"PRIu16")", num_tags); } } HostRelease(host); SCReturnInt(updated); }
/** * \brief This function is used to match packets via the eDDOS rule * * \param t pointer to thread vars * \param det_ctx pointer to the pattern matcher thread * \param p pointer to the current packet * \param m pointer to the sigmatch that we will cast into DetectDummyData * * \retval 0 no match * \retval 1 match */ int DetecteDDOSMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, SigMatch *m) { int ret = 0; DetecteDDOSSig *dsig = (DetecteDDOSSig *) m->ctx; DetecteDDOSData *ddata; Host *h; time_t t1; double time_diff_ms; if (PKT_IS_PSEUDOPKT(p) || !PKT_IS_IPV4(p) || p->flags & PKT_HOST_SRC_LOOKED_UP) { return 0; } /* TODO: Inspect the packet contents here. * Suricata defines a `Packet` structure in decode.h which already defines * many useful elements -- have a look! */ h = HostGetHostFromHash(&(p->src)); // Only SRC or can DEST be used too? p->flags |= PKT_HOST_SRC_LOOKED_UP; if (h == NULL) { printf("host not found!\n"); return 0; } ddata = (DetecteDDOSData *) h->eddos; if (!ddata) { /* initialize fresh dummydata */ ddata = SCMalloc(sizeof (DetecteDDOSData)); bzero(ddata, sizeof (DetecteDDOSData)); h->eddos = ddata; } /** * Start counting for evaluation */ (ddata->cnt_packets)++; if (PKT_IS_TCP(p)) { //counter host (ddata->cnt_tcp)++; //counter global tcp_pkts_gesamt++; //printf("\nPakets TCP Flag: %d\n", p->tcph->th_flags); if (p->tcph->th_flags == tcp_syn_ack_flag) { (ddata->cnt_tcp_syn_ack)++; tcp_syn_ack_gesamt++; //printf("TCP_SYN_ACK"); } if (p->tcph->th_flags == tcp_fin_ack_flag) { (ddata->cnt_tcp_fin_ack)++; tcp_fin_ack_gesamt++; //printf("TCP_FIN_ACK"); } if (p->tcph->th_flags == TH_SYN) { (ddata->cnt_tcp_syn)++; tcp_syn_gesamt++; //printf("TCP_SYN"); } } if (PKT_IS_UDP(p)) { (ddata->cnt_udp)++; udp_pkt_gesamt++; } if (PKT_IS_ICMPV4(p) && p->icmpv4h->type == ICMP_ECHO) { (ddata->cnt_icmp_echo_req)++; icmp_gesamt++; } /** * End Counting */ /** * Start evaluation */ if (PKT_IS_UDP(p) || PKT_IS_TCP(p)) { t1 = p->ts.tv_sec; time_diff_ms = difftime(t1, ddata->PeriodStart); if (time_diff_ms > (60)) { /*check for alarm here*/ // abweichung vom 1:2 verhältnis SYN/ACK zu FIN/ACK float ver_syn_ack; float abw_syn_ack; // verhältnis von ICMP echo req paketen zu allen paketen float ver_echoreq_norm; // verhältnis von udp pakten zu allen paketen float ver_udp_norm; if (ddata->cnt_tcp_fin_ack != 0) { ver_syn_ack = ((float) (ddata->cnt_tcp_syn_ack) / ddata->cnt_tcp_fin_ack); } else { // we have syn but no syn_acks if ((((ddata->cnt_tcp_syn - ddata->cnt_tcp_syn_ack)*2) > dsig->max_abweichung_syn_ack ) && ddata->cnt_tcp_syn > 250) { printf("\nSYN zu SYN/ACK Host\n"); printf("\n SYN: %llu SYN/ACK: %llu \n", ddata->cnt_tcp_syn, ddata->cnt_tcp_syn_ack ); ver_syn_ack = -1; } ver_syn_ack = 0; } abw_syn_ack = (((1 / 2) - ver_syn_ack))*2; //printf("\nSYN/ACK zu FIN/ACK Host Value: %f # SYN/ACK: %llu - FIN/ACK: %llu\n", (abw_syn_ack), ddata->cnt_tcp_syn_ack, ddata->cnt_tcp_fin_ack); if (abw_syn_ack < 0) { // check if abweichung größer als in signatur angegeben if (fabs(abw_syn_ack) > dsig->max_abweichung_syn_ack) { ret = 1; printf("\nSYN/ACK zu FIN/ACK Host Value: %f # SYN/ACK: %llu - FIN/ACK: %llu\n", fabs(abw_syn_ack), ddata->cnt_tcp_syn_ack, ddata->cnt_tcp_fin_ack); } } // verhältnis icmp echo request berechnen ver_echoreq_norm = ((float) (ddata->cnt_icmp_echo_req) / ddata->cnt_packets)*100; // check if ICMP echo request pakete zu viel im verhältnis zu allen if (ver_echoreq_norm > (float) (dsig->max_icmp_echo_req_packets)) { ret = 1; //printf("\nICMP Host\n"); } /** // verhältnis udp paketen berechnen ver_udp_norm = ((float)(ddata->cnt_udp) / ddata->cnt_packets); // check if udp pakete zu viel im verhältnis zu allen if ( ver_udp_norm > (float)(dsig->max_udp_packets) ) { ret = 1; } */ /** * gesamtauswertung */ time_diff_ms = difftime(t1, start_time); if (time_diff_ms > (300)) { // auswertung udp pakete // verhältnis udp paketen berechnen ver_udp_norm = ((float) (udp_pkt_gesamt) / (udp_pkt_gesamt + tcp_pkts_gesamt))*100; //printf("UDP Pakete Verhaeltnis: %f", ver_udp_norm); // check if udp pakete zu viel im verhältnis zu allen if (ver_udp_norm > (float) (dsig->max_verhaeltnis_udp_packets)) { ret = 1; //printf("\nUDP ALL\n"); } // auswertung echo requests ver_echoreq_norm = ((float) (icmp_gesamt) / (udp_pkt_gesamt + tcp_pkts_gesamt))*100; if (ver_echoreq_norm > (float) (icmp_gesamt)) { ret = 1; printf("\nICMP ALL\n"); } // auswertung syn/ack if (tcp_fin_ack_gesamt != 0) { ver_syn_ack = ((float) (tcp_syn_ack_gesamt) / tcp_fin_ack_gesamt); } else { // we have syn but no syn_acks if (fabs((float)((tcp_syn_gesamt - tcp_syn_gesamt)*2)) > dsig->max_abweichung_syn_ack) { printf("\nSYN zu SYN/ACK ALL\n"); ver_syn_ack = -1; } ver_syn_ack = 0; } abw_syn_ack = (((1 / 2) - ver_syn_ack))*2; if (abw_syn_ack < 0) { // check if abweichung größer als in signatur angegeben if (fabs(abw_syn_ack) > dsig->max_abweichung_syn_ack) { ret = 1; printf("\nSYN/ACK zu FIN/ACK ALL\n"); } } // reset global counter for new interval tcp_pkts_gesamt = 0; udp_pkt_gesamt = 0; tcp_fin_ack_gesamt = 0; tcp_syn_ack_gesamt = 0; icmp_gesamt = 0; } /**printf("host found, packets now %d\n", (int)(ddata->cnt_packets)); ret = (ddata->cnt_packets > dsig->max_numpackets); */ // reset der parameter, da neuer zeitraum beginnt ddata->PeriodStart = p->ts.tv_sec; ddata->cnt_icmp_echo_req = 0; ddata->cnt_packets = 0; ddata->cnt_tcp = 0; ddata->cnt_tcp_fin_ack = 0; ddata->cnt_tcp_syn_ack = 0; ddata->cnt_udp = 0; } else { ret = 0; } } /** * End of evaluation */ //printf("\nHost: %d - %d\n", (int)h, ddata->cnt_packets); /** printf("#################################\n"); printf("Host: %d\n",(int)h); printf("\n TCP-SYN: %d \n", ddata->cnt_tcp_syn); printf("\n TCP-ACK: %d \n", ddata->cnt_tcp_ack); printf("\n Packets gesamt: %d \n", ddata->cnt_packets); printf("\n Packets TCP gesamt: %d \n", ddata->cnt_tcp); printf("\n Packets UDP gesamt: %d \n", ddata->cnt_udp); printf("\n ICMP ECHO REQUEST Packets: %d \n", ddata->cnt_icmp_echo_req); printf("#################################\n"); printf("\n\nTCP Gesamt: %llu\n",tcp_pkts_gesamt); printf("UDP Gesamt: %llu\n",udp_pkt_gesamt); printf("SYN: %llu\n",tcp_syn_gesamt); printf("ICMP: %llu\n",icmp_gesamt); printf("SYN_ACK gesamt %d\n",(int)tcp_syn_ack_gesamt); printf("FIN_ACK_gesamt %d\n\n",(int)tcp_fin_ack_gesamt); */ HostRelease(h); return ret; }