Logging improvements:

* redo the logger in a way that allows the host ip from the connection to be
   saved to the db
 * ignore mysql errors (such as connectivity problems)


git-svn-id: https://kippo.googlecode.com/svn/trunk@123 951d7100-d841-11de-b865-b3884708a8e2
This commit is contained in:
desaster 2010-06-16 14:51:26 +00:00
parent 7ca121347a
commit f1381d2e96
3 changed files with 59 additions and 41 deletions

View File

@ -5,9 +5,13 @@ import re, time, datetime, socket
class DBLogger(object):
def __init__(self, cfg):
self.cfg = cfg
self.sessions = {}
self.ttylogs = {}
self.re_unique = re.compile('.*(SSHServerTransport,[0-9]+,[0-9.]+)$')
self.re_connected = re.compile(
'^New connection: ([0-9.]+):([0-9]+) \(([0-9.]+):([0-9]+)\) ' + \
'\[session: ([0-9]+)\]$')
self.re_sessionlog = re.compile('.*HoneyPotTransport,([0-9]+),[0-9.]+$')
self.re_map = [(re.compile(x[0]), x[1]) for x in (
('^connection lost$',
self._connectionLost),
@ -24,45 +28,42 @@ class DBLogger(object):
('^INPUT \((?P<realm>[a-zA-Z0-9]+)\): (?P<input>.*)$',
self.handleInput),
)]
if cfg.has_option('honeypot', 'sensor_name'):
self.sensor = cfg.get('honeypot', 'sensor_name')
else:
self.sensor = socket.gethostbyaddr(socket.gethostname())[2][0]
self.start(cfg)
def start():
pass
def getSensor(self):
if self.cfg.has_option('honeypot', 'sensor_name'):
return self.cfg.get('honeypot', 'sensor_name')
return None
def nowUnix(self):
"""return the current UTC time as an UNIX timestamp"""
return int(time.mktime(datetime.datetime.utcnow().utctimetuple()))
def uniqstr(self, system):
matches = self.re_unique.match(system)
return matches.groups()[0]
def emit(self, ev):
if ev['system'] == '-' or not len(ev['message']):
if not len(ev['message']):
return
match = self.re_unique.match(ev['system'])
match = self.re_connected.match(ev['message'][0])
if match:
sessionid = int(match.groups()[4])
self.sessions[sessionid] = \
self.createSession(
match.groups()[0], int(match.groups()[1]),
match.groups()[2], int(match.groups()[3]))
return
match = self.re_sessionlog.match(ev['system'])
if not match:
return
uniqstr = match.groups()[0]
if uniqstr not in self.sessions.keys():
ip = uniqstr.split(',')[2]
session = self.createSession(ip)
self.sessions[uniqstr] = session
else:
session = self.sessions[uniqstr]
if session is None:
sessionid = int(match.groups()[0])
if sessionid not in self.sessions.keys():
return
message = ev['message'][0]
for regex, func in self.re_map:
match = regex.match(message)
if match:
func(session, match.groupdict())
func(self.sessions[sessionid], match.groupdict())
break
def _connectionLost(self, session, args):
@ -81,7 +82,7 @@ class DBLogger(object):
return ttylog
# We have to return an unique ID
def createSession(self, ip):
def createSession(self, peerIP, peerPort, hostIP, hostPort):
return 0
# args has: logfile

View File

@ -332,6 +332,15 @@ class HoneyPotRealm:
else:
raise Exception, "No supported interfaces found."
class HoneyPotTransport(transport.SSHServerTransport):
def connectionMade(self):
print 'New connection: %s:%s (%s:%s) [session: %d]' % \
(self.transport.getPeer().host, self.transport.getPeer().port,
self.transport.getHost().host, self.transport.getHost().port,
self.transport.sessionno)
transport.SSHServerTransport.connectionMade(self)
# As implemented by Kojoney
class HoneyPotSSHFactory(factory.SSHFactory):
#publicKeys = {'ssh-rsa': keys.getPublicKeyString(data=publicKey)}
@ -352,7 +361,8 @@ class HoneyPotSSHFactory(factory.SSHFactory):
def buildProtocol(self, addr):
# FIXME: try to mimic something real 100%
t = transport.SSHServerTransport()
t = HoneyPotTransport()
t.ourVersionString = 'SSH-2.0-OpenSSH_5.1p1 Debian-5'
t.supportedPublicKeys = self.privateKeys.keys()
if not self.primes:

View File

@ -10,20 +10,32 @@ class DBLogger(dblog.DBLogger):
passwd = cfg.get('database', 'password'),
reconnect = True)
def createSession(self, ip):
def query(self, sql, params = None):
cursor = self.db.cursor()
try:
if params is None:
cursor.execute(sql)
else:
cursor.execute(sql, params)
return cursor
except MySQLdb.MySQLError:
return None
def createSession(self, peerIP, peerPort, hostIP, hostPort):
sql = 'INSERT INTO `session` (`starttime`, `sensor`, `ip`)' + \
' VALUES (FROM_UNIXTIME(%s), %s, %s)'
params = (self.nowUnix(), self.sensor, ip)
cursor = self.db.cursor()
cursor.execute(sql, params)
return int(cursor.lastrowid)
params = (self.nowUnix(), self.getSensor() or hostIP, peerIP)
cursor = self.query(sql, params)
if cursor is not None:
return int(cursor.lastrowid)
else:
return None
def handleConnectionLost(self, session, args):
sql = 'UPDATE `session` SET `endtime` = FROM_UNIXTIME(%s)' + \
', `ttylog` = %s WHERE `id` = %s'
params = (self.nowUnix(), self.ttylog(session), session)
cursor = self.db.cursor()
cursor.execute(sql, params)
self.query(sql, params)
def handleLoginFailed(self, session, args):
sql = 'INSERT INTO `auth` (`session`, `success`' + \
@ -31,8 +43,7 @@ class DBLogger(dblog.DBLogger):
' VALUES (%s, %s, %s, %s, FROM_UNIXTIME(%s))'
params = (session, 0, args['username'], args['password'],
self.nowUnix())
cursor = self.db.cursor()
cursor.execute(sql, params)
self.query(sql, params)
def handleLoginSucceeded(self, session, args):
sql = 'INSERT INTO `auth` (`session`, `success`' + \
@ -40,31 +51,27 @@ class DBLogger(dblog.DBLogger):
' VALUES (%s, %s, %s, %s, FROM_UNIXTIME(%s))'
params = (session, 1, args['username'], args['password'],
self.nowUnix())
cursor = self.db.cursor()
cursor.execute(sql, params)
self.query(sql, params)
def handleCommand(self, session, args):
sql = 'INSERT INTO `input`' + \
' (`session`, `timestamp`, `success`, `input`)' + \
' VALUES (%s, FROM_UNIXTIME(%s), %s, %s)'
params = (session, self.nowUnix(), 1, args['input'])
cursor = self.db.cursor()
cursor.execute(sql, params)
self.query(sql, params)
def handleUnknownCommand(self, session, args):
sql = 'INSERT INTO `input`' + \
' (`session`, `timestamp`, `success`, `input`)' + \
' VALUES (%s, FROM_UNIXTIME(%s), %s, %s)'
params = (session, self.nowUnix(), 0, args['input'])
cursor = self.db.cursor()
cursor.execute(sql, params)
self.query(sql, params)
def handleInput(self, session, args):
sql = 'INSERT INTO `input`' + \
' (`session`, `timestamp`, `realm`, `input`)' + \
' VALUES (%s, FROM_UNIXTIME(%s), %s, %s)'
params = (session, self.nowUnix(), args['realm'], args['input'])
cursor = self.db.cursor()
cursor.execute(sql, params)
self.query(sql, params)
# vim: set sw=4 et: