Changeset 1562

Show
Ignore:
Timestamp:
02/21/08 19:11:09 (8 months ago)
Author:
till
Message:

nebula
- fixes: memory leaks, null pointer references
- append generated signatures to a snort rule file
- force snort to reload rules

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • nebula/trunk/ChangeLog

    r1431 r1562  
     10.2.0 
     2- daemon version 
     3- generalized suffix tree-based signature generation 
     4- snort rule output 
    150.1.0 
    26- queues as default data structures (restrictable in size) 
  • nebula/trunk/configure.in

    r1558 r1562  
    11# $Id$  
    22AC_PREREQ(02.50) 
    3 AC_INIT([nebula], [0.1.0], [tillmann.werner@gmx.de]) 
     3AC_INIT([nebula], [0.2.0], [tillmann.werner@gmx.de]) 
    44AM_CONFIG_HEADER(config.h) 
    5 AM_INIT_AUTOMAKE(nebula,0.1.0) 
     5AM_INIT_AUTOMAKE(nebula,0.2.0) 
    66 
    77AC_PROG_CC 
  • nebula/trunk/src/classify.c

    r1558 r1562  
    198198 
    199199        // 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) { 
    201201                        printf("[=] cluster hit size threshold, generating signature.\n"); 
    202202                        if (pthread_create(&ntid, NULL, pt_siggen, (void *) ((hash*)t->data)->cl)) { 
  • nebula/trunk/src/nebula.c

    r1560 r1562  
    5656void usage(const char* progname, const int exit_val) { 
    5757        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" 
    5960                "\t\t -c <similarity> cluster criteria (a similarity measure in percent)\n" 
    6061                "\t\t -d\t\t daemonize\n" 
    6162                "\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" 
    6364                "\t\t -O <size>\t outlier queue size\n" 
    6465                "\t\t -p <port>\t listen on this port\n" 
     
    9293        qsize                   = 0; 
    9394 
     95 
    9496        /* 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 
    95105        secret                  = NULL;         // s: NULL 
    96         daemonize               = 0;            // d: 0 
    97         port                    = 12346;        // p: 12345 
    98106        verbose                 = 0;            // v: don't be verbose 
    99         cluster_radius          = 95.0;         // c: 95% similarity as cluster criteria 
    100         outlierq_max            = 500000;       // O 
    101         clusterhashq_max        = 500000;       // E 
    102         clusterq_max            = 5000;         // C 
    103107 
    104108        memset(&md5sum_trie, 0, sizeof(trie_node)); 
     
    117121 
    118122        // 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) { 
    120124                switch(option) { 
     125                        case 'a': 
     126                                rules_file = optarg; 
     127                                break; 
    121128                        case 'c': 
    122129                                cluster_radius = atof(optarg); 
     
    143150                                } 
    144151                                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; 
    145159                        case 'O': 
    146160                                outlierq_max = atoi(optarg); 
     
    163177                                verbose++; 
    164178                                break; 
    165                         case 'h': 
    166179                        case '?': 
    167180                                usage(argv[0], EXIT_SUCCESS); 
     
    184197                printf("Warning - No submission secret given.\n"); 
    185198        } 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 
    186208 
    187209        // process incoming connections 
  • nebula/trunk/src/session.c

    r1560 r1562  
    3535 
    3636void session_reset(submission *s, struct pollfd *pfd) { 
     37        if (!s) return; 
     38 
    3739        free(s->cattack); 
    3840        free(s->attack); 
     
    4345                close(pfd->fd); 
    4446                memset(pfd, 0, sizeof(struct pollfd)); 
     47                pfd->fd = -1; 
    4548        } 
    4649 
     
    147150                                        return(-1); 
    148151                                } 
    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 
    150157                                session_reset(s, pfd); 
    151158                                return(0); 
     
    264271 
    265272                        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); 
    267274                        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); 
    269276 
    270277                        // calculate and check md5sum 
     
    277284                        } 
    278285                        free(md5sum); 
     286                        free(s->cattack); 
     287                        s->cattack = NULL; 
    279288 
    280289                        if (verbose) printf("Connection terminated.\n"); 
  • nebula/trunk/src/sig.c

    r1560 r1562  
    2020 
    2121#include <ctype.h> 
     22#include <errno.h> 
     23#include <signal.h> 
    2224#include <stdio.h> 
    2325#include <stdlib.h> 
    2426#include <string.h> 
     27#include <sys/types.h> 
    2528 
    2629#include "cluster.h" 
     
    3134#include "sig.h" 
    3235#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; 
    4136 
    4237 
     
    149144                // signature was generated earlier so skip it 
    150145                printf("[=] signature was already published.\n"); 
     146                free(sigdata); 
    151147                free(sha512sum); 
    152148                return; 
     
    158154                pthread_rwlock_unlock(&sighash_trie_lock); 
    159155        } 
     156        free(sigdata); 
    160157        free(sha512sum); 
    161158         
     
    171168                        printf("\033[1;31m]\033[1;32m[%lu]\033[1;0m  ", (long unsigned int) seglist[i-1].max_off+seglist[i-1].len); 
    172169                } 
    173                 printf("-----------------------------------------------------------------------------------------------------------\n\n"); 
     170                printf("-------------------------------------------------------------------------------------------------------\n\n"); 
    174171                break; 
    175172        case SIG_SNORT: 
     
    183180                // increase revision number 
    184181                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                } 
    185195 
    186196                // print snort signature 
     
    262272                        printf(" \\\n sid: %u; rev: %u;)\n", cl->sig_id, cl->sig_rev); 
    263273                } 
    264                 printf("-----------------------------------------------------------------------------------------------------------\n\n"); 
     274                printf("-------------------------------------------------------------------------------------------------------\n\n"); 
    265275                break; 
    266276        default: 
     
    411421        return(0); 
    412422} 
     423 
     424int 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  
    2222#define __NEBULA_SIG_H 1 
    2323 
     24#include <stdio.h> 
     25 
    2426#include "cluster.h" 
    2527#include "lca.h" 
     
    3032u_int32_t               global_sid;     // incrementing snort sid, must be mutexed 
    3133pthread_rwlock_t        sidlock; 
     34 
     35pid_t                   snort_pid; 
     36char                    *rules_file; 
     37 
    3238 
    3339typedef enum sig_type { 
     
    5258 
    5359 
     60typedef struct { 
     61        ssize_t org_off; 
     62        ssize_t min_off; 
     63        ssize_t max_off; 
     64        ssize_t len; 
     65} sseg; 
     66 
     67 
     68void *pt_siggen(void *cl); 
    5469void 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); 
     70int append_snortsig_to_rulefile(const char *filename, const stree *t, const cluster *cl, const sseg *seglist, const ssize_t num_frags); 
    5671 
    5772#endif 
  • nebula/trunk/src/stree.c

    r1558 r1562  
    638638                } 
    639639 
    640                 if (!l[id-1]) 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 
     640                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 
    642642 
    643643                // check if left interval boundary must be moved 
  • nebula/trunk/src/util.c

    r1560 r1562  
    3434#include "nebula.h" 
    3535#include "queue.h" 
     36#include "sig.h" 
    3637#include "signals.h" 
    3738#include "trie.h" 
    3839#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 } 
    8140 
    8241 
     
    162121        pthread_rwlock_destroy(&spamsum_trie_lock); 
    163122        pthread_rwlock_destroy(&sighash_trie_lock); 
     123        pthread_rwlock_destroy(&sidlock); 
    164124 
    165125        return;