* Experimental MySQL logging; see kippo.cfg.dist and doc/sql/mysql.sql

* Initial root password now set in kippo.cfg



git-svn-id: https://kippo.googlecode.com/svn/trunk@116 951d7100-d841-11de-b865-b3884708a8e2
This commit is contained in:
desaster
2010-06-08 17:37:16 +00:00
parent 8a34f34062
commit dc6432bcdd
7 changed files with 233 additions and 9 deletions

33
doc/sql/mysql.sql Normal file
View File

@@ -0,0 +1,33 @@
CREATE TABLE IF NOT EXISTS `auth` (
`id` int(11) NOT NULL auto_increment,
`session` int(11) NOT NULL,
`success` tinyint(1) NOT NULL,
`username` varchar(100) NOT NULL,
`password` varchar(100) NOT NULL,
`timestamp` datetime NOT NULL,
PRIMARY KEY (`id`)
) ;
CREATE TABLE IF NOT EXISTS `input` (
`id` int(11) NOT NULL auto_increment,
`session` int(11) NOT NULL,
`timestamp` datetime NOT NULL,
`realm` varchar(50) default NULL,
`success` tinyint(1) default NULL,
`input` text NOT NULL,
PRIMARY KEY (`id`),
KEY `session` (`session`,`timestamp`,`realm`)
) ;
CREATE TABLE IF NOT EXISTS `session` (
`id` int(11) NOT NULL auto_increment,
`starttime` datetime NOT NULL,
`endtime` datetime default NULL,
`sensor` varchar(50) NOT NULL,
`ip` varchar(15) NOT NULL default '',
`ttylog` blob,
PRIMARY KEY (`id`),
KEY `starttime` (`starttime`,`sensor`)
) ;

View File

@@ -9,3 +9,11 @@ txtcmds_path = txtcmds
filesystem_file = fs.pickle
public_key = public.key
private_key = private.key
password = 123456
;[database]
;engine = mysql
;host = localhost
;database = kippo
;username = kippo
;password = secret

View File

@@ -29,11 +29,7 @@ factory = honeypot.HoneyPotSSHFactory()
factory.portal = portal.Portal(honeypot.HoneyPotRealm())
pubKeyString, privKeyString = honeypot.getRSAKeys()
# This is only the initial password, the rest will be in data/pass.db
users = (
('root', '123456'),
)
factory.portal.registerChecker(honeypot.HoneypotPasswordChecker(users))
factory.portal.registerChecker(honeypot.HoneypotPasswordChecker(factory))
factory.publicKeys = {'ssh-rsa': keys.Key.fromString(data=pubKeyString)}
factory.privateKeys = {'ssh-rsa': keys.Key.fromString(data=privKeyString)}

100
kippo/core/dblog.py Normal file
View File

@@ -0,0 +1,100 @@
# Copyright (c) 2009 Upi Tamminen <desaster@gmail.com>
# See the COPYRIGHT file for more information
import re, time, datetime, socket
class DBLogger(object):
def __init__(self, cfg):
self.sessions = {}
self.ttylogs = {}
self.re_unique = re.compile('.*(SSHServerTransport,[0-9]+,[0-9.]+)$')
self.re_map = [(re.compile(x[0]), x[1]) for x in (
('^connection lost$',
self._connectionLost),
('^login attempt \[(?P<username>.*)/(?P<password>.*)\] failed',
self.handleLoginFailed),
('^login attempt \[(?P<username>.*)/(?P<password>.*)\] succeeded',
self.handleLoginSucceeded),
('^Opening TTY log: (?P<logfile>.*)$',
self.handleTTYLogOpened),
('^Command found: (?P<input>.*)$',
self.handleCommand),
('^Command not found: (?P<input>.*)$',
self.handleUnknownCommand),
('^INPUT \((?P<realm>[a-zA-Z0-9]+)\): (?P<input>.*)$',
self.handleInput),
)]
self.start(cfg)
def start():
pass
def sensorName(self):
# TODO: configurable sensor name
return socket.gethostbyaddr(socket.gethostname())[2][0]
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'] == '-':
return
uniqstr = self.re_unique.match(ev['system']).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]
message = ev['message'][0]
for regex, func in self.re_map:
match = regex.match(message)
if match:
func(session, match.groupdict())
break
def _connectionLost(self, session, args):
self.handleConnectionLost(session, args)
if session in self.ttylogs:
del self.ttylogs[session]
for i in [x for x in self.sessions if self.sessions[x] == session]:
del self.sessions[i]
# We have to return an unique ID
def createSession(self, ip):
return 0
# args has: logfile
def handleTTYLogOpened(self, session, args):
self.ttylogs[session] = args['logfile']
# args is empty
def handleConnectionLost(self, session, args):
pass
# args has: username, password
def handleLoginFailed(self, session, args):
pass
# args has: username, password
def handleLoginSucceeded(self, session, args):
pass
# args has: input
def handleCommand(self, session, args):
pass
# args has: input
def handleUnknownCommand(self, session, args):
pass
# args has: realm, input
def handleInput(self, session, args):
pass
# vim: set sw=4 et:

