mirror of
https://github.com/aljazceru/cowrie.git
synced 2025-12-18 06:24:20 +01:00
* 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:
33
doc/sql/mysql.sql
Normal file
33
doc/sql/mysql.sql
Normal 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`)
|
||||
) ;
|
||||
@@ -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
|
||||
|
||||
@@ -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
100
kippo/core/dblog.py
Normal 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:
|
||||
@@ -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
0
kippo/dblog/__init__.py
Normal file
74
kippo/dblog/mysql.py
Normal file
74
kippo/dblog/mysql.py
Normal 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:
|
||||
Reference in New Issue
Block a user