diff --git a/kippo.cfg.dist b/kippo.cfg.dist index 1f2d380d..fa2d7a58 100644 --- a/kippo.cfg.dist +++ b/kippo.cfg.dist @@ -81,6 +81,12 @@ txtcmds_path = txtcmds public_key = public.key private_key = private.key +# Enables passing commands using ssh execCommand +# e.g. ssh root@localhost +# +# (default: false) +exec_enabled = true + # Initial root password. NO LONGER USED! # Instead, see {data_path}/userdb.txt #password = 123456 diff --git a/kippo/core/honeypot.py b/kippo/core/honeypot.py index 1402c051..a74e357d 100644 --- a/kippo/core/honeypot.py +++ b/kippo/core/honeypot.py @@ -11,7 +11,7 @@ from twisted.internet import reactor, protocol, defer from twisted.python import failure, log from zope.interface import implements from copy import deepcopy, copy -import sys, os, random, pickle, time, stat, shlex, anydbm +import sys, os, random, pickle, time, stat, shlex, anydbm, struct from kippo.core import ttylog, fs, utils from kippo.core.userdb import UserDB @@ -137,6 +137,8 @@ class HoneyPotShell(object): self.runCommand() def showPrompt(self): + if (self.honeypot.execcmd != None): + return # Example: nas3:~# #prompt = '%s:%%(path)s' % self.honeypot.hostname # Example: root@nas3:~# (More of a "Debianu" feel) @@ -244,9 +246,10 @@ class HoneyPotShell(object): self.honeypot.terminal.write(newbuf) class HoneyPotProtocol(recvline.HistoricRecvLine): - def __init__(self, user, env): + def __init__(self, user, env, execcmd = None): self.user = user self.env = env + self.execcmd = execcmd self.hostname = self.env.cfg.get('honeypot', 'hostname') self.fs = fs.HoneyPotFilesystem(deepcopy(self.env.fs)) if self.fs.exists(user.home): @@ -283,6 +286,13 @@ class HoneyPotProtocol(recvline.HistoricRecvLine): else: self.clientIP = self.realClientIP + if self.execcmd != None: + print 'Running exec cmd "%s"' % self.execcmd + self.cmdstack[0].lineReceived(self.execcmd) + self.terminal.transport.session.conn.sendRequest(self.terminal.transport.session, 'exit-status', struct.pack('>L', 0)) + self.terminal.transport.session.conn.sendClose(self.terminal.transport.session) + return + self.keyHandlers.update({ '\x04': self.handle_CTRL_D, '\x15': self.handle_CTRL_U, @@ -344,6 +354,9 @@ class HoneyPotProtocol(recvline.HistoricRecvLine): return None def lineReceived(self, line): + # Don't execute additional commands after execcmd + if self.execcmd != None: + return if len(self.cmdstack): self.cmdstack[-1].lineReceived(line) @@ -473,7 +486,16 @@ class HoneyPotAvatar(avatar.ConchUser): return None def execCommand(self, protocol, cmd): - raise NotImplementedError + cfg = config() + if cfg.has_option('honeypot', 'exec_enabled'): + if ( cfg.get('honeypot', 'exec_enabled') != "true" ): + print 'exec disabled. Not executing command: "%s"' % cmd + raise os.OSError + + print 'exec command: "%s"' % cmd + serverProtocol = LoggingServerProtocol(HoneyPotProtocol, self, self.env, cmd) + serverProtocol.makeConnection(protocol) + protocol.makeConnection(session.wrapProtocol(serverProtocol)) def closed(self): pass