View File

@@ -103,6 +103,7 @@ class HoneyPotShell(object):
rargs.append(arg)
cmdclass = self.honeypot.getCommand(cmd, envvars['PATH'].split(':'))
if cmdclass:
print 'Command found: %s' % (cmd,)
self.honeypot.call_command(cmdclass, *rargs)
else:
print 'Command not found: %s' % (cmd,)
@@ -149,6 +150,7 @@ class HoneyPotProtocol(recvline.HistoricRecvLine):
# You are in a maze of twisty little passages, all alike
p = self.terminal.transport.session.conn.transport.transport.getPeer()
self.clientIP = p.host
self.logintime = time.time()
@@ -339,6 +341,15 @@ class HoneyPotSSHFactory(factory.SSHFactory):
'ssh-connection': connection.SSHConnection,
}
def __init__(self):
cfg = config()
if cfg.has_option('database', 'engine'):
engine = cfg.get('database', 'engine')
self.dblogger = __import__(
'kippo.dblog.%s' % (engine,),
globals(), locals(), ['dblog']).DBLogger(cfg)
log.startLoggingWithObserver(self.dblogger.emit, setStdout=False)
def buildProtocol(self, addr):
# FIXME: try to mimic something real 100%
t = transport.SSHServerTransport()
@@ -356,14 +367,16 @@ class HoneypotPasswordChecker:
credentialInterfaces = (credentials.IUsernamePassword,)
def __init__(self, users):
self.users = users
def __init__(self, factory):
self.factory = factory
def requestAvatarId(self, credentials):
data_path = config().get('honeypot', 'data_path')
cfg = config()
data_path = cfg.get('honeypot', 'data_path')
passdb = anydbm.open('%s/pass.db' % (data_path,), 'c')
success = False
if (credentials.username, credentials.password) in self.users:
if credentials.username == 'root' and \
credentials.password == cfg.get('honeypot', 'password'):
success = True
elif credentials.username == 'root' and \
credentials.password in passdb:

0
kippo/dblog/__init__.py Normal file
View File

74
kippo/dblog/mysql.py Normal file
View File

@@ -0,0 +1,74 @@
from kippo.core import dblog
import MySQLdb
class DBLogger(dblog.DBLogger):
def start(self, cfg):
self.db = MySQLdb.connect(
host = cfg.get('database', 'host'),
db = cfg.get('database', 'database'),
user = cfg.get('database', 'username'),
passwd = cfg.get('database', 'password'))
def createSession(self, ip):
sql = 'INSERT INTO `session` (`starttime`, `sensor`, `ip`)' + \
' VALUES (FROM_UNIXTIME(%s), %s, %s)'
params = (self.nowUnix(), self.sensorName(), ip)
cursor = self.db.cursor()
cursor.execute(sql, params)
return int(cursor.lastrowid)
def handleConnectionLost(self, session, args):
ttylog = None
if session in self.ttylogs:
f = file(self.ttylogs[session])
ttylog = f.read()
f.close()
sql = 'UPDATE `session` SET `endtime` = FROM_UNIXTIME(%s)' + \
', `ttylog` = %s WHERE `id` = %s'
params = (self.nowUnix(), ttylog, session)
cursor = self.db.cursor()
cursor.execute(sql, params)
def handleLoginFailed(self, session, args):
sql = 'INSERT INTO `auth` (`session`, `success`' + \
', `username`, `password`, `timestamp`)' + \
' 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)
def handleLoginSucceeded(self, session, args):
sql = 'INSERT INTO `auth` (`session`, `success`' + \
', `username`, `password`, `timestamp`)' + \
' 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)
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)
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)
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)
# vim: set sw=4 et: