📄 spp_sfportscan.c
字号:
/*** @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 "portscan.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;/*** 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 *)calloc(1, sizeof(Packet)); if(!p) return -1; p->pkth = calloc(1, sizeof(struct pcap_pkthdr) + ETHERNET_HEADER_LEN + 2 + IP_MAXPACKET); if(!p->pkth) return -1; p->pkth = (struct pcap_pkthdr *)(((u_char *)p->pkth)); /* Add 2 to align iph struct members on 4 byte boundaries - for sparc, etc */ p->pkt = ((u_char *)p->pkth + sizeof(SnortPktHeader) + 2); 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. */ p->eh->ether_type = htons(0x0800); memcpy(p->eh->ether_dst, mac_addr, 6); memcpy(p->eh->ether_src, mac_addr, 6); g_tmp_pkt = p; return 0;}/*** 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 = (char *)&proto->low_ip; ip2 = (char *)&proto->high_ip; if(proto->alerts == PS_ALERT_PORTSWEEP || proto->alerts == PS_ALERT_PORTSWEEP_FILTERED) { dsize = snprintf((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[0],ip1[1],ip1[2],ip1[3], ip2[0],ip2[1],ip2[2],ip2[3], proto->u_port_count, proto->low_p, proto->high_p); } else { dsize = snprintf((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[0],ip1[1],ip1[2],ip1[3], ip2[0],ip2[1],ip2[2],ip2[3], proto->u_port_count, proto->low_p, proto->high_p); } *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]; u_long src_addr = 0; u_long dst_addr = 0; if(!p->iph) return -1; /* Do not log if being suppressed */ if ( p->iph ) { src_addr = p->iph->ip_src.s_addr; dst_addr = p->iph->ip_dst.s_addr; } 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); fprintf(g_logfile, "%s ", inet_ntoa(p->iph->ip_src)); fprintf(g_logfile, "-> %s %s\n", inet_ntoa(p->iph->ip_dst), msg); 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, p->iph->ip_src.s_addr, p->iph->ip_dst.s_addr, p->pkth->ts.tv_sec) ) { return 0; } CallLogFuncs(p,msg,NULL,&event); } 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; dsize = snprintf((char *)buffer, PROTO_BUFFER_SIZE, "Open Port: %u\n", *((unsigned short *)user)); *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; 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(g_tmp_pkt->iph, p->iph, hlen); if(ps_pkt->reverse_pkt) { tmp_addr = p->iph->ip_src.s_addr; g_tmp_pkt->iph->ip_src.s_addr = p->iph->ip_dst.s_addr; g_tmp_pkt->iph->ip_dst.s_addr = tmp_addr; } ip_size += hlen; g_tmp_pkt->iph->ip_proto = 0xff; g_tmp_pkt->iph->ip_ttl = 0x00; g_tmp_pkt->data = (u_char *)((u_char *)g_tmp_pkt->iph + hlen); g_tmp_pkt->pkth->ts.tv_sec = p->pkth->ts.tv_sec; g_tmp_pkt->pkth->ts.tv_usec = p->pkth->ts.tv_usec; } switch(proto_type) { case PS_PROTO_TCP: case PS_PROTO_UDP:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -