mirror of
https://github.com/aljazceru/cowrie.git
synced 2026-02-23 15:24:30 +01:00
dblog : work in progress : formatted log messages
This commit is contained in:
@@ -3,55 +3,57 @@
|
||||
|
||||
import re
|
||||
import time
|
||||
import abc
|
||||
|
||||
# KIPP0001 : create session
|
||||
# KIPP0002 : succesful login
|
||||
# KIPP0003 : failed login
|
||||
# KIPP0004 : TTY log opened
|
||||
# KIPP0005 : handle command
|
||||
# KIPP0006 : handle unknown command
|
||||
# KIPP0007 : file download
|
||||
# KIPP0008 : INPUT
|
||||
# KIPP0009 : SSH Version
|
||||
# KIPP0010 : Terminal Size
|
||||
# KIPP0011 : Connection Lost
|
||||
|
||||
class DBLogger(object):
|
||||
|
||||
def __init__(self, cfg):
|
||||
self.cfg = cfg
|
||||
self.sessions = {}
|
||||
self.ttylogs = {}
|
||||
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.]+$')
|
||||
|
||||
# :dispatch: means the message has been delivered directly via
|
||||
# logDispatch, instead of relying on the twisted logging, which breaks
|
||||
# on scope changes.
|
||||
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),
|
||||
('^:dispatch: Command found: (?P<input>.*)$',
|
||||
self.handleCommand),
|
||||
('^:dispatch: Command not found: (?P<input>.*)$',
|
||||
self.handleUnknownCommand),
|
||||
('^:dispatch: Saving URL \((?P<url>.*)\) to (?P<outfile>.*)$',
|
||||
self.handleFileDownload),
|
||||
('^INPUT \((?P<realm>[a-zA-Z0-9]+)\): (?P<input>.*)$',
|
||||
self.handleInput),
|
||||
('^Terminal size: (?P<height>[0-9]+) (?P<width>[0-9]+)$',
|
||||
self.handleTerminalSize),
|
||||
('^Remote SSH version: (?P<version>.*)$',
|
||||
self.handleClientVersion),
|
||||
)]
|
||||
# KIPP0001 is special since it kicks off new logging event,
|
||||
# and is not handled here
|
||||
self.events = {
|
||||
'KIPP0002': self.handleLoginSucceeded,
|
||||
'KIPP0003': self.handleLoginFailed,
|
||||
'KIPP0004': self.handleTTYLogOpened,
|
||||
'KIPP0005': self.handleCommand,
|
||||
'KIPP0006': self.handleUnknownCommand,
|
||||
'KIPP0007': self.handleFileDownload,
|
||||
'KIPP0008': self.handleInput,
|
||||
'KIPP0009': self.handleClientVersion,
|
||||
'KIPP0010': self.handleTerminalSize,
|
||||
'KIPP0011': self._connectionLost,
|
||||
}
|
||||
|
||||
self.start(cfg)
|
||||
|
||||
# use logDispatch when the HoneypotTransport prefix is not available.
|
||||
# here you can explicitly set the sessionIds to tie the sessions together
|
||||
def logDispatch(self, sessionid, msg):
|
||||
if sessionid not in self.sessions.keys():
|
||||
return
|
||||
for regex, func in self.re_map:
|
||||
match = regex.match(msg)
|
||||
if match:
|
||||
func(self.sessions[sessionid], match.groupdict())
|
||||
break
|
||||
if isinstance( msg, dict ):
|
||||
msg['sessionid'] = sessionid
|
||||
return self.emit( msg )
|
||||
elif isinstance( msg, str ):
|
||||
return self.emit( { 'message':msg, 'sessionid':sessionid } )
|
||||
|
||||
def start():
|
||||
"""Hook that can be used to set up connections in dbloggers"""
|
||||
pass
|
||||
|
||||
def getSensor(self):
|
||||
@@ -64,28 +66,43 @@ class DBLogger(object):
|
||||
return int(time.mktime(time.gmtime()[:-1] + (-1,)))
|
||||
|
||||
def emit(self, ev):
|
||||
if not len(ev['message']):
|
||||
# ignore stdout and stderr
|
||||
if 'printed' in ev:
|
||||
return
|
||||
match = self.re_connected.match(ev['message'][0])
|
||||
if match:
|
||||
sessionid = int(match.groups()[4])
|
||||
|
||||
# ignore anything without eventid
|
||||
if not 'eventid' in ev:
|
||||
return
|
||||
|
||||
# DEBUG: REMOVE ME
|
||||
# print "emitting: %s" % repr( ev )
|
||||
|
||||
# connection event is special. adds to list
|
||||
if ev['eventid'] == 'KIPP0001':
|
||||
sessionid = ev['sessionno']
|
||||
self.sessions[sessionid] = \
|
||||
self.createSession(
|
||||
match.groups()[0], int(match.groups()[1]),
|
||||
match.groups()[2], int(match.groups()[3]))
|
||||
ev['src_ip'], ev['src_port'], ev['dst_ip'], ev['dst_port'] )
|
||||
return
|
||||
match = self.re_sessionlog.match(ev['system'])
|
||||
if not match:
|
||||
return
|
||||
sessionid = int(match.groups()[0])
|
||||
|
||||
# extract session id from the twisted log prefix
|
||||
if 'system' in ev:
|
||||
match = self.re_sessionlog.match(ev['system'])
|
||||
if not match:
|
||||
return
|
||||
sessionid = int(match.groups()[0])
|
||||
elif 'sessionid' in ev:
|
||||
sessionid = ev['sessionid']
|
||||
|
||||
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(self.sessions[sessionid], match.groupdict())
|
||||
break
|
||||
|
||||
if 'eventid' in ev:
|
||||
if ev['eventid'] in self.events:
|
||||
self.events[ev['eventid']]( self.sessions[sessionid], ev )
|
||||
return
|
||||
|
||||
print "error, can't dblog %s" % repr(ev)
|
||||
|
||||
def _connectionLost(self, session, args):
|
||||
self.handleConnectionLost(session, args)
|
||||
@@ -102,7 +119,8 @@ class DBLogger(object):
|
||||
f.close()
|
||||
return ttylog
|
||||
|
||||
# We have to return an unique ID
|
||||
# We have to return a unique ID
|
||||
@abc.abstractmethod
|
||||
def createSession(self, peerIP, peerPort, hostIP, hostPort):
|
||||
return 0
|
||||
|
||||
|
||||
@@ -177,6 +177,12 @@ class HoneyPotTransport(kippo.core.sshserver.KippoSSHServerTransport):
|
||||
self.transport.getHost().host, self.transport.getHost().port,
|
||||
self.transport.sessionno) )
|
||||
|
||||
log.msg( eventid='KIPP0001',
|
||||
format='New connection: %(src_ip)s:%(src_port)s (%(dst_ip)s:%(dst_port)s) [session: %(sessionno)s]',
|
||||
src_ip=self.transport.getPeer().host, src_port=self.transport.getPeer().port,
|
||||
dst_ip=self.transport.getHost().host, dst_port=self.transport.getHost().port,
|
||||
sessionno=self.transport.sessionno )
|
||||
|
||||
kippo.core.sshserver.KippoSSHServerTransport.connectionMade(self)
|
||||
|
||||
def sendKexInit(self):
|
||||
@@ -204,6 +210,7 @@ class HoneyPotTransport(kippo.core.sshserver.KippoSSHServerTransport):
|
||||
log.msg('KEXINIT: client supported compression: %s' % compCS )
|
||||
log.msg('KEXINIT: client supported lang: %s' % langCS )
|
||||
log.msg( 'Remote SSH version: %s' % self.otherVersionString,)
|
||||
log.msg( eventid='KIPP0009', version=self.otherVersionString, format='Remote SSH version: %(version)s' )
|
||||
return kippo.core.sshserver.KippoSSHServerTransport.ssh_KEXINIT(self, packet)
|
||||
|
||||
def lastlogExit(self):
|
||||
@@ -287,6 +294,9 @@ class HoneyPotAvatar(avatar.ConchUser):
|
||||
|
||||
def getPty(self, terminal, windowSize, attrs):
|
||||
log.msg( 'Terminal size: %s %s' % windowSize[0:2] )
|
||||
log.msg( eventid='KIPP0010', width=windowSize[0], height=windowSize[1],
|
||||
format='Terminal Size: %(width)s %(height)s' )
|
||||
|
||||
self.windowSize = windowSize
|
||||
return None
|
||||
|
||||
|
||||
Reference in New Issue
Block a user