00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #ifdef HAVE_CONFIG_H
00042 #include "config.h"
00043 #endif
00044
00045 #define MODNAME "spp_portscan2"
00046 #define MAX_TARGETS 5
00047 #define MAX_PORTS 64
00048 #define MEM_CHUNK 32
00049 #define PS_T 1
00050 #define TGT_T 2
00051
00052 #ifndef TRUE
00053 #define TRUE 0
00054 #endif
00055 #ifndef FALSE
00056 #define FALSE 1
00057 #endif
00058
00059 #define OPT_TARGET_COUNT "targets_max"
00060 #define OPT_MAX_SCANNER "scanners_max"
00061 #define OPT_TGT_LIMIT "target_limit"
00062 #define OPT_PORT_LIMIT "port_limit"
00063 #define OPT_TIMEOUT "timeout"
00064 #define OPT_LOG "log"
00065
00066 #define DEFAULT_MAX_SCANNER 1000
00067 #define DEFAULT_TARGET_COUNT 1000
00068 #define DEFAULT_TARGET_LIMIT 5
00069 #define DEFAULT_PORT_LIMIT 20
00070 #define DEFAULT_TIMEOUT 60
00071
00072
00073
00074
00075 #ifndef DEBUG
00076 #ifndef INLINE
00077 #define INLINE inline
00078 #endif
00079 #else
00080 #ifdef INLINE
00081 #undef INLINE
00082 #endif
00083 #define INLINE
00084 #endif
00085
00086 #include "spp_portscan2.h"
00087 #include "spp_conversation.h"
00088 #include "mempool.h"
00089 #include "plugbase.h"
00090 #include "mstring.h"
00091 #include "util.h"
00092 #include "log.h"
00093 #include "parser.h"
00094 #include "detect.h"
00095 #include "rules.h"
00096 #include "decode.h"
00097 #include "debug.h"
00098 #include "ubi_SplayTree.h"
00099 #include "ubi_BinTree.h"
00100 #ifndef WIN32
00101 #include <sys/socket.h>
00102 #include <netinet/in.h>
00103 #include <arpa/inet.h>
00104 #endif
00105 #include "generators.h"
00106 #ifdef GIDS
00107 #include "spp_stickydrop.h"
00108 #endif
00109
00110 #include <assert.h>
00111
00112
00113 typedef struct _PortScanner
00114 {
00115 ubi_trNode Node;
00116 MemBucket *bucket;
00117
00118 u_int32_t scanner_ip;
00119
00120 struct timeval initial_time;
00121 struct timeval last_time;
00122
00123 int port_count;
00124 int target_count;
00125
00126 ubi_trRoot targetRoot;
00127 ubi_trRootPtr targetRootPtr;
00128
00129 int targetsExceeded;
00130 int portsExceeded;
00131
00132 int bytes;
00133 int packets;
00134
00135 u_int32_t event_id;
00136 } Portscanner;
00137
00138 typedef struct _ScanTarget
00139 {
00140 ubi_trNode Node;
00141 Portscanner *parent;
00142 MemBucket *bucket;
00143
00144
00145 u_int32_t target_ip;
00146 int port_count;
00147
00148 struct timeval initial_time;
00149 struct timeval last_time;
00150
00151 char plist[65536/8];
00152 } ScanTarget;
00153
00154 typedef struct _hostNode
00155 {
00156 IpAddrSet *address;
00157 u_short hsp;
00158 u_short lsp;
00159 u_int32_t flags;
00160 struct _hostNode *nextNode;
00161 } HostNode;
00162
00163 HostNode *ignoreList;
00164
00165
00166 int num_ports_from;
00167 int num_ports_to;
00168 u_int32_t *ignorePortFrom;
00169 u_int32_t *ignorePortTo;
00170
00171 typedef struct _Portscan2Data
00172 {
00173 ubi_trRoot Scanners;
00174
00175 ubi_trRootPtr ScannersPtr;
00176
00177 u_int32_t scanner_count;
00178 u_int32_t target_count;
00179
00180 MemPool TargetPool;
00181 MemPool ScannerPool;
00182
00183
00184 FILE *logfile;
00185 char *logpath;
00186
00187 int tgtThreshold;
00188 int portThreshold;
00189 int timeout;
00190 char isInitialized;
00191 struct timeval prune_time;
00192 } Portscan2Data;
00193
00194
00195 Portscan2Data ps2data;
00196
00197
00198 extern char *file_name;
00199 extern int file_line;
00200 extern u_int32_t event_id;
00201
00202 #ifdef GIDS
00203
00204 extern SDtimeout sdt;
00205 #endif
00206
00207
00208 void Scan2Init(u_char *);
00209 static int targetCompareFunc(ubi_trItemPtr , ubi_trNodePtr);
00210
00211
00212 void ParseScanmungeArgs(u_char *);
00213
00214 static int PruneTargets(Portscanner *p, u_int32_t now, int tokill);
00215 static int PrunePortscanners(u_int32_t now, int tokill, Portscanner *saveme);
00216
00217 void SLog(Packet *, int, Portscanner *);
00218 void SAlert(Packet *, int, Portscanner *);
00219 INLINE int portIsSet(char *, int);
00220 INLINE void InitPortlist(ScanTarget *target);
00221 void setPort(char *, int);
00222 void dumpPacketStats(Portscanner *);
00223
00224
00225 void InitIgnoreHosts(u_char *);
00226 IpAddrSet* IgnoreAllocAddrNode(HostNode *);
00227 void ScanParseIp(char *, HostNode *);
00228
00229
00230 void InitIgnoreFrom(u_char *);
00231 void InitIgnoreTo(u_char *);
00232 void InitIgnorePorts(u_char *, u_int32_t **, int *);
00233 u_int32_t ScanParsePort(char *);
00234
00235 int IsIgnored(Packet *);
00236
00237
00238
00239
00240
00241
00242 void ParseScanmungeArgs(u_char *args)
00243 {
00244 int num_toks, s_toks;
00245 char **toks = NULL;
00246 char **stoks;
00247 int i;
00248 char* index;
00249 char logpath[STD_BUF], tmp[STD_BUF];
00250
00251
00252 strncpy(logpath, pv.log_dir, STD_BUF);
00253 strncpy(tmp, "/scan.log", STD_BUF);
00254 strncat(logpath, tmp, STD_BUF);
00255
00256
00257 ps2data.scanner_count = DEFAULT_MAX_SCANNER;
00258 ps2data.target_count = DEFAULT_TARGET_COUNT;
00259 ps2data.tgtThreshold = DEFAULT_TARGET_LIMIT;
00260 ps2data.portThreshold = DEFAULT_PORT_LIMIT;
00261 ps2data.timeout = DEFAULT_TIMEOUT;
00262
00263 if (args)
00264 {
00265
00266 toks = mSplit(args, ",", 11, &num_toks, 0);
00267
00268 i=0;
00269
00270 while (i < num_toks)
00271 {
00272 index = toks[i];
00273
00274 while(isspace((int)*index)) index++;
00275
00276 stoks = mSplit(index, " ", 4, &s_toks, 0);
00277
00278 if (!stoks[1] || stoks[1][0] == '\0')
00279 {
00280 FatalError("%s: %s(%d) => '%s' has null value. ",
00281 MODNAME, file_name, file_line, stoks[0]);
00282 }
00283 if(!strcasecmp(stoks[0], OPT_MAX_SCANNER))
00284 {
00285 if(isdigit((int)stoks[1][0]))
00286 {
00287
00288 ps2data.scanner_count = atoi(stoks[1]);
00289 i++;
00290 }
00291 else
00292 {
00293
00294 FatalError("%s: %s(%d) => '%s' has invalid value '%s'. ",
00295 MODNAME, file_name, file_line,
00296 stoks[0], stoks[1]);
00297 }
00298 }
00299 else if(!strcasecmp(stoks[0], OPT_TARGET_COUNT))
00300 {
00301 if(isdigit((int)(stoks[1][0])))
00302 {
00303
00304 ps2data.target_count = atoi(stoks[1]);
00305 i++;
00306 }
00307 else
00308 {
00309 FatalError("%s: %s(%d) => '%s' has invalid value '%s'. ",
00310 MODNAME, file_name, file_line,
00311 stoks[0], stoks[1]);
00312 }
00313 }
00314 else if(!strcasecmp(stoks[0], OPT_TGT_LIMIT))
00315 {
00316 if(isdigit((int)(stoks[1][0])))
00317 {
00318
00319 ps2data.tgtThreshold = atoi(stoks[1]);
00320 i++;
00321 }
00322 else
00323 {
00324 FatalError("%s: %s(%d) => '%s' has invalid value '%s'. ",
00325 MODNAME, file_name, file_line,
00326 stoks[0], stoks[1]);
00327 }
00328 }
00329 else if(!strcasecmp(stoks[0], OPT_PORT_LIMIT))
00330 {
00331 if(isdigit((int)(stoks[1][0])))
00332 {
00333
00334 ps2data.portThreshold = atoi(stoks[1]);
00335 i++;
00336 }
00337 else
00338 {
00339 FatalError("%s: %s(%d) => '%s' has invalid value '%s'. ",
00340 MODNAME, file_name, file_line,
00341 stoks[0], stoks[1]);
00342 }
00343 }
00344 else if(!strcasecmp(stoks[0], OPT_TIMEOUT))
00345 {
00346 if(isdigit((int)(stoks[1][0])))
00347 {
00348 ps2data.timeout = atoi(stoks[1]);
00349 i++;
00350 }
00351 else
00352 {
00353 FatalError("%s: %s(%d) => '%s' has invalid value '%s'. ",
00354 MODNAME, file_name, file_line,
00355 stoks[0], stoks[1]);
00356 }
00357 }
00358 else if(!strcasecmp(stoks[0], OPT_LOG))
00359 {
00360 if(isascii((int)(stoks[1][0])))
00361 {
00362 if (stoks[1][0] == '/')
00363 strncpy (logpath, stoks[1], STD_BUF);
00364 else
00365 {
00366 strncpy(logpath, pv.log_dir, STD_BUF);
00367 strncat(logpath, "/", STD_BUF);
00368 strncat(logpath, stoks[1], STD_BUF);
00369 }
00370 i++;
00371 }
00372 else
00373 {
00374 FatalError("%s: %s(%d) => '%s' has invalid value '%s'. ",
00375 MODNAME, file_name, file_line,
00376 stoks[0], stoks[1]);
00377 }
00378 }
00379 else
00380 {
00381 FatalError("%s: %s(%d) => option '%s' is undefined. ",
00382 MODNAME, file_name, file_line, stoks[0]);
00383 }
00384
00385 mSplitFree(&stoks, s_toks);
00386 }
00387 mSplitFree(&toks, num_toks);
00388 }
00389 LogMessage (" %s: %s\n", OPT_LOG, logpath);
00390 LogMessage (" %s: %d\n", OPT_MAX_SCANNER, ps2data.scanner_count);
00391 LogMessage (" %s: %d\n", OPT_TARGET_COUNT, ps2data.target_count);
00392 LogMessage (" %s: %d\n", OPT_TGT_LIMIT, ps2data.tgtThreshold);
00393 LogMessage (" %s: %d\n", OPT_PORT_LIMIT, ps2data.portThreshold);
00394 LogMessage (" %s: %d\n", OPT_TIMEOUT, ps2data.timeout);
00395
00396
00397 ps2data.logfile = fopen(logpath, "a+");
00398
00399 if(ps2data.logfile == NULL)
00400 {
00401 FatalError("Can't open logfile: %s", ps2data.logpath);
00402 }
00403 }
00404
00405
00406
00407
00408
00409 void InitIgnoreHosts(u_char *hosts)
00410 {
00411 char **toks;
00412 int num_toks;
00413 int num_hosts = 0;
00414 HostNode *currentHost;
00415
00416
00417 #ifdef DEBUG
00418 char ruleIP[16], ruleNetMask[16];
00419 #endif
00420
00421 currentHost = NULL;
00422 ignoreList = NULL;
00423
00424 if(hosts == NULL)
00425 {
00426 ErrorMessage(MODNAME ": ERROR: %s(%d)=> No arguments to "
00427 "portscan2-ignorehosts, ignoring.\n",
00428 file_name, file_line);
00429 return;
00430 }
00431
00432 toks = mSplit(hosts, " ", 127, &num_toks, '\\');
00433
00434 for(num_hosts = 0; num_hosts < num_toks; num_hosts++)
00435 {
00436 if((currentHost = (HostNode *) calloc(1, sizeof(HostNode))) == NULL)
00437 {
00438 FatalError("[!] ERROR: Unable to allocate space for "
00439 "portscan IgnoreHost");
00440 }
00441 currentHost->address = NULL;
00442 currentHost->nextNode = ignoreList;
00443 ignoreList = currentHost;
00444
00445 #ifdef DEBUG
00446 printf(MODNAME ": InitIgnoreHosts(): Adding server %s\n",
00447 toks[num_hosts]);
00448 #endif
00449
00450 ScanParseIp(toks[num_hosts], currentHost);
00451 }
00452
00453 mSplitFree(&toks, num_toks);
00454
00455 #ifdef DEBUG
00456 currentHost = ignoreList;
00457
00458 while(currentHost)
00459 {
00460 memset(ruleIP, '\0', 16);
00461 memset(ruleNetMask, '\0', 16);
00462
00463 strncpy(ruleIP,
00464 inet_ntoa(*(struct in_addr *) & currentHost->address->ip_addr),
00465 15);
00466 strncpy(ruleNetMask,
00467 inet_ntoa(*(struct in_addr *) & currentHost->address->netmask),
00468 15);
00469
00470 printf(MODNAME ": InitIgnoreHosts(): Added server %s/%s\n",
00471 ruleIP, ruleNetMask);
00472 currentHost = currentHost->nextNode;
00473 }
00474 #endif
00475
00476 }
00477
00478
00479
00480
00481 IpAddrSet* IgnoreAllocAddrNode(HostNode *host)
00482 {
00483 IpAddrSet *idx;
00484
00485 if((idx = (IpAddrSet *) calloc(1, sizeof(IpAddrSet))) == NULL)
00486 {
00487 FatalError("[!] ERROR: Unable to allocate space for "
00488 "portscan IP addr\n");
00489 }
00490
00491 idx->next = host->address;
00492 host->address = idx;
00493
00494 return idx;
00495 }
00496
00497
00498
00499
00500 void ScanParseIp(char *addr, HostNode *host)
00501 {
00502 char **toks;
00503 int num_toks;
00504 int i, not_flag;
00505 IpAddrSet *tmp_addr;
00506 char *enbracket, *ports;
00507 char *tmp;
00508
00509 if(addr == NULL)
00510 {
00511 ErrorMessage("ERROR %s(%d) => Undefine address in "
00512 "portscan-ignorehosts directive, igoring.\n", file_name,
00513 file_line);
00514
00515 return;
00516 }
00517
00518 if(*addr == '!')
00519 {
00520 host->flags |= EXCEPT_SRC_IP;
00521 addr++;
00522 }
00523
00524 if(*addr == '$')
00525 {
00526 if((tmp = VarGet(addr + 1)) == NULL)
00527 {
00528 ErrorMessage("ERROR %s (%d) => Undefined variable \"%s\", "
00529 "ignoring\n", file_name, file_line, addr);
00530
00531 return;
00532 }
00533 }
00534 else
00535 {
00536 tmp = addr;
00537 }
00538
00539 ports = strrchr(tmp, (int)'@');
00540
00541 if (*tmp == '[')
00542 {
00543 enbracket = strrchr(tmp, (int)']');
00544 if (enbracket) *enbracket = '\x0';
00545
00546 if (ports && enbracket && (ports < enbracket))
00547 {
00548 FatalError("[!] ERROR %s(%d) => syntax error in"
00549 "portscan2-ignorehosts \"%s\"\n",
00550 file_name, file_line, tmp);
00551 }
00552 toks = mSplit(tmp+1, ",", 128, &num_toks, 0);
00553
00554 for(i = 0; i < num_toks; i++)
00555 {
00556 tmp_addr = IgnoreAllocAddrNode(host);
00557
00558 ParseIP(toks[i], tmp_addr);
00559 }
00560
00561 mSplitFree(&toks, num_toks);
00562 }
00563 else
00564 {
00565 if (ports) *ports = '\x0';
00566
00567 tmp_addr = IgnoreAllocAddrNode(host);
00568
00569 ParseIP(tmp, tmp_addr);
00570 }
00571
00572 if (ports)
00573 {
00574 ports++;
00575 if (ParsePort(ports, &(host->hsp), &(host->lsp), "ip", ¬_flag))
00576 host->flags |= ANY_SRC_PORT;
00577 if (not_flag)
00578 host->flags |= EXCEPT_SRC_PORT;
00579 } else {
00580 host->flags |= ANY_SRC_PORT;
00581 }
00582
00583 }
00584
00585
00586
00587
00588
00589 void InitIgnoreFrom(u_char *args)
00590 {
00591 InitIgnorePorts(args, &ignorePortFrom, &num_ports_from);
00592 }
00593
00594
00595
00596
00597
00598 void InitIgnoreTo(u_char *args)
00599 {
00600 InitIgnorePorts(args, &ignorePortTo, &num_ports_to);
00601 }
00602
00603
00604
00605
00606
00607 void InitIgnorePorts(u_char *list, u_int32_t **ports, int *num)
00608 {
00609 int new_ports, max_ports;
00610 u_int32_t *pool;
00611 char **toks;
00612 int num_toks;
00613
00614 *ports = NULL;
00615 *num = 0;
00616 max_ports = 0;
00617
00618 if(list == NULL)
00619 {
00620 ErrorMessage(MODNAME ": ERROR: %s(%d)=> No arguments to "
00621 "portscan2-ignoreports, ignoring.\n",
00622 file_name, file_line);
00623 return;
00624 }
00625
00626 toks = mSplit(list, " ", MAX_PORTS, &num_toks, '\\');
00627
00628 for(;*num < num_toks; (*num)++)
00629 {
00630 if(*num >= max_ports)
00631 {
00632 new_ports = max_ports + MEM_CHUNK;
00633 if((pool = (u_int32_t *) calloc(new_ports, sizeof(u_int32_t))) == NULL)
00634 {
00635 FatalError("[!] ERROR: Unable to allocate space for "
00636 "portscan2-ignoreports");
00637 }
00638 if (*ports != NULL)
00639 {
00640 memcpy(pool, *ports, max_ports * sizeof(u_int32_t));
00641 free(*ports);
00642 }
00643 max_ports = new_ports;
00644 *ports = pool;
00645 }
00646 (*ports)[*num] = ScanParsePort(toks[*num]);
00647 #ifdef DEBUG
00648 printf(MODNAME ": InitIgnorePorts(): Added port %u\n",
00649 (unsigned) (*ports)[*num]);
00650 #endif
00651 }
00652
00653 mSplitFree(&toks, num_toks);
00654
00655 #ifdef DEBUG
00656 printf(MODNAME ": InitIgnorePorts(): %d port(s) added\n", *num);
00657 #endif
00658 }
00659
00660
00661
00662
00663 u_int32_t ScanParsePort(char *port)
00664 {
00665 char *tmp;
00666
00667 if(port == NULL)
00668 {
00669 FatalError("ERROR %s(%d) => Undefined ports in "
00670 "portscan2-ignoreports directive\n",
00671 file_name, file_line);
00672 }
00673
00674 if(*port == '$')
00675 {
00676 if((tmp = VarGet(port + 1)) == NULL)
00677 {
00678 FatalError("ERROR %s (%d) => Undefined variable \"%s\"\n",
00679 file_name, file_line, port);
00680
00681 }
00682 }
00683 else
00684 {
00685 tmp = port;
00686 }
00687
00688 if(!isdigit((int)tmp[0]))
00689 {
00690 FatalError("ERROR %s(%d) => Bad port list to "
00691 "portscan2-ignoreports\n", file_name, file_line);
00692 }
00693 return((u_int32_t)atol(tmp));
00694 }
00695
00696
00697
00698
00699
00700 int IsIgnored(Packet *p)
00701 {
00702 #ifdef DEBUG
00703 char sourceIP[16], ruleIP[16], ruleNetMask[16];
00704 #endif
00705 HostNode *currentHost = ignoreList;
00706 int i;
00707
00708 for(i = 0; i < num_ports_from; i++)
00709 {
00710 if (p->sp == ignorePortFrom[i])
00711 {
00712 #ifdef DEBUG
00713 memset(sourceIP, '\0', 16);
00714 strncpy(sourceIP, inet_ntoa(p->iph->ip_src), 15);
00715 printf(MODNAME ": IsIgnored(): Source port %u from %s found!\n",
00716 (unsigned) p->sp, sourceIP);
00717 #endif
00718 return(1);
00719 }
00720 }
00721
00722 for(i = 0; i < num_ports_to; i++)
00723 {
00724 if (p->dp == ignorePortTo[i])
00725 {
00726 #ifdef DEBUG
00727 memset(sourceIP, '\0', 16);
00728 strncpy(sourceIP, inet_ntoa(p->iph->ip_src), 15);
00729 printf(MODNAME ": IsIgnored(): Destination port %u "
00730 "from %s found!\n",
00731 (unsigned) p->dp, sourceIP);
00732 #endif
00733 return(1);
00734 }
00735 }
00736
00737 while(currentHost)
00738 {
00739
00740
00741
00742
00743 if(CheckAddrPort(currentHost->address, currentHost->hsp,
00744 currentHost->lsp, p, currentHost->flags, CHECK_SRC))
00745 {
00746 #ifdef DEBUG
00747 memset(sourceIP, '\0', 16);
00748 memset(ruleIP, '\0', 16);
00749 memset(ruleNetMask, '\0', 16);
00750 strncpy(sourceIP, inet_ntoa(p->iph->ip_src), 15);
00751 strncpy(ruleIP, inet_ntoa(*(struct in_addr*)
00752 &(currentHost->address->ip_addr)), 14);
00753 strncpy(ruleNetMask,
00754 inet_ntoa(*(struct in_addr *)
00755 &(currentHost->address->netmask)), 15);
00756
00757 printf(MODNAME ": IsIgnored(): Server %s found in %s/%s!\n",
00758 sourceIP, ruleIP, ruleNetMask);
00759 #endif
00760 return(1);
00761 }
00762
00763 currentHost = currentHost->nextNode;
00764 }
00765
00766 return(0);
00767 }
00768
00769
00770
00771
00772
00773 INLINE void InitPortlist(ScanTarget *target)
00774 {
00775 int i;
00776
00777 for(i=0; i<65536/8; i++)
00778 {
00779 target->plist[i] = 0;
00780 }
00781 }
00782
00783
00784
00785
00786
00787
00788
00789 INLINE void AddTargetPort(ScanTarget *target, u_int16_t offset, Packet *p)
00790 {
00791
00792
00793
00794
00795
00796 target->plist[(offset/8)] |= 1<<(offset%8);
00797
00798 target->port_count++;
00799 target->parent->port_count++;
00800
00801 if(target->parent->port_count > ps2data.portThreshold)
00802 {
00803 if(target->parent->portsExceeded == FALSE)
00804 {
00805 SLog(p, 0, target->parent);
00806 SAlert(p, 0, target->parent);
00807 target->parent->portsExceeded = TRUE;
00808
00809
00810 #ifdef GIDS
00811 if((SppStickydIsRunning()) && sdt.portscan2)
00812 {
00813 AddIpToBlockTree(p, 0, sdt.portscan2);
00814 }
00815 #endif
00816
00817 }
00818 else
00819 {
00820 SLog(p, 0, target->parent);
00821 }
00822 }
00823 }
00824
00825
00826
00827
00828 INLINE int portIsSet(char *portlist, int offset)
00829 {
00830
00831 return portlist[(offset/8)] & (1<<(offset%8));
00832 }
00833
00834
00835
00836
00837
00838
00839
00840 void AddTarget(Portscanner *ps, Packet *p)
00841 {
00842 struct in_addr tmp;
00843 ScanTarget *target = NULL;
00844 MemBucket *mb = NULL;
00845 int pruned;
00846
00847
00848 mb = mempool_alloc(&ps2data.TargetPool);
00849
00850 if(mb == NULL)
00851 {
00852 DEBUG_WRAP(DebugMessage(DEBUG_PORTSCAN2, "Outta Target Nodes :(\n"););
00853
00854
00855
00856
00857
00858
00859 pruned = PrunePortscanners(p->pkth->ts.tv_sec, 0, ps);
00860
00861 if(pruned <= 0)
00862 {
00863 DEBUG_WRAP(DebugMessage(DEBUG_PORTSCAN2,
00864 "Pruned got %d nodes --- forcing\n"););
00865 pruned = PrunePortscanners(p->pkth->ts.tv_sec, 5, ps);
00866 }
00867
00868 mb = mempool_alloc(&ps2data.TargetPool);
00869 }
00870
00871 if(mb == NULL)
00872 {
00873 DEBUG_WRAP(DebugMessage(DEBUG_PORTSCAN2,
00874 "[*] Outta Target Nodes -- stage2 returning\n"););
00875 return;
00876 }
00877
00878 target = (ScanTarget *) mb->data;
00879 target->bucket = mb;
00880
00881
00882
00883
00884 target->target_ip = (u_int32_t)p->iph->ip_dst.s_addr;
00885 target->port_count = 1;
00886 target->initial_time.tv_sec = p->pkth->ts.tv_sec;
00887 target->last_time.tv_sec = p->pkth->ts.tv_sec;
00888 target->parent = ps;
00889
00890 InitPortlist(target);
00891
00892
00893 if(ubi_sptInsert(ps->targetRootPtr, (ubi_btNodePtr)target,
00894 (ubi_btNodePtr)target, NULL) == ubi_trFALSE)
00895 {
00896 DEBUG_WRAP(DebugMessage(DEBUG_PORTSCAN2,
00897 "Insert into Targets failed\n"););
00898 }
00899
00900
00901 target->parent->target_count++;
00902
00903
00904 AddTargetPort(target, p->dp, p);
00905
00906
00907 if(ps->target_count > ps2data.tgtThreshold)
00908 {
00909 if(ps->targetsExceeded == FALSE)
00910 {
00911 tmp.s_addr = ps->scanner_ip;
00912
00913 DEBUG_WRAP(DebugMessage(DEBUG_PORTSCAN2,
00914 "Portscanner %s # targets exceeded\n",
00915 inet_ntoa(tmp)););
00916
00917 SLog(p, 0, ps);
00918 SAlert(p, 0, ps);
00919 ps->targetsExceeded = TRUE;
00920
00921
00922 #ifdef GIDS
00923 if((SppStickydIsRunning()) && sdt.portscan2)
00924 {
00925 AddIpToBlockTree(p, 0, sdt.portscan2);
00926 }
00927 #endif
00928
00929 }
00930 else
00931 {
00932 SLog(p, 0, ps);
00933 }
00934 }
00935 }
00936
00937
00938
00939
00940
00941 void AddPortScanner(Packet *p)
00942 {
00943 Portscanner *ps = NULL;
00944 MemBucket *mb = NULL;
00945
00946 mb = mempool_alloc(&ps2data.ScannerPool);
00947
00948 if(mb == NULL)
00949 {
00950 DEBUG_WRAP(DebugMessage(DEBUG_PORTSCAN2, "out of Scanner Nodes\n"););
00951
00952 return;
00953 }
00954
00955 ps = (Portscanner *) mb->data;
00956 ps->bucket = mb;
00957
00958
00959 ps->scanner_ip = (u_int32_t)p->iph->ip_src.s_addr;
00960 ps->last_time.tv_sec = p->pkth->ts.tv_sec;
00961 ps->initial_time.tv_sec = p->pkth->ts.tv_sec;
00962 ps->port_count = 0;
00963 ps->target_count = 0;
00964 ps->targetRootPtr = &ps->targetRoot;
00965 ps->portsExceeded = FALSE;
00966 ps->targetsExceeded = FALSE;
00967
00968 DEBUG_WRAP(DebugMessage(DEBUG_PORTSCAN2,
00969 "Assigning a scanner ip of %s\n",
00970 inet_ntoa(p->iph->ip_src)););
00971
00972
00973 if(ubi_trInitTree(ps->targetRootPtr, targetCompareFunc,
00974 0) == ubi_trFALSE)
00975 {
00976 printf("init tree failed!\n");
00977 }
00978
00979
00980 AddTarget(ps, p);
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991 if(ubi_sptInsert(ps2data.ScannersPtr,
00992 (ubi_btNodePtr)ps,
00993 (ubi_btNodePtr)ps, NULL) == ubi_trFALSE)
00994 {
00995 DEBUG_WRAP(DebugMessage(DEBUG_PORTSCAN2,
00996 "Insert into Scanners failed\n"););
00997 }
00998 }
00999
01000
01001
01002
01003 static int psCompareFunc(ubi_trItemPtr ItemPtr, ubi_trNodePtr NodePtr)
01004 {
01005 Portscanner *A = (Portscanner *) NodePtr;
01006 Portscanner *B = (Portscanner *) ItemPtr;
01007 #ifdef DEBUG
01008 #define IPLEN 256
01009 char sip[IPLEN];
01010
01011 strncpy(sip, inet_ntoa(*(struct in_addr *) &A->scanner_ip), IPLEN);
01012 DebugMessage(DEBUG_PORTSCAN2,"psCompareFunc %s %s\n",
01013 sip,
01014 inet_ntoa(*(struct in_addr *) &B->scanner_ip));
01015
01016 #undef IPLEN
01017 #endif
01018
01019
01020
01021 if(A->scanner_ip < B->scanner_ip)
01022 {
01023 return 1;
01024 }
01025 else if(A->scanner_ip > B->scanner_ip)
01026 {
01027 return -1;
01028 }
01029
01030 return 0;
01031 }
01032
01033
01034
01035
01036 static int targetCompareFunc(ubi_trItemPtr ItemPtr, ubi_trNodePtr NodePtr)
01037 {
01038 ScanTarget *A;
01039 ScanTarget *B;
01040
01041 A = (ScanTarget *) NodePtr;
01042 B = (ScanTarget *) ItemPtr;
01043
01044 if(A->target_ip < B->target_ip)
01045 return 1;
01046 else if(B->target_ip < A->target_ip)
01047 return -1;
01048
01049 return 0;
01050 }
01051
01052
01053
01054
01055
01056
01057 void SAlert(Packet *p, int scan_type, Portscanner *ps)
01058 {
01059 Event event;
01060 char outstring[255];
01061
01062 snprintf(outstring, 255, SCAN2_PREFIX_STR
01063 "%s: %d targets %d ports in %d seconds",
01064 inet_ntoa(*((struct in_addr *) &ps->scanner_ip)),
01065 ps->target_count,
01066 ps->port_count,
01067 (int) (p->pkth->ts.tv_sec - ps->initial_time.tv_sec));
01068
01069
01070 DEBUG_WRAP(DebugMessage(DEBUG_PORTSCAN2, "%s\n", outstring););
01071 SetEvent(&event, GENERATOR_SPP_SCAN2, SCAN_TYPE, 1, 0, 0, 0);
01072
01073 CallAlertFuncs(p, outstring, NULL, &event);
01074 ps->event_id = event.event_id;
01075 }
01076
01077
01078
01079
01080
01081 void SLog(Packet *p, int scan_type, Portscanner *ps)
01082 {
01083 char src[STD_BUF];
01084 char dst[STD_BUF];
01085 char timestamp[TIMEBUF_SIZE];
01086 char flagString[9];
01087
01088 strlcpy(src, inet_ntoa(p->iph->ip_src), 16);
01089 strlcpy(dst, inet_ntoa(p->iph->ip_dst), 16);
01090 ts_print((struct timeval *) &p->pkth->ts, timestamp);
01091
01092 if(p->tcph)
01093 {
01094 CreateTCPFlagString(p, flagString);
01095 fprintf(ps2data.logfile,"%s TCP src: %s dst: %s sport: %u dport: %u "
01096 "tgts: %u ports: %u flags: %s event_id: %u\n", timestamp, src,
01097 dst, p->sp, p->dp, ps->target_count, ps->port_count,
01098 flagString, ps->event_id);
01099 }
01100 else if(p->udph)
01101 {
01102 fprintf(ps2data.logfile, "%s UDP src: %s dst: %s sport: %u dport: %u "
01103 "tgts: %u ports: %u event_id: %u\n", timestamp, src, dst,
01104 p->sp, p->dp, ps->target_count, ps->port_count, ps->event_id);
01105 }
01106 else if(p->icmph)
01107 {
01108 fprintf(ps2data.logfile, "%s ICMP src: %s dst: %s type: %u code: %u "
01109 "tgts: %u event_id: %u\n", timestamp, src, dst, p->icmph->type,
01110 p->icmph->code, ps->target_count, ps->event_id);
01111 }
01112
01113 fflush(ps2data.logfile);
01114 }
01115
01116
01117
01118
01119
01120 void psWatch(Packet *p)
01121 {
01122 Portscanner tmp;
01123 Portscanner *returned;
01124 ScanTarget tgt;
01125 ScanTarget *rtgt;
01126
01127 #ifdef DEBUG
01128 #define IPLEN 256
01129 char sip[IPLEN];
01130
01131 strncpy(sip, inet_ntoa(p->iph->ip_src), IPLEN);
01132 DebugMessage(DEBUG_PORTSCAN2,"In PsWatch... %s:%d->%s:%d state: %p\n",
01133 sip,
01134 p->dp,
01135 inet_ntoa(p->iph->ip_dst),
01136 p->sp);
01137
01138 #undef IPLEN
01139 #endif
01140
01141
01142 if(IsIgnored(p))
01143 {
01144 DEBUG_WRAP(DebugMessage(DEBUG_PORTSCAN2,"Matched ignore list.\n"););
01145 return;
01146 }
01147
01148
01149 tmp.scanner_ip = (u_int32_t)p->iph->ip_src.s_addr;
01150
01151 DEBUG_WRAP(DebugMessage(DEBUG_PORTSCAN2,"scanner_ip to lookfor: %s\n", inet_ntoa(p->iph->ip_src)););
01152 returned = (Portscanner *) ubi_sptFind(ps2data.ScannersPtr, (ubi_btItemPtr)&tmp);
01153
01154 if(returned == NULL)
01155 {
01156 DEBUG_WRAP(DebugMessage(DEBUG_PORTSCAN2,
01157 "Portscanner not found. Allocating\n", returned););
01158
01159 AddPortScanner(p);
01160 }
01161 else
01162 {
01163
01164 DEBUG_WRAP(DebugMessage(DEBUG_PORTSCAN2,
01165 "Found portscanner: %p, returned->scanner_ip: %s\n",
01166 returned,
01167 inet_ntoa(*(struct in_addr *) &returned->scanner_ip)););
01168
01169
01170 returned->last_time.tv_sec = p->pkth->ts.tv_sec;
01171
01172 tgt.target_ip = (u_int32_t)p->iph->ip_dst.s_addr;
01173
01174
01175 rtgt = (ScanTarget *) ubi_sptFind((ubi_trRootPtr)returned->targetRootPtr,
01176 (ubi_btItemPtr)&tgt);
01177
01178 if(rtgt == NULL)
01179 {
01180
01181 AddTarget(returned, p);
01182
01183
01184
01185
01186
01187
01188 }
01189 else
01190 {
01191
01192 if(!portIsSet(rtgt->plist, p->dp))
01193 {
01194
01195 AddTargetPort(rtgt, p->dp, p);
01196
01197
01198
01199
01200
01201
01202 }
01203
01204 if(p->pkth->ts.tv_sec >= (returned->initial_time.tv_sec + ps2data.timeout))
01205 {
01206 DEBUG_WRAP(DebugMessage(DEBUG_PORTSCAN2,
01207 "Pruning out targets %p due to timeout\n",
01208 returned););
01209
01210
01211 PruneTargets(returned, p->pkth->ts.tv_sec, 0);
01212 returned->initial_time.tv_sec = p->pkth->ts.tv_sec;
01213 }
01214 }
01215 }
01216
01217 if(p->pkth->ts.tv_sec >= (ps2data.prune_time.tv_sec + ps2data.timeout))
01218 {
01219 DEBUG_WRAP(DebugMessage(DEBUG_PORTSCAN2,
01220 "Pruning out scanners due to timeout\n"););
01221
01222
01223 PrunePortscanners(p->pkth->ts.tv_sec, 0, NULL);
01224 ps2data.prune_time.tv_sec = p->pkth->ts.tv_sec;
01225 }
01226
01227 DEBUG_WRAP(DebugMessage(DEBUG_PORTSCAN2,
01228 "leaving pswatch: Scanner count: %u\n",
01229 ubi_trCount(ps2data.ScannersPtr)););
01230 }
01231
01232 void SetupScan2(void)
01233 {
01234 RegisterPreprocessor("portscan2", Scan2Init);
01235 RegisterPreprocessor("portscan2-ignorehosts", InitIgnoreHosts);
01236 RegisterPreprocessor("portscan2-ignoreports-from", InitIgnoreFrom);
01237 RegisterPreprocessor("portscan2-ignoreports-to", InitIgnoreTo);
01238 }
01239
01240
01241
01242
01243 void Scan2Init(u_char *args)
01244 {
01245 struct timeval tv;
01246 struct timezone tz;
01247
01248 LogMessage("WARNING: the portscan2 preprocessor will be deprecated in "
01249 "the next release of snort. Please switch to using SFPortscan.\n");
01250
01251 memset(&ps2data, 0, sizeof(Portscan2Data));
01252
01253 if(conv_data.isInitialized != 1)
01254 {
01255 FatalError("Please activate spp_conversation before"
01256 " trying to activate spp_portscan2\n");
01257 }
01258
01259 LogMessage ("Portscan2 config:\n");
01260 ParseScanmungeArgs(args);
01261 gettimeofday(&tv, &tz);
01262
01263 ps2data.ScannersPtr = &ps2data.Scanners;
01264
01265
01266 ubi_trInitTree(ps2data.ScannersPtr, psCompareFunc, 0);
01267
01268
01269 if(mempool_init(&ps2data.ScannerPool,
01270 ps2data.scanner_count,
01271 sizeof(Portscanner)))
01272 {
01273 FatalError("ERROR: Can't initialize mempool for Scanners\n");
01274 }
01275
01276 if(mempool_init(&ps2data.TargetPool , ps2data.target_count, sizeof(ScanTarget)))
01277 {
01278 FatalError("ERROR: Can't initialize mempool for Targets\n");
01279 }
01280
01281 ps2data.isInitialized = 1;
01282 conv_data.watch_scans = 1;
01283 }
01284
01285 static void DeleteTarget(ScanTarget *target)
01286 {
01287 mempool_free(&ps2data.TargetPool,target->bucket);
01288 }
01289
01290
01291 static void DeletePortscanner(Portscanner *ps)
01292 {
01293 Portscanner *oldps;
01294
01295
01296 DEBUG_WRAP(DebugMessage(DEBUG_PORTSCAN2, "Deleteing portscanner %p\n", ps);
01297 DebugMessage(DEBUG_PORTSCAN2,
01298 "ps->scanner_ip: %X\n", ps->scanner_ip);
01299 DebugMessage(DEBUG_PORTSCAN2,
01300 "ps->initial_time: %u\n", ps->initial_time.tv_sec);
01301 DebugMessage(DEBUG_PORTSCAN2,
01302 "ps->last_time: %u\n", ps->last_time.tv_sec);
01303 DebugMessage(DEBUG_PORTSCAN2,
01304 "ps->targetRootPtr: %p\n", ps->targetRootPtr);
01305
01306 );
01307
01308 (void)ubi_trKillTree(ps->targetRootPtr, DeleteTarget);
01309
01310
01311 oldps = (Portscanner *) ubi_sptRemove(ps2data.ScannersPtr,
01312 (ubi_btNodePtr) ps);
01313
01314 mempool_free(&ps2data.ScannerPool,ps->bucket);
01315 }
01316
01317
01318
01319 static int PruneTargets(Portscanner *p, u_int32_t now, int tokill)
01320 {
01321 ScanTarget *idx;
01322 u_int32_t pruned = 0;
01323
01324 if(ubi_trCount(p->targetRootPtr) == 0)
01325 {
01326 return 0;
01327 }
01328
01329
01330 if(tokill == 0)
01331 {
01332 idx = (ScanTarget *) ubi_btFirst((ubi_btNodePtr)p->targetRootPtr);
01333
01334 if(idx == NULL)
01335 {
01336 return 0;
01337 }
01338
01339 do
01340 {
01341 if((idx->last_time.tv_sec + ps2data.timeout) > now)
01342 {
01343 ScanTarget *savidx = idx;
01344
01345 if(ubi_trCount(p->targetRootPtr) > 1)
01346 {
01347 idx = (ScanTarget *) ubi_btNext((ubi_btNodePtr)idx);
01348 DEBUG_WRAP(DebugMessage(DEBUG_CONVERSATION,
01349 "pruning stale target\n"););
01350
01351 p->port_count -= savidx->port_count;
01352 p->target_count--;
01353 savidx = (ScanTarget *)ubi_sptRemove(p->targetRootPtr, (ubi_btNodePtr) savidx);
01354 DeleteTarget(savidx);
01355 pruned++;
01356 }
01357 else
01358 {
01359 p->port_count -= savidx->port_count;
01360 p->target_count--;
01361 savidx = (ScanTarget *)ubi_sptRemove(p->targetRootPtr, (ubi_btNodePtr) savidx);
01362 DeleteTarget(savidx);
01363 pruned++;
01364 return pruned;
01365 }
01366 }
01367 else
01368 {
01369 if(idx != NULL && ubi_trCount(p->targetRootPtr))
01370 {
01371 idx = (ScanTarget *) ubi_btNext((ubi_btNodePtr)idx);
01372 }
01373 else
01374 {
01375 return pruned;
01376 }
01377 }
01378 } while(idx != NULL);
01379
01380 return pruned;
01381 }
01382 else
01383 {
01384 while(tokill-- && ubi_trCount(p->targetRootPtr) > 1)
01385 {
01386 idx = (ScanTarget *) ubi_btLeafNode((ubi_btNodePtr)p->targetRootPtr);
01387 p->target_count--;
01388 DeleteTarget(idx);
01389 }
01390 return 0;
01391 }
01392
01393 return 0;
01394 }
01395
01396 static int PrunePortscanners(u_int32_t now, int tokill, Portscanner *saveme)
01397 {
01398 Portscanner *idx;
01399 u_int32_t pruned = 0;
01400
01401 DEBUG_WRAP(DebugMessage(DEBUG_CONVERSATION,
01402 "Pruneport scanners called now: "
01403 " %u tokill: %d: saveme: %p, count: %u\n",
01404 now, tokill, saveme,
01405 ubi_trCount(ps2data.ScannersPtr)););
01406
01407 if(ubi_trCount(ps2data.ScannersPtr) <= 1)
01408 {
01409 DEBUG_WRAP(DebugMessage(DEBUG_CONVERSATION,
01410 "1 or less to prune. returning\n"););
01411 return 0;
01412 }
01413
01414
01415 if(tokill == 0)
01416 {
01417 idx = (Portscanner *) ubi_btFirst((ubi_btNodePtr)ps2data.ScannersPtr->root);
01418
01419 if(idx == NULL)
01420 {
01421 return 0;
01422 }
01423
01424 do
01425 {
01426 if(idx == saveme)
01427 {
01428 idx = (Portscanner *) ubi_btNext((ubi_btNodePtr)idx);
01429 continue;
01430 }
01431
01432 if((idx->last_time.tv_sec+ps2data.timeout) > now)
01433 {
01434 Portscanner *savidx = idx;
01435
01436 if(ubi_trCount(ps2data.ScannersPtr) > 1)
01437 {
01438 idx = (Portscanner *) ubi_btNext((ubi_btNodePtr)idx);
01439 DEBUG_WRAP(DebugMessage(DEBUG_CONVERSATION,
01440 "pruning stale portscanner\n"););
01441 DeletePortscanner(savidx);
01442 pruned++;
01443 }
01444 else
01445 {
01446 DeletePortscanner(savidx);
01447 pruned++;
01448 return pruned;
01449 }
01450 }
01451 else
01452 {
01453 if(idx != NULL && ubi_trCount(ps2data.ScannersPtr))
01454 {
01455 idx = (Portscanner *) ubi_btNext((ubi_btNodePtr)idx);
01456 }
01457 else
01458 {
01459 return pruned;
01460 }
01461 }
01462 } while(idx != NULL);
01463
01464 return pruned;
01465 }
01466 else
01467 {
01468 while(tokill-- && ubi_trCount(ps2data.ScannersPtr) > 1)
01469 {
01470 idx = (Portscanner *) ubi_btLeafNode((ubi_btNodePtr)ps2data.ScannersPtr);
01471 DeletePortscanner(idx);
01472 }
01473 return 0;
01474 }
01475
01476 return 0;
01477 }