Web interface done, web server fixed, pcap support

This commit is contained in:
BlackLight 2010-10-11 17:00:03 +02:00
parent 6c3e00bc8d
commit 7a73cdbc85
20 changed files with 4633 additions and 142 deletions

View File

@ -4,7 +4,7 @@ AUTOMAKE_OPTIONS=foreign no-dependencies
libdir = ${exec_prefix}/lib/snort_dynamicpreprocessor
lib_LTLIBRARIES = libsf_ai_preproc.la
libsf_ai_preproc_la_CFLAGS = -I./uthash -I./include ${LIBXML2_INCLUDES} ${LIBGRAPH_INCLUDES} -DDYNAMIC_PLUGIN -D_XOPEN_SOURCE -D_GNU_SOURCE -fvisibility=hidden -fno-strict-aliasing -Wall -pedantic -pedantic-errors -std=c99 -fstack-protector
libsf_ai_preproc_la_CFLAGS = -I./uthash -I./base64 -I./include ${LIBXML2_INCLUDES} ${LIBGRAPH_INCLUDES} -DDYNAMIC_PLUGIN -D_XOPEN_SOURCE -D_GNU_SOURCE -fvisibility=hidden -fno-strict-aliasing -Wall -pedantic -pedantic-errors -std=c99 -fstack-protector
libsf_ai_preproc_la_LDFLAGS = -module -export-dynamic
BUILT_SOURCES = \
@ -18,6 +18,9 @@ include/sfPolicyUserData.c
libsf_ai_preproc_la_SOURCES = \
alert_history.c \
alert_parser.c \
base64/base64.c \
base64/cdecode.c \
base64/cencode.c \
bayesian.c \
cluster.c \
correlation.c \
@ -54,10 +57,10 @@ install-data-hook:
mkdir -p "${SHARE_PREFIX}/htdocs"
mkdir -p "${SHARE_PREFIX}/htdocs/js"
install -m 0644 "${PWD}/htdocs/index.html" "${SHARE_PREFIX}/htdocs"
install -m 0755 "${PWD}/htdocs/test.cgi" "${SHARE_PREFIX}/htdocs"
install -m 0755 "${PWD}/htdocs/pcap.cgi" "${SHARE_PREFIX}/htdocs"
install -m 0644 "${PWD}/htdocs/js/Curry-1.0.1.js" "${SHARE_PREFIX}/htdocs/js"
install -m 0644 "${PWD}/htdocs/js/dracula_algorithms.js" "${SHARE_PREFIX}/htdocs/js"
install -m 0644 "${PWD}/htdocs/js/dracula_graffle.js" "${SHARE_PREFIX}/htdocs/js"
install -m 0644 "${PWD}/htdocs/js/dracula_graph.js" "${SHARE_PREFIX}/htdocs/js"
install -m 0644 "${PWD}/htdocs/js/raphael-min.js" "${SHARE_PREFIX}/htdocs/js"
install -m 0644 "${PWD}/htdocs/js/raphael.js" "${SHARE_PREFIX}/htdocs/js"
install -m 0644 "${PWD}/htdocs/js/seedrandom.js" "${SHARE_PREFIX}/htdocs/js"

View File

@ -80,7 +80,9 @@ LTLIBRARIES = $(lib_LTLIBRARIES)
libsf_ai_preproc_la_LIBADD =
am_libsf_ai_preproc_la_OBJECTS = libsf_ai_preproc_la-alert_history.lo \
libsf_ai_preproc_la-alert_parser.lo \
libsf_ai_preproc_la-bayesian.lo libsf_ai_preproc_la-cluster.lo \
libsf_ai_preproc_la-base64.lo libsf_ai_preproc_la-cdecode.lo \
libsf_ai_preproc_la-cencode.lo libsf_ai_preproc_la-bayesian.lo \
libsf_ai_preproc_la-cluster.lo \
libsf_ai_preproc_la-correlation.lo libsf_ai_preproc_la-db.lo \
libsf_ai_preproc_la-mysql.lo libsf_ai_preproc_la-outdb.lo \
libsf_ai_preproc_la-postgresql.lo libsf_ai_preproc_la-regex.lo \
@ -244,7 +246,7 @@ top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
AUTOMAKE_OPTIONS = foreign no-dependencies
lib_LTLIBRARIES = libsf_ai_preproc.la
libsf_ai_preproc_la_CFLAGS = -I./uthash -I./include ${LIBXML2_INCLUDES} ${LIBGRAPH_INCLUDES} -DDYNAMIC_PLUGIN -D_XOPEN_SOURCE -D_GNU_SOURCE -fvisibility=hidden -fno-strict-aliasing -Wall -pedantic -pedantic-errors -std=c99 -fstack-protector
libsf_ai_preproc_la_CFLAGS = -I./uthash -I./base64 -I./include ${LIBXML2_INCLUDES} ${LIBGRAPH_INCLUDES} -DDYNAMIC_PLUGIN -D_XOPEN_SOURCE -D_GNU_SOURCE -fvisibility=hidden -fno-strict-aliasing -Wall -pedantic -pedantic-errors -std=c99 -fstack-protector
libsf_ai_preproc_la_LDFLAGS = -module -export-dynamic
BUILT_SOURCES = \
include/sf_dynamic_preproc_lib.c \
@ -257,6 +259,9 @@ include/sfPolicyUserData.c
libsf_ai_preproc_la_SOURCES = \
alert_history.c \
alert_parser.c \
base64/base64.c \
base64/cdecode.c \
base64/cencode.c \
bayesian.c \
cluster.c \
correlation.c \
@ -386,6 +391,15 @@ libsf_ai_preproc_la-alert_history.lo: alert_history.c
libsf_ai_preproc_la-alert_parser.lo: alert_parser.c
$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsf_ai_preproc_la_CFLAGS) $(CFLAGS) -c -o libsf_ai_preproc_la-alert_parser.lo `test -f 'alert_parser.c' || echo '$(srcdir)/'`alert_parser.c
libsf_ai_preproc_la-base64.lo: base64/base64.c
$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsf_ai_preproc_la_CFLAGS) $(CFLAGS) -c -o libsf_ai_preproc_la-base64.lo `test -f 'base64/base64.c' || echo '$(srcdir)/'`base64/base64.c
libsf_ai_preproc_la-cdecode.lo: base64/cdecode.c
$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsf_ai_preproc_la_CFLAGS) $(CFLAGS) -c -o libsf_ai_preproc_la-cdecode.lo `test -f 'base64/cdecode.c' || echo '$(srcdir)/'`base64/cdecode.c
libsf_ai_preproc_la-cencode.lo: base64/cencode.c
$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsf_ai_preproc_la_CFLAGS) $(CFLAGS) -c -o libsf_ai_preproc_la-cencode.lo `test -f 'base64/cencode.c' || echo '$(srcdir)/'`base64/cencode.c
libsf_ai_preproc_la-bayesian.lo: bayesian.c
$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsf_ai_preproc_la_CFLAGS) $(CFLAGS) -c -o libsf_ai_preproc_la-bayesian.lo `test -f 'bayesian.c' || echo '$(srcdir)/'`bayesian.c
@ -819,12 +833,12 @@ install-data-hook:
mkdir -p "${SHARE_PREFIX}/htdocs"
mkdir -p "${SHARE_PREFIX}/htdocs/js"
install -m 0644 "${PWD}/htdocs/index.html" "${SHARE_PREFIX}/htdocs"
install -m 0755 "${PWD}/htdocs/test.cgi" "${SHARE_PREFIX}/htdocs"
install -m 0755 "${PWD}/htdocs/pcap.cgi" "${SHARE_PREFIX}/htdocs"
install -m 0644 "${PWD}/htdocs/js/Curry-1.0.1.js" "${SHARE_PREFIX}/htdocs/js"
install -m 0644 "${PWD}/htdocs/js/dracula_algorithms.js" "${SHARE_PREFIX}/htdocs/js"
install -m 0644 "${PWD}/htdocs/js/dracula_graffle.js" "${SHARE_PREFIX}/htdocs/js"
install -m 0644 "${PWD}/htdocs/js/dracula_graph.js" "${SHARE_PREFIX}/htdocs/js"
install -m 0644 "${PWD}/htdocs/js/raphael-min.js" "${SHARE_PREFIX}/htdocs/js"
install -m 0644 "${PWD}/htdocs/js/raphael.js" "${SHARE_PREFIX}/htdocs/js"
install -m 0644 "${PWD}/htdocs/js/seedrandom.js" "${SHARE_PREFIX}/htdocs/js"
# Tell versions [3.59,3.63) of GNU make to not export all variables.

4
TODO
View File

@ -2,8 +2,6 @@
AVERAGE/HIGH PRIORITY:
======================
- Web interface
- Function names (private functions with _ or __ ?)
- Bayesian network
- Modules for correlation coefficients
- Code profiling
@ -36,4 +34,6 @@ DONE:
+ Save clusters and correlations to db
+ Uniformed error messages format
+ Full PostgreSQL support for output db
+ Web interface
+ Function names (private functions with _ or __ ?)

View File

@ -463,7 +463,7 @@ AI_file_alertparser_thread ( void* arg )
* \return A copy of the alert log linked list
*/
PRIVATE AI_snort_alert*
_AI_copy_alerts ( AI_snort_alert *node )
__AI_copy_alerts ( AI_snort_alert *node )
{
AI_snort_alert *current = NULL, *next = NULL;
@ -474,7 +474,7 @@ _AI_copy_alerts ( AI_snort_alert *node )
if ( node->next )
{
next = _AI_copy_alerts ( node->next );
next = __AI_copy_alerts ( node->next );
}
if ( !( current = ( AI_snort_alert* ) malloc ( sizeof ( AI_snort_alert )) ))
@ -485,7 +485,7 @@ _AI_copy_alerts ( AI_snort_alert *node )
memcpy ( current, node, sizeof ( AI_snort_alert ));
current->next = next;
return current;
} /* ----- end of function _AI_copy_alerts ----- */
} /* ----- end of function __AI_copy_alerts ----- */
/**
@ -498,7 +498,7 @@ AI_get_alerts ()
AI_snort_alert *alerts_copy;
pthread_mutex_lock ( &alert_mutex );
alerts_copy = _AI_copy_alerts ( alerts );
alerts_copy = __AI_copy_alerts ( alerts );
pthread_mutex_unlock ( &alert_mutex );
return alerts_copy;

View File

@ -61,13 +61,13 @@ PRIVATE double k_exp_value = 0.0;
*/
PRIVATE double
_AI_bayesian_correlation_function ( time_t ta, time_t tb )
__AI_bayesian_correlation_function ( time_t ta, time_t tb )
{
if ( k_exp_value == 0.0 )
k_exp_value = - (double) (config->bayesianCorrelationInterval * config->bayesianCorrelationInterval) / log ( CUTOFF_Y_VALUE );
return exp ( -((ta - tb) * (ta - tb)) / k_exp_value );
} /* ----- end of function _AI_bayesian_correlation_function ----- */
} /* ----- end of function __AI_bayesian_correlation_function ----- */
/**
* \brief Compute the correlation between two alerts, A -> B: p[A|B] = p[Corr(A,B)] / P[B]
@ -134,7 +134,7 @@ AI_alert_bayesian_correlation ( AI_snort_alert *a, AI_snort_alert *b )
{
is_a_correlated = true;
corr_count++;
corr += _AI_bayesian_correlation_function ( events_iterator_a->timestamp, events_iterator_b->timestamp );
corr += __AI_bayesian_correlation_function ( events_iterator_a->timestamp, events_iterator_b->timestamp );
}
}

View File

@ -61,7 +61,7 @@ PRIVATE pthread_mutex_t mutex;
*/
PRIVATE int
_heuristic_func ( cluster_type type )
__AI_heuristic_func ( cluster_type type )
{
AI_snort_alert *alert_iterator;
attribute_key key;
@ -119,7 +119,7 @@ _heuristic_func ( cluster_type type )
}
return max;
} /* ----- end of function _heuristic_func ----- */
} /* ----- end of function __AI_heuristic_func ----- */
/**
* \brief Create a new clustering hierarchy node
@ -130,7 +130,7 @@ _heuristic_func ( cluster_type type )
*/
PRIVATE hierarchy_node*
_hierarchy_node_new ( char *label, int min_val, int max_val )
__AI_hierarchy_node_new ( char *label, int min_val, int max_val )
{
hierarchy_node *n = NULL;
@ -147,7 +147,7 @@ _hierarchy_node_new ( char *label, int min_val, int max_val )
strncpy ( n->label, label, sizeof ( n->label ));
return n;
} /* ----- end of function _hierarchy_node_new ----- */
} /* ----- end of function __AI_hierarchy_node_new ----- */
/**
@ -157,7 +157,7 @@ _hierarchy_node_new ( char *label, int min_val, int max_val )
*/
PRIVATE void
_hierarchy_node_append ( hierarchy_node *parent, hierarchy_node *child )
__AI_hierarchy_node_append ( hierarchy_node *parent, hierarchy_node *child )
{
if ( !( parent->children = ( hierarchy_node** ) realloc ( parent->children, (++(parent->nchildren)) * sizeof ( hierarchy_node* )) ))
{
@ -166,7 +166,7 @@ _hierarchy_node_append ( hierarchy_node *parent, hierarchy_node *child )
parent->children[ parent->nchildren - 1 ] = child;
child->parent = parent;
} /* ----- end of function _hierarchy_node_append ----- */
} /* ----- end of function __AI_hierarchy_node_append ----- */
/**
@ -176,7 +176,7 @@ _hierarchy_node_append ( hierarchy_node *parent, hierarchy_node *child )
* \return The minimum node that matches the value if any, NULL otherwise
*/
PRIVATE hierarchy_node*
_AI_get_min_hierarchy_node ( int val, hierarchy_node *root )
__AI_get_min_hierarchy_node ( int val, hierarchy_node *root )
{
int i;
hierarchy_node *next = NULL;
@ -202,8 +202,8 @@ _AI_get_min_hierarchy_node ( int val, hierarchy_node *root )
if ( !next )
return root;
return _AI_get_min_hierarchy_node ( val, next );
} /* ----- end of function _AI_get_min_hierarchy_node ----- */
return __AI_get_min_hierarchy_node ( val, next );
} /* ----- end of function __AI_get_min_hierarchy_node ----- */
/**
* \brief Check if two alerts are semantically equal
@ -213,7 +213,7 @@ _AI_get_min_hierarchy_node ( int val, hierarchy_node *root )
*/
PRIVATE BOOL
_AI_equal_alerts ( AI_snort_alert *a1, AI_snort_alert *a2 )
__AI_equal_alerts ( AI_snort_alert *a1, AI_snort_alert *a2 )
{
if ( a1->gid != a2->gid || a1->sid != a2->sid || a1->rev != a2->rev )
{
@ -249,7 +249,7 @@ _AI_equal_alerts ( AI_snort_alert *a1, AI_snort_alert *a2 )
}
return true;
} /* ----- end of function _AI_equal_alerts ----- */
} /* ----- end of function __AI_equal_alerts ----- */
/**
@ -259,7 +259,7 @@ _AI_equal_alerts ( AI_snort_alert *a1, AI_snort_alert *a2 )
*/
PRIVATE int
_AI_merge_alerts ( AI_snort_alert **log )
__AI_merge_alerts ( AI_snort_alert **log )
{
AI_snort_alert *tmp, *tmp2, *tmp3;
AI_alerts_couple *alerts_couple;
@ -279,7 +279,7 @@ _AI_merge_alerts ( AI_snort_alert **log )
if ( tmp != tmp2->next )
{
/* If the two alerts are equal... */
if ( _AI_equal_alerts ( tmp, tmp2->next ))
if ( __AI_equal_alerts ( tmp, tmp2->next ))
{
/* If we are storing the outputs of the module to a database, save the cluster containing the two alerts */
if ( config->outdbtype != outdb_none )
@ -321,7 +321,7 @@ _AI_merge_alerts ( AI_snort_alert **log )
}
return count;
} /* ----- end of function _AI_merge_alerts ----- */
} /* ----- end of function __AI_merge_alerts ----- */
/**
* \brief Get the average heterogeneity coefficient of the set of alerts
@ -329,7 +329,7 @@ _AI_merge_alerts ( AI_snort_alert **log )
*/
double
_AI_get_alerts_heterogeneity ( int *alert_count )
__AI_get_alerts_heterogeneity ( int *alert_count )
{
double heterogeneity = 0.0;
int distinct_count = 0;
@ -379,7 +379,7 @@ _AI_get_alerts_heterogeneity ( int *alert_count )
}
return heterogeneity;
} /* ----- end of function _AI_get_alerts_heterogeneity ----- */
} /* ----- end of function __AI_get_alerts_heterogeneity ----- */
/**
* \brief Print the clustered alerts to a log file
@ -388,7 +388,7 @@ _AI_get_alerts_heterogeneity ( int *alert_count )
*/
PRIVATE void
_AI_print_clustered_alerts ( AI_snort_alert *log, FILE *fp )
__AI_print_clustered_alerts ( AI_snort_alert *log, FILE *fp )
{
AI_snort_alert *tmp;
char ip[INET_ADDRSTRLEN];
@ -440,14 +440,14 @@ _AI_print_clustered_alerts ( AI_snort_alert *log, FILE *fp )
fprintf ( fp, "\n" );
}
} /* ----- end of function _AI_print_clustered_alerts ----- */
} /* ----- end of function __AI_print_clustered_alerts ----- */
/**
* \brief Thread for periodically clustering the log information
*/
PRIVATE void*
_AI_cluster_thread ( void* arg )
__AI_cluster_thread ( void* arg )
{
AI_snort_alert *tmp;
hierarchy_node *node, *child;
@ -523,14 +523,14 @@ _AI_cluster_thread ( void* arg )
return (void*) 0;
}
node = _AI_get_min_hierarchy_node ( hostval, h_root[type] );
node = __AI_get_min_hierarchy_node ( hostval, h_root[type] );
if ( node )
{
if ( node->min_val < node->max_val )
{
child = _hierarchy_node_new ( label, hostval, hostval);
_hierarchy_node_append ( node, child );
child = __AI_hierarchy_node_new ( label, hostval, hostval);
__AI_hierarchy_node_append ( node, child );
node = child;
}
@ -540,8 +540,8 @@ _AI_cluster_thread ( void* arg )
}
}
alert_count -= _AI_merge_alerts ( &alert_log );
heterogeneity = _AI_get_alerts_heterogeneity( &single_alerts_count );
alert_count -= __AI_merge_alerts ( &alert_log );
heterogeneity = __AI_get_alerts_heterogeneity ( &single_alerts_count );
/* Get the minimum size for the clusters in function of the heterogeneity of alerts' set */
if ( heterogeneity > 0 )
@ -560,7 +560,7 @@ _AI_cluster_thread ( void* arg )
{
if ( type != none && h_root[type] )
{
if (( heuristic_val = _heuristic_func ( type )) > 0 && heuristic_val < minval )
if (( heuristic_val = __AI_heuristic_func ( type )) > 0 && heuristic_val < minval )
{
minval = heuristic_val;
best_type = type;
@ -580,7 +580,7 @@ _AI_cluster_thread ( void* arg )
}
}
alert_count -= _AI_merge_alerts ( &alert_log );
alert_count -= __AI_merge_alerts ( &alert_log );
} while ( old_alert_count != alert_count );
pthread_mutex_unlock ( &mutex );
@ -591,7 +591,7 @@ _AI_cluster_thread ( void* arg )
return (void*) 0;
}
_AI_print_clustered_alerts ( alert_log, cluster_fp );
__AI_print_clustered_alerts ( alert_log, cluster_fp );
fclose ( cluster_fp );
}
@ -608,7 +608,7 @@ _AI_cluster_thread ( void* arg )
*/
PRIVATE BOOL
_AI_check_duplicate ( hierarchy_node *node, hierarchy_node *root )
__AI_check_duplicate ( hierarchy_node *node, hierarchy_node *root )
{
int i;
@ -620,7 +620,7 @@ _AI_check_duplicate ( hierarchy_node *node, hierarchy_node *root )
for ( i=0; i < root->nchildren; i++ )
{
if ( _AI_check_duplicate ( node, root->children[i] ))
if ( __AI_check_duplicate ( node, root->children[i] ))
return true;
}
@ -650,7 +650,7 @@ AI_hierarchies_build ( hierarchy_node **nodes, int n_nodes )
case src_port:
case dst_port:
if ( !h_root[ nodes[i]->type ] )
h_root[ nodes[i]->type ] = _hierarchy_node_new ( "1-65535", 1, 65535 );
h_root[ nodes[i]->type ] = __AI_hierarchy_node_new ( "1-65535", 1, 65535 );
min_range = 65534;
break;
@ -658,7 +658,7 @@ AI_hierarchies_build ( hierarchy_node **nodes, int n_nodes )
case src_addr:
case dst_addr:
if ( !h_root[ nodes[i]->type ] )
h_root[ nodes[i]->type ] = _hierarchy_node_new ( "0.0.0.0/0", 0x0, 0xffffffff );
h_root[ nodes[i]->type ] = __AI_hierarchy_node_new ( "0.0.0.0/0", 0x0, 0xffffffff );
min_range = 0xffffffff;
break;
@ -671,7 +671,7 @@ AI_hierarchies_build ( hierarchy_node **nodes, int n_nodes )
root = h_root[ nodes[i]->type ];
cover = NULL;
if ( _AI_check_duplicate ( nodes[i], root ))
if ( __AI_check_duplicate ( nodes[i], root ))
{
AI_fatal_err ( "Parse error: duplicate cluster range in module configuration", __FILE__, __LINE__ );
}
@ -696,17 +696,17 @@ AI_hierarchies_build ( hierarchy_node **nodes, int n_nodes )
if ( cover )
{
_hierarchy_node_append ( cover, nodes[i] );
__AI_hierarchy_node_append ( cover, nodes[i] );
} else {
if ( (unsigned) nodes[i]->min_val >= (unsigned) root->min_val && (unsigned) nodes[i]->max_val <= (unsigned) root->max_val &&
( (unsigned) nodes[i]->min_val != (unsigned) root->min_val || (unsigned) nodes[i]->max_val != (unsigned) root->max_val ))
{
_hierarchy_node_append ( root, nodes[i] );
__AI_hierarchy_node_append ( root, nodes[i] );
}
}
}
if ( pthread_create ( &cluster_thread, NULL, _AI_cluster_thread, NULL ) != 0 )
if ( pthread_create ( &cluster_thread, NULL, __AI_cluster_thread, NULL ) != 0 )
{
AI_fatal_err ( "Failed to create the hash cleanup thread", __FILE__, __LINE__ );
}
@ -719,7 +719,7 @@ AI_hierarchies_build ( hierarchy_node **nodes, int n_nodes )
*/
PRIVATE AI_snort_alert*
_AI_copy_clustered_alerts ( AI_snort_alert *node )
__AI_copy_clustered_alerts ( AI_snort_alert *node )
{
AI_snort_alert *current = NULL, *next = NULL;
@ -730,7 +730,7 @@ _AI_copy_clustered_alerts ( AI_snort_alert *node )
if ( node->next )
{
next = _AI_copy_clustered_alerts ( node->next );
next = __AI_copy_clustered_alerts ( node->next );
}
if ( !( current = ( AI_snort_alert* ) malloc ( sizeof ( AI_snort_alert )) ))
@ -741,7 +741,7 @@ _AI_copy_clustered_alerts ( AI_snort_alert *node )
memcpy ( current, node, sizeof ( AI_snort_alert ));
current->next = next;
return current;
} /* ----- end of function _AI_copy_clustered_alerts ----- */
} /* ----- end of function __AI_copy_clustered_alerts ----- */
/**
@ -755,7 +755,7 @@ AI_get_clustered_alerts ()
AI_snort_alert *alerts_copy;
pthread_mutex_lock ( &mutex );
alerts_copy = _AI_copy_clustered_alerts ( alert_log );
alerts_copy = __AI_copy_clustered_alerts ( alert_log );
pthread_mutex_unlock ( &mutex );
return alerts_copy;

View File

@ -54,7 +54,7 @@ PRIVATE pthread_mutex_t mutex;
*/
PRIVATE void
_AI_correlation_table_cleanup ()
__AI_correlation_table_cleanup ()
{
AI_alert_correlation *current;
@ -64,7 +64,7 @@ _AI_correlation_table_cleanup ()
HASH_DEL ( correlation_table, current );
free ( current );
}
} /* ----- end of function _AI_correlation_table_cleanup ----- */
} /* ----- end of function __AI_correlation_table_cleanup ----- */
/**
* \brief Recursively write a flow of correlated alerts to a .dot file, ready for being rendered as graph
@ -73,7 +73,7 @@ _AI_correlation_table_cleanup ()
*/
PRIVATE void
_AI_correlated_alerts_to_dot ( AI_alert_correlation *corr, FILE *fp )
__AI_correlated_alerts_to_dot ( AI_alert_correlation *corr, FILE *fp )
{
char src_addr1[INET_ADDRSTRLEN],
dst_addr1[INET_ADDRSTRLEN],
@ -130,19 +130,29 @@ _AI_correlated_alerts_to_dot ( AI_alert_correlation *corr, FILE *fp )
timestamp2,
corr->key.b->grouped_alerts_count
);
} /* ----- end of function _AI_correlated_alerts_to_dot ----- */
} /* ----- end of function __AI_correlated_alerts_to_dot ----- */
/**
* \brief Recursively write the flow of correlated alerts to a .json file, ready for being rendered in the web interface
*/
PRIVATE void
_AI_correlated_alerts_to_json ()
__AI_correlated_alerts_to_json ()
{
unsigned int i = 0;
char json_file[1040] = { 0 };
AI_snort_alert *alert_iterator = NULL;
struct pkt_info *pkt_iterator = NULL;
FILE *fp;
AI_snort_alert *alert_iterator = NULL;
unsigned int i = 0,
pkt_len = 0;
char *strtime = NULL,
*encoded_pkt = NULL,
json_file[1040] = { 0 },
srcip[INET_ADDRSTRLEN] = { 0 },
dstip[INET_ADDRSTRLEN] = { 0 },
srcport[10] = { 0 },
dstport[10] = { 0 };
/* If there is no directory configured for the web interface, just exit */
if ( strlen ( config->webserv_dir ) == 0 )
@ -159,10 +169,136 @@ _AI_correlated_alerts_to_json ()
for ( alert_iterator = alerts; alert_iterator; alert_iterator = alert_iterator->next )
{
strtime = ctime ( &(alert_iterator->timestamp ));
strtime[ strlen(strtime) - 1 ] = 0;
inet_ntop ( AF_INET, &(alert_iterator->ip_src_addr), srcip, INET_ADDRSTRLEN );
inet_ntop ( AF_INET, &(alert_iterator->ip_dst_addr), dstip, INET_ADDRSTRLEN );
snprintf ( srcport, sizeof ( srcport ), "%d", htons ( alert_iterator->tcp_src_port ));
snprintf ( dstport, sizeof ( dstport ), "%d", htons ( alert_iterator->tcp_dst_port ));
fprintf ( fp, "{\n"
"\t\"id\": %lu,\n"
"\t\"label\": \"%s\"",
alert_iterator->alert_id, alert_iterator->desc );
"\t\"label\": \"%s\",\n"
"\t\"date\": \"%s\",\n"
"\t\"clusteredAlertsCount\": %u,\n"
"\t\"from\": \"%s:%s\",\n"
"\t\"to\": \"%s:%s\"",
alert_iterator->alert_id,
alert_iterator->desc,
strtime,
alert_iterator->grouped_alerts_count,
srcip, srcport, dstip, dstport
);
if ( alert_iterator->stream )
{
fprintf ( fp, ",\n"
"\t\"packets\": [\n" );
for ( pkt_iterator = alert_iterator->stream; pkt_iterator; pkt_iterator = pkt_iterator->next )
{
pkt_len = pkt_iterator->pkt->pcap_header->len + pkt_iterator->pkt->payload_size;
if ( !( encoded_pkt = (char*) malloc ( 4*pkt_len + 1 )))
{
AI_fatal_err ( "Fatal dynamic memory allocation", __FILE__, __LINE__ );
}
memset ( encoded_pkt, 0, 4*pkt_len + 1 );
base64_encode (
(const char*) pkt_iterator->pkt->pkt_data,
pkt_len,
&encoded_pkt
);
fprintf ( fp, "\t\t\"%s\"%s\n",
encoded_pkt, ((pkt_iterator->next) ? "," : ""));
free ( encoded_pkt );
encoded_pkt = NULL;
}
fprintf ( fp, "\t]" );
}
for ( i=1; i < alert_iterator->grouped_alerts_count; i++ )
{
if ( i == 1 )
{
fprintf ( fp, ",\n\t\"clusteredAlerts\": [\n" );
}
if ( alert_iterator->grouped_alerts )
{
if ( alert_iterator->grouped_alerts[i] )
{
strtime = ctime ( &(alert_iterator->grouped_alerts[i]->timestamp ));
strtime[ strlen ( strtime ) - 1 ] = 0;
inet_ntop ( AF_INET, &(alert_iterator->grouped_alerts[i]->ip_src_addr), srcip, INET_ADDRSTRLEN );
inet_ntop ( AF_INET, &(alert_iterator->grouped_alerts[i]->ip_dst_addr), dstip, INET_ADDRSTRLEN );
snprintf ( srcport, sizeof ( srcport ), "%d", htons ( alert_iterator->grouped_alerts[i]->tcp_src_port ));
snprintf ( dstport, sizeof ( dstport ), "%d", htons ( alert_iterator->grouped_alerts[i]->tcp_dst_port ));
fprintf ( fp, "\t\t{\n"
"\t\t\t\"id\": %lu,\n"
"\t\t\t\"label\": \"%s\",\n"
"\t\t\t\"date\": \"%s\",\n"
"\t\t\t\"from\": \"%s:%s\",\n"
"\t\t\t\"to\": \"%s:%s\"%s",
alert_iterator->grouped_alerts[i]->alert_id,
alert_iterator->grouped_alerts[i]->desc,
strtime,
srcip, srcport, dstip, dstport,
(( alert_iterator->grouped_alerts[i]->stream ) ? ",\n" : "\n" )
);
if ( alert_iterator->grouped_alerts[i]->stream )
{
fprintf ( fp, "\t\t\t\"packets\": [\n" );
for ( pkt_iterator = alert_iterator->grouped_alerts[i]->stream; pkt_iterator; pkt_iterator = pkt_iterator->next )
{
if ( !pkt_iterator->pkt->ip4_header )
{
pkt_len = pkt_iterator->pkt->pcap_header->len +
pkt_iterator->pkt->tcp_options_length +
pkt_iterator->pkt->payload_size;
} else {
pkt_len = pkt_iterator->pkt->ip4_header->data_length;
}
if ( !( encoded_pkt = (char*) malloc ( 4*pkt_len + 1 )))
{
AI_fatal_err ( "Fatal dynamic memory allocation", __FILE__, __LINE__ );
}
memset ( encoded_pkt, 0, 4*pkt_len + 1 );
base64_encode (
(const char*) pkt_iterator->pkt->pkt_data,
pkt_len,
&encoded_pkt
);
fprintf ( fp, "\t\t\t\t\"%s\"%s\n",
encoded_pkt, ((pkt_iterator->next) ? "," : ""));
}
fprintf ( fp, "\t\t\t]\n" );
}
fprintf ( fp,
"\t\t}%s\n",
(( i < alert_iterator->grouped_alerts_count - 1 ) ? "," : "" ));
}
}
if ( i == alert_iterator->grouped_alerts_count - 1 )
{
fprintf ( fp, "\t]" );
}
}
for ( i=0; i < alert_iterator->n_derived_alerts; i++ )
{
@ -188,7 +324,7 @@ _AI_correlated_alerts_to_json ()
fprintf ( fp, "]\n" );
fclose ( fp );
chmod ( json_file, 0644 );
} /* ----- end of function _AI_correlated_alerts_to_json ----- */
} /* ----- end of function __AI_correlated_alerts_to_json ----- */
/**
* \brief Get the name of the function called by a pre-condition or post-condition predicate
@ -197,7 +333,7 @@ _AI_correlated_alerts_to_json ()
*/
PRIVATE char*
_AI_get_function_name ( const char *orig_stmt )
__AI_get_function_name ( const char *orig_stmt )
{
int parenthesis_pos, function_name_len;
char function_name[4096];
@ -217,7 +353,7 @@ _AI_get_function_name ( const char *orig_stmt )
strncpy ( function_name, stmt, function_name_len );
return strdup(function_name);
} /* ----- end of function _AI_get_function_name ----- */
} /* ----- end of function __AI_get_function_name ----- */
/**
@ -228,7 +364,7 @@ _AI_get_function_name ( const char *orig_stmt )
*/
PRIVATE char**
_AI_get_function_arguments ( char *orig_stmt, int *n_args )
__AI_get_function_arguments ( char *orig_stmt, int *n_args )
{
char **args = NULL;
char *tok = NULL;
@ -263,7 +399,7 @@ _AI_get_function_arguments ( char *orig_stmt, int *n_args )
return NULL;
return args;
} /* ----- end of function _AI_get_function_arguments ----- */
} /* ----- end of function __AI_get_function_arguments ----- */
/**
@ -274,7 +410,7 @@ _AI_get_function_arguments ( char *orig_stmt, int *n_args )
*/
PRIVATE double
_AI_kb_correlation_coefficient ( AI_snort_alert *a, AI_snort_alert *b )
__AI_kb_correlation_coefficient ( AI_snort_alert *a, AI_snort_alert *b )
{
unsigned int i, j, k, l,
n_intersection = 0,
@ -314,13 +450,13 @@ _AI_kb_correlation_coefficient ( AI_snort_alert *a, AI_snort_alert *b )
} else {
/* Check if the predicates are the same, have the same number of arguments, and
* substitute possible occurrencies of +ANY_ADDR+ and +ANY_PORT+ or IP netmasks */
function_name1 = _AI_get_function_name ( a->hyperalert->postconds[i] );
function_name2 = _AI_get_function_name ( b->hyperalert->preconds[j] );
function_name1 = __AI_get_function_name ( a->hyperalert->postconds[i] );
function_name2 = __AI_get_function_name ( b->hyperalert->preconds[j] );
if ( !strcasecmp ( function_name1, function_name2 ))
{
args1 = _AI_get_function_arguments ( a->hyperalert->postconds[i], &n_args1 );
args2 = _AI_get_function_arguments ( b->hyperalert->preconds[j] , &n_args2 );
args1 = __AI_get_function_arguments ( a->hyperalert->postconds[i], &n_args1 );
args2 = __AI_get_function_arguments ( b->hyperalert->preconds[j] , &n_args2 );
if ( args1 && args2 )
{
@ -478,7 +614,7 @@ _AI_kb_correlation_coefficient ( AI_snort_alert *a, AI_snort_alert *b )
}
return (double) ((double) n_intersection / (double) n_union );
} /* ----- end of function _AI_kb_correlation_coefficient ----- */
} /* ----- end of function __AI_kb_correlation_coefficient ----- */
/**
@ -487,7 +623,7 @@ _AI_kb_correlation_coefficient ( AI_snort_alert *a, AI_snort_alert *b )
*/
PRIVATE void
_AI_macro_subst ( AI_snort_alert **alert )
__AI_macro_subst ( AI_snort_alert **alert )
{
/*
* Recognized macros:
@ -570,7 +706,7 @@ _AI_macro_subst ( AI_snort_alert **alert )
free ( tmp );
}
}
} /* ----- end of function _AI_macro_subst ----- */
} /* ----- end of function __AI_macro_subst ----- */
/**
* \brief Parse info about a hyperalert from a correlation XML file, if it exists
@ -579,7 +715,7 @@ _AI_macro_subst ( AI_snort_alert **alert )
*/
PRIVATE AI_hyperalert_info*
_AI_hyperalert_from_XML ( AI_hyperalert_key key )
__AI_hyperalert_from_XML ( AI_hyperalert_key key )
{
char hyperalert_file[1024] = {0};
char snort_id[1024] = {0};
@ -706,7 +842,7 @@ _AI_hyperalert_from_XML ( AI_hyperalert_key key )
xmlFreeTextReader ( xml );
xmlCleanupParser();
return hyp;
} /* ----- end of function _AI_hyperalert_from_XML ----- */
} /* ----- end of function __AI_hyperalert_from_XML ----- */
/**
* \brief Thread for correlating clustered alerts
@ -786,7 +922,7 @@ AI_alert_correlation_thread ( void *arg )
if ( !hyp )
{
/* If there is no hyperalert knowledge on XML for this alert, ignore it and get the next one */
if ( !( hyp = _AI_hyperalert_from_XML ( key )))
if ( !( hyp = __AI_hyperalert_from_XML ( key )))
continue;
/* If the XML file exists and it's valid, add the hypertalert to the hash table */
@ -813,10 +949,10 @@ AI_alert_correlation_thread ( void *arg )
for ( i=0; i < alert_iterator->hyperalert->n_postconds; i++ )
alert_iterator->hyperalert->postconds[i] = strdup ( hyp->postconds[i] );
_AI_macro_subst ( &alert_iterator );
__AI_macro_subst ( &alert_iterator );
}
_AI_correlation_table_cleanup();
__AI_correlation_table_cleanup();
correlation_table = NULL;
for ( alert_iterator = alerts; alert_iterator; alert_iterator = alert_iterator->next )
@ -835,7 +971,7 @@ AI_alert_correlation_thread ( void *arg )
corr_key.b = alert_iterator2;
corr->key = corr_key;
kb_correlation = _AI_kb_correlation_coefficient ( corr_key.a, corr_key.b );
kb_correlation = __AI_kb_correlation_coefficient ( corr_key.a, corr_key.b );
bayesian_correlation = AI_alert_bayesian_correlation ( corr_key.a, corr_key.b );
if ( bayesian_correlation == 0.0 || config->bayesianCorrelationInterval == 0 )
@ -905,7 +1041,7 @@ AI_alert_correlation_thread ( void *arg )
corr->key.a->derived_alerts[ corr->key.a->n_derived_alerts - 1 ] = corr->key.b;
corr->key.b->parent_alerts [ corr->key.b->n_parent_alerts - 1 ] = corr->key.a;
_AI_correlated_alerts_to_dot ( corr, fp );
__AI_correlated_alerts_to_dot ( corr, fp );
if ( config->outdbtype != outdb_none )
{
@ -953,7 +1089,7 @@ AI_alert_correlation_thread ( void *arg )
{
if ( strlen ( config->webserv_dir ) != 0 )
{
_AI_correlated_alerts_to_json ();
__AI_correlated_alerts_to_json ();
}
}
}

8
db.c
View File

@ -236,7 +236,7 @@ AI_db_alertparser_thread ( void *arg )
* \return A copy of the alert log linked list
*/
PRIVATE AI_snort_alert*
_AI_db_copy_alerts ( AI_snort_alert *node )
__AI_db_copy_alerts ( AI_snort_alert *node )
{
AI_snort_alert *current = NULL, *next = NULL;
@ -247,7 +247,7 @@ _AI_db_copy_alerts ( AI_snort_alert *node )
if ( node->next )
{
next = _AI_db_copy_alerts ( node->next );
next = __AI_db_copy_alerts ( node->next );
}
if ( !( current = ( AI_snort_alert* ) malloc ( sizeof ( AI_snort_alert )) ))
@ -258,7 +258,7 @@ _AI_db_copy_alerts ( AI_snort_alert *node )
memcpy ( current, node, sizeof ( AI_snort_alert ));
current->next = next;
return current;
} /* ----- end of function _AI_db_copy_alerts ----- */
} /* ----- end of function __AI_db_copy_alerts ----- */
/**
@ -271,7 +271,7 @@ AI_db_get_alerts ()
AI_snort_alert *alerts_copy;
pthread_mutex_lock ( &mutex );
alerts_copy = _AI_db_copy_alerts ( alerts );
alerts_copy = __AI_db_copy_alerts ( alerts );
pthread_mutex_unlock ( &mutex );
return alerts_copy;

View File

@ -1,32 +1,62 @@
<html>
<head>
<script type="text/javascript" src="js/raphael-min.js"></script>
<script type="text/javascript" src="js/dracula_graffle.js"></script>
<script type="text/javascript" src="js/dracula_graph.js"></script>
<script type="text/javascript">
<style rel="stylesheet" type="text/css">
#popupAlert {
z-index : 100;
display : none;
position : absolute;
border : 1px solid #000;
background-color : #89ffa7;
color : #000;
opacity : 0.6;
padding : 5px;
}
#alertInfo {
display : none;
border : 1px solid #888;
padding : 3px;
height : 150px;
}
#alertInfoTable {
font : Fixed;
font-size : 12px;
width : 100%;
}
a {
color : #22dd22;
}
</style>
<script type="text/javascript" src="js/raphael.js"></script>
<script type="text/javascript" src="js/dracula_graffle.js"></script>
<script type="text/javascript" src="js/dracula_graph.js"></script>
<script type="text/javascript">
<!--
var redraw;
var width;
var height;
var layouter = null;
var renderer = null;
var json = [];
redraw = null;
width = 0;
height = 0;
layouter = null;
renderer = null;
json = [];
window.onload = function() {
window.onload = function() {
var req = new XMLHttpRequest();
if ( navigator.appName.indexOf('Microsoft') != -1 )
{
width = (document.body.offsetWidth > 50) ?
document.body.offsetWidth - 50 : 50;
height = (document.body.offsetHeight > 50 ) ?
document.body.offsetHeight - 50 : 50;
width = (document.body.offsetWidth > 20) ?
document.body.offsetWidth - 20 : 20;
height = (document.body.offsetHeight > 200 ) ?
document.body.offsetHeight - 200 : 200;
} else {
width = (window.innerWidth > 50) ?
window.innerWidth - 50 : 50;
height = (window.innerHeight > 50) ?
window.innerHeight- 50 : 50;
width = (window.innerWidth > 20) ?
window.innerWidth - 20 : 20;
height = (window.innerHeight > 200) ?
window.innerHeight - 200 : 200;
}
req.open ( 'GET', 'http://' + window.location.host + '/correlation_graph.json', true );
@ -58,6 +88,10 @@ window.onload = function() {
g.addEdge ( connections[i].from, connections[i].to, { directed: true });
}
var canvas = document.getElementById ( 'canvas' );
canvas.style.width = width;
canvas.style.height = height;
var layouter = new Graph.Layout.Spring ( g );
layouter.layout();
@ -68,6 +102,154 @@ window.onload = function() {
layouter.layout();
renderer.draw();
};
for ( var i=0; i < json.length; i++ )
{
var node = document.getElementById ( 'alert' + json[i].id );
if ( node )
{
node.onclick = function() {
var div = document.getElementById ( 'alertInfo' );
if ( div )
{
var id = this.id.replace ( /^alert/, "" );
var json_element = null;
for ( var i=0; i < json.length; i++ )
{
if ( json[i].id == id )
{
json_element = json[i];
break;
}
}
div.style.display = 'block';
var content =
'<table id="alertInfoTable" cellspacing="5"><tr style="background-color:#99ff99">' +
'<td><b>Type</b></td><td><b>From</b></td>' +
'<td><b>To</b></td><td><b>Date</b></td></tr>' +
'<tr><td>' + json_element.label;
if ( json_element.packets )
{
content += ' (<a href="http://' + window.location.host + '/pcap.cgi?packets=' +
json_element.packets.length;
for ( var j=0; j < json_element.packets.length; j++ )
{
json_element.packets[j].match ( /^.*(=*)$/ );
var pad = RegExp.$1;
var len = parseInt ( json_element.packets[j].length * 3 / 4 ) - pad.length;
json_element.date.match ( /[a-zA-Z]+\s+([a-zA-Z]+)\s+([0-9]+)\s+([0-9]+):([0-9]+):([0-9]+)\s+([0-9]+)/ );
var month = RegExp.$1;
var day = RegExp.$2;
var hour = RegExp.$3;
var min = RegExp.$4;
var sec = RegExp.$5;
var year = RegExp.$6;
switch ( month )
{
case 'Jan': month = 1; break;
case 'Feb': month = 2; break;
case 'Mar': month = 3; break;
case 'Apr': month = 4; break;
case 'May': month = 5; break;
case 'Jun': month = 6; break;
case 'Jul': month = 7; break;
case 'Ago': month = 8; break;
case 'Sep': month = 9; break;
case 'Oct': month = 10; break;
case 'Nov': month = 11; break;
case 'Dec': month = 12; break;
default : month = 1; break;
}
var timestamp = new Date ( year, month, day, hour, min, sec).getTime().toString();
timestamp = timestamp.replace ( /0{3}$/, "" );
content += '&packet_len' + j + '=' + len +
'&time' + j + '=' + timestamp +
'&packet' + j + '=' + escape ( json_element.packets[j] );
}
content += '">save as pcap file</a>)';
}
content += '</td><td>' +
json_element.from + '</td><td>' + json_element.to + '</td>' +
'<td>' + json_element.date + '</td></tr>';
if ( json_element.clusteredAlerts )
{
for ( var j=0; j < json_element.clusteredAlerts.length; j++ )
{
content +=
'<tr><td>' + json_element.clusteredAlerts[j].label;
if ( json_element.clusteredAlerts[j].packets )
{
content += ' (<a href="http://' + window.location.host + '/pcap.cgi?packets=' +
json_element.clusteredAlerts[j].packets.length;
for ( var k=0; k < json_element.clusteredAlerts[j].packets.length; k++ )
{
var unescaped = unescape ( json_element.clusteredAlerts[j].packets[k] );
unescaped.match ( /(=+)/ );
var pad = RegExp.$1;
var len = parseInt ( json_element.clusteredAlerts[j].packets[k].length * 3 / 4 ) - pad.length;
json_element.clusteredAlerts[j].date.match ( /[a-zA-Z]+\s+([a-zA-Z]+)\s+([0-9]+)\s+([0-9]+):([0-9]+):([0-9]+)\s+([0-9]+)/ );
var month = RegExp.$1;
var day = RegExp.$2;
var hour = RegExp.$3;
var min = RegExp.$4;
var sec = RegExp.$5;
var year = RegExp.$6;
switch ( month )
{
case 'Jan': month = 1; break;
case 'Feb': month = 2; break;
case 'Mar': month = 3; break;
case 'Apr': month = 4; break;
case 'May': month = 5; break;
case 'Jun': month = 6; break;
case 'Jul': month = 7; break;
case 'Ago': month = 8; break;
case 'Sep': month = 9; break;
case 'Oct': month = 10; break;
case 'Nov': month = 11; break;
case 'Dec': month = 12; break;
default : month = 1; break;
}
var timestamp = new Date ( year, month, day, hour, min, sec).getTime().toString();
timestamp = timestamp.replace ( /0{3}$/, "" );
content += '&packet_len' + k + '=' + len +
'&time' + k + '=' + timestamp +
'&packet' + k + '=' + escape ( json_element.clusteredAlerts[j].packets[k] );
}
content += '">save as pcap file</a>)';
}
content += '</td>' +
'<td>' + json_element.clusteredAlerts[j].from + '</td>' +
'<td>' + json_element.clusteredAlerts[j].to + '</td>' +
'<td>' + json_element.clusteredAlerts[j].date + '</td></tr>';
}
}
content += '</table>';
div.innerHTML = content;
}
};
}
}
}
};
@ -78,8 +260,11 @@ window.onload = function() {
</script>
</head>
<body>
<div id="canvas" style="border: 1px"></div>
<button id="redraw" onclick="redraw();">redraw</button>
<div id="canvas" style="border: 1px solid #000"></div>
<button id="redraw" onclick="redraw();">Redraw</button>
<div id="popupAlert"></div>
<div id="alertInfo"></div>
</body>
</html>

143
htdocs/js/base64.js Normal file
View File

@ -0,0 +1,143 @@
/**
*
* Base64 encode / decode
* http://www.webtoolkit.info/
*
**/
 
var Base64 = {
 
// private property
_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
 
// public method for encoding
encode : function (input) {
var output = "";
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
var i = 0;
 
input = Base64._utf8_encode(input);
 
while (i < input.length) {
 
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
 
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
 
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
 
output = output +
this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
 
}
 
return output;
},
 
// public method for decoding
decode : function (input) {
var output = "";
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0;
 
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
 
while (i < input.length) {
 
enc1 = this._keyStr.indexOf(input.charAt(i++));
enc2 = this._keyStr.indexOf(input.charAt(i++));
enc3 = this._keyStr.indexOf(input.charAt(i++));
enc4 = this._keyStr.indexOf(input.charAt(i++));
 
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
 
output = output + String.fromCharCode(chr1);
 
if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}
 
}
 
output = Base64._utf8_decode(output);
 
return output;
 
},
 
// private method for UTF-8 encoding
_utf8_encode : function (string) {
string = string.replace(/\r\n/g,"\n");
var utftext = "";
 
for (var n = 0; n < string.length; n++) {
 
var c = string.charCodeAt(n);
 
if (c < 128) {
utftext += String.fromCharCode(c);
}
else if((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
}
else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
 
}
 
return utftext;
},
 
// private method for UTF-8 decoding
_utf8_decode : function (utftext) {
var string = "";
var i = 0;
var c = c1 = c2 = 0;
 
while ( i < utftext.length ) {
 
c = utftext.charCodeAt(i);
 
if (c < 128) {
string += String.fromCharCode(c);
i++;
}
else if((c > 191) && (c < 224)) {
c2 = utftext.charCodeAt(i+1);
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
i += 2;
}
else {
c2 = utftext.charCodeAt(i+1);
c3 = utftext.charCodeAt(i+2);
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
i += 3;
}
 
}
 
return string;
}
 
}

View File

@ -208,7 +208,9 @@ Graph.Renderer.Raphael.prototype = {
} else {
var color = Raphael.getColor();
shape = this.r.set().
push(this.r.ellipse(point[0], point[1], 30, 20).attr({fill: color, stroke: color, "stroke-width": 2})).
push(this.r.ellipse(point[0], point[1], 30, 20).attr({fill: color, stroke: color, "stroke-width": 2,
/* Added by BlackLight */
"id": "alert" + node.id})).
push(this.r.text(point[0], point[1] + 30, node.label || node.id));
}
shape.attr({"fill-opacity": .6});

129
htdocs/js/popup.js Normal file
View File

@ -0,0 +1,129 @@
var dom = (document.getElementById) ? true : false;
var ns5 = ((navigator.userAgent.indexOf("Gecko")>-1) && dom) ? true: false;
var ie5 = ((navigator.userAgent.indexOf("MSIE")>-1) && dom) ? true : false;
var ns4 = (document.layers && !dom) ? true : false;
var ie4 = (document.all && !dom) ? true : false;
var nodyn = (!ns5 && !ns4 && !ie4 && !ie5) ? true : false;
var origWidth, origHeight;
if (ns4) {
origWidth = window.innerWidth; origHeight = window.innerHeight;
window.onresize = function() { if (window.innerWidth != origWidth || window.innerHeight != origHeight) history.go(0); }
}
if (nodyn) { event = "nope" }
var tipFollowMouse = true;
var tipWidth = 160;
var offX = 12; // how far from mouse to show tip
var offY = 12;
var tipFontFamily = "Verdana, arial, helvetica, sans-serif";
var tipFontSize = "8pt";
var tipFontColor = "#000000";
var tipBgColor = "#DDECFF";
var origBgColor = tipBgColor; // in case no bgColor set in array
var tipBorderColor = "#000080";
var tipBorderWidth = 2;
var tipBorderStyle = "ridge";
var tipPadding = 4;
var messages = new Array();
messages[0] = new Array('http://planmagic.com/images/plmbiz.jpg','Professional business planning software.',"#FFFFFF");
messages[1] = new Array('http://planmagic.com/images/plmmar.jpg','Professional marketing planning software.',"#DDECFF");
messages[2] = new Array('http://planmagic.com/images/plmfinance.jpg','Financial calculations and projections made easy.',"#E9E9E9");
if (document.images) {
var theImgs = new Array();
for (var i=0; i<messages.length; i++) {
theImgs[i] = new Image();
theImgs[i].src = messages[i][0];
}
}
var startStr = '<table width="' + tipWidth + '"><tr><td align="center" width="100%"><img src="';
var midStr = '" border="0"></td></tr><tr><td valign="top">';
var endStr = '</td></tr></table>';
var tooltip, tipcss;
function initTip() {
if (nodyn) return;
tooltip = (ns4)? document.tipDiv.document: (ie4)? document.all['tipDiv']: (ie5||ns5)? document.getElementById('tipDiv'): null;
tipcss = (ns4)? document.tipDiv: tooltip.style;
if (ie4||ie5||ns5) { // ns4 would lose all this on rewrites
tipcss.width = tipWidth+"px";
tipcss.fontFamily = tipFontFamily;
tipcss.fontSize = tipFontSize;
tipcss.color = tipFontColor;
tipcss.backgroundColor = tipBgColor;
tipcss.borderColor = tipBorderColor;
tipcss.borderWidth = tipBorderWidth+"px";
tipcss.padding = tipPadding+"px";
tipcss.borderStyle = tipBorderStyle;
}
if (tooltip&&tipFollowMouse) {
if (ns4) document.captureEvents(Event.MOUSEMOVE);
document.onmousemove = trackMouse;
}
}
window.onload = initTip;
var t1,t2; // for setTimeouts
var tipOn = false; // check if over tooltip link
function doTooltip(evt,num) {
if (!tooltip) return;
if (t1) clearTimeout(t1); if (t2) clearTimeout(t2);
tipOn = true;
// set colors if included in messages array
if (messages[num][2]) var curBgColor = messages[num][2];
else curBgColor = tipBgColor;
if (messages[num][3]) var curFontColor = messages[num][3];
else curFontColor = tipFontColor;
if (ns4) {
var tip = '<table bgcolor="' + tipBorderColor + '" width="' + tipWidth + '" cellspacing="0" cellpadding="' + tipBorderWidth + '" border="0"><tr><td><table bgcolor="' + curBgColor + '" width="100%" cellspacing="0" cellpadding="' + tipPadding + '" border="0"><tr><td>'+ startStr + messages[num][0] + midStr + '<span style="font-family:' + tipFontFamily + '; font-size:' + tipFontSize + '; color:' + curFontColor + ';">' + messages[num][1] + '</span>' + endStr + '</td></tr></table></td></tr></table>';
tooltip.write(tip);
tooltip.close();
} else if (ie4||ie5||ns5) {
var tip = startStr + messages[num][0] + midStr + '<span style="font-family:' + tipFontFamily + '; font-size:' + tipFontSize + '; color:' + curFontColor + ';">' + messages[num][1] + '</span>' + endStr;
tipcss.backgroundColor = curBgColor;
tooltip.innerHTML = tip;
}
if (!tipFollowMouse) positionTip(evt);
else t1=setTimeout("tipcss.visibility='visible'",100);
}
var mouseX, mouseY;
function trackMouse(evt) {
mouseX = (ns4||ns5)? evt.pageX: window.event.clientX + document.body.scrollLeft;
mouseY = (ns4||ns5)? evt.pageY: window.event.clientY + document.body.scrollTop;
if (tipOn) positionTip(evt);
}
function positionTip(evt) {
if (!tipFollowMouse) {
mouseX = (ns4||ns5)? evt.pageX: window.event.clientX + document.body.scrollLeft;
mouseY = (ns4||ns5)? evt.pageY: window.event.clientY + document.body.scrollTop;
}
// tooltip width and height
var tpWd = (ns4)? tooltip.width: (ie4||ie5)? tooltip.clientWidth: tooltip.offsetWidth;
var tpHt = (ns4)? tooltip.height: (ie4||ie5)? tooltip.clientHeight: tooltip.offsetHeight;
// document area in view (subtract scrollbar width for ns)
var winWd = (ns4||ns5)? window.innerWidth-20+window.pageXOffset: document.body.clientWidth+document.body.scrollLeft;
var winHt = (ns4||ns5)? window.innerHeight-20+window.pageYOffset: document.body.clientHeight+document.body.scrollTop;
// check mouse position against tip and window dimensions
// and position the tooltip
if ((mouseX+offX+tpWd)>winWd)
tipcss.left = (ns4)? mouseX-(tpWd+offX): mouseX-(tpWd+offX)+"px";
else tipcss.left = (ns4)? mouseX+offX: mouseX+offX+"px";
if ((mouseY+offY+tpHt)>winHt)
tipcss.top = (ns4)? winHt-(tpHt+offY): winHt-(tpHt+offY)+"px";
else tipcss.top = (ns4)? mouseY+offY: mouseY+offY+"px";
if (!tipFollowMouse) t1=setTimeout("tipcss.visibility='visible'",100);
}
function hideTip() {
if (!tooltip) return;
t2=setTimeout("tipcss.visibility='hidden'",100);
tipOn = false;
}

