From 640652207d181fe529bcf1ed1e4e8b0202fc04cf Mon Sep 17 00:00:00 2001 From: Olivier Bilodeau Date: Sun, 14 Aug 2016 00:08:47 -0400 Subject: [PATCH] Basic Telnet support implemented A squash merge of GoSecure/cowrie telnet-poc branch: https://github.com/GoSecure/cowrie/tree/telnet-poc Rebased on current upstream master. August 2016 update: Resolved several conflicts when rebasing --- README.md | 2 +- cowrie.cfg.dist | 29 +++++- cowrie/core/dblog.py | 4 +- cowrie/core/output.py | 4 +- cowrie/core/protocol.py | 61 +++++++++--- cowrie/core/realm.py | 11 ++- cowrie/insults/insults.py | 16 ++- cowrie/ssh/transport.py | 8 +- cowrie/telnet/__init__.py | 0 cowrie/telnet/session.py | 154 +++++++++++++++++++++++++++++ cowrie/telnet/transport.py | 164 +++++++++++++++++++++++++++++++ honeyfs/etc/issue.net | 2 + twisted/plugins/cowrie_plugin.py | 44 +++++++-- 13 files changed, 461 insertions(+), 38 deletions(-) create mode 100644 cowrie/telnet/__init__.py create mode 100644 cowrie/telnet/session.py create mode 100644 cowrie/telnet/transport.py create mode 100644 honeyfs/etc/issue.net diff --git a/README.md b/README.md index 55031fc1..e63114f7 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Cowrie -Cowrie is a medium interaction SSH honeypot designed to log brute force attacks and the shell interaction performed by the attacker. +Cowrie is a medium interaction SSH and Telnet honeypot designed to log brute force attacks and the shell interaction performed by the attacker. [Cowrie](http://github.com/micheloosterhof/cowrie/) is developed by Michel Oosterhof and is based on [Kippo](http://github.com/desaster/kippo/) by Upi Tamminen (desaster). diff --git a/cowrie.cfg.dist b/cowrie.cfg.dist index 0e10d83f..8b976c18 100644 --- a/cowrie.cfg.dist +++ b/cowrie.cfg.dist @@ -16,7 +16,6 @@ # (default: not specified) #sensor_name=myhostname - # Hostname for the honeypot. Displayed by the shell prompt of the virtual # environment # @@ -174,15 +173,15 @@ auth_class = UserDB # IP addresses to listen for incoming SSH connections. # # (default: 0.0.0.0) = any IPv4 address -#listen_addr = 0.0.0.0 +#listen_ssh_addr = 0.0.0.0 # (use :: for listen to all IPv6 and IPv4 addresses) -#listen_addr = :: +#listen_ssh_addr = :: # Port to listen for incoming SSH connections. # # (default: 2222) -#listen_port = 2222 +#listen_ssh_port = 2222 # SSH Version String @@ -245,6 +244,28 @@ forward_redirect_443 = 127.0.0.1:8443 forward_redirect_25 = 127.0.0.1:12525 forward_redirect_587 = 127.0.0.1:12525 + +# ============================================================================ +# Telnet Specific Options +# ============================================================================ + +# IP addresses to listen for incoming Telnet connections. +# +# (default: 0.0.0.0) = any IPv4 address +#listen_telnet_addr = 0.0.0.0 +# (use :: for listen to all IPv6 and IPv4 addresses) +#listen_telnet_addr = :: + + +# Port to listen for incoming Telnet connections. +# +# (default: 2223) +#listen_telnet_port = 2223 + +# Source Port to report in logs (useful if you use iptables to forward ports to Cowrie) +#reported_telnet_port = 23 + + # ============================================================================ # Database logging Specific Options # ============================================================================ diff --git a/cowrie/core/dblog.py b/cowrie/core/dblog.py index 80279c8b..f2b734f4 100644 --- a/cowrie/core/dblog.py +++ b/cowrie/core/dblog.py @@ -19,9 +19,11 @@ class DBLogger(object): self.cfg = cfg self.sessions = {} self.ttylogs = {} + # FIXME figure out what needs to be done here regarding + # HoneyPotTransport renamed to HoneyPotSSHTransport #:* Handles ipv6 self.re_sessionlog = re.compile( - r'.*HoneyPotTransport,([0-9]+),[:a-f0-9.]+$') + r'.*HoneyPotSSHTransport,([0-9]+),[:a-f0-9.]+$') # cowrie.session.connect is special since it kicks off new logging session, # and is not handled here diff --git a/cowrie/core/output.py b/cowrie/core/output.py index dbff7033..fd118748 100644 --- a/cowrie/core/output.py +++ b/cowrie/core/output.py @@ -67,8 +67,10 @@ class Output(object): self.cfg = cfg self.sessions = {} self.ips = {} + # FIXME figure out what needs to be done here regarding + # HoneyPotTransport renamed to HoneyPotSSHTransport self.re_sessionlog = re.compile( - '.*HoneyPotTransport,([0-9]+),[0-9a-f:.]+$') + '.*HoneyPotSSHTransport,([0-9]+),[0-9a-f:.]+$') try: self.sensor = self.cfg.get('honeypot', 'sensor_name') except: diff --git a/cowrie/core/protocol.py b/cowrie/core/protocol.py index fdaa3625..7ab20013 100644 --- a/cowrie/core/protocol.py +++ b/cowrie/core/protocol.py @@ -53,24 +53,32 @@ class HoneyPotBaseProtocol(insults.TerminalProtocol, TimeoutMixin): self.password_input = False self.cmdstack = [] + def getProtoTransport(self): + """ + Due to protocol nesting differences, we need provide how we grab + the proper transport to access underlying SSH information. Meant to be + overridden for other protocols. + """ + return self.terminal.transport.session.conn.transport + def logDispatch(self, *msg, **args): """ Send log directly to factory, avoiding normal log dispatch """ - transport = self.terminal.transport.session.conn.transport - args['sessionno'] = transport.transport.sessionno - transport.factory.logDispatch(*msg, **args) + pt = self.getProtoTransport() + args['sessionno'] = pt.transport.sessionno + pt.factory.logDispatch(*msg, **args) def connectionMade(self): """ """ - transport = self.terminal.transport.session.conn.transport + pt = self.getProtoTransport() - self.realClientIP = transport.transport.getPeer().host - self.realClientPort = transport.transport.getPeer().port - self.clientVersion = transport.otherVersionString + self.realClientIP = pt.transport.getPeer().host + self.realClientPort = pt.transport.getPeer().port + self.clientVersion = self.getClientVersion() self.logintime = time.time() self.setTimeout(1800) @@ -189,10 +197,15 @@ class HoneyPotBaseProtocol(insults.TerminalProtocol, TimeoutMixin): """ Uptime """ - transport = self.terminal.transport.session.conn.transport - r = time.time() - transport.factory.starttime + pt = self.getProtoTransport() + r = time.time() - pt.factory.starttime + if reset: + pt.factory.starttime = reset return r + def getClientVersion(self): + pt = self.getProtoTransport() + return pt.otherVersionString class HoneyPotExecProtocol(HoneyPotBaseProtocol): @@ -235,8 +248,8 @@ class HoneyPotInteractiveProtocol(HoneyPotBaseProtocol, recvline.HistoricRecvLin self.cmdstack = [honeypot.HoneyPotShell(self)] - transport = self.terminal.transport.session.conn.transport - transport.factory.sessions[transport.transport.sessionno] = self + pt = self.getProtoTransport() + pt.factory.sessions[pt.transport.sessionno] = self self.keyHandlers.update({ '\x01': self.handle_HOME, # CTRL-A @@ -292,9 +305,9 @@ class HoneyPotInteractiveProtocol(HoneyPotBaseProtocol, recvline.HistoricRecvLin def connectionLost(self, reason): """ """ - transport = self.terminal.transport.session.conn.transport - if transport.transport.sessionno in transport.factory.sessions: - del transport.factory.sessions[transport.transport.sessionno] + pt = self.getProtoTransport() + if pt.transport.sessionno in pt.factory.sessions: + del pt.factory.sessions[pt.transport.sessionno] self.lastlogExit() HoneyPotBaseProtocol.connectionLost(self, reason) @@ -396,3 +409,23 @@ class HoneyPotInteractiveProtocol(HoneyPotBaseProtocol, recvline.HistoricRecvLin """ pass + +class HoneyPotInteractiveTelnetProtocol(HoneyPotInteractiveProtocol): + """ + Specialized HoneyPotInteractiveProtocol that provides Telnet specific + overrides. + """ + + def __init__(self, avatar): + recvline.HistoricRecvLine.__init__(self) + HoneyPotInteractiveProtocol.__init__(self, avatar) + + def getProtoTransport(self): + """ + Due to protocol nesting differences, we need to override how we grab + the proper transport to access underlying Telnet information. + """ + return self.terminal.transport.session.transport + + def getClientVersion(self): + return 'Telnet' diff --git a/cowrie/core/realm.py b/cowrie/core/realm.py index cf8df865..5bbf1897 100644 --- a/cowrie/core/realm.py +++ b/cowrie/core/realm.py @@ -38,12 +38,14 @@ import pickle import twisted from twisted.conch import interfaces as conchinterfaces +from twisted.conch.telnet import ITelnetProtocol from twisted.python import log from cowrie.core import protocol from cowrie.core import server from cowrie.core import avatar from cowrie.core import fs +from cowrie.telnet import session @implementer(twisted.cred.portal.IRealm) @@ -78,6 +80,11 @@ class HoneyPotRealm(object): serv = server.CowrieServer(self) user = avatar.CowrieUser(avatarId, serv) return interfaces[0], user, user.logout - else: - raise Exception("No supported interfaces found.") + elif ITelnetProtocol in interfaces: + cs = server.CowrieServer(self) + av = session.HoneyPotTelnetSession(avatarId, cs) + return interfaces[0], av, lambda:None + log.msg('No supported interfaces found.') + # TODO: this exception doesn't raise for a reason I don't understand + raise NotImplementedError("No supported interfaces found.") diff --git a/cowrie/insults/insults.py b/cowrie/insults/insults.py index d7d4d4ea..d67df749 100644 --- a/cowrie/insults/insults.py +++ b/cowrie/insults/insults.py @@ -41,12 +41,15 @@ class LoggingServerProtocol(insults.ServerProtocol): else: self.type = 'i' # Interactive + def getSessionId(self): + transportId = self.transport.session.conn.transport.transportId + channelId = self.transport.session.id + return (transportId, channelId) def connectionMade(self): """ """ - transportId = self.transport.session.conn.transport.transportId - channelId = self.transport.session.id + transportId, channelId = self.getSessionId() self.startTime = time.time() self.ttylogFile = '%s/tty/%s-%s-%s%s.log' % \ @@ -176,3 +179,12 @@ class LoggingServerProtocol(insults.ServerProtocol): insults.ServerProtocol.connectionLost(self, reason) +class LoggingTelnetServerProtocol(LoggingServerProtocol): + """ + Wrap LoggingServerProtocol with single method to fetch session id for Telnet + """ + + def getSessionId(self): + transportId = self.transport.session.transportId + sn = self.transport.session.transport.transport.sessionno + return (transportId, sn) diff --git a/cowrie/ssh/transport.py b/cowrie/ssh/transport.py index 9b8f2569..619e42da 100644 --- a/cowrie/ssh/transport.py +++ b/cowrie/ssh/transport.py @@ -26,7 +26,7 @@ from cowrie.core import keys as cowriekeys class HoneyPotSSHFactory(factory.SSHFactory): """ - This factory creates HoneyPotTransport instances + This factory creates HoneyPotSSHTransport instances They listen directly to the TCP port """ @@ -119,13 +119,13 @@ class HoneyPotSSHFactory(factory.SSHFactory): @type addr: L{twisted.internet.interfaces.IAddress} provider @param addr: The address at which the server will listen. - @rtype: L{cowrie.core.HoneyPotTransport} + @rtype: L{cowrie.ssh.transport.HoneyPotSSHTransport} @return: The built transport. """ _modulis = '/etc/ssh/moduli', '/private/etc/moduli' - t = HoneyPotTransport() + t = HoneyPotSSHTransport() try: t.ourVersionString = self.cfg.get('honeypot', 'ssh_version_string') @@ -164,7 +164,7 @@ class HoneyPotSSHFactory(factory.SSHFactory): -class HoneyPotTransport(transport.SSHServerTransport, TimeoutMixin): +class HoneyPotSSHTransport(transport.SSHServerTransport, TimeoutMixin): """ """ diff --git a/cowrie/telnet/__init__.py b/cowrie/telnet/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/cowrie/telnet/session.py b/cowrie/telnet/session.py new file mode 100644 index 00000000..b07b0dcf --- /dev/null +++ b/cowrie/telnet/session.py @@ -0,0 +1,154 @@ +# Copyright (C) 2015, 2016 GoSecure Inc. +""" +Telnet User Session management for the Honeypot + +@author: Olivier Bilodeau +""" + +from zope.interface import implementer + +from twisted.internet import interfaces, protocol +from twisted.python import log +from twisted.conch.ssh import session +from twisted.conch.telnet import StatefulTelnetProtocol, TelnetBootstrapProtocol + +from cowrie.core import pwd +from cowrie.core import protocol as cproto +from cowrie.insults import insults + +class HoneyPotTelnetSession(TelnetBootstrapProtocol): + + def __init__(self, username, server): + self.username = username + self.server = server + self.cfg = self.server.cfg + + try: + pwentry = pwd.Passwd(self.cfg).getpwnam(self.username) + self.uid = pwentry["pw_uid"] + self.gid = pwentry["pw_gid"] + self.home = pwentry["pw_dir"] + except: + self.uid = 1001 + self.gid = 1001 + self.home = '/home' + + self.environ = { + 'LOGNAME': self.username, + 'USER': self.username, + 'HOME': self.home, + 'TMOUT': '1800'} + + if self.uid==0: + self.environ['PATH']='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin' + else: + self.environ['PATH']='/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games' + + # required because HoneyPotBaseProtocol relies on avatar.avatar.home + self.avatar = self + + # to be populated by HoneyPotTelnetAuthTransport after auth + self.transportId = None + + def connectionMade(self): + processprotocol = TelnetSessionProcessProtocol(self) + + self.protocol = insults.LoggingTelnetServerProtocol( + cproto.HoneyPotInteractiveTelnetProtocol, self) + self.protocol.makeConnection(processprotocol) + processprotocol.makeConnection(session.wrapProtocol(self.protocol)) + + # TODO do I need to implement connectionLost? + # XXX verify if HoneyPotTelnetAuthTransport's connectionLost fires otherwise + # we'll have to reimplement some of the stuff here + #def connectionLost(self, reason): + # pt = self.transport + # if pt.transport.sessionno in pt.factory.sessions: + # del pt.factory.sessions[pt.transport.sessionno] + # pt.connectionLost(reason) + +# def lineReceived(self, line): +# self.transport.write("I received %r from you\r\n" % (line,)) + + + def logout(self): + """ + """ + log.msg('avatar {} logging out'.format(self.username)) + +# Taken and adapted from +# https://github.com/twisted/twisted/blob/26ad16ab41db5f0f6d2526a891e81bbd3e260247/twisted/conch/ssh/session.py#L186 +@implementer(interfaces.ITransport) +class TelnetSessionProcessProtocol(protocol.ProcessProtocol): + """I am both an L{IProcessProtocol} and an L{ITransport}. + I am a transport to the remote endpoint and a process protocol to the + local subsystem. + """ + + def __init__(self, sess): + self.session = sess + self.lostOutOrErrFlag = False + + # FIXME probably no such thing such as buffering in Telnet protocol + #def connectionMade(self): + # if self.session.buf: + # self.session.write(self.session.buf) + # self.session.buf = None + + def outReceived(self, data): + self.session.write(data) + + def errReceived(self, err): + self.session.writeExtended(connection.EXTENDED_DATA_STDERR, err) + + def outConnectionLost(self): + """ + EOF should only be sent when both STDOUT and STDERR have been closed. + """ + if self.lostOutOrErrFlag: + self.session.conn.sendEOF(self.session) + else: + self.lostOutOrErrFlag = True + + def errConnectionLost(self): + """ + See outConnectionLost(). + """ + self.outConnectionLost() + + def connectionLost(self, reason = None): + self.session.loseConnection() + + + # here SSH is doing signal handling, I don't think telnet supports that so + # I'm simply going to bail out + def processEnded(self, reason=None): + # TODO: log reason maybe? + log.msg("Process ended. Telnet Session disconnected") + self.session.loseConnection() + + + def getHost(self): + """ + Return the host from my session's transport. + """ + return self.session.transport.getHost() + + + def getPeer(self): + """ + Return the peer from my session's transport. + """ + return self.session.transport.getPeer() + + + def write(self, data): + self.session.write(data) + + + def writeSequence(self, seq): + self.session.write(''.join(seq)) + + + def loseConnection(self): + self.session.loseConnection() diff --git a/cowrie/telnet/transport.py b/cowrie/telnet/transport.py new file mode 100644 index 00000000..f725d5e3 --- /dev/null +++ b/cowrie/telnet/transport.py @@ -0,0 +1,164 @@ +# Copyright (C) 2015, 2016 GoSecure Inc. +""" +Telnet Transport and Authentication for the Honeypot + +@author: Olivier Bilodeau +""" + +import time +import uuid + +from twisted.python import log +from twisted.internet import protocol +from twisted.conch.telnet import AuthenticatingTelnetProtocol, ECHO, \ + ITelnetProtocol, ProtocolTransportMixin, \ + TelnetTransport +from twisted.protocols.policies import TimeoutMixin + +from cowrie.core.credentials import UsernamePasswordIP + +class HoneyPotTelnetFactory(protocol.ServerFactory): + """ + This factory creates HoneyPotTelnetAuthTransport instances + They listen directly to the TCP port + """ + + 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): + """ + """ + # The banner to serve + honeyfs = self.portal.realm.cfg.get('honeypot', 'contents_path') + issuefile = honeyfs + "/etc/issue.net" + self.banner = file(issuefile).read() + + # Interactive protocols are kept here for the interact feature + self.sessions = {} + + # For use by the uptime command + self.starttime = time.time() + + # 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)) + + # hook protocol + self.protocol = lambda: TelnetTransport(HoneyPotTelnetAuthTransport, + self.portal) + + protocol.ServerFactory.startFactory(self) + + def stopFactory(self): + """ + Stop output plugins + """ + for output in self.output_plugins: + output.stop() + protocol.ServerFactory.stopFactory(self) + + +class HoneyPotTelnetAuthTransport(AuthenticatingTelnetProtocol, ProtocolTransportMixin, TimeoutMixin): + """ + Telnet Transport that takes care of Authentication. Once authenticated this + transport is replaced with HoneyPotTelnetSession. + """ + + def connectionMade(self): + + self.transportId = uuid.uuid4().hex[:8] + sessionno = self.transport.transport.sessionno + self.factory.sessions[sessionno] = self.transportId + + log.msg(eventid='cowrie.session.connect', + 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, + session=self.transportId, sessionno=sessionno) + + # p/Cisco telnetd/ d/router/ o/IOS/ cpe:/a:cisco:telnet/ cpe:/o:cisco:ios/a + # NB _write() is for raw data and write() handles telnet special bytes + self.transport._write("\xff\xfb\x01\xff\xfb\x03\xff\xfb\0\xff\xfd\0\xff\xfd\x1f\r\n") + self.transport.write(self.factory.banner) + self.transport._write("User Access Verification\r\n\r\nUsername: ") + + self.setTimeout(120) + + # FIXME TelnetTransport is throwing an exception when client disconnects + # Not sure if this is true anymore + def connectionLost(self, reason): + """ + This seems to be the only reliable place of catching lost connection + """ + self.setTimeout(None) + if self.transport.transport.sessionno in self.factory.sessions: + del self.factory.sessions[self.transport.transport.sessionno] + self.transport.connectionLost(reason) + self.transport = None + log.msg(eventid='cowrie.session.closed', format='Connection lost') + + def telnet_Password(self, line): + username, password = self.username, line + del self.username + def login(ignored): + self.src_ip = self.transport.getPeer().host + creds = UsernamePasswordIP(username, password, self.src_ip) + d = self.portal.login(creds, self.src_ip, ITelnetProtocol) + d.addCallback(self._cbLogin) + d.addErrback(self._ebLogin) + self.transport.wont(ECHO).addCallback(login) + + return 'Discard' + + def _cbLogin(self, ial): + """ + """ + interface, protocol, logout = ial + self.protocol = protocol + self.logout = logout + self.state = 'Command' + + # transfer important state info to new transport + protocol.transportId = self.transportId + + # replace myself with avatar protocol + protocol.makeConnection(self.transport) + self.transport.protocol = protocol diff --git a/honeyfs/etc/issue.net b/honeyfs/etc/issue.net new file mode 100644 index 00000000..ff10a9de --- /dev/null +++ b/honeyfs/etc/issue.net @@ -0,0 +1,2 @@ +Debian GNU/Linux 7 + diff --git a/twisted/plugins/cowrie_plugin.py b/twisted/plugins/cowrie_plugin.py index 99fc2da8..2d967319 100644 --- a/twisted/plugins/cowrie_plugin.py +++ b/twisted/plugins/cowrie_plugin.py @@ -48,6 +48,7 @@ from cowrie import core import cowrie.core.realm import cowrie.core.checkers +import cowrie.telnet.transport import cowrie.ssh.transport class Options(usage.Options): @@ -99,28 +100,53 @@ class CowrieServiceMaker(object): factory.portal.registerChecker( core.checkers.HoneypotNoneChecker()) - if cfg.has_option('honeypot', 'listen_addr'): - listenAddr = cfg.get('honeypot', 'listen_addr') + if cfg.has_option('honeypot', 'listen_ssh_addr'): + listen_ssh_addr = cfg.get('honeypot', 'listen_ssh_addr') else: - listenAddr = '0.0.0.0' + listen_ssh_addr = '0.0.0.0' # Preference: 1, option, 2, config, 3, default of 2222 if options['port'] != 0: - listenPort = int(options["port"]) - elif cfg.has_option('honeypot', 'listen_port'): - listenPort = int(cfg.get('honeypot', 'listen_port')) + listen_ssh_port = int(options["port"]) + elif cfg.has_option('honeypot', 'listen_ssh_port'): + listen_ssh_port = int(cfg.get('honeypot', 'listen_ssh_port')) else: - listenPort = 2222 + listen_ssh_port = 2222 - for i in listenAddr.split(): - svc = internet.TCPServer(listenPort, factory, interface=i) + for i in listen_ssh_addr.split(): + svc = internet.TCPServer(listen_ssh_port, factory, interface=i) # FIXME: Use addService on topService ? svc.setServiceParent(topService) + # TODO deduplicate telnet and ssh into a generic loop for each service + if cfg.has_option('honeypot', 'listen_telnet_addr'): + listen_telnet_addr = cfg.get('honeypot', 'listen_telnet_addr') + else: + listen_telnet_addr = '0.0.0.0' + + # Preference: 1, config, 2, default of 2223 + if cfg.has_option('honeypot', 'listen_telnet_port'): + listen_telnet_port = int(cfg.get('honeypot', 'listen_telnet_port')) + else: + listen_telnet_port = 2223 + + f = cowrie.telnet.transport.HoneyPotTelnetFactory(cfg) + f.portal = portal.Portal(core.realm.HoneyPotRealm(cfg)) + f.portal.registerChecker(core.checkers.HoneypotPasswordChecker(cfg)) + if cfg.has_option('honeypot', 'auth_none_enabled') and \ + cfg.get('honeypot', 'auth_none_enabled').lower() in \ + ('yes', 'true', 'on'): + f.portal.registerChecker(core.checkers.HoneypotNoneChecker()) + for i in listen_telnet_addr.split(): + tsvc = internet.TCPServer(listen_telnet_port, f, interface=i) + # FIXME: Use addService on topService ? + tsvc.setServiceParent(topService) + if cfg.has_option('honeypot', 'interact_enabled') and \ cfg.get('honeypot', 'interact_enabled').lower() in \ ('yes', 'true', 'on'): iport = int(cfg.get('honeypot', 'interact_port')) + # FIXME this doesn't support checking both Telnet and SSH sessions from cowrie.core import interact svc = internet.TCPServer(iport, interact.makeInteractFactory(factory), interface='127.0.0.1')