mirror of
https://github.com/BlackLight/Snort_AIPreproc.git
synced 2024-11-23 20:25:12 +01:00
Python module rewritten in pure Python
This commit is contained in:
parent
95db8a6486
commit
e406b637f0
12 changed files with 190 additions and 164 deletions
27
README
27
README
|
@ -582,15 +582,16 @@ libsf_ai_preproc.la if you want to use some of the functions from the module,
|
|||
database, the current correlations, and so on.
|
||||
|
||||
It is also possible to write your own modules in Python language. See the file
|
||||
'example.py' in corr_modules/ for a quick overview. All you need to do is to
|
||||
declare in your module the functions AI_corr_index (taking two arguments, two
|
||||
alert descriptions) and AI_corr_index_weight (taking no argument),
|
||||
both returning a real value descibing, respectively, the correlation
|
||||
value between the two alerts and the weight of that index, both between
|
||||
0 and 1. You can also access the alert information and all the alerts
|
||||
acquired so far by the module by importing in your Python code the
|
||||
'snortai' module. You can compile it and install it by moving to
|
||||
'pymodule/' directory and running
|
||||
'example_module.py' in corr_modules/ for a quick overview. All you need to
|
||||
do is to declare in your module the functions AI_corr_index (taking two
|
||||
arguments, two alert descriptions) and AI_corr_index_weight
|
||||
(taking no argument), both returning a real value descibing,
|
||||
respectively, the correlation value between the two alerts and the
|
||||
weight of that index, both between 0 and 1. You can also access the
|
||||
alert information and all the alerts acquired so far by the module
|
||||
by importing in your Python code the 'snortai' module. You can
|
||||
compile it and install it by moving to 'pymodule/'
|
||||
directory and running
|
||||
|
||||
$ python setup.py build
|
||||
$ [sudo] python setup.py install
|
||||
|
@ -604,10 +605,10 @@ alerts = snortai.alerts()
|
|||
for alert in alerts:
|
||||
# Access the alerts information
|
||||
|
||||
The fields in the alert class can be viewed in pymodule/module.py and
|
||||
corr_modules/example.py examples. Take these files as guides for interfacing
|
||||
your Python scripts with SnortAI module or writing new correlation modules in
|
||||
Python.
|
||||
The fields in the alert class can be viewed in
|
||||
pymodule/test.py and corr_modules/example_module.py examples. Take these
|
||||
files as guides for interfacing your Python scripts with SnortAI module
|
||||
or writing new correlation modules in Python.
|
||||
|
||||
|
||||
===========================
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
# Example correlation index in Python
|
||||
|
||||
# XXX You may have an 'undefined reference to PyNone_Struct
|
||||
# after running Snort with your module, you're facing an
|
||||
# annoying bug due to the dynamically linked Python library.
|
||||
# I'm sorry, but I'm still looking for a solution for this,
|
||||
# and anyway it only happens when you import the module
|
||||
# 'snortai'
|
||||
|
||||
# import snortai
|
||||
|
||||
# Function that takes two alerts as arguments (arguments of
|
||||
# alert object:
|
||||
# id, gid, sid, rev, description, priority, classification,
|
||||
# timestamp, from, to, from_port, to_port, latitude,
|
||||
# longitude, alerts_count) and returns a correlation index
|
||||
# between 0 and 1 expressing how correlated these two alerts are
|
||||
|
||||
def AI_corr_index ( alert1, alert2 ):
|
||||
return 0.0
|
||||
|
||||
# Return the weight of this index, between 0 and 1
|
||||
|
||||
def AI_corr_index_weight():
|
||||
return 0.0
|
||||
|
34
corr_modules/example_module.py
Normal file
34
corr_modules/example_module.py
Normal file
|
@ -0,0 +1,34 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
# Example correlation index in Python
|
||||
# It simply does nothing (both the correlation index
|
||||
# and the correlation weight are zero), use it as
|
||||
# track for writing your own correlation modules
|
||||
|
||||
# Go to pymodule and run
|
||||
# $ python setup.py build
|
||||
# $ [sudo] python setup.py install
|
||||
# in order to build and install the snortai Python module
|
||||
import snortai
|
||||
|
||||
# Function that takes two alerts as arguments (arguments of
|
||||
# alert object:
|
||||
# id, gid, sid, rev, description, priority, classification,
|
||||
# timestamp, src_addr, dst_addr, src_port, dst_port, latitude,
|
||||
# longitude) and returns a correlation index between 0 and 1
|
||||
# expressing how correlated these two alerts are
|
||||
|
||||
def AI_corr_index ( alert1, alert2 ):
|
||||
# alerts = snortai.alerts()
|
||||
# for alert in alerts:
|
||||
# do_something
|
||||
#
|
||||
# print alert1.gid, alert1.sid, alert1.rev
|
||||
# print alert2.gid, alert2.sid, alert2.rev
|
||||
return 0.0
|
||||
|
||||
# Return the weight of this index, between 0 and 1
|
||||
|
||||
def AI_corr_index_weight():
|
||||
return 0.0
|
||||
|
|
@ -385,7 +385,7 @@ AI_alert_correlation_thread ( void *arg )
|
|||
double (**corr_weights)() = NULL;
|
||||
|
||||
#ifdef HAVE_LIBPYTHON2_6
|
||||
PyAlert *pyA = NULL,
|
||||
PyObject *pyA = NULL,
|
||||
*pyB = NULL;
|
||||
|
||||
PyObject *pArgs = NULL,
|
||||
|
@ -556,7 +556,8 @@ AI_alert_correlation_thread ( void *arg )
|
|||
}
|
||||
}
|
||||
|
||||
free ( pyA ); free ( pyB );
|
||||
Py_DECREF ( pyA ); Py_DECREF ( pyB );
|
||||
/* free ( pyA ); free ( pyB ); */
|
||||
pyA = NULL; pyB = NULL;
|
||||
}
|
||||
}
|
||||
|
|
62
modules.c
62
modules.c
|
@ -99,37 +99,61 @@ AI_get_py_weights ( size_t *n_functions )
|
|||
/**
|
||||
* \brief Convert an AI_snort_alert object to a PyAlert object that can be managed by a Python module
|
||||
* \param alert AI_snort_alert object to be converted
|
||||
* \return A PyAlert object wrapping the original AI_snort_alert object
|
||||
* \return A PyObject object wrapping the original AI_snort_alert object
|
||||
*/
|
||||
|
||||
PyAlert*
|
||||
PyObject*
|
||||
AI_alert_to_pyalert ( AI_snort_alert *alert )
|
||||
{
|
||||
PyAlert *pyalert = NULL;
|
||||
PyObject *pyalert = NULL;
|
||||
|
||||
PyObject *pMod = NULL,
|
||||
*pObj = NULL,
|
||||
*pArgs = NULL;
|
||||
|
||||
char src_addr[INET_ADDRSTRLEN] = { 0 },
|
||||
dst_addr[INET_ADDRSTRLEN] = { 0 };
|
||||
|
||||
if ( !( pyalert = (PyAlert*) malloc ( sizeof ( PyAlert ))))
|
||||
if ( !( pMod = PyImport_ImportModule ( "snortai" )))
|
||||
{
|
||||
AI_fatal_err ( "Fatal dynamic memory allocation error", __FILE__, __LINE__ );
|
||||
PyErr_Print();
|
||||
AI_fatal_err ( "Could not load Python module 'snortai'", __FILE__, __LINE__ );
|
||||
}
|
||||
|
||||
inet_ntop ( AF_INET, &(alert->ip_src_addr), src_addr, INET_ADDRSTRLEN );
|
||||
inet_ntop ( AF_INET, &(alert->ip_dst_addr), dst_addr, INET_ADDRSTRLEN );
|
||||
if ( !( pObj = PyObject_GetAttrString ( pMod, "alert" )))
|
||||
{
|
||||
PyErr_Print();
|
||||
AI_fatal_err ( "'alert' object not found in the Python module 'snortai'", __FILE__, __LINE__ );
|
||||
}
|
||||
|
||||
pyalert->classification = alert->classification ? PyString_FromString ( alert->classification ) : Py_None;
|
||||
pyalert->clusteredAlertsCount = alert->grouped_alerts_count;
|
||||
pyalert->desc = alert->desc ? PyString_FromString ( alert->desc ) : Py_None;
|
||||
pyalert->gid = alert->gid;
|
||||
pyalert->ip_src_addr = ( strlen ( src_addr ) > 0 ) ? PyString_FromString ( src_addr ) : Py_None;
|
||||
pyalert->ip_dst_addr = ( strlen ( dst_addr ) > 0 ) ? PyString_FromString ( dst_addr ) : Py_None;
|
||||
pyalert->priority = alert->priority;
|
||||
pyalert->rev = alert->rev;
|
||||
pyalert->sid = alert->sid;
|
||||
pyalert->tcp_src_port = ntohs ( alert->tcp_src_port );
|
||||
pyalert->tcp_dst_port = ntohs ( alert->tcp_dst_port );
|
||||
pyalert->timestamp = alert->timestamp;
|
||||
Py_DECREF ( pMod );
|
||||
|
||||
if ( !( pArgs = Py_BuildValue ( "(OOOOOOOOOOOOO)",
|
||||
Py_None,
|
||||
PyLong_FromUnsignedLong ( alert->gid ),
|
||||
PyLong_FromUnsignedLong ( alert->sid ),
|
||||
PyLong_FromUnsignedLong ( alert->rev ),
|
||||
PyLong_FromUnsignedLong ((long int) alert->priority ),
|
||||
alert->classification ? PyString_FromString ( alert->classification ) : Py_None,
|
||||
alert->desc ? PyString_FromString ( alert->desc ) : Py_None,
|
||||
PyString_FromString ( src_addr ),
|
||||
PyString_FromString ( dst_addr ),
|
||||
PyLong_FromLong ((long int) ntohs ( alert->tcp_src_port )),
|
||||
PyLong_FromLong ((long int) ntohs ( alert->tcp_dst_port )),
|
||||
Py_None,
|
||||
Py_None )))
|
||||
{
|
||||
PyErr_Print();
|
||||
AI_fatal_err ( "Could not initialize the argument list for calling the Python 'alert' constructor", __FILE__, __LINE__ );
|
||||
}
|
||||
|
||||
if ( !( pyalert = PyObject_CallObject ( pObj, pArgs )))
|
||||
{
|
||||
PyErr_Print();
|
||||
AI_fatal_err ( "Could not call the constructor over the Python object 'alert'", __FILE__, __LINE__ );
|
||||
}
|
||||
|
||||
Py_DECREF ( pArgs ); Py_DECREF ( pObj );
|
||||
return pyalert;
|
||||
} /* ----- end of function AI_alert_to_pyalert ----- */
|
||||
#endif
|
||||
|
|
|
@ -12,9 +12,10 @@ alerts = snortai.alerts()
|
|||
|
||||
for alert in alerts:
|
||||
# Access the information
|
||||
print alert.gid, alert.sid, alert.rev
|
||||
|
||||
The alert class has the following members:
|
||||
|
||||
# id, gid, sid, rev, description, priority, classification, timestamp
|
||||
# from, to, from_port, to_port, latitude, longitude, alerts_count
|
||||
# src_addr, dst_addr, src_port, dst_port, latitude, longitude
|
||||
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
# Compile snortai module by typing, in pymodule directory:
|
||||
# $ python setup.py build
|
||||
# $ [sudo] python setup.py install
|
||||
import snortai
|
||||
|
||||
# Get the alerts from Snort module as tuple
|
||||
# (IMPORTANT: Snort and SnortAI module, as well as
|
||||
# the web server running on top of the module, must
|
||||
# be running in order to have this call successful)
|
||||
alerts = snortai.alerts()
|
||||
|
||||
# Navigate the tuple of alerts
|
||||
# Fields:
|
||||
# id, gid, sid, rev, description, priority, classification,
|
||||
# timestamp, from, to, from_port, to_port, latitude,
|
||||
# longitude, alerts_count
|
||||
for alert in alerts:
|
||||
print alert.gid, alert.sid, alert.rev, alert.description
|
||||
|
|
@ -1,20 +1,6 @@
|
|||
#!/usr/bin/python
|
||||
#!/usr/bin/env python
|
||||
|
||||
from distutils.core import setup, Extension
|
||||
import commands
|
||||
import re
|
||||
|
||||
xml_include = commands.getoutput ( 'pkg-config --cflags libxml-2.0' )
|
||||
m = re.match ( '^-I\s*(.+?)\s*$', xml_include )
|
||||
|
||||
if m:
|
||||
xml_include = m.group ( 1 )
|
||||
|
||||
xml_libs = commands.getoutput ( 'pkg-config --libs libxml-2.0' )
|
||||
m = re.match ( '^-l\s*(.+?)\s*$', xml_libs )
|
||||
|
||||
if m:
|
||||
xml_libs = m.group ( 1 )
|
||||
|
||||
setup (
|
||||
name = 'snortai',
|
||||
|
@ -22,13 +8,6 @@ setup (
|
|||
description = 'Python interface to SnortAI module',
|
||||
author = 'Fabio "BlackLight" Manganiello',
|
||||
author_email = 'blacklight@autistici.org',
|
||||
ext_modules = [
|
||||
Extension (
|
||||
'snortai',
|
||||
sources = ['snortai_module.c'],
|
||||
include_dirs = ['..', '../include', '../uthash', xml_include],
|
||||
libraries = [xml_libs]
|
||||
)
|
||||
]
|
||||
packages = ['snortai']
|
||||
)
|
||||
|
||||
|
|
57
pymodule/snortai/__init__.py
Normal file
57
pymodule/snortai/__init__.py
Normal file
|
@ -0,0 +1,57 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
import urllib
|
||||
import xml.dom.minidom as xml
|
||||
|
||||
class alert:
|
||||
"""Class that models a Snort alert type"""
|
||||
def __init__ ( self, id = None, gid = None, sid = None, rev = None,
|
||||
priority = None, classification = None, description = None,
|
||||
src_addr = None, dst_addr = None, src_port = None, dst_port = None,
|
||||
latitude = None, longitude = None, ):
|
||||
self.id = id
|
||||
self.gid = gid
|
||||
self.sid = sid
|
||||
self.rev = rev
|
||||
self.priority = priority
|
||||
self.latitude = latitude
|
||||
self.longitude = longitude
|
||||
self.description = description
|
||||
self.classification = classification
|
||||
self.src_addr = src_addr
|
||||
self.dst_addr = dst_addr
|
||||
self.src_port = src_port
|
||||
self.dst_port = dst_port
|
||||
|
||||
resource_url = 'http://localhost:7654/alerts.cgi'
|
||||
response_text = None;
|
||||
|
||||
def alerts():
|
||||
url = urllib.urlopen ( resource_url )
|
||||
response_text = url.read()
|
||||
document = xml.parseString ( response_text )
|
||||
alerts = []
|
||||
|
||||
for element in document.getElementsByTagName ( 'alert' ):
|
||||
a = alert()
|
||||
|
||||
for attr in element.attributes.keys():
|
||||
if attr in ['id', 'gid', 'sid', 'rev', 'priority', 'latitude', 'longitude', 'classification']:
|
||||
setattr ( a, attr, element.attributes[attr].value )
|
||||
elif attr == 'date':
|
||||
setattr ( a, 'timestamp', element.attributes[attr].value )
|
||||
elif attr == 'label':
|
||||
setattr ( a, 'description', element.attributes[attr].value )
|
||||
elif attr == 'from':
|
||||
setattr ( a, 'src_addr', element.attributes[attr].value )
|
||||
elif attr == 'to':
|
||||
setattr ( a, 'dst_addr', element.attributes[attr].value )
|
||||
elif attr == 'from_port':
|
||||
setattr ( a, 'src_port', element.attributes[attr].value )
|
||||
elif attr == 'to_port':
|
||||
setattr ( a, 'dst_port', element.attributes[attr].value )
|
||||
|
||||
alerts.append ( a )
|
||||
|
||||
return alerts
|
||||
|
|
@ -17,6 +17,12 @@
|
|||
* =====================================================================================
|
||||
*/
|
||||
|
||||
/* This is the old C-based module for Python interface to SnortAI
|
||||
* and it is now completely *DEPRECATED* and kept only for
|
||||
* back-compatibility purposes. Use the pure Python interface
|
||||
* instead, running python setup.py build && sudo python setup.py install
|
||||
* will build and install the new Python module */
|
||||
|
||||
#ifndef HAVE_LIBPYTHON2_6
|
||||
#define HAVE_LIBPYTHON2_6 1
|
||||
#endif
|
||||
|
|
8
pymodule/test.py
Normal file
8
pymodule/test.py
Normal file
|
@ -0,0 +1,8 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
import snortai
|
||||
|
||||
alerts = snortai.alerts()
|
||||
|
||||
for alert in alerts:
|
||||
print alert.gid, alert.sid, alert.rev
|
76
spp_ai.h
76
spp_ai.h
|
@ -31,6 +31,25 @@
|
|||
#include <netinet/in.h>
|
||||
#include <pthread.h>
|
||||
|
||||
/*******************************************/
|
||||
#ifdef HAVE_LIBPYTHON2_6
|
||||
/* Avoid conflicts with Snort header files */
|
||||
#ifdef _POSIX_C_SOURCE
|
||||
#undef _POSIX_C_SOURCE
|
||||
#endif
|
||||
|
||||
#ifdef _XOPEN_C_SOURCE
|
||||
#undef _XOPEN_C_SOURCE
|
||||
#endif
|
||||
|
||||
#ifdef _XOPEN_SOURCE
|
||||
#undef _XOPEN_SOURCE
|
||||
#endif
|
||||
|
||||
#include <Python.h>
|
||||
#endif
|
||||
/*******************************************/
|
||||
|
||||
#define PRIVATE static
|
||||
|
||||
/** Default interval in seconds for the thread cleaning up TCP streams */
|
||||
|
@ -543,61 +562,6 @@ typedef struct {
|
|||
UT_hash_handle hh;
|
||||
} AI_alert_type_pair;
|
||||
/*****************************************************************/
|
||||
#ifdef HAVE_LIBPYTHON2_6
|
||||
|
||||
/*******************************************/
|
||||
/* Avoid conflicts with Snort header files */
|
||||
#ifdef _POSIX_C_SOURCE
|
||||
#undef _POSIX_C_SOURCE
|
||||
#endif
|
||||
|
||||
#ifdef _XOPEN_C_SOURCE
|
||||
#undef _XOPEN_C_SOURCE
|
||||
#endif
|
||||
|
||||
#ifdef _XOPEN_SOURCE
|
||||
#undef _XOPEN_SOURCE
|
||||
#endif
|
||||
/*******************************************/
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
/** Definition of the alert type for Python binding */
|
||||
typedef struct _PyAlert
|
||||
{
|
||||
PyObject_HEAD
|
||||
|
||||
unsigned int id;
|
||||
|
||||
/* Identifiers of the alert */
|
||||
unsigned int gid;
|
||||
unsigned int sid;
|
||||
unsigned int rev;
|
||||
|
||||
/* Snort priority, description,
|
||||
* classification and timestamp
|
||||
* of the alert */
|
||||
unsigned short priority;
|
||||
PyObject* desc;
|
||||
PyObject* classification;
|
||||
time_t timestamp;
|
||||
|
||||
PyObject* ip_src_addr;
|
||||
PyObject* ip_dst_addr;
|
||||
unsigned short tcp_src_port;
|
||||
unsigned short tcp_dst_port;
|
||||
|
||||
double latitude;
|
||||
double longitude;
|
||||
|
||||
unsigned int clusteredAlertsCount;
|
||||
|
||||
struct _PyAlert *next;
|
||||
} PyAlert;
|
||||
|
||||
#endif
|
||||
/*****************************************************************/
|
||||
|
||||
|
||||
/** Enumeration for describing the table in the output database */
|
||||
enum { ALERTS_TABLE, IPV4_HEADERS_TABLE, TCP_HEADERS_TABLE, PACKET_STREAMS_TABLE, CLUSTERED_ALERTS_TABLE, CORRELATED_ALERTS_TABLE, N_TABLES };
|
||||
|
@ -678,7 +642,7 @@ double(**AI_get_corr_weights ( size_t* ))( void );
|
|||
|
||||
PyObject** AI_get_py_functions ( size_t* );
|
||||
PyObject** AI_get_py_weights ( size_t* );
|
||||
PyAlert* AI_alert_to_pyalert ( AI_snort_alert* );
|
||||
PyObject* AI_alert_to_pyalert ( AI_snort_alert* );
|
||||
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in a new issue