File diff suppressed because one or more lines are too long

3737
htdocs/js/raphael.js Normal file

File diff suppressed because it is too large Load Diff

132
htdocs/pcap.cgi Executable file
View File

@ -0,0 +1,132 @@
#!/usr/bin/perl
use strict;
use warnings;
use MIME::Base64;
use Env qw(QUERY_STRING DOCUMENT_ROOT);
sub url_decode {
my $str = shift;
$str =~ s/%([A-Fa-f0-9]{2})/pack('C', hex($1))/seg;;
return $str;
}
sub print_pcap_header {
my $out = shift;
# pcap magic_number
print $out pack ( 'L', 0xa1b2c3d4 );
# pcap version_major
print $out pack ( 'S', 0x2 );
# pcap version_minor
print $out pack ( 'S', 0x4 );
# pcap thiszone
print $out pack ( 'l', 0x0 );
# pcap sigfigs
print $out pack ( 'L', 0x0 );
# pcap snaplen
print $out pack ( 'L', 0xffff );
# pcap network
print $out pack ( 'L', 0x1 );
}
sub print_packet {
my ( $out, $packet ) = @_;
# ts_sec
print $out pack ( 'L', $packet->{'time'} );
# ts_usec
print $out pack ( 'L', 0x0 );
my $pkt_data = decode_base64 ( url_decode ( $packet->{'content'} ));
my $hex = unpack ( 'H*', $pkt_data );
my @pairs = $hex =~ /([a-fA-F0-9]{2})/g;
# If this is not an IP packet, trust what the client has told you as packet length
if (( $pairs[0] ne '45' && $pairs[1] ne '00' ) || ( @pairs < 5 ))
{
# incl_len
print $out pack ( 'L', $packet->{'length'} + 12 );
# orig_len
print $out pack ( 'L', $packet->{'length'} + 12 );
} else {
# Otherwise, the length of the packet is the one specified in the IP header
my $length = hex ( $pairs[2].$pairs[3] );
# If the lengths differ (IP length and actual length of the stream received), pad
# the end of the packet with some 0's so that its length matches the one
# specified in the IP header
if ( $length > ( length ( $hex ) / 2 ))
{
my $pad_size = $length - ( length ( $hex ) / 2 );
$hex .= '00' for ( 0..$pad_size-1 );
$pkt_data = pack ( 'H*', $hex );
}
# Add the length of a pseudo-ethernet header
$length += 14;
# incl_len
print $out pack ( 'L', $length );
# orig_len
print $out pack ( 'L', $length );
}
# pseudo ethernet header
print $out pack ( 'H*', 0 x24 );
# ethernet type (IP)
print $out pack ( 'S', 0x8 );
# packet content
print $out $pkt_data;
}
$QUERY_STRING =~ /packets=([0-9]+)/;
my $packets_num = $1;
my %packets = ();
for ( my $i=0; $i < $packets_num; $i++ )
{
$QUERY_STRING =~ /packet_len$i=([0-9]+)/;
my $length = $1;
$QUERY_STRING =~ /time$i=([0-9]+)/;
my $time = $1;
$QUERY_STRING =~ /packet$i=(.+?)(&|$)/;
my $content = $1;
$packets{$i} = {
'length' => $length,
'time' => $time,
'content' => $content
};
}
print "Content-Type: application/pcap\n\n";
# open my $out, "> $DOCUMENT_ROOT/out.pcap";
open my $out, ">&STDOUT";
binmode $out;
print_pcap_header $out;
for ( my $i=0; $i < $packets_num; $i++ )
{
print_packet $out, $packets{$i};
}
close $out;
# print "Content-Type: text/html\\n\\n";
# print "<meta http-equiv=\\"refresh\\" content=\\"0;url=/out.pcap\\">\\n";

View File

@ -1,10 +0,0 @@
#!/bin/sh
echo "Content-Type: text/html"
echo
echo "<h1>LOL</h1>"
echo "Query string: <b>$QUERY_STRING</b><br>"
echo "Accept: <b>$HTTP_ACCEPT</b><br>"
echo "User-Agent: <b>$HTTP_USER_AGENT</b><br>"
echo "Client addr : <b>$REMOTE_ADDR</b><br>"

15
outdb.c
View File

@ -239,16 +239,25 @@ AI_store_alert_to_db_thread ( void *arg )
for ( pkt = alert->stream; pkt; pkt = pkt->next )
{
pkt_data = NULL;
pkt_size = pkt->pkt->pcap_cap_len;
if ( !pkt->pkt->ip4_header )
{
pkt_size = pkt->pkt->pcap_header->len +
pkt->pkt->tcp_options_length +
pkt->pkt->payload_size;
} else {
pkt_size = pkt->pkt->ip4_header->data_length;
}
pkt_size_offset = 0;
if ( !( pkt_data = (unsigned char*) alloca ( 2 * (pkt->pkt->pcap_header->len + pkt->pkt->payload_size) + 1 )))
if ( !( pkt_data = (unsigned char*) alloca ( 2 * ( pkt_size ) + 1 )))
AI_fatal_err ( "Fatal dynamic memory allocation error", __FILE__, __LINE__ );
DB_out_escape_string (
(char**) &pkt_data,
(const char*) pkt->pkt->pkt_data,
pkt->pkt->pcap_header->len + pkt->pkt->payload_size );
pkt_size );
memset ( query, 0, sizeof ( query ));

View File

@ -408,6 +408,8 @@ typedef struct {
int preg_match ( const char*, char*, char***, int* );
char* str_replace ( char*, char*, char *);
char* str_replace_all ( char*, char*, char* );
void base64_encode ( const char*, size_t, char** );
void base64_decode ( const char*, char** );
void AI_fatal_err ( const char *msg, const char *file, const int line );
void* AI_hashcleanup_thread ( void* );

View File

@ -40,7 +40,7 @@ PRIVATE pthread_mutex_t hash_mutex = PTHREAD_MUTEX_INITIALIZER;
*/
PRIVATE void
_AI_stream_free ( struct pkt_info* stream )
__AI_stream_free ( struct pkt_info* stream )
{
struct pkt_info *tmp = NULL;
char ip [ INET_ADDRSTRLEN ];
@ -85,7 +85,7 @@ _AI_stream_free ( struct pkt_info* stream )
}
stream = NULL;
} /* ----- end of function _AI_stream_free ----- */
} /* ----- end of function __AI_stream_free ----- */
/**
@ -131,7 +131,7 @@ AI_hashcleanup_thread ( void* arg )
* I won't find an answer to these enigmatic questions, I will leave
* this code commented, so if a certain stream goes timeout it won't
* be removed. I'm sorry but it's not my fault. Ask the karma about this */
/* _AI_stream_free ( stream ); */
/* __AI_stream_free ( stream ); */
}
}
}
@ -199,7 +199,7 @@ AI_pkt_enqueue ( SFSnortPacket* pkt )
if ( found ) {
if ( !found->observed ) {
_AI_stream_free ( found );
__AI_stream_free ( found );
}
}
} else {
@ -233,7 +233,7 @@ AI_pkt_enqueue ( SFSnortPacket* pkt )
if ( found ) {
if ( !found->observed ) {
_AI_stream_free ( found );
__AI_stream_free ( found );
}
}
}

View File

@ -196,6 +196,7 @@ __AI_webservlet_thread ( void *arg )
nmatches = 0,
max_content_length = 0,
max_headers_length = 0,
read_bytes = 0,
req_file_absolute_path_size = 0;
char ch,
@ -419,9 +420,14 @@ __AI_webservlet_thread ( void *arg )
}
http_response [ http_response_len - 2 ] = ch;
read_bytes++;
}
if ( http_response )
{
http_response [ http_response_len - 1 ] = 0;
}
http_response [ http_response_len - 1 ] = 0;
pclose ( pipe );
if ( !http_response )
@ -440,8 +446,10 @@ __AI_webservlet_thread ( void *arg )
!strcasecmp ( extension, "ppm" )) {
snprintf ( content_type, sizeof ( content_type ),
"image/%s", extension );
} else {
} else if ( strlen ( extension ) == 0 || !strcasecmp ( extension, "txt" )) {
strncpy ( content_type, "text/plain", sizeof ( content_type ));
} else {
snprintf ( content_type, sizeof ( content_type ), "application/%s", extension );
}
if ( !is_cgi )
@ -464,11 +472,17 @@ __AI_webservlet_thread ( void *arg )
if ( is_cgi )
{
snprintf ( http_headers, max_headers_length, HTTP_CGI_RESPONSE_HEADERS_FORMAT,
http_ver, 200, "Found", strtime, config->webserv_banner, strlen ( http_response ));
http_ver, 200, "Found", strtime, config->webserv_banner,
/* strlen ( http_response )); */
read_bytes );
} else {
read_bytes = (unsigned int) st.st_size;
snprintf ( http_headers, max_headers_length, HTTP_RESPONSE_HEADERS_FORMAT,
http_ver, 200, "Found", strtime, config->webserv_banner,
content_type, strlen ( http_response ));
content_type,
/* strlen ( http_response )); */
read_bytes );
}
free ( strtime );
@ -588,7 +602,9 @@ __AI_webservlet_thread ( void *arg )
line = NULL;
}
fprintf ( sock, "%s%s", http_headers, http_response );
/* fprintf ( sock, "%s%s", http_headers, http_response ); */
fprintf ( sock, "%s", http_headers );
fwrite ( http_response, read_bytes, 1, sock );
fclose ( sock );
close ( sd );
free ( arg );