Python module rewritten in pure Python

This commit is contained in:
BlackLight 2011-02-04 00:43:59 +01:00
parent 95db8a6486
commit e406b637f0
12 changed files with 190 additions and 164 deletions

27
README
View file

@ -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. database, the current correlations, and so on.
It is also possible to write your own modules in Python language. See the file 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 'example_module.py' in corr_modules/ for a quick overview. All you need to
declare in your module the functions AI_corr_index (taking two arguments, two do is to declare in your module the functions AI_corr_index (taking two
alert descriptions) and AI_corr_index_weight (taking no argument), arguments, two alert descriptions) and AI_corr_index_weight
both returning a real value descibing, respectively, the correlation (taking no argument), both returning a real value descibing,
value between the two alerts and the weight of that index, both between respectively, the correlation value between the two alerts and the
0 and 1. You can also access the alert information and all the alerts weight of that index, both between 0 and 1. You can also access the
acquired so far by the module by importing in your Python code the alert information and all the alerts acquired so far by the module
'snortai' module. You can compile it and install it by moving to by importing in your Python code the 'snortai' module. You can
'pymodule/' directory and running compile it and install it by moving to 'pymodule/'
directory and running
$ python setup.py build $ python setup.py build
$ [sudo] python setup.py install $ [sudo] python setup.py install
@ -604,10 +605,10 @@ alerts = snortai.alerts()
for alert in alerts: for alert in alerts:
# Access the alerts information # Access the alerts information
The fields in the alert class can be viewed in pymodule/module.py and The fields in the alert class can be viewed in
corr_modules/example.py examples. Take these files as guides for interfacing pymodule/test.py and corr_modules/example_module.py examples. Take these
your Python scripts with SnortAI module or writing new correlation modules in files as guides for interfacing your Python scripts with SnortAI module
Python. or writing new correlation modules in Python.
=========================== ===========================

View file

@ -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

View 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

View file

@ -385,7 +385,7 @@ AI_alert_correlation_thread ( void *arg )
double (**corr_weights)() = NULL; double (**corr_weights)() = NULL;
#ifdef HAVE_LIBPYTHON2_6 #ifdef HAVE_LIBPYTHON2_6
PyAlert *pyA = NULL, PyObject *pyA = NULL,
*pyB = NULL; *pyB = NULL;
PyObject *pArgs = 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; pyA = NULL; pyB = NULL;
} }
} }

View file

@ -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 * \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 * \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 ) 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 }, char src_addr[INET_ADDRSTRLEN] = { 0 },
dst_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 ); if ( !( pObj = PyObject_GetAttrString ( pMod, "alert" )))
inet_ntop ( AF_INET, &(alert->ip_dst_addr), dst_addr, INET_ADDRSTRLEN ); {
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; Py_DECREF ( pMod );
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;
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; return pyalert;
} /* ----- end of function AI_alert_to_pyalert ----- */ } /* ----- end of function AI_alert_to_pyalert ----- */
#endif #endif

View file

@ -12,9 +12,10 @@ alerts = snortai.alerts()
for alert in alerts: for alert in alerts:
# Access the information # Access the information
print alert.gid, alert.sid, alert.rev
The alert class has the following members: The alert class has the following members:
# id, gid, sid, rev, description, priority, classification, timestamp # 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

View file

@ -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

View file

@ -1,20 +1,6 @@
#!/usr/bin/python #!/usr/bin/env python
from distutils.core import setup, Extension 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 ( setup (
name = 'snortai', name = 'snortai',
@ -22,13 +8,6 @@ setup (
description = 'Python interface to SnortAI module', description = 'Python interface to SnortAI module',
author = 'Fabio "BlackLight" Manganiello', author = 'Fabio "BlackLight" Manganiello',
author_email = 'blacklight@autistici.org', author_email = 'blacklight@autistici.org',
ext_modules = [ packages = ['snortai']
Extension (
'snortai',
sources = ['snortai_module.c'],
include_dirs = ['..', '../include', '../uthash', xml_include],
libraries = [xml_libs]
)
]
) )

View 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

View file

@ -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 #ifndef HAVE_LIBPYTHON2_6
#define HAVE_LIBPYTHON2_6 1 #define HAVE_LIBPYTHON2_6 1
#endif #endif

8
pymodule/test.py Normal file
View file

@ -0,0 +1,8 @@
#!/usr/bin/python
import snortai
alerts = snortai.alerts()
for alert in alerts:
print alert.gid, alert.sid, alert.rev

View file

@ -31,6 +31,25 @@
#include <netinet/in.h> #include <netinet/in.h>
#include <pthread.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 #define PRIVATE static
/** Default interval in seconds for the thread cleaning up TCP streams */ /** Default interval in seconds for the thread cleaning up TCP streams */
@ -543,61 +562,6 @@ typedef struct {
UT_hash_handle hh; UT_hash_handle hh;
} AI_alert_type_pair; } 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 */ /** 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 }; 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_functions ( size_t* );
PyObject** AI_get_py_weights ( 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 #endif