mirror of https://github.com/desaster/kippo.git
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:
parent
7ca121347a
commit
f1381d2e96
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue