📄 spp_sfportscan.c
字号:
/**************************************************************************** * * Copyright (C) 2004-2007 Sourcefire, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License Version 2 as * published by the Free Software Foundation. You may not use, modify or * distribute this program under any other version of the GNU General * Public License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ****************************************************************************/ /*** @file spp_sfportscan.c**** @author Daniel Roelker <droelker@sourcefire.com>**** @brief Portscan detection**** NOTES** - User Configuration: The following is a list of parameters that can** be configured through the user interface:**** proto { tcp udp icmp ip all }** scan_type { portscan portsweep decoy_portscan distributed_portscan all }** sense_level { high } # high, medium, low** watch_ip { } # list of IPs, CIDR blocks** ignore_scanners { } # list of IPs, CIDR blocks** ignore_scanned { } # list of IPs, CIDR blocks** memcap { 10000000 } # number of max bytes to allocate** logfile { /tmp/ps.log } # file to log detailed portscan info*/#include <sys/types.h>#ifndef WIN32 #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h>#endif /* !WIN32 */#include "decode.h"#include "plugbase.h"#include "generators.h"#include "event_wrapper.h"#include "util.h"#include "ipobj.h"#include "checksum.h"#include "packet_time.h"#include "snort.h"#include "sfthreshold.h"#include "sfsnprintfappend.h"#include "sf_iph.h"#include "portscan.h"#include "profiler.h"#define DELIMITERS " \t\n"#define TOKEN_ARG_BEGIN "{"#define TOKEN_ARG_END "}"#define PROTO_BUFFER_SIZE 256extern PV pv;extern char *file_name;extern int file_line;static int g_print_tracker = 0;static u_char g_logpath[256];static FILE *g_logfile = NULL;static Packet *g_tmp_pkt;int g_include_midstream = 0;#ifdef PERF_PROFILINGPreprocStats sfpsPerfStats;#endif/*** NAME** PortscanPacketInit::*//**** Initialize the Packet structure buffer so we can generate our** alert packets for portscan. We initialize the various fields in** the Packet structure and set the hardware layer for easy identification** by user interfaces.**** @return int**** @retval !0 initialization failed** @retval 0 success*/static int PortscanPacketInit(void){ const char mac_addr[] = "MACDAD"; Packet *p; p = (Packet *)SnortAlloc(sizeof(Packet)); p->pkth = (struct pcap_pkthdr *)SnortAlloc(sizeof(struct pcap_pkthdr) + ETHERNET_HEADER_LEN + SPARC_TWIDDLE + IP_MAXPACKET); /* Add 2 to align iph struct members on 4 byte boundaries - for sparc, etc */ p->pkt = ((u_char *)p->pkth + sizeof(struct pcap_pkthdr) + SPARC_TWIDDLE); p->eh = (EtherHdr *)p->pkt; p->iph = (IPHdr *)(((u_char *)p->eh) + ETHERNET_HEADER_LEN); p->data = ((u_char *)p->iph) + sizeof(IPHdr); /* ** Set the ethernet header with our cooked values. */ ((EtherHdr *)p->eh)->ether_type = htons(0x0800); memcpy(((EtherHdr *)p->eh)->ether_dst, mac_addr, 6); memcpy(((EtherHdr *)p->eh)->ether_src, mac_addr, 6); g_tmp_pkt = p; return 0;}void PortscanCleanExitFunction(int signal, void *foo){ ps_cleanup(); free((void *)g_tmp_pkt->pkth); free(g_tmp_pkt); g_tmp_pkt = NULL;}void PortscanRestartFunction(int signal, void *foo){ ps_cleanup(); free((void *)g_tmp_pkt->pkth); free(g_tmp_pkt); g_tmp_pkt = NULL;}/*** NAME** MakeProtoInfo::*//**** This routine makes the portscan payload for the events. The listed** info is:** - priority count (number of error transmissions RST/ICMP UNREACH)** - connection count (number of protocol connections SYN)** - ip count (number of IPs that communicated with host)** - ip range (low to high range of IPs)** - port count (number of port changes that occurred on host)** - port range (low to high range of ports connected too)**** @return integer**** @retval -1 buffer not large enough** @retval 0 successful*/static int MakeProtoInfo(PS_PROTO *proto, u_char *buffer, u_int *total_size){ unsigned char *ip1; unsigned char *ip2; int dsize; if(!total_size || !buffer) return -1; dsize = (IP_MAXPACKET - *total_size); if(dsize < PROTO_BUFFER_SIZE) return -1; ip1 = (unsigned char *)&proto->low_ip; ip2 = (unsigned char *)&proto->high_ip; if(proto->alerts == PS_ALERT_PORTSWEEP || proto->alerts == PS_ALERT_PORTSWEEP_FILTERED) { SnortSnprintf((char *)buffer, PROTO_BUFFER_SIZE, "Priority Count: %d\n" "Connection Count: %d\n" "IP Count: %d\n" "Scanned IP Range: %d.%d.%d.%d:%d.%d.%d.%d\n" "Port/Proto Count: %d\n" "Port/Proto Range: %d:%d\n", proto->priority_count, proto->connection_count, proto->u_ip_count, ip1[3],ip1[2],ip1[1],ip1[0], ip2[3],ip2[2],ip2[1],ip2[0], proto->u_port_count, proto->low_p, proto->high_p); } else { SnortSnprintf((char *)buffer, PROTO_BUFFER_SIZE, "Priority Count: %d\n" "Connection Count: %d\n" "IP Count: %d\n" "Scanner IP Range: %d.%d.%d.%d:%d.%d.%d.%d\n" "Port/Proto Count: %d\n" "Port/Proto Range: %d:%d\n", proto->priority_count, proto->connection_count, proto->u_ip_count, ip1[3],ip1[2],ip1[1],ip1[0], ip2[3],ip2[2],ip2[1],ip2[0], proto->u_port_count, proto->low_p, proto->high_p); } dsize = SnortStrnlen((const char *)buffer, PROTO_BUFFER_SIZE); *total_size += dsize; /* ** Set the payload size. This is protocol independent. */ g_tmp_pkt->dsize = dsize; return 0;}static int LogPortscanAlert(Packet *p, char *msg, u_int32_t event_id, u_int32_t event_ref, u_int32_t gen_id, u_int32_t sig_id){ char timebuf[TIMEBUF_SIZE]; ip_p src_addr; ip_p dst_addr; if(!p->iph) return -1; /* Do not log if being suppressed */ src_addr = GET_SRC_IP(p); dst_addr = GET_DST_IP(p); if( !sfthreshold_test(gen_id, sig_id, src_addr, dst_addr, p->pkth->ts.tv_sec) ) { return 0; } ts_print((struct timeval *)&p->pkth->ts, timebuf); fprintf(g_logfile, "Time: %s\n", timebuf); if(event_id) fprintf(g_logfile, "event_id: %u\n", event_id); else fprintf(g_logfile, "event_ref: %u\n", event_ref);#ifdef SUP_IP6 fprintf(g_logfile, "%s ", inet_ntoa(GET_SRC_IP(p))); fprintf(g_logfile, "-> %s %s\n", inet_ntoa(GET_DST_IP(p)), msg);#else fprintf(g_logfile, "%s ", inet_ntoa(p->iph->ip_src)); fprintf(g_logfile, "-> %s %s\n", inet_ntoa(p->iph->ip_dst), msg);#endif fprintf(g_logfile, "%.*s\n", p->dsize, p->data); fflush(g_logfile); return 0;}static int GeneratePSSnortEvent(Packet *p,u_int32_t gen_id,u_int32_t sig_id, u_int32_t sig_rev, u_int32_t class, u_int32_t priority, char *msg){ unsigned int event_id; event_id = GenerateSnortEvent(p,gen_id,sig_id,sig_rev,class,priority,msg); if(g_logfile) LogPortscanAlert(p, msg, event_id, 0, gen_id, sig_id); return event_id;}/*** NAME** GenerateOpenPortEvent::*//**** We have to generate open port events differently because we tag these** to the original portscan event.**** @return int**** @retval 0 success*/static int GenerateOpenPortEvent(Packet *p, u_int32_t gen_id, u_int32_t sig_id, u_int32_t sig_rev, u_int32_t class, u_int32_t pri, u_int32_t event_ref, struct timeval *event_time, char *msg){ Event event; /* ** This means that we logged an open port, but we don't have a event ** reference for it, so we don't log a snort event. We still keep ** track of it though. */ if(!event_ref) return 0; /* reset the thresholding subsystem checks for this packet */ sfthreshold_reset(); SetEvent(&event, gen_id, sig_id, sig_rev, class, pri, event_ref); //CallAlertFuncs(p,msg,NULL,&event); event.ref_time.tv_sec = event_time->tv_sec; event.ref_time.tv_usec = event_time->tv_usec; if(p) { /* * Do threshold test for suppression and thresholding. We have to do it * here since these are tagged packets, which aren't subject to thresholding, * but we want to do it for open port events. */ if( !sfthreshold_test(gen_id, sig_id, GET_SRC_IP(p), GET_DST_IP(p), p->pkth->ts.tv_sec) ) { return 0; } CallLogFuncs(p,msg,NULL,&event); } else { return -1; } if(g_logfile) LogPortscanAlert(p, msg, 0, event_ref, gen_id, sig_id); return event.event_id;}/*** NAME** MakeOpenPortInfo::*//** ** Write out the open ports info for open port alerts.**** @return integer*/static int MakeOpenPortInfo(PS_PROTO *proto, u_char *buffer, u_int *total_size, void *user){ int dsize; if(!total_size || !buffer) return -1; dsize = (IP_MAXPACKET - *total_size); if(dsize < PROTO_BUFFER_SIZE) return -1; SnortSnprintf((char *)buffer, PROTO_BUFFER_SIZE, "Open Port: %u\n", *((unsigned short *)user)); dsize = SnortStrnlen((const char *)buffer, PROTO_BUFFER_SIZE); *total_size += dsize; /* ** Set the payload size. This is protocol independent. */ g_tmp_pkt->dsize = dsize; return 0;}/*** NAME** MakePortscanPkt::*//*** We have to create this fake packet so portscan data can be passed** through the unified output.**** We want to copy the network and transport layer headers into our** fake packet.** */static int MakePortscanPkt(PS_PKT *ps_pkt, PS_PROTO *proto, int proto_type, void *user){ Packet *p; unsigned long tmp_addr; unsigned int hlen; unsigned int ip_size = 0; struct pcap_pkthdr *pkth = (struct pcap_pkthdr *)g_tmp_pkt->pkth; if(!ps_pkt && proto_type != PS_PROTO_OPEN_PORT) return -1; if(ps_pkt) { p = (Packet *)ps_pkt->pkt; if(!p->iph) return -1; hlen = IP_HLEN(p->iph)<<2; if ( p->iph != g_tmp_pkt->iph ) /* * it happen that ps_pkt->pkt can be the same * as g_tmp_pkt. Avoid overlapping copy then. */ memcpy((IPHdr *)g_tmp_pkt->iph, p->iph, hlen); if(ps_pkt->reverse_pkt) { tmp_addr = p->iph->ip_src.s_addr; ((IPHdr *)g_tmp_pkt->iph)->ip_src.s_addr = p->iph->ip_dst.s_addr; ((IPHdr *)g_tmp_pkt->iph)->ip_dst.s_addr = tmp_addr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -