00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifdef GIDS
00019 #ifndef IPFW
00020
00021 #include <sys/types.h>
00022 #include <stdlib.h>
00023 #include <ctype.h>
00024 #include <rpc/types.h>
00025 #include <string.h>
00026 #include <stdio.h>
00027 #include "generators.h"
00028 #include "event_wrapper.h"
00029 #include "assert.h"
00030 #include "util.h"
00031 #include "plugbase.h"
00032 #include "parser.h"
00033 #include "mempool.h"
00034 #include "plugbase.h"
00035 #include "mstring.h"
00036 #include "util.h"
00037 #include "log.h"
00038 #include "parser.h"
00039 #include "detect.h"
00040 #include "rules.h"
00041 #include "decode.h"
00042 #include "debug.h"
00043 #include "ubi_SplayTree.h"
00044 #include "ubi_BinTree.h"
00045
00046 #ifndef WIN32
00047 #include <sys/socket.h>
00048 #include <netinet/in.h>
00049 #include <arpa/inet.h>
00050 #endif
00051
00052 #include "spp_bait_and_switch.h"
00053 #include "inline.h"
00054
00055 #define MAX_PORTS 64
00056 #define MEM_CHUNK 32
00057 #define DIRECTION_SOURCE 0
00058 #define DIRECTION_DST 1
00059
00060
00061 typedef struct _BandS
00062 {
00063 ubi_trRoot attackerRoot;
00064 ubi_trRootPtr attackerRootPtr;
00065 MemPool AttackerPool;
00066 u_int32_t max_reroute_entries;
00067 char log;
00068 FILE *logfile;
00069 char *logpath;
00070 char iptpath[255];
00071 char iptcmd[255];
00072 char *insertmode;
00073 } BandS;
00074
00075 BandS bands;
00076
00077
00078 typedef struct _Attacker
00079 {
00080 ubi_trNode Node;
00081 MemBucket *bucket;
00082 u_int32_t attackerip;
00083 u_int32_t honeypotip;
00084 u_int32_t attackedip;
00085 u_int32_t timeout;
00086 struct timeval ruleaddtime;
00087 struct timeval ruledeletetime;
00088 char iptdnatcmd[255];
00089 char iptsnatcmd[255];
00090 char iptundnatcmd[255];
00091 char iptunsnatcmd[255];
00092 } Attacker;
00093
00094 Attacker attacker;
00095
00096 typedef struct _bashostNode
00097 {
00098 IpAddrSet *address;
00099 u_short hsp;
00100 u_short lsp;
00101 u_int32_t flags;
00102 struct _bashostNode *nextNode;
00103
00104 } basHostNode;
00105
00106 basHostNode *basignoreList;
00107 int num_ports_from;
00108 int num_ports_to;
00109 u_int32_t *basignorePortFrom;
00110 u_int32_t *basignorePortTo;
00111
00112 static void BaitandSwitchInit(u_char *);
00113 static void ParseBaitandSwitchArgs(char *);
00114 void BaitAndSwitch(Packet *, void *);
00115 void BASLog(Packet *);
00116
00117 static int IpAddressCompareFunction(ubi_trItemPtr, ubi_trNodePtr);
00118 static int PruneAttackers(u_int32_t now, int tokill, Attacker *saveme);
00119 static void BaitAndSwitchCleanExitFunction(int, void *);
00120 static void BaitAndSwitchRestartFunction(int, void *);
00121
00122
00123 void basInitIgnoreHosts(u_char *);
00124 IpAddrSet* basIgnoreAllocAddrNode(basHostNode *);
00125 void basScanParseIp(char *, basHostNode *);
00126
00127
00128 void basInitIgnoreFrom(u_char *);
00129 void basInitIgnoreTo(u_char *);
00130 void basInitIgnorePorts(u_char *, u_int32_t **, int *);
00131 u_int32_t basScanParsePort(char *);
00132
00133 int basIsIgnored(Packet *, char);
00134 int basAttackerSearch(Packet *, char);
00135
00136 static int s_bas_running = 0;
00137
00138 extern int do_detect;
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 void SetupBaitAndSwitch()
00154 {
00155
00156
00157
00158
00159 RegisterPreprocessor("bait-and-switch", BaitandSwitchInit);
00160 RegisterPreprocessor("bait-and-switch-ignorehosts", basInitIgnoreHosts);
00161 RegisterPreprocessor("bait-and-switch-ignoreports-from", basInitIgnoreFrom);
00162 RegisterPreprocessor("bait-and-switch-ignoreports-to", basInitIgnoreTo);
00163 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Preprocessor: BaitAndSwitch is setup...\n"););
00164 }
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178 static void BaitandSwitchInit(u_char *args)
00179 {
00180 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Preprocessor: BaitAndSwitch Initialized\n"););
00181
00182 memset(&bands, 0, sizeof(BandS));
00183 ParseBaitandSwitchArgs(args);
00184 bands.attackerRootPtr = &bands.attackerRoot;
00185
00186 ubi_trInitTree(bands.attackerRootPtr, IpAddressCompareFunction, 0);
00187 if(mempool_init(&bands.AttackerPool , bands.max_reroute_entries, sizeof(Attacker)))
00188 {
00189 FatalError("ERROR: Could not alloc memory for baitandswitch entries\n");
00190 }
00191 else if(!InlineMode())
00192 {
00193 FatalError("ERROR: We have to be in InlineMode() to use baitandswitch\n");
00194 }
00195
00196 s_bas_running = 1;
00197 if (system(savecmd) != 0)
00198 {
00199 FatalError("ERROR: failed to save iptables state before Bait-And-Switch bailing\n");
00200 }
00201
00202 AddFuncToPreprocList(BaitAndSwitch);
00203 AddFuncToCleanExitList(BaitAndSwitchCleanExitFunction, NULL);
00204 AddFuncToRestartList(BaitAndSwitchRestartFunction, NULL);
00205 }
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221 static void ParseBaitandSwitchArgs(char *args)
00222 {
00223 int num_toks, s_toks;
00224 char **toks = NULL;
00225 char **stoks;
00226 char **iptdirtoks;
00227 int num_iptdirtoks = 0;
00228 int i;
00229 char* index;
00230 char logpath[STD_BUF], tmp[STD_BUF];
00231 bands.insertmode="A";
00232
00233 strlcpy(logpath, pv.log_dir, STD_BUF);
00234 strlcpy(tmp, "/bands.log", STD_BUF);
00235 strlcat(logpath, tmp, STD_BUF);
00236
00237 strlcpy(bands.iptpath,"/sbin",STD_BUF);
00238
00239 if(snprintf(bands.iptcmd,sizeof(bands.iptcmd) -1,"%s/iptables",bands.iptpath) >= sizeof(bands.iptcmd))
00240 {
00241 FatalError("The iptcmd supplied is too long\n");
00242 }
00243 else if(snprintf(savecmd,sizeof(savecmd) -1,"%s/iptables-save > %s/iptables-rules",bands.iptpath,pv.log_dir) >= sizeof(savecmd))
00244 {
00245 FatalError("The iptsavecmd is too long\n");
00246 }
00247 else if(snprintf(restorecmd,sizeof(restorecmd) -1,"%s/iptables-restore < %s/iptables-rules",bands.iptpath,pv.log_dir) >= sizeof(restorecmd))
00248 {
00249 FatalError("The iptrestorecmd is too long\n");
00250 }
00251 else
00252 {
00253 LogMessage("default iptcmd is %s\n",bands.iptcmd);
00254 LogMessage("default iptsave is %s\n",savecmd);
00255 LogMessage("default iptrestore is %s\n",restorecmd);
00256 }
00257 bands.max_reroute_entries = 100;
00258 bands.log = 0;
00259 if (args)
00260 {
00261
00262 toks = mSplit(args, ",", 7, &num_toks, 0);
00263
00264 i=0;
00265
00266 while (i < num_toks)
00267 {
00268 index = toks[i];
00269
00270 while(isspace((int)*index)) index++;
00271
00272 stoks = mSplit(index, " ", 5, &s_toks, 0);
00273 if(!strcasecmp(stoks[0], "max_entries"))
00274 {
00275 if(isdigit((int)(stoks[1][0])))
00276 {
00277
00278 bands.max_reroute_entries = atoi(stoks[1]);
00279 i++;
00280 }
00281 else
00282 {
00283 FatalError("Bad BaitAndSwitch Max Entries Arg",file_name,file_line);
00284 }
00285
00286 }
00287 else if(!strcasecmp(stoks[0], "log"))
00288 {
00289 bands.log = 1;
00290 i++;
00291 }
00292 else if(!strcasecmp(stoks[0], "log-file"))
00293 {
00294 if(isascii((int)(stoks[1][0])))
00295 {
00296 if (stoks[1][0] == '/')
00297 strlcpy (logpath, stoks[1], STD_BUF);
00298 else
00299 {
00300 strlcpy(logpath, pv.log_dir, STD_BUF);
00301 strlcat(logpath, "/", STD_BUF);
00302 strlcat(logpath, stoks[1], STD_BUF);
00303 }
00304 i++;
00305 }
00306 }
00307 else if(!strcasecmp(stoks[0],"insert_before"))
00308 {
00309 bands.insertmode = "I";
00310 i++;
00311 }
00312 else if(!strncasecmp(index, "iptpath", 7))
00313 {
00314
00315 iptdirtoks = mSplit(index, " ", 1, &num_iptdirtoks, 0);
00316
00317
00318 if(strlcpy(bands.iptpath, iptdirtoks[1], sizeof(bands.iptpath)) >= sizeof(bands.iptpath))
00319 {
00320 FatalError("The iptpath supplied in the config is too long\n");
00321 }
00322 else if(snprintf(bands.iptcmd,sizeof(bands.iptcmd) -1,"%s/iptables",bands.iptpath) >= sizeof(bands.iptcmd))
00323 {
00324 FatalError("The iptcmd supplied is too long\n");
00325 }
00326 else if(snprintf(savecmd,sizeof(savecmd) -1,"%s/iptables-save > %s/iptables-rules",bands.iptpath,pv.log_dir) >= sizeof(savecmd))
00327 {
00328 FatalError("The iptsavecmd is too long\n");
00329 }
00330 else if(snprintf(restorecmd,sizeof(restorecmd) -1,"%s/iptables-restore < %s/iptables-rules",bands.iptpath,pv.log_dir) >= sizeof(restorecmd))
00331 {
00332 FatalError("The iptrestorecmd is too long\n");
00333 }
00334 else
00335 {
00336 mSplitFree(&iptdirtoks, num_iptdirtoks);
00337 LogMessage("iptcmd command is now %s\n",bands.iptcmd);
00338 LogMessage("iptsave command is now %s\n",savecmd);
00339 LogMessage("iptrestore command is now %s\n",restorecmd);
00340 i++;
00341 }
00342
00343 }
00344 else
00345 {
00346 FatalError("%s(%d) => option '%s' is undefined. ",
00347 file_name, file_line, stoks[0]);
00348 }
00349
00350 mSplitFree(&stoks, s_toks);
00351 }
00352 mSplitFree(&toks, num_toks);
00353 }
00354 if(bands.log)
00355 {
00356 bands.logfile = fopen(logpath, "a+");
00357
00358 if(bands.logfile == NULL)
00359 {
00360 FatalError("Can't open logfile: %s", bands.logpath);
00361 }
00362 }
00363 }
00364 void basInitIgnoreHosts(u_char *hosts)
00365 {
00366 char **toks;
00367 int num_toks;
00368 int num_hosts = 0;
00369 basHostNode *bascurrentHost;
00370
00371
00372 bascurrentHost = NULL;
00373 basignoreList = NULL;
00374
00375 if(hosts == NULL)
00376 {
00377 ErrorMessage(" ERROR: %s(%d)=> No arguments to "
00378 "bait-and-switch-ignorehosts, ignoring.\n",
00379 file_name, file_line);
00380 return;
00381 }
00382
00383 toks = mSplit(hosts, " ", 127, &num_toks, '\\');
00384
00385 for(num_hosts = 0; num_hosts < num_toks; num_hosts++)
00386 {
00387 if((bascurrentHost = (basHostNode *) calloc(1, sizeof(basHostNode))) == NULL)
00388 {
00389 FatalError("[!] ERROR: Unable to allocate space for "
00390 "bait-and-switch IgnoreHost");
00391 }
00392 bascurrentHost->address = NULL;
00393 bascurrentHost->nextNode = basignoreList;
00394 basignoreList = bascurrentHost;
00395
00396
00397 basScanParseIp(toks[num_hosts], bascurrentHost);
00398 }
00399
00400 mSplitFree(&toks, num_toks);
00401 }
00402
00403
00404 IpAddrSet* basIgnoreAllocAddrNode(basHostNode *host)
00405 {
00406 IpAddrSet *idx;
00407
00408 if((idx = (IpAddrSet *) calloc(1, sizeof(IpAddrSet))) == NULL)
00409 {
00410 FatalError("[!] ERROR: Unable to allocate space for "
00411 "BaitAndSwitch IP addr\n");
00412 }
00413
00414 idx->next = host->address;
00415 host->address = idx;
00416
00417 return idx;
00418 }
00419
00420
00421 void basScanParseIp(char *addr, basHostNode *host)
00422 {
00423 char **toks;
00424 int num_toks;
00425 int i, not_flag;
00426 IpAddrSet *tmp_addr;
00427 char *enbracket, *ports;
00428 char *tmp;
00429
00430 if(addr == NULL)
00431 {
00432 ErrorMessage("ERROR %s(%d) => Undefine address in "
00433 "bait-and-switch-ignorehosts directive, igoring.\n", file_name,
00434 file_line);
00435
00436 return;
00437 }
00438
00439 if(*addr == '!')
00440 {
00441 host->flags |= EXCEPT_SRC_IP;
00442 addr++;
00443 }
00444
00445 if(*addr == '$')
00446 {
00447 if((tmp = VarGet(addr + 1)) == NULL)
00448 {
00449 ErrorMessage("ERROR %s (%d) => Undefined variable \"%s\", "
00450 "ignoring\n", file_name, file_line, addr);
00451
00452 return;
00453 }
00454 }
00455 else
00456 {
00457 tmp = addr;
00458 }
00459
00460 ports = strrchr(tmp, (int)'@');
00461
00462 if (*tmp == '[')
00463 {
00464 enbracket = strrchr(tmp, (int)']');
00465 if (enbracket) *enbracket = '\x0';
00466
00467 if (ports && enbracket && (ports < enbracket))
00468 {
00469 FatalError("[!] ERROR %s(%d) => syntax error in"
00470 "bait-and-switch-ignorehosts \"%s\"\n",
00471 file_name, file_line, tmp);
00472 }
00473 toks = mSplit(tmp+1, ",", 128, &num_toks, 0);
00474
00475 for(i = 0; i < num_toks; i++)
00476 {
00477 tmp_addr = basIgnoreAllocAddrNode(host);
00478
00479 ParseIP(toks[i], tmp_addr);
00480 }
00481
00482 mSplitFree(&toks, num_toks);
00483 }
00484 else
00485 {
00486 if (ports) *ports = '\x0';
00487
00488 tmp_addr = basIgnoreAllocAddrNode(host);
00489 ParseIP(tmp, tmp_addr);
00490 }
00491
00492 if (ports)
00493 {
00494 ports++;
00495 if (ParsePort(ports, &(host->hsp), &(host->lsp), "ip", ¬_flag))
00496 host->flags |= ANY_SRC_PORT;
00497 if (not_flag)
00498 host->flags |= EXCEPT_SRC_PORT;
00499 } else {
00500 host->flags |= ANY_SRC_PORT;
00501 }
00502
00503 }
00504
00505
00506 void basInitIgnoreFrom(u_char *args)
00507 {
00508 basInitIgnorePorts(args, &basignorePortFrom, &num_ports_from);
00509 }
00510
00511
00512 void basInitIgnoreTo(u_char *args)
00513 {
00514 basInitIgnorePorts(args, &basignorePortTo, &num_ports_to);
00515 }
00516
00517
00518 void basInitIgnorePorts(u_char *list, u_int32_t **ports, int *num)
00519 {
00520 int new_ports, max_ports;
00521 u_int32_t *pool;
00522 char **toks;
00523 int num_toks;
00524
00525 *ports = NULL;
00526 *num = 0;
00527 max_ports = 0;
00528
00529 if(list == NULL)
00530 {
00531 ErrorMessage(" ERROR: %s(%d)=> No arguments to "
00532 "bait-and-switch-ignoreports, ignoring.\n",
00533 file_name, file_line);
00534 return;
00535 }
00536
00537 toks = mSplit(list, " ", MAX_PORTS, &num_toks, '\\');
00538
00539 for(;*num < num_toks; (*num)++)
00540 {
00541 if(*num >= max_ports)
00542 {
00543 new_ports = max_ports + MEM_CHUNK;
00544 if((pool = (u_int32_t *) calloc(new_ports, sizeof(u_int32_t))) == NULL)
00545 {
00546 FatalError("[!] ERROR: Unable to allocate space for "
00547 "bait-and-switch-ignoreports");
00548 }
00549 if (*ports != NULL)
00550 {
00551 memcpy(pool, *ports, max_ports * sizeof(u_int32_t));
00552 free(*ports);
00553 }
00554 max_ports = new_ports;
00555 *ports = pool;
00556 }
00557 (*ports)[*num] = basScanParsePort(toks[*num]);
00558 }
00559
00560 mSplitFree(&toks, num_toks);
00561
00562 }
00563
00564
00565 u_int32_t basScanParsePort(char *port)
00566 {
00567 char *tmp;
00568
00569 if(port == NULL)
00570 {
00571 FatalError("ERROR %s(%d) => Undefined ports in "
00572 "bait-and-switch-ignoreports directive\n",
00573 file_name, file_line);
00574 }
00575
00576 if(*port == '$')
00577 {
00578 if((tmp = VarGet(port + 1)) == NULL)
00579 {
00580 FatalError("ERROR %s (%d) => Undefined variable \"%s\"\n",
00581 file_name, file_line, port);
00582
00583 }
00584 }
00585 else
00586 {
00587 tmp = port;
00588 }
00589
00590 if(!isdigit((int)tmp[0]))
00591 {
00592 FatalError("ERROR %s(%d) => Bad port list to "
00593 "bait-and-switch-ignoreports\n", file_name, file_line);
00594 }
00595
00596 return((u_int32_t)atol(tmp));
00597 }
00598
00599 int basAttackerSearch(Packet *p, char direction)
00600 {
00601 Attacker *searchval;
00602 Attacker tmp;
00603 char pattacker[STD_BUF];
00604 char phoneypot[STD_BUF];
00605
00606 if(direction == DIRECTION_SOURCE)
00607 {
00608 tmp.attackerip = (u_int32_t)p->iph->ip_src.s_addr;
00609 tmp.honeypotip = (u_int32_t)p->iph->ip_dst.s_addr;
00610 snprintf(pattacker,sizeof(pattacker) -1,"%s",(char *)inet_ntoa(p->iph->ip_src));
00611 snprintf(phoneypot,sizeof(phoneypot) -1,"%s",(char *)inet_ntoa(p->iph->ip_dst));
00612
00613 }
00614 if(direction == DIRECTION_DST)
00615 {
00616 tmp.attackerip = (u_int32_t)p->iph->ip_dst.s_addr;
00617 tmp.honeypotip = (u_int32_t)p->iph->ip_src.s_addr;
00618 snprintf(pattacker,sizeof(pattacker) -1,"%s",(char *)inet_ntoa(p->iph->ip_src));
00619 snprintf(phoneypot,sizeof(phoneypot) -1,"%s",(char *)inet_ntoa(p->iph->ip_dst));
00620 }
00621 if(ubi_trCount(bands.attackerRootPtr) == 0)
00622 {
00623 DEBUG_WRAP(DebugMessage(DEBUG_BAITANDSWITCH,
00624 "we don't have any entries in the attacker table running through normal snort preprocessors and detection engine\n"););
00625 return 0;
00626 }
00627
00628 searchval = (Attacker *) ubi_btFirst((ubi_btNodePtr)bands.attackerRootPtr->root);
00629
00630 if(searchval == NULL)
00631 {
00632 return 0;
00633 }
00634
00635 do
00636 {
00637
00638
00639 if((searchval->attackerip == tmp.attackerip) && (searchval->honeypotip == tmp.honeypotip))
00640 {
00641
00642 if(p->pkth->ts.tv_sec >= (searchval->ruledeletetime.tv_sec))
00643 {
00644 DEBUG_WRAP(DebugMessage(DEBUG_BAITANDSWITCH,
00645 "Pruning out Attacker entry %s due to timeout\n",pattacker););
00646
00647 PruneAttackers(p->pkth->ts.tv_sec, 1, NULL);
00648
00649 return(0);
00650 }
00651
00652 else
00653 {
00654 DEBUG_WRAP(DebugMessage(DEBUG_BAITANDSWITCH,
00655 "Attacker/Honeypot attacker:%s honeypot:%s pair found in tree\n",pattacker,phoneypot););
00656 return(1);
00657 }
00658 }
00659 else if((searchval->attackerip == tmp.attackerip) && (searchval->attackedip == tmp.honeypotip))
00660 {
00661
00662
00663 DEBUG_WRAP(DebugMessage(DEBUG_BAITANDSWITCH,
00664 "assuming stale iptables connection tearing down session attacker:%s attackedip:%s\n",pattacker,phoneypot););
00665 InlineReject(p);
00666 return(1);
00667 }
00668 else
00669 {
00670 if(searchval != NULL && ubi_trCount(bands.attackerRootPtr))
00671 {
00672 searchval = (Attacker *) ubi_btNext((ubi_btNodePtr)searchval);
00673 }
00674 else
00675 {
00676 DEBUG_WRAP(DebugMessage(DEBUG_BAITANDSWITCH,
00677 "attacker not found src %s dst %s\n",pattacker,phoneypot););
00678 return (0);
00679 }
00680 }
00681 } while(searchval != NULL);
00682
00683 return (0);
00684 }
00685 int basIsIgnored(Packet *p, char dir)
00686 {
00687 basHostNode *bascurrentHost = basignoreList;
00688 int i;
00689
00690 for(i = 0; i < num_ports_from; i++)
00691 {
00692 if (p->sp == basignorePortFrom[i])
00693 {
00694 return(1);
00695 }
00696 }
00697
00698 for(i = 0; i < num_ports_to; i++)
00699 {
00700 if (p->dp == basignorePortTo[i])
00701 {
00702 return(1);
00703 }
00704 }
00705
00706 while(bascurrentHost)
00707 {
00708
00709
00710
00711
00712 if(dir == DIRECTION_SOURCE)
00713 {
00714 if(CheckAddrPort(bascurrentHost->address, bascurrentHost->hsp,
00715 bascurrentHost->lsp, p, bascurrentHost->flags, CHECK_SRC))
00716 {
00717 return(1);
00718 }
00719 }
00720 else if(dir == DIRECTION_DST)
00721 {
00722 if(CheckAddrPort(bascurrentHost->address, bascurrentHost->hsp,
00723 bascurrentHost->lsp, p, bascurrentHost->flags, INVERSE))
00724 {
00725 return(1);
00726 }
00727 }
00728 bascurrentHost = bascurrentHost->nextNode;
00729 }
00730 return(0);
00731 }
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742 void AddIpToRerouteTree(Packet *p, char bdirection, u_int32_t timeout, u_int32_t hpotip)
00743 {
00744
00745 if((bdirection == DIRECTION_SOURCE) && (basIsIgnored(p, DIRECTION_SOURCE)))
00746 {
00747 DEBUG_WRAP(DebugMessage(DEBUG_BAITANDSWITCH,"Host %s matched ignore list, not adding to reroute tree.\n",inet_ntoa(p->iph->ip_src)););
00748 return;
00749 }
00750 else if((bdirection == DIRECTION_DST) && (basIsIgnored(p, DIRECTION_DST)))
00751 {
00752 DEBUG_WRAP(DebugMessage(DEBUG_BAITANDSWITCH,"Host %s matched ignore list, not adding to reroute tree.\n",inet_ntoa(p->iph->ip_dst)););
00753 return;
00754 }
00755
00756 else
00757 {
00758 Attacker *a = NULL;
00759 MemBucket *mb = NULL;
00760 char fattacker[STD_BUF];
00761 char fattacked[STD_BUF];
00762 char fhoneypot[STD_BUF];
00763 struct in_addr hpot;
00764
00765 mb = mempool_alloc(&bands.AttackerPool);
00766
00767 if(mb == NULL)
00768 {
00769
00770 PruneAttackers(p->pkth->ts.tv_sec, 5, NULL);
00771 }
00772 a = (Attacker *) mb->data;
00773 a->bucket = mb;
00774 hpot.s_addr=(ulong)hpotip;
00775
00776 if(bdirection == DIRECTION_SOURCE)
00777 {
00778 a->attackerip = (u_int32_t)p->iph->ip_src.s_addr;
00779 a->attackedip = (u_int32_t)p->iph->ip_dst.s_addr;
00780 a->honeypotip = (u_int32_t)hpot.s_addr;
00781 snprintf(fattacker,sizeof(fattacker) -1,"%s",(char *)inet_ntoa(p->iph->ip_src));
00782 snprintf(fattacked,sizeof(fattacked) -1,"%s",(char *)inet_ntoa(p->iph->ip_dst));
00783 snprintf(fhoneypot,sizeof(fhoneypot) -1,"%s",(char *)inet_ntoa(hpot));
00784 }
00785 else if(bdirection == DIRECTION_DST)
00786 {
00787 a->attackerip = (u_int32_t)p->iph->ip_dst.s_addr;
00788 a->attackedip = (u_int32_t)p->iph->ip_src.s_addr;
00789 a->honeypotip = (u_int32_t)hpot.s_addr;
00790 snprintf(fattacker,sizeof(fattacker) -1,"%s",(char *)inet_ntoa(p->iph->ip_dst));
00791 snprintf(fattacked,sizeof(fattacked) -1,"%s",(char *)inet_ntoa(p->iph->ip_src));
00792 snprintf(fhoneypot,sizeof(fhoneypot) -1,"%s",(char *)inet_ntoa(hpot));
00793 }
00794 else
00795 {
00796 DEBUG_WRAP(DebugMessage(DEBUG_BAITANDSWITCH,
00797 "not inserting into tree we need src or dst\n"););
00798 mempool_free(&bands.AttackerPool,a->bucket);
00799 return;
00800
00801 }
00802
00803
00804 if(a->attackedip == a->honeypotip)
00805 {
00806 DEBUG_WRAP(DebugMessage(DEBUG_BAITANDSWITCH,
00807 "attackedip %s is equal to the honeypot ip address %s\n",fattacked,fhoneypot););
00808 mempool_free(&bands.AttackerPool,a->bucket);
00809 return;
00810 }
00811 DEBUG_WRAP(DebugMessage(DEBUG_BAITANDSWITCH,
00812 "attacker %s attacked %s hpot %s\n",fattacker,fattacked,fhoneypot););
00813
00814 if(snprintf(a->iptdnatcmd,sizeof(a->iptdnatcmd) -1,"%s -t nat -%s PREROUTING -s %s -d %s -j DNAT --to-destination %s",bands.iptcmd,bands.insertmode,fattacker,fattacked,fhoneypot) >= sizeof(a->iptdnatcmd))
00815 {
00816 DEBUG_WRAP(DebugMessage(DEBUG_BAITANDSWITCH,
00817 "could not add PREROUTING -A rule it was to long\n"););
00818 return;
00819 }
00820 if(snprintf(a->iptsnatcmd,sizeof(a->iptsnatcmd) -1,"%s -t nat -%s POSTROUTING -s %s -d %s -j SNAT --to-source %s",bands.iptcmd,bands.insertmode,fhoneypot, fattacker, fattacked) >= sizeof(a->iptsnatcmd))
00821 {
00822 DEBUG_WRAP(DebugMessage(DEBUG_BAITANDSWITCH,
00823 "could not add POSTROUTING -A rule it was to long\n"););
00824 return;
00825 }
00826 if(snprintf(a->iptundnatcmd,sizeof(a->iptundnatcmd) -1,"%s -t nat -D PREROUTING -s %s -d %s -j DNAT --to-destination %s",bands.iptcmd,fattacker, fattacked, fhoneypot) >= sizeof(a->iptundnatcmd))
00827 {
00828 DEBUG_WRAP(DebugMessage(DEBUG_BAITANDSWITCH,
00829 "could not add PREROUTING -D rule it was to long\n"););
00830 return;
00831 }
00832 if(snprintf(a->iptunsnatcmd,sizeof(a->iptunsnatcmd) -1,"%s -t nat -D POSTROUTING -s %s -d %s -j SNAT --to-source %s",bands.iptcmd,fhoneypot, fattacker, fattacked) >= sizeof(a->iptunsnatcmd))
00833 {
00834 DEBUG_WRAP(DebugMessage(DEBUG_BAITANDSWITCH,
00835 "could not add POSTROUTING -D rule it was to long\n"););
00836 return;
00837 }
00838
00839 a->ruleaddtime.tv_sec = p->pkth->ts.tv_sec;
00840 a->ruledeletetime.tv_sec = a->ruleaddtime.tv_sec + timeout;
00841 if(ubi_sptInsert(bands.attackerRootPtr,
00842 (ubi_btNodePtr)a,
00843 (ubi_btNodePtr)a, NULL) == ubi_trFALSE)
00844 {
00845 DEBUG_WRAP(DebugMessage(DEBUG_BAITANDSWITCH,
00846 "Entry already exists, or something has gone terribly wrong\n"););
00847
00848 mempool_free(&bands.AttackerPool,a->bucket);
00849 }
00850 else
00851 {
00852 DEBUG_WRAP(DebugMessage(DEBUG_BAITANDSWITCH,
00853 "Insert into reroute tree was successful\n"););
00854 if(system(a->iptdnatcmd) !=0)
00855 {
00856 DEBUG_WRAP(DebugMessage(DEBUG_BAITANDSWITCH,
00857 "failed to add iptables DNAT rule"););
00858 }
00859 else
00860 {
00861 DEBUG_WRAP(DebugMessage(DEBUG_BAITANDSWITCH,
00862 "added iptables DNAT rule\n"););
00863 if(bands.log)
00864 {
00865 fprintf(bands.logfile,"DNATing all traffic from attackerip: %s bound for ip address: %s to honeypotip of %s\n",fattacker, fattacked, fhoneypot);
00866 }
00867 }
00868
00869 if(system(a->iptsnatcmd) != 0)
00870 {
00871 DEBUG_WRAP(DebugMessage(DEBUG_BAITANDSWITCH,
00872 "failed to add iptables SNAT rule\n"););
00873 }
00874 else
00875 {
00876 DEBUG_WRAP(DebugMessage(DEBUG_BAITANDSWITCH,
00877 "added iptables SNAT rule\n"););
00878 if(bands.log)
00879 {
00880 fprintf(bands.logfile,"SNATing all traffic from honeypot ip: %s bound for attackerip: %s to source of attacked ip: %s\n",fhoneypot, fattacker, fattacked);
00881 }
00882 }
00883 do_detect = 0;
00884 p->preprocessors = 0;
00885 InlineReject(p);
00886 }
00887 }
00888 }
00889
00890
00891 void BASLog(Packet *p)
00892 {
00893 char src[STD_BUF];
00894 char dst[STD_BUF];
00895 char timestamp[TIMEBUF_SIZE];
00896 char flagString[9];
00897
00898 strlcpy(src, (char *)inet_ntoa(p->iph->ip_src), sizeof(src));
00899 strlcpy(dst, (char *)inet_ntoa(p->iph->ip_dst), sizeof(dst));
00900 ts_print((struct timeval *) &p->pkth->ts, timestamp);
00901
00902 if(p->tcph)
00903 {
00904 CreateTCPFlagString(p, flagString);
00905 fprintf(bands.logfile,"Rerouted Packet %s TCP %s:%u->%s:%u %s\n", timestamp, src, p->sp, dst, p->dp, flagString);
00906
00907 }
00908 else if(p->udph)
00909 {
00910 fprintf(bands.logfile,"Rerouted Packet %s UDP %s:%u->%s:%u\n", timestamp, src, p->sp, dst, p->dp);
00911
00912 }
00913 else if(p->icmph)
00914 {
00915 fprintf(bands.logfile, "Rerouted Packet %s ICMP %s->%s type: %u code: %u \n", timestamp, src, dst, p->icmph->type, p->icmph->code);
00916
00917 }
00918
00919 fflush(bands.logfile);
00920 }
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936 void BaitAndSwitch(Packet *p, void *context)
00937 {
00938 if(basAttackerSearch(p, DIRECTION_SOURCE))
00939 {
00940 DEBUG_WRAP(DebugMessage(DEBUG_BAITANDSWITCH,
00941 "Attacker was found, lets log if specified and set do_detect = 0 and p->processors =0; the packet\n"););
00942 if(bands.log)
00943 {
00944
00945 BASLog(p);
00946 }
00947
00948
00949
00950 do_detect = 0;
00951 p->preprocessors = 0;
00952
00953 }
00954 if(basAttackerSearch(p, DIRECTION_DST))
00955 {
00956 DEBUG_WRAP(DebugMessage(DEBUG_BAITANDSWITCH,
00957 "Attacker was found, lets log if specified and set do_detect = 0 and p->processors =0; the packet\n"););
00958 if(bands.log)
00959 {
00960
00961 BASLog(p);
00962 }
00963
00964
00965
00966 do_detect = 0;
00967 p->preprocessors = 0;
00968
00969 }
00970 else
00971 {
00972 DEBUG_WRAP(DebugMessage(DEBUG_BAITANDSWITCH,
00973 "ip address not found in drop list passing\n"););
00974 }
00975 DEBUG_WRAP(DebugMessage(DEBUG_BAITANDSWITCH,
00976 "Calling Global Prune Check \n"););
00977
00978 PruneAttackers(p->pkth->ts.tv_sec,0,NULL);
00979 }
00980
00981
00982 static int IpAddressCompareFunction(ubi_trItemPtr ItemPtr, ubi_trNodePtr NodePtr)
00983 {
00984 Attacker *A = (Attacker *) NodePtr;
00985 Attacker *B = (Attacker *) ItemPtr;
00986
00987 if(A->attackerip < B->attackerip)
00988 {
00989 return 1;
00990 }
00991 else if(A->attackerip > B->attackerip)
00992 {
00993 return -1;
00994 }
00995 if(A->attackedip < B->attackedip)
00996 {
00997 return 1;
00998 }
00999 else if(A->attackedip > B->attackedip)
01000 {
01001 return -1;
01002 }
01003 if(A->honeypotip < B->honeypotip)
01004 {
01005 return 1;
01006 }
01007 else if(A->honeypotip > B->honeypotip)
01008 {
01009 return -1;
01010 }
01011 return 0;
01012 }
01013
01014
01015 static void DeleteAttacker(Attacker *a)
01016 {
01017 Attacker *olda;
01018
01019 DEBUG_WRAP(DebugMessage(DEBUG_BAITANDSWITCH, "Deleteing Attacker %p\n", a);
01020 DebugMessage(DEBUG_BAITANDSWITCH,
01021 "a->ip: %X\n", a->attackerip);
01022 DebugMessage(DEBUG_BAITANDSWITCH,
01023 "a->ruleaddtime: %u\n", a->ruleaddtime.tv_sec);
01024 DebugMessage(DEBUG_BAITANDSWITCH,
01025 "a->ruledeletetime: %u\n", a->ruledeletetime.tv_sec);
01026
01027 );
01028
01029 if(system(a->iptundnatcmd) !=0)
01030 {
01031 DEBUG_WRAP(DebugMessage(DEBUG_BAITANDSWITCH,
01032 "failed to delete iptables DNAT rule\n"););
01033 }
01034 else
01035 {
01036 DEBUG_WRAP(DebugMessage(DEBUG_BAITANDSWITCH,
01037 "deleted iptables DNAT rule\n"););
01038 }
01039
01040 if(system(a->iptunsnatcmd) != 0)
01041 {
01042 DEBUG_WRAP(DebugMessage(DEBUG_BAITANDSWITCH,
01043 "failed to delete iptables SNAT rule\n"););
01044 }
01045 else
01046 {
01047 DEBUG_WRAP(DebugMessage(DEBUG_BAITANDSWITCH,
01048 "deleted iptables SNAT rule\n"););
01049 }
01050
01051 olda = (Attacker *) ubi_sptRemove(bands.attackerRootPtr,
01052 (ubi_btNodePtr) a);
01053
01054 mempool_free(&bands.AttackerPool,a->bucket);
01055 }
01056
01057
01058 static int PruneAttackers(u_int32_t now, int tokill, Attacker *saveme)
01059 {
01060 Attacker *idx;
01061 u_int32_t pruned = 0;
01062
01063 DEBUG_WRAP(DebugMessage(DEBUG_BAITANDSWITCH,
01064 "PruneAttackers called now: "
01065 " %u tokill: %d: saveme: %p, count: %u\n",
01066 now, tokill, saveme,
01067 ubi_trCount(bands.attackerRootPtr)););
01068
01069 if(ubi_trCount(bands.attackerRootPtr) == 0)
01070 {
01071 return 0;
01072 }
01073
01074 if(tokill == 0)
01075 {
01076 DEBUG_WRAP(DebugMessage(DEBUG_BAITANDSWITCH,
01077 "Running Through Global Prune Check Loop\n"););
01078
01079 idx = (Attacker *) ubi_btFirst((ubi_btNodePtr)bands.attackerRootPtr->root);
01080
01081 if(idx == NULL)
01082 {
01083 return 0;
01084 }
01085
01086 do
01087 {
01088 if(idx == saveme)
01089 {
01090 idx = (Attacker *) ubi_btNext((ubi_btNodePtr)idx);
01091 continue;
01092 }
01093
01094 if((idx->ruledeletetime.tv_sec) < now)
01095 {
01096 Attacker *savidx = idx;
01097
01098 if(ubi_trCount(bands.attackerRootPtr) > 1)
01099 {
01100 idx = (Attacker *) ubi_btNext((ubi_btNodePtr)idx);
01101 DEBUG_WRAP(DebugMessage(DEBUG_BAITANDSWITCH,
01102 "pruning stale BAITANDSWITCH entry\n"););
01103 DeleteAttacker(savidx);
01104 pruned++;
01105 }
01106 else
01107 {
01108 DeleteAttacker(savidx);
01109 pruned++;
01110 return pruned;
01111 }
01112 }
01113 else
01114 {
01115 if(idx != NULL && ubi_trCount(bands.attackerRootPtr) > 1)
01116 {
01117 idx = (Attacker *) ubi_btNext((ubi_btNodePtr)idx);
01118 }
01119 else
01120 {
01121 return pruned;
01122 }
01123 }
01124 } while(idx != NULL);
01125
01126 return pruned;
01127 }
01128 else
01129 {
01130 while(tokill-- && ubi_trCount(bands.attackerRootPtr) > 0)
01131 {
01132 idx = (Attacker *) ubi_btLeafNode((ubi_btNodePtr)bands.attackerRootPtr);
01133 DeleteAttacker(idx);
01134 return 0;
01135 }
01136 }
01137 return 0;
01138 }
01139
01140
01141 int BaitAndSwitchIsRunning(void)
01142 {
01143 return s_bas_running;
01144 }
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161 static void BaitAndSwitchCleanExitFunction(int signal, void *data)
01162 {
01163
01164 }
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182 static void BaitAndSwitchRestartFunction(int signal, void *foo)
01183 {
01184
01185 }
01186
01187 #endif
01188 #endif