mirror of https://github.com/desaster/kippo.git
Initial support for non-root users. Check your root passwords!
Thanks to Walter de Jong for code Thanks to Christian Rohling for the push git-svn-id: https://kippo.googlecode.com/svn/trunk@196 951d7100-d841-11de-b865-b3884708a8e2
This commit is contained in:
parent
7b607acacb
commit
950ac23907
|
@ -0,0 +1 @@
|
|||
root:0:123456
|
|
@ -74,11 +74,9 @@ txtcmds_path = txtcmds
|
|||
public_key = public.key
|
||||
private_key = private.key
|
||||
|
||||
# Initial root password. Future passwords will be stored in
|
||||
# {data_path}/pass.db
|
||||
#
|
||||
# (default: 123456)
|
||||
password = 123456
|
||||
# Initial root password. NO LONGER USED!
|
||||
# Instead, see {data_path}/userdb.txt
|
||||
#password = 123456
|
||||
|
||||
# IP address to bind to when opening outgoing connections. Used exclusively by
|
||||
# the wget command.
|
||||
|
|
|
@ -5,6 +5,7 @@ import os, time, anydbm, datetime
|
|||
from kippo.core.honeypot import HoneyPotCommand
|
||||
from twisted.internet import reactor
|
||||
from kippo.core.config import config
|
||||
from kippo.core.userdb import UserDB
|
||||
|
||||
commands = {}
|
||||
|
||||
|
@ -24,8 +25,9 @@ class command_w(HoneyPotCommand):
|
|||
self.writeln(' %s up 14 days, 3:53, 1 user, load average: 0.08, 0.02, 0.01' % \
|
||||
time.strftime('%H:%M:%S'))
|
||||
self.writeln('USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT')
|
||||
self.writeln('root pts/0 %s %s 0.00s 0.00s 0.00s w' % \
|
||||
(self.honeypot.clientIP[:17].ljust(17),
|
||||
self.writeln('%-8s pts/0 %s %s 0.00s 0.00s 0.00s w' % \
|
||||
(self.honeypot.user.username,
|
||||
self.honeypot.clientIP[:17].ljust(17),
|
||||
time.strftime('%H:%M', time.localtime(self.honeypot.logintime))))
|
||||
commands['/usr/bin/w'] = command_w
|
||||
commands['/usr/bin/who'] = command_w
|
||||
|
@ -125,7 +127,9 @@ commands['/bin/ps'] = command_ps
|
|||
|
||||
class command_id(HoneyPotCommand):
|
||||
def call(self):
|
||||
self.writeln('uid=0(root) gid=0(root) groups=0(root)')
|
||||
u = self.honeypot.user
|
||||
self.writeln('uid=%d(%s) gid=%d(%s) groups=%d(%s)' % \
|
||||
(u.uid, u.username, u.gid, u.username, u.gid, u.username))
|
||||
commands['/usr/bin/id'] = command_id
|
||||
|
||||
class command_passwd(HoneyPotCommand):
|
||||
|
@ -133,18 +137,23 @@ class command_passwd(HoneyPotCommand):
|
|||
self.write('Enter new UNIX password: ')
|
||||
self.honeypot.password_input = True
|
||||
self.callbacks = [self.ask_again, self.finish]
|
||||
self.passwd = None
|
||||
|
||||
def ask_again(self):
|
||||
def ask_again(self, line):
|
||||
self.passwd = line
|
||||
self.write('Retype new UNIX password: ')
|
||||
|
||||
def finish(self):
|
||||
def finish(self, line):
|
||||
self.honeypot.password_input = False
|
||||
|
||||
data_path = self.honeypot.env.cfg.get('honeypot', 'data_path')
|
||||
passdb = anydbm.open('%s/pass.db' % (data_path,), 'c')
|
||||
if len(self.password) and self.password not in passdb:
|
||||
passdb[self.password] = ''
|
||||
passdb.close()
|
||||
if line != self.passwd:
|
||||
self.writeln('Sorry, passwords do not match')
|
||||
self.exit()
|
||||
return
|
||||
|
||||
userdb = UserDB()
|
||||
userdb.adduser(self.honeypot.user.username,
|
||||
self.honeypot.user.uid, self.passwd)
|
||||
|
||||
self.writeln('passwd: password updated successfully')
|
||||
self.exit()
|
||||
|
@ -152,7 +161,7 @@ class command_passwd(HoneyPotCommand):
|
|||
def lineReceived(self, line):
|
||||
print 'INPUT (passwd):', line
|
||||
self.password = line.strip()
|
||||
self.callbacks.pop(0)()
|
||||
self.callbacks.pop(0)(line)
|
||||
commands['/usr/bin/passwd'] = command_passwd
|
||||
|
||||
class command_shutdown(HoneyPotCommand):
|
||||
|
|
|
@ -26,7 +26,7 @@ commands['/bin/cat'] = command_cat
|
|||
class command_cd(HoneyPotCommand):
|
||||
def call(self):
|
||||
if not self.args:
|
||||
path = '/root'
|
||||
path = self.honeypot.user.home
|
||||
else:
|
||||
path = self.args[0]
|
||||
try:
|
||||
|
|
|
@ -14,6 +14,7 @@ from copy import deepcopy, copy
|
|||
import sys, os, random, pickle, time, stat, shlex, anydbm
|
||||
|
||||
from kippo.core import ttylog, fs, utils
|
||||
from kippo.core.userdb import UserDB
|
||||
from kippo.core.config import config
|
||||
import commands
|
||||
|
||||
|
@ -133,10 +134,19 @@ class HoneyPotShell(object):
|
|||
self.runCommand()
|
||||
|
||||
def showPrompt(self):
|
||||
prompt = '%s:%%(path)s# ' % self.honeypot.hostname
|
||||
if not self.honeypot.user.uid:
|
||||
prompt = '%s:%%(path)s# ' % self.honeypot.hostname
|
||||
else:
|
||||
prompt = '%s:%%(path)s$ ' % self.honeypot.hostname
|
||||
|
||||
path = self.honeypot.cwd
|
||||
if path == '/root':
|
||||
homelen = len(self.honeypot.user.home)
|
||||
if path == self.honeypot.user.home:
|
||||
path = '~'
|
||||
elif len(path) > (homelen+1) and \
|
||||
path[:(homelen+1)] == self.honeypot.user.home + '/':
|
||||
path = '~' + path[homelen:]
|
||||
|
||||
attrs = {'path': path}
|
||||
self.honeypot.terminal.write(prompt % attrs)
|
||||
|
||||
|
@ -223,7 +233,7 @@ class HoneyPotProtocol(recvline.HistoricRecvLine):
|
|||
def __init__(self, user, env):
|
||||
self.user = user
|
||||
self.env = env
|
||||
self.cwd = '/root'
|
||||
self.cwd = user.home
|
||||
self.hostname = self.env.cfg.get('honeypot', 'hostname')
|
||||
self.fs = fs.HoneyPotFilesystem(deepcopy(self.env.fs))
|
||||
# commands is also a copy so we can add stuff on the fly
|
||||
|
@ -406,6 +416,14 @@ class HoneyPotAvatar(avatar.ConchUser):
|
|||
self.env = env
|
||||
self.channelLookup.update({'session':session.SSHSession})
|
||||
|
||||
userdb = UserDB()
|
||||
self.uid = self.gid = userdb.getUID(self.username)
|
||||
|
||||
if not self.uid:
|
||||
self.home = '/root'
|
||||
else:
|
||||
self.home = '/home/' + username
|
||||
|
||||
def openShell(self, protocol):
|
||||
serverProtocol = LoggingServerProtocol(HoneyPotProtocol, self, self.env)
|
||||
serverProtocol.makeConnection(protocol)
|
||||
|
@ -476,6 +494,24 @@ class HoneyPotSSHFactory(factory.SSHFactory):
|
|||
|
||||
def __init__(self):
|
||||
cfg = config()
|
||||
|
||||
# convert old pass.db root passwords
|
||||
passdb_file = '%s/pass.db' % (cfg.get('honeypot', 'data_path'),)
|
||||
if os.path.exists(passdb_file):
|
||||
userdb = UserDB()
|
||||
print 'pass.db deprecated - copying passwords over to userdb.txt'
|
||||
if os.path.exists('%s.bak' % (passdb_file,)):
|
||||
print 'ERROR: %s.bak already exists, skipping conversion!' % \
|
||||
(passdb_file,)
|
||||
else:
|
||||
passdb = anydbm.open(passdb_file, 'c')
|
||||
for p in passdb:
|
||||
userdb.adduser('root', 0, p)
|
||||
passdb.close()
|
||||
os.rename(passdb_file, '%s.bak' % (passdb_file,))
|
||||
print 'pass.db backed up to %s.bak' % (passdb_file,)
|
||||
|
||||
# load db loggers
|
||||
for x in cfg.sections():
|
||||
if not x.startswith('database_'):
|
||||
continue
|
||||
|
@ -532,20 +568,12 @@ class HoneypotPasswordChecker:
|
|||
return defer.fail(error.UnauthorizedLogin())
|
||||
|
||||
def checkUserPass(self, username, password):
|
||||
cfg = config()
|
||||
data_path = cfg.get('honeypot', 'data_path')
|
||||
passdb = anydbm.open('%s/pass.db' % (data_path,), 'c')
|
||||
success = False
|
||||
if username == 'root' and password == cfg.get('honeypot', 'password'):
|
||||
success = True
|
||||
elif username == 'root' and password in passdb:
|
||||
success = True
|
||||
passdb.close()
|
||||
if success:
|
||||
if UserDB().checklogin(username, password):
|
||||
print 'login attempt [%s/%s] succeeded' % (username, password)
|
||||
return True
|
||||
else:
|
||||
print 'login attempt [%s/%s] failed' % (username, password)
|
||||
return success
|
||||
return False
|
||||
|
||||
def getRSAKeys():
|
||||
cfg = config()
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
#
|
||||
# userdb.py for kippo
|
||||
# by Walter de Jong <walter@sara.nl>
|
||||
#
|
||||
# adopted and further modified by Upi Tamminen <desaster@gmail.com>
|
||||
#
|
||||
|
||||
from kippo.core.config import config
|
||||
import os
|
||||
import string
|
||||
|
||||
class UserDB:
|
||||
def __init__(self):
|
||||
self.userdb = []
|
||||
self.load()
|
||||
|
||||
def load(self):
|
||||
'''load the user db'''
|
||||
|
||||
userdb_file = '%s/userdb.txt' % \
|
||||
(config().get('honeypot', 'data_path'),)
|
||||
|
||||
f = open(userdb_file, 'r')
|
||||
while True:
|
||||
line = f.readline()
|
||||
if not line:
|
||||
break
|
||||
|
||||
line = string.strip(line)
|
||||
if not line:
|
||||
continue
|
||||
|
||||
(login, uid_str, passwd) = string.split(line, ':')
|
||||
|
||||
uid = 0
|
||||
try:
|
||||
uid = int(uid_str)
|
||||
except ValueError:
|
||||
uid = 1001
|
||||
|
||||
self.userdb.append((login, uid, passwd))
|
||||
|
||||
f.close()
|
||||
|
||||
def save(self):
|
||||
'''save the user db'''
|
||||
|
||||
userdb_file = '%s/userdb.txt' % \
|
||||
(config().get('honeypot', 'data_path'),)
|
||||
|
||||
# Note: this is subject to races between kippo instances, but hey ...
|
||||
f = open(userdb_file, 'w')
|
||||
for (login, uid, passwd) in self.userdb:
|
||||
f.write('%s:%d:%s\n' % (login, uid, passwd))
|
||||
f.close()
|
||||
|
||||
def checklogin(self, thelogin, thepasswd):
|
||||
'''check entered username/password against database'''
|
||||
'''note that it allows multiple passwords for a single username'''
|
||||
|
||||
for (login, uid, passwd) in self.userdb:
|
||||
if login == thelogin and passwd == thepasswd:
|
||||
return True
|
||||
return False
|
||||
|
||||
def user_exists(self, thelogin):
|
||||
for (login, uid, passwd) in self.userdb:
|
||||
if login == thelogin:
|
||||
return True
|
||||
return False
|
||||
|
||||
def user_password_exists(self, thelogin, thepasswd):
|
||||
for (login, uid, passwd) in self.userdb:
|
||||
if login == thelogin and passwd == thepasswd:
|
||||
return True
|
||||
return False
|
||||
|
||||
def getUID(self, loginname):
|
||||
for (login, uid, passwd) in self.userdb:
|
||||
if loginname == login:
|
||||
return uid
|
||||
return 1001
|
||||
|
||||
def allocUID(self):
|
||||
'''allocate the next UID'''
|
||||
|
||||
min_uid = 0
|
||||
for (login, uid, passwd) in self.userdb:
|
||||
if uid > min_uid:
|
||||
min_uid = uid
|
||||
return min_uid + 1
|
||||
|
||||
def adduser(self, login, uid, passwd):
|
||||
if self.user_password_exists(login, passwd):
|
||||
return
|
||||
self.userdb.append((login, uid, passwd))
|
||||
self.save()
|
||||
|
||||
# vim: set sw=4 et:
|
Loading…
Reference in New Issue