Changeset 1560

Show
Ignore:
Timestamp:
02/19/08 22:19:41 (6 months ago)
Author:
till
Message:

nebula
- avoid signature duplicates by tracking signature hashes
- signature specialization inrcreases revision ID
- hash(pss+nonce) for submission authentication

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • nebula/trunk/src/Makefile.am

    r1559 r1560  
    66nebula_SOURCES =        signals.c signals.h \ 
    77                        md5.c md5.h \ 
     8                        sha512.c sha512.h \ 
    89                        spamsum.c spamsum.h \ 
    910                        util.c util.h \ 
  • nebula/trunk/src/cluster.h

    r1558 r1560  
    3636 * for ngram vectors */ 
    3737typedef struct cluster { 
    38         u_int16_t cnt; 
    39         void *parent; 
    40         struct cluster *prev; 
    41         struct cluster *next; 
    42         queue *hq; 
    43  
     38        u_int32_t       cnt; 
     39        u_int32_t       sig_id; 
     40        u_int32_t       sig_rev; 
     41        void            *parent; 
     42        struct cluster  *prev; 
     43        struct cluster  *next; 
     44        queue           *hq; 
    4445} cluster; 
    4546 
  • nebula/trunk/src/nebula.c

    r1558 r1560  
    104104        memset(&md5sum_trie, 0, sizeof(trie_node)); 
    105105        memset(&spamsum_trie, 0, sizeof(trie_node)); 
    106  
    107         pthread_rwlock_init(&md5sum_trie_lock, NULL); 
    108         pthread_rwlock_init(&spamsum_trie_lock, NULL); 
    109         pthread_rwlock_init(&sidlock, NULL); 
     106        memset(&sighash_trie, 0, sizeof(trie_node)); 
     107 
     108        if (pthread_rwlock_init(&md5sum_trie_lock, NULL) || 
     109            pthread_rwlock_init(&spamsum_trie_lock, NULL) || 
     110            pthread_rwlock_init(&sighash_trie_lock, NULL) || 
     111            pthread_rwlock_init(&sidlock, NULL)) { 
     112                fprintf(stderr, "Error - Unable to initialize queue mutex: %m.\n"); 
     113                exit(EXIT_FAILURE); 
     114        } 
    110115 
    111116        printf("\n  Nebula %s Copyright (C) 2007-2008 Tillmann Werner <tillmann.werner@gmx.de>\n\n", VERSION); 
     
    223228                                                // create submission copy so that we can reset the session  
    224229                                                memcpy(&tmp_submission, &s[i], sizeof(submission)); 
    225                                                 s[i].secret     = NULL; 
    226230                                                s[i].attack     = NULL; 
    227231                                                s[i].cattack    = NULL; 
  • nebula/trunk/src/nebula.h

    r1559 r1560  
    3636u_char          verbose; 
    3737char            *secret; 
    38 trie_node       spamsum_trie, md5sum_trie
     38trie_node       spamsum_trie, md5sum_trie, sighash_trie
    3939 
    4040ssize_t         clusterq_max, clusterhashq_max, outlierq_max;  
     
    4747pthread_rwlock_t md5sum_trie_lock; 
    4848pthread_rwlock_t spamsum_trie_lock; 
     49pthread_rwlock_t sighash_trie_lock; 
    4950 
    5051#endif 
  • nebula/trunk/src/session.c

    r1558 r1560  
    3030#include "nebula.h" 
    3131#include "session.h" 
     32#include "sha512.h" 
    3233#include "util.h" 
    3334 
    3435 
    3536void session_reset(submission *s, struct pollfd *pfd) { 
    36         free(s->secret); 
    3737        free(s->cattack); 
    3838        free(s->attack); 
     
    6464 
    6565int session_handle_data(struct pollfd *pfd, submission *s) { 
    66         int     rv; 
    67         char    *md5sum; 
     66        int             rv; 
     67        char            *md5sum; 
     68        char            *sha512sum; 
     69        char            *secret_randno; 
     70        trie_node       *t; 
    6871 
    6972        if (!pfd || !s) { 
     
    7477        switch (s->state) { 
    7578        case NEW: 
    76                 // read secret length 
    77                 if ((rv = session_read_data(pfd->fd, s, (u_char *) &(s->secret_len), 1)) == -1) { 
    78                         session_reset(s, pfd); 
    79                         return(-1); 
    80                 } else if (rv == 1) { 
    81                         s->bytes_read = 0; 
    82                         s->state = SECRET_LEN_READ; 
    83                         if (verbose > 1) printf("  secret length: %u\n", s->secret_len); 
    84                 } 
    85                 break; 
    86         case SECRET_LEN_READ: 
    87                 // read secret 
    88                 if ((s->secret = calloc(sizeof(char), s->secret_len + 1)) == NULL) { 
    89                         fprintf(stderr, "Error - Unable to allocate memory: %s.\n", strerror(errno)); 
    90                         exit(EXIT_FAILURE); 
    91                 } 
    92                 if ((rv = session_read_data(pfd->fd, s, (u_char *) s->secret, s->secret_len)) == -1) { 
    93                         session_reset(s, pfd); 
    94                         return(-1); 
    95                 } else if (rv == s->secret_len) { 
    96                         if (verbose > 1) printf("  secret: %s\n", s->secret); 
    97                         if (strlen(secret) == strlen(s->secret) && !strncmp(secret, s->secret, strlen(secret))) { 
    98                                 s->bytes_read = 0; 
     79                // read random number 
     80                s->bytes_read = 0; 
     81                if ((rv = session_read_data(pfd->fd, s, (u_char *) &(s->rand_no), 4)) == -1) { 
     82                        session_reset(s, pfd); 
     83                        return(-1); 
     84                } else if (rv == 4) { 
     85                        s->state = RANDNO_READ; 
     86                        if (verbose > 1) printf("  random number: %u\n", s->rand_no); 
     87                } 
     88                break; 
     89        case RANDNO_READ: 
     90                // read secret hash 
     91                s->bytes_read = 0; 
     92                if ((rv = session_read_data(pfd->fd, s, (u_char *) s->secret_hash, 128)) == -1) { 
     93                        session_reset(s, pfd); 
     94                        return(-1); 
     95                } else if (rv == 128) { 
     96                        s->state = UNAUTHENTICATED; 
     97 
     98                        if ((secret_randno = malloc(strlen(secret) + 4)) == NULL) { 
     99                                fprintf(stderr, "Error - Unable to allocate memory: %s.\n", strerror(errno)); 
     100                                return(-1); 
     101                        } 
     102                        memcpy(secret_randno, secret, strlen(secret)); 
     103                        memcpy(secret_randno+strlen(secret), &s->rand_no, 4); 
     104 
     105                        if ((sha512sum = mem_sha512sum((u_char *) secret_randno, strlen(secret) + 4)) == NULL) { 
     106                                fprintf(stderr, "Error - Unable to hash secret.\n"); 
     107                                return(-1); 
     108                        } 
     109                        free(secret_randno); 
     110 
     111                        if (!strncmp(sha512sum, s->secret_hash, 128)) { 
    99112                                s->state = AUTHENTICATED; 
    100                                 if (verbose > 1) printf("  session authenticated.\n"); 
    101                         } else { 
    102                                 if (verbose > 1) printf("  secret mismatch.\n"); 
     113                                if (verbose > 1) printf("  valid secret hash read, session authenticated.\n"); 
     114                        } 
     115 
     116                        free(sha512sum); 
     117 
     118                        if (s->state != AUTHENTICATED) { 
     119                                if (verbose > 1) printf("  secret mismatch, dropping session.\n"); 
    103120                                session_reset(s, pfd); 
    104121                        } 
     
    111128                        exit(EXIT_FAILURE); 
    112129                } 
     130                s->bytes_read = 0; 
    113131                if ((rv = session_read_data(pfd->fd, s, (u_char *) s->md5sum, 32)) == -1) { 
    114132                        session_reset(s, pfd); 
     
    116134                } else if (rv == 32) { 
    117135                        s->md5sum[32] = 0; 
    118                         s->bytes_read = 0; 
    119  
    120                         if (write(pfd->fd, "UNKNOWN\n", 8) == -1) { 
    121                                 fprintf(stderr, "Error - Unable to send data request: %s.\n", strerror(errno)); 
    122                                 session_reset(s, pfd); 
    123                                 return(-1); 
    124                         } 
    125  
     136                        if (verbose > 1) printf("  attack md5sum: %s\n", s->md5sum); 
     137 
     138                        pthread_rwlock_rdlock(&md5sum_trie_lock); 
     139                        t = trie_find_memstr(&md5sum_trie, (u_char *) s->md5sum, strlen(s->md5sum)); 
     140                        pthread_rwlock_unlock(&md5sum_trie_lock); 
     141 
     142                        if (t != NULL) { 
     143                                // md5sum is already in trie 
     144                                if (write(pfd->fd, "KNOWN\n", 6) == -1) { 
     145                                        fprintf(stderr, "Error - Unable to send data request: %s.\n", strerror(errno)); 
     146                                        session_reset(s, pfd); 
     147                                        return(-1); 
     148                                } 
     149                                if (verbose > 1) printf("  known attack, rejecting submission.\n"); 
     150                                session_reset(s, pfd); 
     151                                return(0); 
     152                        } else { 
     153                                // unknown attack hash, send request 
     154                                if (write(pfd->fd, "UNKNOWN\n", 8) == -1) { 
     155                                        fprintf(stderr, "Error - Unable to send data request: %s.\n", strerror(errno)); 
     156                                        session_reset(s, pfd); 
     157                                        return(-1); 
     158                                } 
     159                        } 
     160 
     161                        if (verbose > 1) printf("  unknown attack, submission requested.\n"); 
    126162                        s->state = REQUEST_SENT; 
    127                         if (verbose > 1) printf("  md5sum: %s\n", s->md5sum); 
    128163                } 
    129164                break; 
    130165        case REQUEST_SENT: 
    131166                // read protocol 
     167                s->bytes_read = 0; 
    132168                if ((rv = session_read_data(pfd->fd, s, (u_char *) &(s->protocol), 1)) == -1) { 
    133169                        session_reset(s, pfd); 
    134170                        return(-1); 
    135171                } else if (rv == 1) { 
    136                         s->bytes_read = 0; 
    137172                        s->state = PROTOCOL_READ; 
    138173                        switch (s->protocol) { 
     
    153188        case PROTOCOL_READ: 
    154189                // read port 
     190                s->bytes_read = 0; 
    155191                if ((rv = session_read_data(pfd->fd, s, (u_char *) &(s->port), 2)) == -1) { 
    156192                        session_reset(s, pfd); 
    157193                        return(-1); 
    158194                } else if (rv == 2) { 
    159                         s->bytes_read = 0; 
    160195                        s->state = PORT_READ; 
    161196                        if (verbose > 1) printf("  port: %u\n", s->port); 
     
    164199        case PORT_READ: 
    165200                // read length of attack data 
     201                s->bytes_read = 0; 
    166202                if ((rv = session_read_data(pfd->fd, s, (u_char *) &(s->attack_len), 4)) == -1) { 
    167203                        session_reset(s, pfd); 
    168204                        return(-1); 
    169205                } else if (rv == 4) { 
    170                         s->bytes_read = 0; 
    171206                        s->state = ATTACK_LEN_READ; 
    172207                        if (verbose > 1) printf("  bytes of attacks: %lu\n", s->attack_len); 
     
    175210        case ATTACK_LEN_READ: 
    176211                // read length of compressed attack data 
     212                s->bytes_read = 0; 
    177213                if ((rv = session_read_data(pfd->fd, s, (u_char *) &(s->cattack_len), 4)) == -1) { 
    178214                        session_reset(s, pfd); 
    179215                        return(-1); 
    180216                } else if (rv == 4) { 
    181                         s->bytes_read = 0; 
    182217                        s->state = CATTACK_LEN_READ; 
    183218                        if (verbose > 1) printf("  bytes of compressed attacks: %u\n", s->cattack_len); 
     
    185220                break; 
    186221        case CATTACK_LEN_READ: 
    187  
    188222                // read compressed attack 
    189223                if ((s->cattack = calloc(sizeof(u_char), s->cattack_len)) == NULL) { 
     
    191225                        exit(EXIT_FAILURE); 
    192226                } 
     227                s->bytes_read = 0; 
    193228                if ((rv = session_read_data(pfd->fd, s, s->cattack, s->cattack_len)) == -1) { 
    194229                        session_reset(s, pfd); 
  • nebula/trunk/src/session.h

    r1558 r1560  
    2929#include <sys/types.h> 
    3030 
    31  
    3231typedef enum sstate { 
    3332        NEW = 0, 
    34         SECRET_LEN_READ, 
     33        RANDNO_READ, 
     34        UNAUTHENTICATED, 
    3535        AUTHENTICATED, 
    3636        REQUEST_SENT, 
     
    4343 
    4444typedef struct submission { 
    45         sstate          state;          // session state 
    46         ssize_t         bytes_read;     // number of bytes read so far 
    47         u_char         secret_len;     // length of secret string 
    48         char            *secret;       // secret string 
    49         u_char          protocol;       // attack protocol 
    50         u_int16_t       port;           // attack port 
    51         u_int32_t       cattack_len;    // length of compressed attack data 
    52         unsigned long   attack_len;     // length of uncompressed attack data 
    53         u_char          *cattack;       // compressed attack data 
    54         u_char          *attack;        // uncompressed attack data 
    55         char            *md5sum;        // md5 hash of uncompressed attack data 
     45        sstate          state;                 // session state 
     46        ssize_t         bytes_read;            // number of bytes read so far 
     47        u_int32_t      rand_no;                // random number (hashed together with secret string) 
     48        char            secret_hash[129];      // hashed secret 
     49        u_char          protocol;              // attack protocol 
     50        u_int16_t       port;                  // attack port 
     51        u_int32_t       cattack_len;           // length of compressed attack data 
     52        unsigned long   attack_len;            // length of uncompressed attack data 
     53        u_char          *cattack;              // compressed attack data 
     54        u_char          *attack;               // uncompressed attack data 
     55        char            *md5sum;               // md5 hash of uncompressed attack data 
    5656} submission; 
    5757 
  • nebula/trunk/src/sig.c

    r1559 r1560  
    2424#include <string.h> 
    2525 
     26#include "cluster.h" 
    2627#include "cstr.h" 
    2728#include "nebula.h" 
    2829#include "session.h" 
     30#include "sha512.h" 
    2931#include "sig.h" 
    3032#include "stree.h" 
     
    7072 
    7173 
    72 void build_sig(stree *t, lcatbl *lca_table, substr_list list, stnode **leaves, ssize_t num_leaves, ssize_t min_len, double min_ent, sigtype stype) { 
     74void 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) { 
    7375        int             i, j, printable; 
    7476        double          ent; 
    75         u_int32_t       start, sid
    76         ssize_t         leaf, id, l, r; 
     77        u_int32_t       start
     78        ssize_t         sigdata_len, leaf, id, l, r; 
    7779        sseg            *seglist; 
     80        u_char          *sigdata; 
     81        char            *sha512sum; 
     82        trie_node       *n; 
    7883 
    7984        ssize_t         num_frags; 
     
    8186 
    8287        num_frags       = 0; 
     88        sigdata_len     = 0; 
    8389        seglist         = NULL; 
     90        sigdata         = NULL; 
    8491 
    8592        for (i = 0; i < list.len; i++) { 
     
    116123        } 
    117124 
     125 
     126        // store signature info into for hashing a contiguous memory area 
     127        for (i=num_frags; i; i--) { 
     128                // append next signature segment 
     129                if ((sigdata = realloc(sigdata, sigdata_len + sizeof(sseg) + seglist[i-1].len)) == NULL) { 
     130                        fprintf(stderr, "Error - Unable to allocate memory: %m.\n"); 
     131                        free(sigdata); 
     132                        return; 
     133                } 
     134                memcpy(&sigdata[sigdata_len], &seglist[i-1], sizeof(sseg)); 
     135                sigdata_len += sizeof(sseg); 
     136                memcpy(&sigdata[sigdata_len], &t->tree_string[seglist[i-1].org_off+1], seglist[i-1].len); 
     137                sigdata_len += seglist[i-1].len; 
     138        } 
     139 
     140        // hash signature and do a trie lookup 
     141        sha512sum = mem_sha512sum(sigdata, sigdata_len); 
     142        printf("[=] signature hash: %s\n", sha512sum); 
     143 
     144        pthread_rwlock_rdlock(&sighash_trie_lock); 
     145        n = trie_find_memstr(&sighash_trie, (u_char *) sha512sum, 128); 
     146        pthread_rwlock_unlock(&sighash_trie_lock); 
     147 
     148        if (n != NULL) { 
     149                // signature was generated earlier so skip it 
     150                printf("[=] signature was already published.\n"); 
     151                free(sha512sum); 
     152                return; 
     153        } else { 
     154                // insert signature hash into trie 
     155                pthread_rwlock_wrlock(&sighash_trie_lock); 
     156                n = trie_memins(&sighash_trie, (u_char *) sha512sum, 128, NULL); 
     157                n->data = cl; 
     158                pthread_rwlock_unlock(&sighash_trie_lock); 
     159        } 
     160        free(sha512sum); 
     161         
     162 
    118163        switch (stype) { 
    119164        case SIG_RAW: 
    120165                // print raw signature 
     166                printf("\n---- Signature type: raw ------------------------------------------------------------------------------\n"); 
    121167                for (i=num_frags; i; i--) { 
    122168                        printf("#\033[1;32m[%lu]\033[1;31m[\033[1;0m", (long unsigned int) seglist[i-1].min_off); 
     
    125171                        printf("\033[1;31m]\033[1;32m[%lu]\033[1;0m  ", (long unsigned int) seglist[i-1].max_off+seglist[i-1].len); 
    126172                } 
    127                 printf("\n"); 
     173                printf("-----------------------------------------------------------------------------------------------------------\n\n"); 
    128174                break; 
    129175        case SIG_SNORT: 
    130                 // increase global sid 
    131                 pthread_rwlock_wrlock(&sidlock); 
    132                 sid = ++global_sid; 
    133                 pthread_rwlock_unlock(&sidlock); 
     176                if (!cl->sig_id) { 
     177                        // increase global sid 
     178                        pthread_rwlock_wrlock(&sidlock); 
     179                        cl->sig_id = ++global_sid; 
     180                        pthread_rwlock_unlock(&sidlock); 
     181                } 
     182 
     183                // increase revision number 
     184                cl->sig_rev++; 
    134185 
    135186                // print snort signature 
    136187                printf("\n---- Signature type: snort ----------------------------------------------------------------------------\n"); 
    137                 printf("alert tcp any any -> any any (msg: \"nebula rule %u\";", sid);  
     188                printf("alert tcp any any -> any any (msg: \"nebula rule %u rev. %u\";", cl->sig_id, cl->sig_rev);  
    138189                if (num_frags) { 
    139190                        printf(" \\\n content: \""); 
     
    209260                                        (long unsigned int) seglist[i-1].max_off + seglist[i-1].len - seglist[i].min_off); 
    210261                        } 
    211                         printf(" \\\n sid: %u;)\n", sid); 
    212                 } 
    213                 printf("--------------------------------------------------------------------------------------------------\n\n"); 
     262                        printf(" \\\n sid: %u; rev: %u;)\n", cl->sig_id, cl->sig_rev); 
     263                } 
     264                printf("-----------------------------------------------------------------------------------------------------------\n\n"); 
    214265                break; 
    215266        default: 
     
    291342 
    292343        // print concatenated string 
    293         if (verbose) { 
     344        if (verbose > 1) { 
    294345                printf("Concatenated string (%u) is '", strllen); 
    295346                for (i = 0; i < strllen; i++) { 
     
    348399//              list_substrings(gst, cstr_list.elem[i].n, cstr_list.elem[i].len); 
    349400 
    350         build_sig(gst, lca_table, cstr_list, leaves, num_leaves, min_sstr_len, min_sstr_ent, SIG_SNORT); 
     401        build_sig(cl, gst, lca_table, cstr_list, leaves, num_leaves, min_sstr_len, min_sstr_ent, SIG_SNORT); 
    351402 
    352403 
  • nebula/trunk/src/sig.h

    r1558 r1560  
    3939struct { 
    4040        sigtype         type; 
    41         cluster         cl; 
    4241        void            *metainfo; 
    4342        time_t          create_time; 
     
    5352 
    5453 
    55 void build_sig(stree *t, lcatbl *lca_table, substr_list list, stnode **leaves, ssize_t num_leaves, ssize_t min_len, double min_ent, sigtype stype); 
     54void 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); 
    5655void *pt_siggen(void *cl); 
    5756 
  • nebula/trunk/src/util.c

    r1558 r1560  
    155155        pthread_rwlock_unlock(&spamsum_trie_lock); 
    156156         
     157        pthread_rwlock_wrlock(&sighash_trie_lock); 
     158        trie_delete(sighash_trie.childlist, sighash_trie.childlist_len, NULL); 
     159        pthread_rwlock_unlock(&sighash_trie_lock); 
     160         
    157161        pthread_rwlock_destroy(&md5sum_trie_lock); 
    158162        pthread_rwlock_destroy(&spamsum_trie_lock); 
     163        pthread_rwlock_destroy(&sighash_trie_lock); 
    159164 
    160165        return;