Changeset 1562
- Timestamp:
- 02/21/08 19:11:09 (8 months ago)
- Files:
-
- nebula/trunk/ChangeLog (modified) (1 diff)
- nebula/trunk/configure.in (modified) (1 diff)
- nebula/trunk/src/classify.c (modified) (1 diff)
- nebula/trunk/src/nebula.c (modified) (6 diffs)
- nebula/trunk/src/session.c (modified) (5 diffs)
- nebula/trunk/src/sig.c (modified) (8 diffs)
- nebula/trunk/src/sig.h (modified) (3 diffs)
- nebula/trunk/src/stree.c (modified) (1 diff)
- nebula/trunk/src/util.c (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
nebula/trunk/ChangeLog
r1431 r1562 1 0.2.0 2 - daemon version 3 - generalized suffix tree-based signature generation 4 - snort rule output 1 5 0.1.0 2 6 - queues as default data structures (restrictable in size) nebula/trunk/configure.in
r1558 r1562 1 1 # $Id$ 2 2 AC_PREREQ(02.50) 3 AC_INIT([nebula], [0. 1.0], [tillmann.werner@gmx.de])3 AC_INIT([nebula], [0.2.0], [tillmann.werner@gmx.de]) 4 4 AM_CONFIG_HEADER(config.h) 5 AM_INIT_AUTOMAKE(nebula,0. 1.0)5 AM_INIT_AUTOMAKE(nebula,0.2.0) 6 6 7 7 AC_PROG_CC nebula/trunk/src/classify.c
r1558 r1562 198 198 199 199 // check for signature generation criteria here 200 if ((((hash*)t->data)->cl) && ((hash*)t->data)->cl->cnt > 5) {200 if ((((hash*)t->data)->cl) && ((hash*)t->data)->cl->cnt > 2) { 201 201 printf("[=] cluster hit size threshold, generating signature.\n"); 202 202 if (pthread_create(&ntid, NULL, pt_siggen, (void *) ((hash*)t->data)->cl)) { nebula/trunk/src/nebula.c
r1560 r1562 56 56 void usage(const char* progname, const int exit_val) { 57 57 printf("Usage: %s " 58 " -C <size>\t cluster queue size\n" 58 " -a <filename>\t append new snort signatures to this file\n" 59 "\t\t-C <size>\t cluster queue size\n" 59 60 "\t\t -c <similarity> cluster criteria (a similarity measure in percent)\n" 60 61 "\t\t -d\t\t daemonize\n" 61 62 "\t\t -E <size>\t cluster element queue size\n" 62 "\t\t -h \t\t show this help\n"63 "\t\t -h <snort pid>\t send a SIGHUP to this process ID after a new rule was generated\n" 63 64 "\t\t -O <size>\t outlier queue size\n" 64 65 "\t\t -p <port>\t listen on this port\n" … … 92 93 qsize = 0; 93 94 95 94 96 /* default values for parameters */ 97 rules_file = NULL; // a: NULL 98 clusterq_max = 5000; // C 99 cluster_radius = 95.0; // c: 95% similarity as cluster criteria 100 daemonize = 0; // d: 0 101 clusterhashq_max = 500000; // E 102 snort_pid = 0; // h 103 outlierq_max = 500000; // O 104 port = 12346; // p: 12345 95 105 secret = NULL; // s: NULL 96 daemonize = 0; // d: 097 port = 12346; // p: 1234598 106 verbose = 0; // v: don't be verbose 99 cluster_radius = 95.0; // c: 95% similarity as cluster criteria100 outlierq_max = 500000; // O101 clusterhashq_max = 500000; // E102 clusterq_max = 5000; // C103 107 104 108 memset(&md5sum_trie, 0, sizeof(trie_node)); … … 117 121 118 122 // process args 119 while((option = getopt(argc, argv, " c:C:dE:hO:p:s:v?")) > 0) {123 while((option = getopt(argc, argv, "a:c:C:dE:h:O:p:s:v?")) > 0) { 120 124 switch(option) { 125 case 'a': 126 rules_file = optarg; 127 break; 121 128 case 'c': 122 129 cluster_radius = atof(optarg); … … 143 150 } 144 151 break; 152 case 'h': 153 snort_pid = atoi(optarg); 154 if (!snort_pid) { 155 fprintf(stderr, "Error - Invalid process ID.\n"); 156 exit(EXIT_FAILURE); 157 } 158 break; 145 159 case 'O': 146 160 outlierq_max = atoi(optarg); … … 163 177 verbose++; 164 178 break; 165 case 'h':166 179 case '?': 167 180 usage(argv[0], EXIT_SUCCESS); … … 184 197 printf("Warning - No submission secret given.\n"); 185 198 } else if (verbose) printf("Submission secret: %s\n", secret); 199 200 if (snort_pid && !rules_file) { 201 printf("Warning - Snort will not be notified about updated rules: No rule filename given.\n"); 202 } else if (!snort_pid && rules_file) { 203 printf("Warning - Snort will not be notified about updated rules: No pid given.\n"); 204 } else if (verbose) { 205 printf("Notifying snort about rule file updates in %s.\n", rules_file); 206 } 207 186 208 187 209 // process incoming connections nebula/trunk/src/session.c
r1560 r1562 35 35 36 36 void session_reset(submission *s, struct pollfd *pfd) { 37 if (!s) return; 38 37 39 free(s->cattack); 38 40 free(s->attack); … … 43 45 close(pfd->fd); 44 46 memset(pfd, 0, sizeof(struct pollfd)); 47 pfd->fd = -1; 45 48 } 46 49 … … 147 150 return(-1); 148 151 } 149 if (verbose > 1) printf(" known attack, rejecting submission.\n"); 152 if (s->protocol == 6) 153 printf("[x] rejected known attack (%lu bytes from port %u/tcp)\n", s->attack_len, s->port); 154 else if (s->protocol == 17) 155 printf("[x] rejected known attack (%lu bytes from port %u/udp)\n", s->attack_len, s->port); 156 150 157 session_reset(s, pfd); 151 158 return(0); … … 264 271 265 272 if (s->protocol == 6) 266 printf("[.] %lu bytes from port %u/tcp\n", s->attack_len, s->port);273 printf("[.] received new attack (%lu bytes from port %u/tcp)\n", s->attack_len, s->port); 267 274 else if (s->protocol == 17) 268 printf("[.] %lu bytes from port %u/udp\n", s->attack_len, s->port);275 printf("[.] received new attack (%lu bytes from port %u/udp)\n", s->attack_len, s->port); 269 276 270 277 // calculate and check md5sum … … 277 284 } 278 285 free(md5sum); 286 free(s->cattack); 287 s->cattack = NULL; 279 288 280 289 if (verbose) printf("Connection terminated.\n"); nebula/trunk/src/sig.c
r1560 r1562 20 20 21 21 #include <ctype.h> 22 #include <errno.h> 23 #include <signal.h> 22 24 #include <stdio.h> 23 25 #include <stdlib.h> 24 26 #include <string.h> 27 #include <sys/types.h> 25 28 26 29 #include "cluster.h" … … 31 34 #include "sig.h" 32 35 #include "stree.h" 33 34 35 typedef struct {36 ssize_t org_off;37 ssize_t min_off;38 ssize_t max_off;39 ssize_t len;40 } sseg;41 36 42 37 … … 149 144 // signature was generated earlier so skip it 150 145 printf("[=] signature was already published.\n"); 146 free(sigdata); 151 147 free(sha512sum); 152 148 return; … … 158 154 pthread_rwlock_unlock(&sighash_trie_lock); 159 155 } 156 free(sigdata); 160 157 free(sha512sum); 161 158 … … 171 168 printf("\033[1;31m]\033[1;32m[%lu]\033[1;0m ", (long unsigned int) seglist[i-1].max_off+seglist[i-1].len); 172 169 } 173 printf("------------------------------------------------------------------------------------------------------- ----\n\n");170 printf("-------------------------------------------------------------------------------------------------------\n\n"); 174 171 break; 175 172 case SIG_SNORT: … … 183 180 // increase revision number 184 181 cl->sig_rev++; 182 183 if (rules_file) { 184 // append snort signature to rules file 185 if (append_snortsig_to_rulefile(rules_file, t, cl, seglist, num_frags) > 0) { 186 if (snort_pid) { 187 printf("[#] forcing snort to reload rule set\n"); 188 // make snort reload its configuration 189 if (kill(snort_pid, SIGHUP) != 0) { 190 fprintf(stderr, "Error - Sending SIGHUP to snort (%u) failed: %s.\n", snort_pid, strerror(errno)); 191 } 192 } 193 } 194 } 185 195 186 196 // print snort signature … … 262 272 printf(" \\\n sid: %u; rev: %u;)\n", cl->sig_id, cl->sig_rev); 263 273 } 264 printf("------------------------------------------------------------------------------------------------------- ----\n\n");274 printf("-------------------------------------------------------------------------------------------------------\n\n"); 265 275 break; 266 276 default: … … 411 421 return(0); 412 422 } 423 424 int append_snortsig_to_rulefile(const char *filename, const stree *t, const cluster *cl, const sseg *seglist, const ssize_t num_frags) { 425 int i, j, printable; 426 FILE *rfile; 427 428 if ((rfile = fopen(filename, "a")) == NULL) { 429 fprintf(stderr, "Error - Unable to open rules file: %s.\n", strerror(errno)); 430 return(-1); 431 } 432 433 fprintf(rfile, "\nalert tcp any any -> any any (msg: \"nebula rule %u rev. %u\";", cl->sig_id, cl->sig_rev); 434 if (num_frags) { 435 fprintf(rfile, " \\\n content: \""); 436 printable = 1; 437 for (j=1; j<=seglist[num_frags-1].len; j++) { 438 if (!isprint(t->tree_string[seglist[num_frags-1].org_off+j]) 439 || t->tree_string[seglist[num_frags-1].org_off+j] == '|' 440 || t->tree_string[seglist[num_frags-1].org_off+j] == '$') { 441 if (printable) { 442 printable = 0; 443 fprintf(rfile, "|"); 444 } else fprintf(rfile, " "); 445 fprintf(rfile, "%02x", t->tree_string[seglist[num_frags-1].org_off+j]); 446 } else if (isprint(t->tree_string[seglist[num_frags-1].org_off+j])) { 447 if (!printable) { 448 printable = 1; 449 fprintf(rfile, "|"); 450 } 451 // quote special characters 452 switch (t->tree_string[seglist[num_frags-1].org_off+j]) { 453 case ':': 454 case ';': 455 case '\\': 456 case '"': 457 fprintf(rfile, "\\%c", t->tree_string[seglist[num_frags-1].org_off+j]); 458 break; 459 default: 460 fprintf(rfile, "%c", t->tree_string[seglist[num_frags-1].org_off+j]); 461 } 462 } 463 } 464 if (!printable) fprintf(rfile, "|"); 465 fprintf(rfile, "\"; depth: %lu; offset: %lu;", 466 (long unsigned int) seglist[num_frags-1].max_off+seglist[num_frags-1].len, 467 (long unsigned int) (seglist[num_frags-1].min_off > seglist[num_frags-1].len ? seglist[num_frags-1].min_off - seglist[num_frags-1].len : 0)); 468 469 // process other segments 470 for (i=num_frags-1; i; i--) { 471 printable = 1; 472 fprintf(rfile, " \\\n content: \""); 473 for (j=1; j<=seglist[i-1].len; j++) { 474 if (!isprint(t->tree_string[seglist[i-1].org_off+j]) 475 || t->tree_string[seglist[i-1].org_off+j] == '|' 476 || t->tree_string[seglist[i-1].org_off+j] == '$') { 477 if (printable) { 478 printable = 0; 479 fprintf(rfile, "|"); 480 } else fprintf(rfile, " "); 481 fprintf(rfile, "%02x", t->tree_string[seglist[i-1].org_off+j]); 482 } else if (isprint(t->tree_string[seglist[i-1].org_off+j])) { 483 if (!printable) { 484 printable = 1; 485 fprintf(rfile, "|"); 486 } 487 // quote special characters 488 switch (t->tree_string[seglist[i-1].org_off+j]) { 489 case ':': 490 case ';': 491 case '\\': 492 case '"': 493 case '|': 494 fprintf(rfile, "\\%c", t->tree_string[seglist[i-1].org_off+j]); 495 break; 496 default: 497 fprintf(rfile, "%c", t->tree_string[seglist[i-1].org_off+j]); 498 } 499 } 500 } 501 if (!printable) fprintf(rfile, "|"); 502 503 fprintf(rfile, "\"; distance: %lu; within: %lu;", 504 (long unsigned int) seglist[i-1].min_off - seglist[i].max_off - seglist[i].len, 505 (long unsigned int) seglist[i-1].max_off + seglist[i-1].len - seglist[i].min_off); 506 } 507 fprintf(rfile, " \\\n sid: %u; rev: %u;)\n", cl->sig_id, cl->sig_rev); 508 } 509 510 fclose(rfile); 511 512 return(1); 513 } nebula/trunk/src/sig.h
r1560 r1562 22 22 #define __NEBULA_SIG_H 1 23 23 24 #include <stdio.h> 25 24 26 #include "cluster.h" 25 27 #include "lca.h" … … 30 32 u_int32_t global_sid; // incrementing snort sid, must be mutexed 31 33 pthread_rwlock_t sidlock; 34 35 pid_t snort_pid; 36 char *rules_file; 37 32 38 33 39 typedef enum sig_type { … … 52 58 53 59 60 typedef struct { 61 ssize_t org_off; 62 ssize_t min_off; 63 ssize_t max_off; 64 ssize_t len; 65 } sseg; 66 67 68 void *pt_siggen(void *cl); 54 69 void build_sig(cluster *cl, stree *t, lcatbl *lca_table, substr_list list, stnode **leaves, ssize_t num_leaves, ssize_t min_len, double min_ent, sigtype stype); 55 void *pt_siggen(void *cl);70 int append_snortsig_to_rulefile(const char *filename, const stree *t, const cluster *cl, const sseg *seglist, const ssize_t num_frags); 56 71 57 72 #endif nebula/trunk/src/stree.c
r1558 r1562 638 638 } 639 639 640 if ( !l[id-1]) nl++; // increase leaf counter if list entry for ID is empty641 l[id-1] = leaves[i]; // update list entry so that it always contains the right-most leaf for this ID640 if (l[id-1] == NULL) nl++; // increase leaf counter if list entry for ID is empty 641 l[id-1] = leaves[i]; // update list entry so that it always contains the right-most leaf for this ID 642 642 643 643 // check if left interval boundary must be moved nebula/trunk/src/util.c
r1560 r1562 34 34 #include "nebula.h" 35 35 #include "queue.h" 36 #include "sig.h" 36 37 #include "signals.h" 37 38 #include "trie.h" 38 39 #include "util.h" 39 40 41 bstring bstr_map(const char* filename) {42 u_char buffer[BUFSIZ+1];43 int fd, bytes_read;44 bstring bstr;45 46 if (filename == NULL) {47 fprintf(stderr, "Error - Unable to map file into memory: No filename given.\n");48 exit(EXIT_FAILURE);49 }50 51 if ((fd = open(filename, O_RDONLY)) == -1) {52 fprintf(stderr, "Unable to open file %s: %m.\n", filename);53 exit(EXIT_FAILURE);54 }55 56 memset(&bstr, 0, sizeof(bstring));57 while ((bytes_read = read(fd, buffer, BUFSIZ)) > 0) {58 if ((bstr.data = (void *) realloc(bstr.data, bstr.len+bytes_read)) == NULL) {59 fprintf(stderr, "Unable to allocate memory: %m.\n");60 exit(EXIT_FAILURE);61 }62 memcpy(bstr.data+bstr.len, buffer, bytes_read);63 bstr.len += bytes_read;64 }65 if (bytes_read < 0) {66 fprintf(stderr, "Unable to read from %s: %m.\n", filename);67 exit(EXIT_FAILURE);68 }69 close(fd);70 71 return(bstr);72 }73 74 75 void bstr_unmap(bstring bstr) {76 free(bstr.data);77 memset(&bstr, 0, sizeof(bstring));78 79 return;80 }81 40 82 41 … … 162 121 pthread_rwlock_destroy(&spamsum_trie_lock); 163 122 pthread_rwlock_destroy(&sighash_trie_lock); 123 pthread_rwlock_destroy(&sidlock); 164 124 165 125 return;
