📄 spp_portscan2.c
字号:
/* $Id$ *//*** Copyright (C) 1998,1999,2000,2001 Martin Roesch <roesch@clark.net>** Copyright (C) 2001 Jed Haile <jhaile@nitrodata.com>** Copyright (C) 2002 Sourcefire, Inc** Chris Green <cmg@sourcefire.com>**** This program is free software; you can redistribute it and/or modify** it under the terms of the GNU General Public License as published by** the Free Software Foundation; either version 2 of the License, or** (at your option) any later version.**** 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.*//* state based portscan detector * by Jed Haile <jhaile@nitrodata.com> * version 0.0.1 * todo: 1. track timestamp, src, dst, proto, sport/icode, * dport/itype, length *//* ChangeLog: * * Fri Nov 22 2002 Joerg Lehrke <jlehrke@noc.de> * - fixed ignorehosts * * Tue Nov 26 2002 Joerg Lehrke <jlehrke@noc.de> * - added ignoreports * * Thu Nov 28 2002 Joerg Lehrke <jlehrke@noc.de> * - added port restriction to ignorehosts * * Tue Dec 3 2002 Joerg Lehrke <jlehrke@noc.de> * - fixed precedence problems */#ifdef HAVE_CONFIG_H#include "config.h"#endif#define MODNAME "spp_portscan2"#define MAX_TARGETS 5#define MAX_PORTS 64#define MEM_CHUNK 32#define PS_T 1#define TGT_T 2#ifndef TRUE#define TRUE 0#endif#ifndef FALSE#define FALSE 1#endif#define OPT_TARGET_COUNT "targets_max"#define OPT_MAX_SCANNER "scanners_max"#define OPT_TGT_LIMIT "target_limit"#define OPT_PORT_LIMIT "port_limit"#define OPT_TIMEOUT "timeout"#define OPT_LOG "log"#define DEFAULT_MAX_SCANNER 1000#define DEFAULT_TARGET_COUNT 1000#define DEFAULT_TARGET_LIMIT 5#define DEFAULT_PORT_LIMIT 20#define DEFAULT_TIMEOUT 60#ifndef DEBUG #ifndef INLINE #define INLINE inline #endif#else #ifdef INLINE #undef INLINE #endif #define INLINE #endif /* DEBUG */#include "spp_portscan2.h"#include "spp_conversation.h"#include "mempool.h"#include "plugbase.h"#include "mstring.h"#include "util.h"#include "log.h"#include "parser.h"#include "detect.h"#include "rules.h"#include "decode.h"#include "debug.h"#include "ubi_SplayTree.h"#include "ubi_BinTree.h"#ifndef WIN32#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#endif /* !WIN32 */#include "generators.h"#include <assert.h>/* this represents the incoming host */typedef struct _PortScanner{ ubi_trNode Node; /* for the splay tree */ MemBucket *bucket; u_int32_t scanner_ip; struct timeval initial_time; struct timeval last_time; int port_count; /* total count of ports this scanner has hit */ int target_count; /* total count of targets this scanner has hit */ ubi_trRoot targetRoot; /* this scanner's target tree*/ ubi_trRootPtr targetRootPtr; int targetsExceeded; int portsExceeded; int bytes; /* counts of things that happended */ int packets; u_int32_t event_id; } Portscanner;typedef struct _ScanTarget{ ubi_trNode Node; Portscanner *parent; /*pointer to the parent Portscanner node */ MemBucket *bucket; u_int32_t target_ip; int port_count; /* number of ports on this target hit by parent portscanner*/ struct timeval initial_time; struct timeval last_time; char plist[65536/8]; /* an array of bytes to store port info */} ScanTarget;typedef struct _hostNode{ IpAddrSet *address; u_short hsp; /* hi src port */ u_short lsp; /* lo src port */ u_int32_t flags; /* control flags */ struct _hostNode *nextNode;} HostNode;HostNode *ignoreList; /* for ignore-hosts *//* ignore-ports-from, ignore-ports-to */int num_ports_from;int num_ports_to;u_int32_t *ignorePortFrom;u_int32_t *ignorePortTo;typedef struct _Portscan2Data{ ubi_trRoot Scanners; ubi_trRootPtr ScannersPtr; u_int32_t scanner_count; u_int32_t target_count; MemPool TargetPool; MemPool ScannerPool; /** Global Program Data **/ FILE *logfile; char *logpath; int tgtThreshold; /* number of distinc targets to allow */ int portThreshold; /* number of distinct ports to allow before alerting */ int timeout; char isInitialized; struct timeval prune_time;} Portscan2Data;Portscan2Data ps2data;/** external globals from rules.c **/extern char *file_name;extern int file_line;extern u_int32_t event_id;/** FUNCTION PROTOTYPES **/void Scan2Init(u_char *);static int targetCompareFunc(ubi_trItemPtr , ubi_trNodePtr);/* void AddTarget(ubi_trRootPtr, u_int32_t, u_int16_t, u_int32_t); */void ParseScanmungeArgs(u_char *);/* delete the nodes from a portscanner */static int PruneTargets(Portscanner *p, u_int32_t now, int tokill);static int PrunePortscanners(u_int32_t now, int tokill, Portscanner *saveme);void SLog(Packet *, int, Portscanner *);void SAlert(Packet *, int, Portscanner *);INLINE int portIsSet(char *, int);INLINE void InitPortlist(ScanTarget *target);void setPort(char *, int);void dumpPacketStats(Portscanner *);/* For ignore hosts */void InitIgnoreHosts(u_char *);IpAddrSet* IgnoreAllocAddrNode(HostNode *);void ScanParseIp(char *, HostNode *);/* For ignore ports */void InitIgnoreFrom(u_char *);void InitIgnoreTo(u_char *);void InitIgnorePorts(u_char *, u_int32_t **, int *);u_int32_t ScanParsePort(char *);int IsIgnored(Packet *);/*************************************************************//* Parses all of scan2's args. They are as follows: *//* int psnodes, int targetnodes, char log, int targets, *//* int ports, int timeout *//*************************************************************/void ParseScanmungeArgs(u_char *args){ int num_toks, s_toks; char **toks = NULL; char **stoks; int i; char* index; char logpath[STD_BUF], tmp[STD_BUF]; /* setup the defaults */ strncpy(logpath, pv.log_dir, STD_BUF); strncpy(tmp, "/scan.log", STD_BUF); strncat(logpath, tmp, STD_BUF); /* way too low of defaults */ ps2data.scanner_count = DEFAULT_MAX_SCANNER; ps2data.target_count = DEFAULT_TARGET_COUNT; ps2data.tgtThreshold = DEFAULT_TARGET_LIMIT; ps2data.portThreshold = DEFAULT_PORT_LIMIT; ps2data.timeout = DEFAULT_TIMEOUT; if (args) { toks = mSplit(args, ",", 11, &num_toks, 0); i=0; while (i < num_toks) { index = toks[i]; while(isspace((int)*index)) index++; stoks = mSplit(index, " ", 4, &s_toks, 0); if (!stoks[1] || stoks[1][0] == '\0') { FatalError("%s: %s(%d) => '%s' has null value. ", MODNAME, file_name, file_line, stoks[0]); } if(!strcasecmp(stoks[0], OPT_MAX_SCANNER)) { if(isdigit((int)stoks[1][0])) { /* number of psnodes */ ps2data.scanner_count = atoi(stoks[1]); i++; } else { /* lets cool it with the leeway */ FatalError("%s: %s(%d) => '%s' has invalid value '%s'. ", MODNAME, file_name, file_line, stoks[0], stoks[1]); } } else if(!strcasecmp(stoks[0], OPT_TARGET_COUNT)) { if(isdigit((int)(stoks[1][0]))) { /* number of tgtnodes */ ps2data.target_count = atoi(stoks[1]); i++; } else { FatalError("%s: %s(%d) => '%s' has invalid value '%s'. ", MODNAME, file_name, file_line, stoks[0], stoks[1]); } } else if(!strcasecmp(stoks[0], OPT_TGT_LIMIT)) { if(isdigit((int)(stoks[1][0]))) { /* number of targets */ ps2data.tgtThreshold = atoi(stoks[1]); i++; } else { FatalError("%s: %s(%d) => '%s' has invalid value '%s'. ", MODNAME, file_name, file_line, stoks[0], stoks[1]); } } else if(!strcasecmp(stoks[0], OPT_PORT_LIMIT)) { if(isdigit((int)(stoks[1][0]))) { /* number of ports */ ps2data.portThreshold = atoi(stoks[1]); i++; } else { FatalError("%s: %s(%d) => '%s' has invalid value '%s'. ", MODNAME, file_name, file_line, stoks[0], stoks[1]); } } else if(!strcasecmp(stoks[0], OPT_TIMEOUT)) { if(isdigit((int)(stoks[1][0]))) { ps2data.timeout = atoi(stoks[1]); i++; } else { FatalError("%s: %s(%d) => '%s' has invalid value '%s'. ", MODNAME, file_name, file_line, stoks[0], stoks[1]); } } else if(!strcasecmp(stoks[0], OPT_LOG)) { if(isascii((int)(stoks[1][0]))) { if (stoks[1][0] == '/') strncpy (logpath, stoks[1], STD_BUF); else { strncpy(logpath, pv.log_dir, STD_BUF); strncat(logpath, "/", STD_BUF); strncat(logpath, stoks[1], STD_BUF); } i++; } else { FatalError("%s: %s(%d) => '%s' has invalid value '%s'. ", MODNAME, file_name, file_line, stoks[0], stoks[1]); } } else { FatalError("%s: %s(%d) => option '%s' is undefined. ", MODNAME, file_name, file_line, stoks[0]); } mSplitFree(&stoks, s_toks); } mSplitFree(&toks, num_toks); } LogMessage (" %s: %s\n", OPT_LOG, logpath); LogMessage (" %s: %d\n", OPT_MAX_SCANNER, ps2data.scanner_count); LogMessage (" %s: %d\n", OPT_TARGET_COUNT, ps2data.target_count); LogMessage (" %s: %d\n", OPT_TGT_LIMIT, ps2data.tgtThreshold); LogMessage (" %s: %d\n", OPT_PORT_LIMIT, ps2data.portThreshold); LogMessage (" %s: %d\n", OPT_TIMEOUT, ps2data.timeout); ps2data.logfile = fopen(logpath, "a+"); if(ps2data.logfile == NULL) { FatalError("Can't open logfile: %s", ps2data.logpath); }}/*************************************************************//* Called at runtime to establish the list of hosts who are *//* to be ignored by the portscan detector *//*************************************************************/void InitIgnoreHosts(u_char *hosts){ char **toks; int num_toks; int num_hosts = 0; HostNode *currentHost; /*int i;*/#ifdef DEBUG char ruleIP[16], ruleNetMask[16];#endif currentHost = NULL; ignoreList = NULL; if(hosts == NULL) { ErrorMessage(MODNAME ": ERROR: %s(%d)=> No arguments to " "portscan2-ignorehosts, ignoring.\n", file_name, file_line); return; } toks = mSplit(hosts, " ", 127, &num_toks, '\\'); for(num_hosts = 0; num_hosts < num_toks; num_hosts++) { if((currentHost = (HostNode *) calloc(1, sizeof(HostNode))) == NULL) { FatalError("[!] ERROR: Unable to allocate space for " "portscan IgnoreHost"); } currentHost->address = NULL; /* be paranoid */ currentHost->nextNode = ignoreList; ignoreList = currentHost;#ifdef DEBUG printf(MODNAME ": InitIgnoreHosts(): Adding server %s\n", toks[num_hosts]);#endif /* DEBUG */ ScanParseIp(toks[num_hosts], currentHost); } mSplitFree(&toks, num_toks); #ifdef DEBUG currentHost = ignoreList; while(currentHost) { memset(ruleIP, '\0', 16); memset(ruleNetMask, '\0', 16); strncpy(ruleIP, inet_ntoa(*(struct in_addr *) & currentHost->address->ip_addr), 15); strncpy(ruleNetMask, inet_ntoa(*(struct in_addr *) & currentHost->address->netmask), 15); printf(MODNAME ": InitIgnoreHosts(): Added server %s/%s\n", ruleIP, ruleNetMask); currentHost = currentHost->nextNode; }#endif /* DEBUG */}/************************************************************//* Helper function to set up the list of ignored hosts *//************************************************************/IpAddrSet* IgnoreAllocAddrNode(HostNode *host){ IpAddrSet *idx; if((idx = (IpAddrSet *) calloc(1, sizeof(IpAddrSet))) == NULL) { FatalError("[!] ERROR: Unable to allocate space for " "portscan IP addr\n"); } idx->next = host->address; host->address = idx;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -