From 43fd43481aa75d0544dcdb78b25d41c8ca68339a Mon Sep 17 00:00:00 2001 From: Michel Oosterhof Date: Mon, 22 Aug 2016 17:04:28 +0400 Subject: [PATCH] split off factory from transport. --- cowrie/ssh/factory.py | 164 +++++++++++++++++++++++++++++++ cowrie/ssh/transport.py | 147 --------------------------- twisted/plugins/cowrie_plugin.py | 4 +- 3 files changed, 166 insertions(+), 149 deletions(-) create mode 100644 cowrie/ssh/factory.py diff --git a/cowrie/ssh/factory.py b/cowrie/ssh/factory.py new file mode 100644 index 0000000..795af5c --- /dev/null +++ b/cowrie/ssh/factory.py @@ -0,0 +1,164 @@ +# Copyright (c) 2009-2014 Upi Tamminen +# See the COPYRIGHT file for more information + +""" +This module contains ... +""" + +import time + +from twisted.conch.ssh import factory +from twisted.conch.ssh import keys +from twisted.python import log +from twisted.conch.openssh_compat import primes + +from cowrie.ssh import connection +from cowrie.ssh import userauth +from cowrie.ssh import transport +from cowrie.core import keys as cowriekeys + + +class CowrieSSHFactory(factory.SSHFactory): + """ + This factory creates HoneyPotSSHTransport instances + They listen directly to the TCP port + """ + + services = { + 'ssh-userauth': userauth.HoneyPotSSHUserAuthServer, + 'ssh-connection': connection.CowrieSSHConnection, + } + starttime = None + sessions = {} + privateKeys = None + publicKeys = None + dbloggers = None + output_plugins = None + primes = None + + def __init__(self, cfg): + self.cfg = cfg + + + def logDispatch(self, *msg, **args): + """ + Special delivery to the loggers to avoid scope problems + """ + for dblog in self.dbloggers: + dblog.logDispatch(*msg, **args) + for output in self.output_plugins: + output.logDispatch(*msg, **args) + + + def startFactory(self): + """ + """ + # Interactive protocols are kept here for the interact feature + self.sessions = {} + + # For use by the uptime command + self.starttime = time.time() + + # Load/create keys + rsaPubKeyString, rsaPrivKeyString = cowriekeys.getRSAKeys(self.cfg) + dsaPubKeyString, dsaPrivKeyString = cowriekeys.getDSAKeys(self.cfg) + self.publicKeys = { + 'ssh-rsa': keys.Key.fromString(data=rsaPubKeyString), + 'ssh-dss': keys.Key.fromString(data=dsaPubKeyString)} + self.privateKeys = { + 'ssh-rsa': keys.Key.fromString(data=rsaPrivKeyString), + 'ssh-dss': keys.Key.fromString(data=dsaPrivKeyString)} + + # Load db loggers + self.dbloggers = [] + for x in self.cfg.sections(): + if not x.startswith('database_'): + continue + engine = x.split('_')[1] + try: + dblogger = __import__( 'cowrie.dblog.{}'.format(engine), + globals(), locals(), ['dblog']).DBLogger(self.cfg) + log.addObserver(dblogger.emit) + self.dbloggers.append(dblogger) + log.msg("Loaded dblog engine: {}".format(engine)) + except: + log.err() + log.msg("Failed to load dblog engine: {}".format(engine)) + + # Load output modules + self.output_plugins = [] + for x in self.cfg.sections(): + if not x.startswith('output_'): + continue + engine = x.split('_')[1] + try: + output = __import__( 'cowrie.output.{}'.format(engine), + globals(), locals(), ['output']).Output(self.cfg) + log.addObserver(output.emit) + self.output_plugins.append(output) + log.msg("Loaded output engine: {}".format(engine)) + except: + log.err() + log.msg("Failed to load output engine: {}".format(engine)) + + factory.SSHFactory.startFactory(self) + + + def stopFactory(self): + """ + """ + factory.SSHFactory.stopFactory(self) + for output in self.output_plugins: + output.stop() + + + def buildProtocol(self, addr): + """ + Create an instance of the server side of the SSH protocol. + + @type addr: L{twisted.internet.interfaces.IAddress} provider + @param addr: The address at which the server will listen. + + @rtype: L{cowrie.ssh.transport.HoneyPotSSHTransport} + @return: The built transport. + """ + + _modulis = '/etc/ssh/moduli', '/private/etc/moduli' + + t = transport.HoneyPotSSHTransport() + + try: + t.ourVersionString = self.cfg.get('honeypot', 'ssh_version_string') + except: + t.ourVersionString = "SSH-2.0-OpenSSH_6.0p1 Debian-4+deb7u2" + + t.supportedPublicKeys = list(self.privateKeys.keys()) + + for _moduli in _modulis: + try: + self.primes = primes.parseModuliFile(_moduli) + break + except IOError as err: + pass + + if not self.primes: + ske = t.supportedKeyExchanges[:] + if 'diffie-hellman-group-exchange-sha1' in ske: + ske.remove('diffie-hellman-group-exchange-sha1') + log.msg("No moduli, no diffie-hellman-group-exchange-sha1") + if 'diffie-hellman-group-exchange-sha256' in ske: + ske.remove('diffie-hellman-group-exchange-sha256') + log.msg("No moduli, no diffie-hellman-group-exchange-sha256") + t.supportedKeyExchanges = ske + + # Reorder supported ciphers to resemble current openssh more + t.supportedCiphers = ['aes128-ctr', 'aes192-ctr', 'aes256-ctr', + 'aes128-cbc', '3des-cbc', 'blowfish-cbc', 'cast128-cbc', + 'aes192-cbc', 'aes256-cbc'] + t.supportedPublicKeys = ['ssh-rsa', 'ssh-dss'] + t.supportedMACs = ['hmac-md5', 'hmac-sha1'] + t.supportedCompressions = ['zlib@openssh.com', 'zlib', 'none'] + + t.factory = self + return t + diff --git a/cowrie/ssh/transport.py b/cowrie/ssh/transport.py index 619e42d..8a2b3ca 100644 --- a/cowrie/ssh/transport.py +++ b/cowrie/ssh/transport.py @@ -11,158 +11,11 @@ import uuid import zlib import twisted -from twisted.conch.ssh import factory -from twisted.conch.ssh import keys from twisted.conch.ssh import transport from twisted.python import log -from twisted.conch.openssh_compat import primes from twisted.conch.ssh.common import getNS from twisted.protocols.policies import TimeoutMixin -from cowrie.ssh import connection -from cowrie.ssh import userauth -from cowrie.core import keys as cowriekeys - - -class HoneyPotSSHFactory(factory.SSHFactory): - """ - This factory creates HoneyPotSSHTransport instances - They listen directly to the TCP port - """ - - services = { - 'ssh-userauth': userauth.HoneyPotSSHUserAuthServer, - 'ssh-connection': connection.CowrieSSHConnection, - } - - def __init__(self, cfg): - self.cfg = cfg - - - def logDispatch(self, *msg, **args): - """ - Special delivery to the loggers to avoid scope problems - """ - for dblog in self.dbloggers: - dblog.logDispatch(*msg, **args) - for output in self.output_plugins: - output.logDispatch(*msg, **args) - - - def startFactory(self): - """ - """ - - # Interactive protocols are kept here for the interact feature - self.sessions = {} - - # For use by the uptime command - self.starttime = time.time() - - # Load/create keys - rsaPubKeyString, rsaPrivKeyString = cowriekeys.getRSAKeys(self.cfg) - dsaPubKeyString, dsaPrivKeyString = cowriekeys.getDSAKeys(self.cfg) - self.publicKeys = { - 'ssh-rsa': keys.Key.fromString(data=rsaPubKeyString), - 'ssh-dss': keys.Key.fromString(data=dsaPubKeyString)} - self.privateKeys = { - 'ssh-rsa': keys.Key.fromString(data=rsaPrivKeyString), - 'ssh-dss': keys.Key.fromString(data=dsaPrivKeyString)} - - # Load db loggers - self.dbloggers = [] - for x in self.cfg.sections(): - if not x.startswith('database_'): - continue - engine = x.split('_')[1] - try: - dblogger = __import__( 'cowrie.dblog.{}'.format(engine), - globals(), locals(), ['dblog']).DBLogger(self.cfg) - log.addObserver(dblogger.emit) - self.dbloggers.append(dblogger) - log.msg("Loaded dblog engine: {}".format(engine)) - except: - log.err() - log.msg("Failed to load dblog engine: {}".format(engine)) - - # Load output modules - self.output_plugins = [] - for x in self.cfg.sections(): - if not x.startswith('output_'): - continue - engine = x.split('_')[1] - try: - output = __import__( 'cowrie.output.{}'.format(engine), - globals(), locals(), ['output']).Output(self.cfg) - log.addObserver(output.emit) - self.output_plugins.append(output) - log.msg("Loaded output engine: {}".format(engine)) - except: - log.err() - log.msg("Failed to load output engine: {}".format(engine)) - - factory.SSHFactory.startFactory(self) - - - def stopFactory(self): - """ - """ - factory.SSHFactory.stopFactory(self) - for output in self.output_plugins: - output.stop() - - - def buildProtocol(self, addr): - """ - Create an instance of the server side of the SSH protocol. - - @type addr: L{twisted.internet.interfaces.IAddress} provider - @param addr: The address at which the server will listen. - - @rtype: L{cowrie.ssh.transport.HoneyPotSSHTransport} - @return: The built transport. - """ - - _modulis = '/etc/ssh/moduli', '/private/etc/moduli' - - t = HoneyPotSSHTransport() - - try: - t.ourVersionString = self.cfg.get('honeypot', 'ssh_version_string') - except: - t.ourVersionString = "SSH-2.0-OpenSSH_6.0p1 Debian-4+deb7u2" - - t.supportedPublicKeys = list(self.privateKeys.keys()) - - for _moduli in _modulis: - try: - self.primes = primes.parseModuliFile(_moduli) - break - except IOError as err: - pass - - if not self.primes: - ske = t.supportedKeyExchanges[:] - if 'diffie-hellman-group-exchange-sha1' in ske: - ske.remove('diffie-hellman-group-exchange-sha1') - log.msg("No moduli, no diffie-hellman-group-exchange-sha1") - if 'diffie-hellman-group-exchange-sha256' in ske: - ske.remove('diffie-hellman-group-exchange-sha256') - log.msg("No moduli, no diffie-hellman-group-exchange-sha256") - t.supportedKeyExchanges = ske - - # Reorder supported ciphers to resemble current openssh more - t.supportedCiphers = ['aes128-ctr', 'aes192-ctr', 'aes256-ctr', - 'aes128-cbc', '3des-cbc', 'blowfish-cbc', 'cast128-cbc', - 'aes192-cbc', 'aes256-cbc'] - t.supportedPublicKeys = ['ssh-rsa', 'ssh-dss'] - t.supportedMACs = ['hmac-md5', 'hmac-sha1'] - t.supportedCompressions = ['zlib@openssh.com', 'zlib', 'none'] - - t.factory = self - return t - - class HoneyPotSSHTransport(transport.SSHServerTransport, TimeoutMixin): """ diff --git a/twisted/plugins/cowrie_plugin.py b/twisted/plugins/cowrie_plugin.py index c04ccf4..795fa4d 100644 --- a/twisted/plugins/cowrie_plugin.py +++ b/twisted/plugins/cowrie_plugin.py @@ -49,7 +49,7 @@ import cowrie.core.realm import cowrie.core.checkers import cowrie.telnet.transport -import cowrie.ssh.transport +import cowrie.ssh.factory class Options(usage.Options): """ @@ -86,7 +86,7 @@ class CowrieServiceMaker(object): application = service.Application('cowrie') topService.setServiceParent(application) - factory = cowrie.ssh.transport.HoneyPotSSHFactory(cfg) + factory = cowrie.ssh.factory.CowrieSSHFactory(cfg) factory.portal = portal.Portal(core.realm.HoneyPotRealm(cfg)) factory.portal.registerChecker(