mirror of
https://github.com/cowrie/cowrie.git
synced 2025-07-01 18:07:27 -04:00
remove dblog (#960)
This commit is contained in:
@ -1,182 +0,0 @@
|
|||||||
# Copyright (c) 2009-2014 Upi Tamminen <desaster@gmail.com>
|
|
||||||
# See the COPYRIGHT file for more information
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division
|
|
||||||
|
|
||||||
import abc
|
|
||||||
import re
|
|
||||||
import time
|
|
||||||
|
|
||||||
from cowrie.core.config import CONFIG
|
|
||||||
|
|
||||||
|
|
||||||
# dblog now operates based on eventids, no longer on regex parsing of the entry.
|
|
||||||
# add an eventid using keyword args and it will be picked up by the dblogger
|
|
||||||
|
|
||||||
|
|
||||||
class DBLogger(object):
|
|
||||||
__metaclass__ = abc.ABCMeta
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.sessions = {}
|
|
||||||
self.ttylogs = {}
|
|
||||||
# FIXME figure out what needs to be done here regarding
|
|
||||||
self.re_sessionlog = re.compile(
|
|
||||||
r'.*HoneyPotSSHTransport,([0-9]+),[:a-f0-9.]+$')
|
|
||||||
|
|
||||||
# cowrie.session.connect is special since it kicks off new logging session,
|
|
||||||
# and is not handled here
|
|
||||||
self.events = {
|
|
||||||
'cowrie.login.success': self.handleLoginSucceeded,
|
|
||||||
'cowrie.login.failed': self.handleLoginFailed,
|
|
||||||
'cowrie.command.success': self.handleCommand,
|
|
||||||
'cowrie.command.failed': self.handleUnknownCommand,
|
|
||||||
'cowrie.session.file_download': self.handleFileDownload,
|
|
||||||
'cowrie.command.input': self.handleInput,
|
|
||||||
'cowrie.client.version': self.handleClientVersion,
|
|
||||||
'cowrie.client.size': self.handleTerminalSize,
|
|
||||||
'cowrie.session.closed': self._connectionLost,
|
|
||||||
'cowrie.log.closed': self.handleTTYLogClosed,
|
|
||||||
}
|
|
||||||
|
|
||||||
self.reported_ssh_port = None
|
|
||||||
if CONFIG.has_option('honeypot', 'reported_ssh_port'):
|
|
||||||
self.reported_ssh_port = CONFIG.getint('honeypot', 'reported_ssh_port')
|
|
||||||
|
|
||||||
self.report_public_ip = False
|
|
||||||
if CONFIG.has_option('honeypot', 'report_public_ip'):
|
|
||||||
if CONFIG.getboolean('honeypot', 'report_public_ip'):
|
|
||||||
self.report_public_ip = True
|
|
||||||
import urllib
|
|
||||||
self.public_ip = urllib.urlopen('http://myip.threatstream.com').readline()
|
|
||||||
|
|
||||||
self.start()
|
|
||||||
|
|
||||||
# used when the HoneypotTransport prefix is not available.
|
|
||||||
def logDispatch(self, *msg, **kw):
|
|
||||||
ev = kw
|
|
||||||
ev['message'] = msg
|
|
||||||
self.emit(ev)
|
|
||||||
|
|
||||||
def start(self):
|
|
||||||
"""
|
|
||||||
Hook that can be used to set up connections in dbloggers
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def getSensor(self):
|
|
||||||
if CONFIG.has_option('honeypot', 'sensor_name'):
|
|
||||||
return CONFIG.get('honeypot', 'sensor_name')
|
|
||||||
return None
|
|
||||||
|
|
||||||
def nowUnix(self):
|
|
||||||
"""
|
|
||||||
return the current UTC time as an UNIX timestamp
|
|
||||||
"""
|
|
||||||
return int(time.time())
|
|
||||||
|
|
||||||
def emit(self, ev):
|
|
||||||
# ignore stdout and stderr
|
|
||||||
if 'printed' in ev:
|
|
||||||
return
|
|
||||||
|
|
||||||
# ignore anything without eventid
|
|
||||||
if 'eventid' not in ev:
|
|
||||||
return
|
|
||||||
|
|
||||||
# connection event is special. adds to list
|
|
||||||
if ev['eventid'] == 'cowrie.session.connect':
|
|
||||||
sessionno = ev['sessionno']
|
|
||||||
peerIP, peerPort = ev['src_ip'], ev['src_port']
|
|
||||||
hostIP, hostPort = ev['dst_ip'], ev['dst_port']
|
|
||||||
|
|
||||||
if self.reported_ssh_port:
|
|
||||||
hostPort = self.reported_ssh_port
|
|
||||||
if self.report_public_ip:
|
|
||||||
hostIP = self.public_ip
|
|
||||||
|
|
||||||
self.sessions[sessionno] = \
|
|
||||||
self.createSession(
|
|
||||||
peerIP, peerPort, hostIP, hostPort)
|
|
||||||
return
|
|
||||||
|
|
||||||
# use explicit sessionno if coming from dispatch
|
|
||||||
if 'sessionno' in ev:
|
|
||||||
sessionno = ev['sessionno']
|
|
||||||
del ev['sessionno']
|
|
||||||
# else extract session id from the twisted log prefix
|
|
||||||
elif 'system' in ev:
|
|
||||||
match = self.re_sessionlog.match(ev['system'])
|
|
||||||
if not match:
|
|
||||||
return
|
|
||||||
sessionno = int(match.groups()[0])
|
|
||||||
|
|
||||||
if sessionno not in self.sessions.keys():
|
|
||||||
return
|
|
||||||
|
|
||||||
if 'eventid' in ev:
|
|
||||||
if ev['eventid'] in self.events:
|
|
||||||
self.events[ev['eventid']](self.sessions[sessionno], ev)
|
|
||||||
return
|
|
||||||
|
|
||||||
pass
|
|
||||||
|
|
||||||
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]
|
|
||||||
|
|
||||||
def ttylog(self, session):
|
|
||||||
ttylog = None
|
|
||||||
if session in self.ttylogs:
|
|
||||||
f = open(self.ttylogs[session])
|
|
||||||
ttylog = f.read(10485760)
|
|
||||||
f.close()
|
|
||||||
return ttylog
|
|
||||||
|
|
||||||
# We have to return a unique ID
|
|
||||||
@abc.abstractmethod
|
|
||||||
def createSession(self, peerIP, peerPort, hostIP, hostPort):
|
|
||||||
return 0
|
|
||||||
|
|
||||||
# args has: ttylog
|
|
||||||
def handleTTYLogClosed(self, session, args):
|
|
||||||
self.ttylogs[session] = args['ttylog']
|
|
||||||
|
|
||||||
# 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
|
|
||||||
|
|
||||||
# args has: width, height
|
|
||||||
def handleTerminalSize(self, session, args):
|
|
||||||
pass
|
|
||||||
|
|
||||||
# args has: version
|
|
||||||
def handleClientVersion(self, session, args):
|
|
||||||
pass
|
|
||||||
|
|
||||||
# args has: url, outfile
|
|
||||||
def handleFileDownload(self, session, args):
|
|
||||||
pass
|
|
||||||
@ -1,175 +0,0 @@
|
|||||||
from __future__ import absolute_import, division
|
|
||||||
|
|
||||||
import json
|
|
||||||
import uuid
|
|
||||||
|
|
||||||
from twisted.application import service
|
|
||||||
from twisted.python import log
|
|
||||||
from twisted.words.protocols.jabber import jid
|
|
||||||
from twisted.words.protocols.jabber.jid import JID
|
|
||||||
|
|
||||||
from wokkel import muc
|
|
||||||
from wokkel.client import XMPPClient
|
|
||||||
from wokkel.xmppim import AvailablePresence
|
|
||||||
|
|
||||||
from cowrie.core import dblog
|
|
||||||
from cowrie.core.config import CONFIG
|
|
||||||
|
|
||||||
|
|
||||||
class XMPPLoggerProtocol(muc.MUCClient):
|
|
||||||
|
|
||||||
def __init__(self, rooms, server, nick):
|
|
||||||
muc.MUCClient.__init__(self)
|
|
||||||
self.server = rooms.host
|
|
||||||
self.jrooms = rooms
|
|
||||||
self._roomOccupantMap = {}
|
|
||||||
log.msg(rooms.user)
|
|
||||||
log.msg(rooms.host)
|
|
||||||
self.nick = nick
|
|
||||||
self.last = {}
|
|
||||||
self.activity = None
|
|
||||||
|
|
||||||
def connectionInitialized(self):
|
|
||||||
"""
|
|
||||||
The bot has connected to the xmpp server, now try to join the room.
|
|
||||||
"""
|
|
||||||
self.join(self.jrooms, self.nick)
|
|
||||||
|
|
||||||
def joinedRoom(self, room):
|
|
||||||
log.msg('Joined room %s' % room.name)
|
|
||||||
|
|
||||||
def connectionMade(self):
|
|
||||||
log.msg('Connected!')
|
|
||||||
|
|
||||||
# send initial presence
|
|
||||||
self.send(AvailablePresence())
|
|
||||||
|
|
||||||
def connectionLost(self, reason):
|
|
||||||
log.msg('Disconnected!')
|
|
||||||
|
|
||||||
def onMessage(self, msg):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def receivedGroupChat(self, room, user, body):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def receivedHistory(self, room, user, body, dely, frm=None):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class DBLogger(dblog.DBLogger):
|
|
||||||
def start(self):
|
|
||||||
from random import choice
|
|
||||||
import string
|
|
||||||
|
|
||||||
server = CONFIG.get('database_xmpp', 'server')
|
|
||||||
user = CONFIG.get('database_xmpp', 'user')
|
|
||||||
password = CONFIG.get('database_xmpp', 'password')
|
|
||||||
muc = CONFIG.get('database_xmpp', 'muc')
|
|
||||||
channels = {}
|
|
||||||
for i in ('createsession', 'connectionlost', 'loginfailed',
|
|
||||||
'loginsucceeded', 'command', 'clientversion'):
|
|
||||||
x = CONFIG.get('database_xmpp', 'signal_' + i)
|
|
||||||
if x not in channels:
|
|
||||||
channels[x] = []
|
|
||||||
channels[x].append(i)
|
|
||||||
|
|
||||||
resource = ''.join([choice(string.ascii_letters) for i in range(8)])
|
|
||||||
jid = user + '/' + resource
|
|
||||||
application = service.Application('honeypot')
|
|
||||||
self.run(application, jid, password, JID(None, [muc, server, None]), channels)
|
|
||||||
|
|
||||||
def run(self, application, jidstr, password, muc, channels, anon=True):
|
|
||||||
self.xmppclient = XMPPClient(JID(jidstr), password)
|
|
||||||
if CONFIG.has_option('database_xmpp', 'debug') and CONFIG.getboolean('database_xmpp', 'debug'):
|
|
||||||
self.xmppclient.logTraffic = True # DEBUG HERE
|
|
||||||
(user, host, resource) = jid.parse(jidstr)
|
|
||||||
self.muc = XMPPLoggerProtocol(
|
|
||||||
muc, list(channels.keys()), user + '-' + resource)
|
|
||||||
self.muc.setHandlerParent(self.xmppclient)
|
|
||||||
self.xmppclient.setServiceParent(application)
|
|
||||||
self.signals = {}
|
|
||||||
for channel in channels:
|
|
||||||
for signal in channels[channel]:
|
|
||||||
self.signals[signal] = channel
|
|
||||||
self.anonymous = True
|
|
||||||
self.xmppclient.startService()
|
|
||||||
|
|
||||||
def broadcast(self, msgtype, msg):
|
|
||||||
if msgtype in self.signals:
|
|
||||||
self.report(msgtype, '{}@{}'.format(self.signals[msgtype], self.muc.server), msg)
|
|
||||||
|
|
||||||
def report(self, msgtype, to, xmsg):
|
|
||||||
msg = {}
|
|
||||||
msg['type'] = msgtype
|
|
||||||
msg['message'] = xmsg
|
|
||||||
msgJson = json.dumps(msg, indent=5)
|
|
||||||
self.muc.groupChat(self.muc.jrooms, msgJson)
|
|
||||||
|
|
||||||
# We have to return an unique ID
|
|
||||||
def createSession(self, peerIP, peerPort, hostIP, hostPort):
|
|
||||||
session = uuid.uuid4().hex
|
|
||||||
ses = {}
|
|
||||||
ses['session'] = session
|
|
||||||
ses['remote_host'] = peerIP
|
|
||||||
ses['remote_port'] = str(peerPort)
|
|
||||||
if self.anonymous:
|
|
||||||
ses['local_host'] = '127.0.0.1'
|
|
||||||
else:
|
|
||||||
ses['local_host'] = hostIP
|
|
||||||
ses['local_port'] = str(hostPort)
|
|
||||||
|
|
||||||
self.broadcast('createsession', ses)
|
|
||||||
return session
|
|
||||||
|
|
||||||
def handleTTYLogOpened(self, session, args):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def handleConnectionLost(self, session, args):
|
|
||||||
ses = {}
|
|
||||||
ses['session'] = session
|
|
||||||
self.broadcast('connectionlost', ses)
|
|
||||||
|
|
||||||
def handleLoginFailed(self, session, args):
|
|
||||||
ses = {}
|
|
||||||
ses['session'] = session
|
|
||||||
ses['username'] = args['username']
|
|
||||||
ses['password'] = args['password']
|
|
||||||
self.broadcast('loginfailed', ses)
|
|
||||||
|
|
||||||
def handleLoginSucceeded(self, session, args):
|
|
||||||
ses = {}
|
|
||||||
ses['session'] = session
|
|
||||||
ses['username'] = args['username']
|
|
||||||
ses['password'] = args['password']
|
|
||||||
self.broadcast('loginsucceeded', ses)
|
|
||||||
|
|
||||||
def handleCommand(self, session, args):
|
|
||||||
ses = {}
|
|
||||||
ses['session'] = session
|
|
||||||
ses['command'] = 'known'
|
|
||||||
ses['input'] = args['input']
|
|
||||||
self.broadcast('command', ses)
|
|
||||||
|
|
||||||
def handleUnknownCommand(self, session, args):
|
|
||||||
ses = {}
|
|
||||||
ses['session'] = session
|
|
||||||
ses['command'] = 'unknown'
|
|
||||||
ses['input'] = args['input']
|
|
||||||
self.broadcast('command', ses)
|
|
||||||
|
|
||||||
def handleInput(self, session, args):
|
|
||||||
ses = {}
|
|
||||||
ses['session'] = session
|
|
||||||
ses['realm'] = args['realm']
|
|
||||||
ses['input'] = args['input']
|
|
||||||
self.broadcast('input', ses)
|
|
||||||
|
|
||||||
def handleTerminalSize(self, session, args):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def handleClientVersion(self, session, args):
|
|
||||||
ses = {}
|
|
||||||
ses['session'] = session
|
|
||||||
ses['version'] = args['version']
|
|
||||||
self.broadcast('clientversion', ses)
|
|
||||||
@ -43,8 +43,6 @@ class CowrieSSHFactory(factory.SSHFactory):
|
|||||||
Special delivery to the loggers to avoid scope problems
|
Special delivery to the loggers to avoid scope problems
|
||||||
"""
|
"""
|
||||||
args['sessionno'] = 'S{0}'.format(args['sessionno'])
|
args['sessionno'] = 'S{0}'.format(args['sessionno'])
|
||||||
for dblog in self.tac.dbloggers:
|
|
||||||
dblog.logDispatch(*msg, **args)
|
|
||||||
for output in self.tac.output_plugins:
|
for output in self.tac.output_plugins:
|
||||||
output.logDispatch(*msg, **args)
|
output.logDispatch(*msg, **args)
|
||||||
|
|
||||||
|
|||||||
@ -34,8 +34,6 @@ class HoneyPotTelnetFactory(protocol.ServerFactory):
|
|||||||
Special delivery to the loggers to avoid scope problems
|
Special delivery to the loggers to avoid scope problems
|
||||||
"""
|
"""
|
||||||
args['sessionno'] = 'T{0}'.format(str(args['sessionno']))
|
args['sessionno'] = 'T{0}'.format(str(args['sessionno']))
|
||||||
for dblog in self.tac.dbloggers:
|
|
||||||
dblog.logDispatch(*msg, **args)
|
|
||||||
for output in self.tac.output_plugins:
|
for output in self.tac.output_plugins:
|
||||||
output.logDispatch(*msg, **args)
|
output.logDispatch(*msg, **args)
|
||||||
|
|
||||||
|
|||||||
@ -82,7 +82,6 @@ class CowrieServiceMaker(object):
|
|||||||
tapname = "cowrie"
|
tapname = "cowrie"
|
||||||
description = "She sells sea shells by the sea shore."
|
description = "She sells sea shells by the sea shore."
|
||||||
options = Options
|
options = Options
|
||||||
dbloggers = None
|
|
||||||
output_plugins = None
|
output_plugins = None
|
||||||
|
|
||||||
def makeService(self, options):
|
def makeService(self, options):
|
||||||
@ -115,22 +114,6 @@ Makes a Cowrie SSH/Telnet honeypot.
|
|||||||
print('ERROR: You must at least enable SSH or Telnet')
|
print('ERROR: You must at least enable SSH or Telnet')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# Load db loggers
|
|
||||||
self.dbloggers = []
|
|
||||||
for x in CONFIG.sections():
|
|
||||||
if not x.startswith('database_'):
|
|
||||||
continue
|
|
||||||
engine = x.split('_')[1]
|
|
||||||
try:
|
|
||||||
dblogger = __import__('cowrie.dblog.{}'.format(engine),
|
|
||||||
globals(), locals(), ['dblog']).DBLogger()
|
|
||||||
log.addObserver(dblogger.emit)
|
|
||||||
self.dbloggers.append(dblogger)
|
|
||||||
log.msg("Loaded dblog engine: {}".format(engine))
|
|
||||||
except Exception:
|
|
||||||
log.err()
|
|
||||||
log.msg("Failed to load dblog engine: {}".format(engine))
|
|
||||||
|
|
||||||
# Load output modules
|
# Load output modules
|
||||||
self.output_plugins = []
|
self.output_plugins = []
|
||||||
for x in CONFIG.sections():
|
for x in CONFIG.sections():
|
||||||
|
|||||||
Reference in New Issue
Block a user