mirror of
https://github.com/aljazceru/cowrie.git
synced 2025-12-17 05:54:21 +01:00
cowrie rename
This commit is contained in:
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -1 +1 @@
|
||||
fs.pickle -diff binary
|
||||
data/fs.pickle -diff binary
|
||||
|
||||
8
.gitignore
vendored
8
.gitignore
vendored
@@ -1,5 +1,5 @@
|
||||
kippo.cfg
|
||||
kippo.pid
|
||||
cowrie.cfg
|
||||
cowrie.pid
|
||||
data/lastlog.txt
|
||||
data/ssh_host_dsa_key
|
||||
data/ssh_host_dsa_key.pub
|
||||
@@ -8,13 +8,11 @@ data/ssh_host_rsa_key.pub
|
||||
dl/*
|
||||
log/*
|
||||
log/tty/*
|
||||
kippo-textlog.log
|
||||
cowrie-textlog.log
|
||||
private.key
|
||||
public.key
|
||||
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
|
||||
env/
|
||||
env1/
|
||||
env2/
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* stdin is saved as a file in dl/ when using exec commands
|
||||
to support commands like 'cat >file; ./file'
|
||||
* allow wget download over non-80 port
|
||||
* simple JSON logging to kippo.json
|
||||
* simple JSON logging added
|
||||
* accept log and deny publickey authentication
|
||||
* add uname -r, -m flags
|
||||
* add working sleep command
|
||||
|
||||
20
README.md
20
README.md
@@ -1,7 +1,8 @@
|
||||
# Kippo
|
||||
|
||||
Kippo is a medium interaction SSH honeypot designed to log brute force attacks and, most importantly, the entire shell interaction performed by the attacker.
|
||||
Cowrie is a medium interaction SSH honeypot designed to log brute force attacks and, most importantly, the entire shell interaction performed by the attacker.
|
||||
|
||||
Kippo is directly based on [Kippo] by desaster (http://github.com/desaster/kippo/).
|
||||
Kippo is inspired, but not based on [Kojoney](http://kojoney.sourceforge.net/).
|
||||
|
||||
## Features
|
||||
@@ -10,7 +11,7 @@ Some interesting features:
|
||||
* Fake filesystem with the ability to add/remove files. A full fake filesystem resembling a Debian 5.0 installation is included
|
||||
* Possibility of adding fake file contents so the attacker can 'cat' files such as /etc/passwd. Only minimal file contents are included
|
||||
* Session logs stored in an [UML Compatible](http://user-mode-linux.sourceforge.net/) format for easy replay with original timings
|
||||
* Kippo saves files downloaded with wget or uploaded with SFTP for later inspection
|
||||
* Kippo saves files downloaded with wget/curl or uploaded with SFTP and scp for later inspection
|
||||
|
||||
## Requirements
|
||||
|
||||
@@ -27,24 +28,25 @@ See Wiki for some installation instructions.
|
||||
|
||||
## How to run it?
|
||||
|
||||
Edit kippo.cfg to your liking and start the honeypot by running:
|
||||
Edit cowrie.cfg to your liking and start the honeypot by running:
|
||||
|
||||
`./start.sh`
|
||||
|
||||
start.sh is a simple shell script that runs Kippo in the background using twistd. Detailed startup options can be given by running twistd manually. For example, to run Kippo in foreground:
|
||||
start.sh is a simple shell script that runs Cowrie in the background using twistd. Detailed startup options can be given by running twistd manually. For example, to run Cowrie in foreground:
|
||||
|
||||
`twistd -y kippo.tac -n`
|
||||
`twistd -y cowrie.tac -n`
|
||||
|
||||
By default Kippo listens for ssh connections on port 2222. You can change this, but do not change it to 22 as it requires root privileges. Use port forwarding instead. (More info: [MakingKippoReachable](https://github.com/desaster/kippo/wiki/Making-Kippo-Reachable)).
|
||||
By default Cowrie listens for ssh connections on port 2222. You can change this, but do not change it to 22 as it requires root privileges. Use port forwarding instead. (More info: [MakingKippoReachable](https://github.com/desaster/kippo/wiki/Making-Kippo-Reachable)).
|
||||
|
||||
Files of interest:
|
||||
|
||||
* dl/ - files downloaded with wget are stored here
|
||||
* log/kippo.log - log/debug output
|
||||
* log/cowrie.log - log/debug output
|
||||
* log/cowrie.json - transaction output in JSON format
|
||||
* log/tty/ - session logs
|
||||
* utils/playlog.py - utility to replay session logs
|
||||
* utils/createfs.py - used to create fs.pickle
|
||||
* fs.pickle - fake filesystem
|
||||
* data/fs.pickle - fake filesystem
|
||||
* honeyfs/ - file contents for the fake filesystem - feel free to copy a real system here
|
||||
|
||||
## Is it secure?
|
||||
@@ -53,4 +55,4 @@ Maybe. See [FAQ](https://github.com/desaster/kippo/wiki/FAQ)
|
||||
|
||||
## I have some questions!
|
||||
|
||||
Please visit https://github.com/micheloosterhof/kippo/issues
|
||||
Please visit https://github.com/micheloosterhof/cowrie/issues
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#
|
||||
# Kippo configuration file (kippo.cfg)
|
||||
# Cowrie configuration file (cowrie.cfg)
|
||||
#
|
||||
|
||||
[honeypot]
|
||||
|
||||
# Sensor name use to identify this kippo instance. Used by the database
|
||||
# Sensor name use to identify this cowrie instance. Used by the database
|
||||
# logging modules such as mysql.
|
||||
#
|
||||
# If not specified, the logging modules will instead use the IP address of the
|
||||
@@ -71,7 +71,7 @@ data_path = data
|
||||
|
||||
# Class that implements the checklogin() method.
|
||||
#
|
||||
# Class must be defined in kippo/core/auth.py
|
||||
# Class must be defined in cowrie/core/auth.py
|
||||
# Default is the 'UserDB' class which uses the password database.
|
||||
#
|
||||
# Alternatively the 'AuthRandom' class can be used, which will let
|
||||
@@ -134,7 +134,7 @@ sftp_enabled = true
|
||||
#fake_addr = 192.168.66.254
|
||||
|
||||
# The IP address on which this machine reachable on from the internet.
|
||||
# Useful if you use portforwarding or other mechanisms. If empty, the kippo
|
||||
# Useful if you use portforwarding or other mechanisms. If empty, the cowrie
|
||||
# will determine by itself. Used in 'netstat' output
|
||||
#internet_facing_ip = 9.9.9.9
|
||||
|
||||
@@ -195,8 +195,8 @@ interact_port = 5123
|
||||
|
||||
#[database_mysql]
|
||||
#host = localhost
|
||||
#database = kippo
|
||||
#username = kippo
|
||||
#database = cowrie
|
||||
#username = cowrie
|
||||
#password = secret
|
||||
#port = 3306
|
||||
|
||||
@@ -213,33 +213,28 @@ interact_port = 5123
|
||||
#user = anonymous@sensors.carnivore.it
|
||||
#password = anonymous
|
||||
#muc = dionaea.sensors.carnivore.it
|
||||
#signal_createsession = kippo-events
|
||||
#signal_connectionlost = kippo-events
|
||||
#signal_loginfailed = kippo-events
|
||||
#signal_loginsucceeded = kippo-events
|
||||
#signal_command = kippo-events
|
||||
#signal_clientversion = kippo-events
|
||||
#signal_createsession = cowrie-events
|
||||
#signal_connectionlost = cowrie-events
|
||||
#signal_loginfailed = cowrie-events
|
||||
#signal_loginsucceeded = cowrie-events
|
||||
#signal_command = cowrie-events
|
||||
#signal_clientversion = cowrie-events
|
||||
#debug=true
|
||||
|
||||
# Text based logging module
|
||||
#
|
||||
# While this is a database logging module, it actually just creates a simple
|
||||
# text based log. This may not have much purpose, if you're fine with the
|
||||
# default text based logs generated by kippo in log/
|
||||
# default text based logs generated by cowrie in log/
|
||||
#
|
||||
# To enable this module, remove the comments below, including the
|
||||
# [database_textlog] line.
|
||||
|
||||
#[database_textlog]
|
||||
#logfile = log/kippo-textlog.log
|
||||
#logfile = log/cowrie-textlog.log
|
||||
|
||||
# deprecated JSON based logging module
|
||||
#[database_jsonlog]
|
||||
#logfile = log/kippolog.json
|
||||
|
||||
# new default output module
|
||||
[output_jsonlog]
|
||||
logfile = log/kippo.json
|
||||
# JSON output module [output_jsonlog]
|
||||
logfile = log/cowrie.json
|
||||
|
||||
#[database_hpfeeds]
|
||||
#server = hpfeeds.mysite.org
|
||||
@@ -13,17 +13,17 @@ from twisted.cred import portal
|
||||
from twisted.conch.ssh import factory, keys
|
||||
|
||||
if os.name == 'posix' and os.getuid() == 0:
|
||||
print 'ERROR: You must not run kippo as root!'
|
||||
print 'ERROR: You must not run cowrie as root!'
|
||||
sys.exit(1)
|
||||
|
||||
if not os.path.exists('kippo.cfg'):
|
||||
print 'ERROR: kippo.cfg is missing!'
|
||||
if not os.path.exists('cowrie.cfg'):
|
||||
print 'ERROR: cowrie.cfg is missing!'
|
||||
sys.exit(1)
|
||||
|
||||
from kippo.core.config import config
|
||||
import kippo.core.honeypot
|
||||
import kippo.core.ssh
|
||||
from kippo import core
|
||||
from cowrie.core.config import config
|
||||
import cowrie.core.honeypot
|
||||
import cowrie.core.ssh
|
||||
from cowrie import core
|
||||
|
||||
factory = core.ssh.HoneyPotSSHFactory()
|
||||
factory.portal = portal.Portal(core.ssh.HoneyPotRealm())
|
||||
@@ -66,7 +66,7 @@ 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'))
|
||||
from kippo.core import interact
|
||||
from cowrie.core import interact
|
||||
service = internet.TCPServer(iport, interact.makeInteractFactory(factory))
|
||||
service.setServiceParent(application)
|
||||
|
||||
@@ -5,7 +5,7 @@ import random
|
||||
|
||||
from twisted.internet import reactor
|
||||
|
||||
from kippo.core.honeypot import HoneyPotCommand
|
||||
from cowrie.core.honeypot import HoneyPotCommand
|
||||
|
||||
commands = {}
|
||||
|
||||
@@ -7,7 +7,7 @@ import re
|
||||
from twisted.internet import reactor, defer
|
||||
from twisted.internet.defer import inlineCallbacks
|
||||
|
||||
from kippo.core.honeypot import HoneyPotCommand
|
||||
from cowrie.core.honeypot import HoneyPotCommand
|
||||
|
||||
commands = {}
|
||||
|
||||
@@ -7,10 +7,10 @@ import datetime
|
||||
from twisted.internet import reactor
|
||||
from twisted.python import log
|
||||
|
||||
from kippo.core.honeypot import HoneyPotCommand
|
||||
from kippo.core.config import config
|
||||
from kippo.core.auth import UserDB
|
||||
from kippo.core import utils
|
||||
from cowrie.core.honeypot import HoneyPotCommand
|
||||
from cowrie.core.config import config
|
||||
from cowrie.core.auth import UserDB
|
||||
from cowrie.core import utils
|
||||
|
||||
commands = {}
|
||||
|
||||
@@ -15,8 +15,8 @@ from twisted.web import client
|
||||
from twisted.internet import reactor
|
||||
from twisted.python import log
|
||||
|
||||
from kippo.core.honeypot import HoneyPotCommand
|
||||
from kippo.core.fs import *
|
||||
from cowrie.core.honeypot import HoneyPotCommand
|
||||
from cowrie.core.fs import *
|
||||
|
||||
commands = {}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
# Random commands when running new executables
|
||||
|
||||
from kippo.core.honeypot import HoneyPotCommand
|
||||
from cowrie.core.honeypot import HoneyPotCommand
|
||||
|
||||
commands = {}
|
||||
clist = []
|
||||
@@ -5,8 +5,8 @@ import os
|
||||
import getopt
|
||||
import copy
|
||||
|
||||
from kippo.core.honeypot import HoneyPotCommand
|
||||
from kippo.core.fs import *
|
||||
from cowrie.core.honeypot import HoneyPotCommand
|
||||
from cowrie.core.fs import *
|
||||
|
||||
commands = {}
|
||||
|
||||
@@ -7,7 +7,7 @@ import random
|
||||
|
||||
from twisted.internet import reactor
|
||||
|
||||
from kippo.core.honeypot import HoneyPotCommand
|
||||
from cowrie.core.honeypot import HoneyPotCommand
|
||||
|
||||
commands = {}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import optparse
|
||||
|
||||
from kippo.core.honeypot import HoneyPotCommand
|
||||
from cowrie.core.honeypot import HoneyPotCommand
|
||||
|
||||
commands = {}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# Copyright (c) 2009 Upi Tamminen <desaster@gmail.com>
|
||||
# See the COPYRIGHT file for more information
|
||||
|
||||
from kippo.core.honeypot import HoneyPotCommand
|
||||
from kippo.core.fs import *
|
||||
from kippo.core.config import config
|
||||
from kippo.core import utils
|
||||
from cowrie.core.honeypot import HoneyPotCommand
|
||||
from cowrie.core.fs import *
|
||||
from cowrie.core.config import config
|
||||
from cowrie.core import utils
|
||||
|
||||
commands = {}
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
import stat
|
||||
import time
|
||||
|
||||
from kippo.core.honeypot import HoneyPotCommand
|
||||
from kippo.core.fs import *
|
||||
from cowrie.core.honeypot import HoneyPotCommand
|
||||
from cowrie.core.fs import *
|
||||
|
||||
commands = {}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
# Commands mapped to common malware
|
||||
|
||||
from kippo.core.honeypot import HoneyPotCommand
|
||||
from cowrie.core.honeypot import HoneyPotCommand
|
||||
|
||||
commands = {}
|
||||
clist = {} # names
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import socket
|
||||
|
||||
from kippo.core.honeypot import HoneyPotCommand
|
||||
from cowrie.core.honeypot import HoneyPotCommand
|
||||
|
||||
commands = {}
|
||||
|
||||
@@ -8,7 +8,7 @@ import socket
|
||||
|
||||
from twisted.internet import reactor
|
||||
|
||||
from kippo.core.honeypot import HoneyPotCommand
|
||||
from cowrie.core.honeypot import HoneyPotCommand
|
||||
|
||||
commands = {}
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
import getopt
|
||||
|
||||
from kippo.core.honeypot import HoneyPotCommand
|
||||
from cowrie.core.honeypot import HoneyPotCommand
|
||||
|
||||
commands = {}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
from twisted.internet import reactor
|
||||
|
||||
from kippo.core.honeypot import HoneyPotCommand
|
||||
from cowrie.core.honeypot import HoneyPotCommand
|
||||
|
||||
commands = {}
|
||||
|
||||
@@ -10,7 +10,7 @@ import socket
|
||||
from twisted.python import log
|
||||
from twisted.internet import reactor
|
||||
|
||||
from kippo.core.honeypot import HoneyPotCommand
|
||||
from cowrie.core.honeypot import HoneyPotCommand
|
||||
|
||||
commands = {}
|
||||
|
||||
@@ -7,9 +7,9 @@ import os
|
||||
|
||||
from twisted.python import log
|
||||
|
||||
from kippo.core.honeypot import HoneyPotCommand
|
||||
from kippo.core.fs import *
|
||||
from kippo.commands import dice, malware
|
||||
from cowrie.core.honeypot import HoneyPotCommand
|
||||
from cowrie.core.fs import *
|
||||
from cowrie.commands import dice, malware
|
||||
|
||||
commands = {}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#
|
||||
|
||||
from kippo.core.honeypot import HoneyPotCommand
|
||||
from cowrie.core.honeypot import HoneyPotCommand
|
||||
|
||||
commands = {}
|
||||
|
||||
@@ -13,8 +13,8 @@ from twisted.web import client
|
||||
from twisted.internet import reactor
|
||||
from twisted.python import log
|
||||
|
||||
from kippo.core.honeypot import HoneyPotCommand
|
||||
from kippo.core.fs import *
|
||||
from cowrie.core.honeypot import HoneyPotCommand
|
||||
from cowrie.core.fs import *
|
||||
|
||||
commands = {}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Copyright (c) 2013 Bas Stottelaar <basstottelaar [AT] gmail [DOT] com>
|
||||
|
||||
from kippo.core.honeypot import HoneyPotCommand
|
||||
from cowrie.core.honeypot import HoneyPotCommand
|
||||
|
||||
commands = {}
|
||||
|
||||
@@ -64,7 +64,7 @@ class UserDB(object):
|
||||
save the user db
|
||||
"""
|
||||
|
||||
# Note: this is subject to races between kippo instances, but hey ...
|
||||
# Note: this is subject to races between cowrie instances, but hey ...
|
||||
f = open(self.userdb_file, 'w')
|
||||
for (login, uid, passwd) in self.userdb:
|
||||
f.write('%s:%d:%s\n' % (login, uid, passwd))
|
||||
@@ -154,7 +154,7 @@ class AuthRandom(object):
|
||||
def savevars(self):
|
||||
# Save the user vars to json file
|
||||
data = self.uservar
|
||||
# Note: this is subject to races between kippo logins
|
||||
# Note: this is subject to races between cowrie logins
|
||||
with open(self.uservar_file, 'wb') as fp:
|
||||
json.dump(data, fp)
|
||||
|
||||
@@ -6,7 +6,7 @@ import ConfigParser
|
||||
|
||||
def config():
|
||||
cfg = ConfigParser.ConfigParser()
|
||||
for f in ('kippo.cfg', '/etc/kippo/kippo.cfg', '/etc/kippo.cfg'):
|
||||
for f in ('cowrie.cfg', '/etc/cowrie/cowrie.cfg', '/etc/cowrie.cfg'):
|
||||
if os.path.exists(f):
|
||||
cfg.read(f)
|
||||
return cfg
|
||||
@@ -34,7 +34,7 @@ from twisted.internet import defer
|
||||
|
||||
MSG_CHANNEL_SUCCESS = 99
|
||||
|
||||
class KippoSSHConnection(connection.SSHConnection):
|
||||
class CowrieSSHConnection(connection.SSHConnection):
|
||||
"""
|
||||
Subclass this for a workaround for the Granados SSH library.
|
||||
Channel request for openshell needs to return success immediatly
|
||||
@@ -256,9 +256,9 @@ class HoneyPotEnvironment(object):
|
||||
def __init__(self):
|
||||
self.cfg = config()
|
||||
self.commands = {}
|
||||
import kippo.commands
|
||||
for c in kippo.commands.__all__:
|
||||
module = __import__('kippo.commands.%s' % c,
|
||||
import cowrie.commands
|
||||
for c in cowrie.commands.__all__:
|
||||
module = __import__('cowrie.commands.%s' % c,
|
||||
globals(), locals(), ['commands'])
|
||||
self.commands.update(module.commands)
|
||||
self.fs = pickle.load(file(
|
||||
@@ -20,7 +20,7 @@ class Interact(telnet.Telnet):
|
||||
self.requestNegotiation(telnet.LINEMODE, telnet.LINEMODE_EDIT + '\0')
|
||||
self.will(telnet.ECHO)
|
||||
|
||||
self.transport.write('*** kippo session management console ***\r\n')
|
||||
self.transport.write('*** cowrie session management console ***\r\n')
|
||||
self.cmd_help()
|
||||
|
||||
def connectionLost(self, reason):
|
||||
@@ -49,7 +49,7 @@ import uuid
|
||||
|
||||
class Output(object):
|
||||
"""
|
||||
This is the abstract base class intended to be inherited by kippo output plugins
|
||||
This is the abstract base class intended to be inherited by cowrie output plugins
|
||||
Plugins require the mandatory methods: stop, start and write
|
||||
"""
|
||||
|
||||
@@ -78,7 +78,7 @@ class HoneyPotSSHUserAuthServer(userauth.SSHUserAuthServer):
|
||||
class HoneyPotSSHFactory(factory.SSHFactory):
|
||||
services = {
|
||||
'ssh-userauth': HoneyPotSSHUserAuthServer,
|
||||
'ssh-connection': connection.KippoSSHConnection,
|
||||
'ssh-connection': connection.CowrieSSHConnection,
|
||||
}
|
||||
|
||||
# Special delivery to the loggers to avoid scope problems
|
||||
@@ -113,7 +113,7 @@ class HoneyPotSSHFactory(factory.SSHFactory):
|
||||
lcfg.set('honeypot', i, cfg.get('honeypot', i))
|
||||
log.msg('Loading dblog engine: %s' % (engine,))
|
||||
dblogger = __import__(
|
||||
'kippo.dblog.%s' % (engine,),
|
||||
'cowrie.dblog.%s' % (engine,),
|
||||
globals(), locals(), ['dblog']).DBLogger(lcfg)
|
||||
log.startLoggingWithObserver(dblogger.emit, setStdout=False)
|
||||
self.dbloggers.append(dblogger)
|
||||
@@ -134,7 +134,7 @@ class HoneyPotSSHFactory(factory.SSHFactory):
|
||||
lcfg.set('honeypot', i, cfg.get('honeypot', i))
|
||||
log.msg('Loading output engine: %s' % (engine,))
|
||||
output = __import__(
|
||||
'kippo.output.%s' % (engine,)
|
||||
'cowrie.output.%s' % (engine,)
|
||||
,globals(), locals(), ['output']).Output(lcfg)
|
||||
log.startLoggingWithObserver(output.emit, setStdout=False)
|
||||
self.output_plugins.append(output)
|
||||
@@ -196,7 +196,7 @@ class HoneyPotRealm:
|
||||
else:
|
||||
raise Exception("No supported interfaces found.")
|
||||
|
||||
class HoneyPotTransport(sshserver.KippoSSHServerTransport):
|
||||
class HoneyPotTransport(sshserver.CowrieSSHServerTransport):
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -210,16 +210,16 @@ class HoneyPotTransport(sshserver.KippoSSHServerTransport):
|
||||
dst_ip=self.transport.getHost().host, dst_port=self.transport.getHost().port,
|
||||
sessionno=self.transport.sessionno)
|
||||
|
||||
sshserver.KippoSSHServerTransport.connectionMade(self)
|
||||
sshserver.CowrieSSHServerTransport.connectionMade(self)
|
||||
|
||||
def sendKexInit(self):
|
||||
# Don't send key exchange prematurely
|
||||
if not self.gotVersion:
|
||||
return
|
||||
sshserver.KippoSSHServerTransport.sendKexInit(self)
|
||||
sshserver.CowrieSSHServerTransport.sendKexInit(self)
|
||||
|
||||
def dataReceived(self, data):
|
||||
sshserver.KippoSSHServerTransport.dataReceived(self, data)
|
||||
sshserver.CowrieSSHServerTransport.dataReceived(self, data)
|
||||
# later versions seem to call sendKexInit again on their own
|
||||
if twisted.version.major < 11 and \
|
||||
not self._hadVersion and self.gotVersion:
|
||||
@@ -241,7 +241,7 @@ class HoneyPotTransport(sshserver.KippoSSHServerTransport):
|
||||
kexAlgs=kexAlgs, keyAlgs=keyAlgs, encCS=encCS, macCS=macCS,
|
||||
compCS=compCS, format='Remote SSH version: %(version)s')
|
||||
|
||||
return sshserver.KippoSSHServerTransport.ssh_KEXINIT(self, packet)
|
||||
return sshserver.CowrieSSHServerTransport.ssh_KEXINIT(self, packet)
|
||||
|
||||
# this seems to be the only reliable place of catching lost connection
|
||||
def connectionLost(self, reason):
|
||||
@@ -249,7 +249,7 @@ class HoneyPotTransport(sshserver.KippoSSHServerTransport):
|
||||
i.sessionClosed()
|
||||
if self.transport.sessionno in self.factory.sessions:
|
||||
del self.factory.sessions[self.transport.sessionno]
|
||||
sshserver.KippoSSHServerTransport.connectionLost(self, reason)
|
||||
sshserver.CowrieSSHServerTransport.connectionLost(self, reason)
|
||||
log.msg(eventid='KIPP0011', format='Connection lost')
|
||||
|
||||
class HoneyPotSSHSession(session.SSHSession):
|
||||
@@ -310,7 +310,7 @@ class HoneyPotAvatar(avatar.ConchUser):
|
||||
self.protocol = None
|
||||
|
||||
self.channelLookup.update({'session': HoneyPotSSHSession})
|
||||
self.channelLookup['direct-tcpip'] = KippoOpenConnectForwardingClient
|
||||
self.channelLookup['direct-tcpip'] = CowrieOpenConnectForwardingClient
|
||||
|
||||
# sftp support enabled only when option is explicitly set
|
||||
if self.env.cfg.has_option('honeypot', 'sftp_enabled'):
|
||||
@@ -416,7 +416,7 @@ def getDSAKeys():
|
||||
return publicKeyString, privateKeyString
|
||||
|
||||
@implementer(conchinterfaces.ISFTPFile)
|
||||
class KippoSFTPFile:
|
||||
class CowrieSFTPFile:
|
||||
|
||||
def __init__(self, server, filename, flags, attrs):
|
||||
self.server = server
|
||||
@@ -472,7 +472,7 @@ class KippoSFTPFile:
|
||||
def setAttrs(self, attrs):
|
||||
raise NotImplementedError
|
||||
|
||||
class KippoSFTPDirectory:
|
||||
class CowrieSFTPDirectory:
|
||||
|
||||
def __init__(self, server, directory):
|
||||
self.server = server
|
||||
@@ -497,7 +497,7 @@ class KippoSFTPDirectory:
|
||||
self.files = []
|
||||
|
||||
@implementer(conchinterfaces.ISFTPServer)
|
||||
class KippoSFTPServer:
|
||||
class CowrieSFTPServer:
|
||||
|
||||
def __init__(self, avatar):
|
||||
self.avatar = avatar
|
||||
@@ -530,7 +530,7 @@ class KippoSFTPServer:
|
||||
|
||||
def openFile(self, filename, flags, attrs):
|
||||
log.msg("SFTP openFile: %s" % filename)
|
||||
return KippoSFTPFile(self, self._absPath(filename), flags, attrs)
|
||||
return CowrieSFTPFile(self, self._absPath(filename), flags, attrs)
|
||||
|
||||
def removeFile(self, filename):
|
||||
log.msg("SFTP removeFile: %s" % filename)
|
||||
@@ -553,7 +553,7 @@ class KippoSFTPServer:
|
||||
|
||||
def openDirectory(self, path):
|
||||
log.msg("SFTP OpenDirectory: %s" % path)
|
||||
return KippoSFTPDirectory(self, self._absPath(path))
|
||||
return CowrieSFTPDirectory(self, self._absPath(path))
|
||||
|
||||
def getAttrs(self, path, followLinks):
|
||||
log.msg("SFTP getAttrs: %s" % path)
|
||||
@@ -587,17 +587,17 @@ class KippoSFTPServer:
|
||||
def extendedRequest(self, extName, extData):
|
||||
raise NotImplementedError
|
||||
|
||||
components.registerAdapter(KippoSFTPServer, HoneyPotAvatar, conchinterfaces.ISFTPServer)
|
||||
components.registerAdapter(CowrieSFTPServer, HoneyPotAvatar, conchinterfaces.ISFTPServer)
|
||||
|
||||
def KippoOpenConnectForwardingClient(remoteWindow, remoteMaxPacket, data, avatar):
|
||||
def CowrieOpenConnectForwardingClient(remoteWindow, remoteMaxPacket, data, avatar):
|
||||
remoteHP, origHP = twisted.conch.ssh.forwarding.unpackOpen_direct_tcpip(data)
|
||||
log.msg("direct-tcp connection attempt to %s:%i" % remoteHP)
|
||||
return KippoConnectForwardingChannel(remoteHP,
|
||||
return CowrieConnectForwardingChannel(remoteHP,
|
||||
remoteWindow=remoteWindow,
|
||||
remoteMaxPacket=remoteMaxPacket,
|
||||
avatar=avatar)
|
||||
|
||||
class KippoConnectForwardingChannel(forwarding.SSHConnectForwardingChannel):
|
||||
class CowrieConnectForwardingChannel(forwarding.SSHConnectForwardingChannel):
|
||||
|
||||
def channelOpen(self, specificData):
|
||||
log.msg("Faking channel open %s:%i" % self.hostport)
|
||||
@@ -29,7 +29,7 @@
|
||||
from twisted.conch.ssh import transport
|
||||
from twisted.python import log
|
||||
|
||||
class KippoSSHServerTransport(transport.SSHServerTransport):
|
||||
class CowrieSSHServerTransport(transport.SSHServerTransport):
|
||||
def connectionMade(self):
|
||||
"""
|
||||
Called when the connection is made to the other side. We sent our
|
||||
@@ -1,6 +1,6 @@
|
||||
## From https://github.com/threatstream/kippo/blob/master/kippo/dblog/hpfeeds.py
|
||||
|
||||
from kippo.core import dblog
|
||||
from cowrie.core import dblog
|
||||
from twisted.python import log
|
||||
from datetime import datetime
|
||||
|
||||
@@ -28,7 +28,7 @@ SIZES = {
|
||||
OP_SUBSCRIBE: 5+256*2,
|
||||
}
|
||||
|
||||
KIPPOCHAN = 'kippo.sessions'
|
||||
KIPPOCHAN = 'cowrie.sessions'
|
||||
|
||||
class BadClient(Exception):
|
||||
pass
|
||||
@@ -1,4 +1,4 @@
|
||||
from kippo.core import dblog
|
||||
from cowrie.core import dblog
|
||||
from twisted.enterprise import adbapi
|
||||
from twisted.internet import defer
|
||||
from twisted.python import log
|
||||
@@ -3,7 +3,7 @@
|
||||
# ..so not exactly a dblog.
|
||||
#
|
||||
|
||||
from kippo.core import dblog
|
||||
from cowrie.core import dblog
|
||||
import time
|
||||
import uuid
|
||||
|
||||
@@ -45,7 +45,7 @@ class XMPPLoggerProtocol(muc.MUCClient):
|
||||
from twisted.application import service
|
||||
from twisted.words.protocols.jabber import jid
|
||||
from wokkel.client import XMPPClient
|
||||
from kippo.core import dblog
|
||||
from cowrie.core import dblog
|
||||
from twisted.words.xish import domish
|
||||
|
||||
class DBLogger(dblog.DBLogger):
|
||||
@@ -1,11 +1,11 @@
|
||||
To create additional output plugins, place Python modules in this directory.
|
||||
|
||||
Plugins need to subclass kippo.core.output.Output and define at least the
|
||||
Plugins need to subclass cowrie.core.output.Output and define at least the
|
||||
methods 'start', 'stop' and 'handleLog'
|
||||
|
||||
import kippo.core.output
|
||||
import cowrie.core.output
|
||||
|
||||
class Output(kippo.core.output.Output):
|
||||
class Output(cowrie.core.output.Output):
|
||||
|
||||
def start(self, cfg):
|
||||
|
||||
@@ -31,12 +31,12 @@ import os
|
||||
|
||||
import twisted.python.logfile
|
||||
|
||||
import kippo.core.output
|
||||
import cowrie.core.output
|
||||
|
||||
class Output(kippo.core.output.Output):
|
||||
class Output(cowrie.core.output.Output):
|
||||
|
||||
def __init__(self, cfg):
|
||||
kippo.core.output.Output.__init__(self, cfg)
|
||||
cowrie.core.output.Output.__init__(self, cfg)
|
||||
fn = cfg.get('output_jsonlog', 'logfile')
|
||||
dirs = os.path.dirname(fn)
|
||||
base = os.path.basename(fn)
|
||||
@@ -1,102 +0,0 @@
|
||||
# Copyright (c) 2015 Michel Oosterhof <michel@oosterhof.net>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. The names of the author(s) may not be used to endorse or promote
|
||||
# products derived from this software without specific prior written
|
||||
# permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
|
||||
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
|
||||
import datetime
|
||||
import uuid
|
||||
import json
|
||||
|
||||
from ..core import dblog
|
||||
|
||||
class DBLogger(dblog.DBLogger):
|
||||
|
||||
def __init__(self, cfg):
|
||||
self.sensor = ""
|
||||
self.outfile = ""
|
||||
dblog.DBLogger.__init__(self, cfg)
|
||||
|
||||
def start(self, cfg):
|
||||
self.outfile = file(cfg.get('database_jsonlog', 'logfile'), 'a')
|
||||
|
||||
def write(self, session, logentry):
|
||||
_meta = {
|
||||
'session' : session,
|
||||
'sensor' : self.sensor,
|
||||
'timestamp' : datetime.datetime.utcnow().isoformat() + 'Z'
|
||||
}
|
||||
logentry.update( _meta )
|
||||
json.dump( logentry, self.outfile )
|
||||
self.outfile.write( '\n' )
|
||||
self.outfile.flush()
|
||||
|
||||
def createSession(self, peerIP, peerPort, hostIP, hostPort):
|
||||
sid = uuid.uuid4().hex
|
||||
logentry = { 'message' : 'New connection: %s:%s' % (peerIP, peerPort), 'src_ip' : peerIP }
|
||||
self.sensor = self.getSensor() or hostIP
|
||||
self.write(sid, logentry )
|
||||
return sid
|
||||
|
||||
def handleConnectionLost(self, session, args):
|
||||
logentry = { 'message': 'Connection lost' }
|
||||
self.write( session, logentry )
|
||||
#ttylog = self.ttylog(session)
|
||||
#if ttylog:
|
||||
# self.write( session, { 'message': repr(ttylog) } )
|
||||
|
||||
def handleLoginFailed(self, session, args):
|
||||
logentry = { 'message' : 'Login failed [%s/%s]' % (args['username'], args['password']), 'username' : args['username'], 'password' : args['password'] }
|
||||
self.write( session, logentry )
|
||||
|
||||
def handleLoginSucceeded(self, session, args):
|
||||
logentry = { 'message' : 'Login succeeded [%s/%s]' % (args['username'], args['password']), 'username' : args['username'], 'password' : args['password'] }
|
||||
self.write( session, logentry )
|
||||
|
||||
def handleCommand(self, session, args):
|
||||
logentry = { 'message' : 'command [%s]' % (args['input'],), 'command' : args['input'] }
|
||||
self.write( session, logentry )
|
||||
|
||||
def handleUnknownCommand(self, session, args):
|
||||
logentry = { 'message' : 'unknown command [%s]' % (args['input'],), 'command' : args['input'] }
|
||||
self.write( session, logentry )
|
||||
|
||||
def handleInput(self, session, args):
|
||||
logentry = { 'message' : 'input [%s] @%s' % (args['input'], args['realm']), 'command' : args['input'] }
|
||||
self.write( session, logentry )
|
||||
|
||||
def handleTerminalSize(self, session, args):
|
||||
logentry = { 'message' : 'Terminal size: %sx%s' % (args['width'], args['height']) }
|
||||
self.write( session, logentry )
|
||||
|
||||
def handleClientVersion(self, session, args):
|
||||
logentry = { 'message' : 'Client version: [%s]' % (args['version']), 'client' : args['version'] }
|
||||
self.write( session, logentry )
|
||||
|
||||
def handleFileDownload(self, session, args):
|
||||
logentry = { 'message' : 'File download: [%s] -> %s' % (args['url'], args['outfile']), 'url' : args['url'], 'shasum' : args['shasum'] }
|
||||
self.write( session, logentry )
|
||||
|
||||
# vim: set sw=4 et:
|
||||
4
start.sh
4
start.sh
@@ -24,5 +24,5 @@ then
|
||||
. $VENV/bin/activate
|
||||
fi
|
||||
|
||||
echo "Starting kippo in the background..."
|
||||
twistd -y kippo.tac -l log/kippo.log --pidfile kippo.pid
|
||||
echo "Starting cowrie in the background..."
|
||||
twistd -y cowrie.tac -l log/cowrie.log --pidfile cowrie.pid
|
||||
|
||||
4
stop.sh
4
stop.sh
@@ -1,12 +1,12 @@
|
||||
#!/bin/sh
|
||||
|
||||
PIDFILE=kippo.pid
|
||||
PIDFILE=cowrie.pid
|
||||
|
||||
cd $(dirname $0)
|
||||
|
||||
PID=$(cat $PIDFILE 2>/dev/null)
|
||||
|
||||
if [ -n "$PID" ]; then
|
||||
echo "Stopping kippo...\n"
|
||||
echo "Stopping cowrie...\n"
|
||||
kill -TERM $PID
|
||||
fi
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# How to process Kippo output in an ELK stack
|
||||
# How to process Cowrie output in an ELK stack
|
||||
|
||||
(Note: work in progress, instructions are not verified)
|
||||
|
||||
|
||||
## Prerequisites
|
||||
|
||||
* Working Kippo installation
|
||||
* Kippo JSON log file (enable database json in kippo.cfg)
|
||||
* Working Cowrie installation
|
||||
* Cowrie JSON log file (enable database json in cowrie.cfg)
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -40,7 +40,7 @@ wget http://download.maxmind.com/download/geoip/database/asnum/GeoIPASNum.dat.gz
|
||||
* Configure logstash
|
||||
|
||||
```
|
||||
cp logstash-kippo.conf /etc/logstash/conf.d
|
||||
cp logstash-cowrie.conf /etc/logstash/conf.d
|
||||
```
|
||||
|
||||
* Make sure the configuration file is correct. Check the input section (path), filter (geoip databases) and output (elasticsearch hostname)
|
||||
@@ -54,13 +54,13 @@ service logstash restart
|
||||
* To test whether logstash is working correctly, check the file in /tmp
|
||||
|
||||
```
|
||||
tail /tmp/kippo-logstash.log
|
||||
tail /tmp/cowrie-logstash.log
|
||||
```
|
||||
|
||||
* To test whether data is loaded into ElasticSearch, run the following query:
|
||||
|
||||
```
|
||||
http://<hostname>:9200/_search?q=kippo&size=5
|
||||
http://<hostname>:9200/_search?q=cowrie&size=5
|
||||
```
|
||||
|
||||
* If this gives output, your data is correctly loaded into ElasticSearch
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"title": "Kippo2ElasticSearch",
|
||||
"title": "Cowrie2ElasticSearch",
|
||||
"services": {
|
||||
"query": {
|
||||
"list": {
|
||||
@@ -22,7 +22,7 @@
|
||||
"0": {
|
||||
"type": "terms",
|
||||
"field": "_type",
|
||||
"value": "kippo",
|
||||
"value": "cowrie",
|
||||
"mandate": "must",
|
||||
"active": true,
|
||||
"alias": "",
|
||||
@@ -1,19 +1,19 @@
|
||||
input {
|
||||
# this is the actual live log file to monitor
|
||||
file {
|
||||
path => ["/home/kippo/kippo-git/log/kippo.json"]
|
||||
path => ["/home/cowrie/cowrie-git/log/cowrie.json"]
|
||||
codec => json_lines
|
||||
type => "kippo"
|
||||
type => "cowrie"
|
||||
}
|
||||
# this is to send old logs to for reprocessing
|
||||
tcp {
|
||||
port => 3333
|
||||
type => "kippo"
|
||||
type => "cowrie"
|
||||
}
|
||||
}
|
||||
|
||||
filter {
|
||||
if [type] == "kippo" {
|
||||
if [type] == "cowrie" {
|
||||
|
||||
json {
|
||||
source => message
|
||||
@@ -51,13 +51,13 @@ filter {
|
||||
}
|
||||
|
||||
output {
|
||||
if [type] == "kippo" {
|
||||
if [type] == "cowrie" {
|
||||
elasticsearch {
|
||||
host => helium
|
||||
protocol => http
|
||||
}
|
||||
file {
|
||||
path => "/tmp/kippo-logstash.log"
|
||||
path => "/tmp/cowrie-logstash.log"
|
||||
codec => json
|
||||
}
|
||||
stdout {
|
||||
@@ -2,14 +2,14 @@
|
||||
|
||||
###############################################################
|
||||
# This program creates a command line interpreter used to edit
|
||||
# kippo file system pickle files.
|
||||
# cowrie file system pickle files.
|
||||
#
|
||||
# It is intended to mimic a basic bash shell and supports relative
|
||||
# file references.
|
||||
#
|
||||
# This isn't meant to build a brand new filesystem. Instead it
|
||||
# should be used to edit existing filesystems such as the default
|
||||
# /opt/kippo/fs.pickle.
|
||||
# /opt/cowrie/data/fs.pickle.
|
||||
#
|
||||
# Donovan Hubbard
|
||||
# Douglas Hubbard
|
||||
@@ -555,18 +555,18 @@ class fseditCmd(cmd.Cmd):
|
||||
def help_about(self):
|
||||
print "Kippo stores information about its file systems in a " + \
|
||||
"series of nested lists. Once the lists are made, they are " + \
|
||||
"stored in a pickle file on the hard drive. Every time kippo " + \
|
||||
"stored in a pickle file on the hard drive. Every time cowrie " + \
|
||||
"gets a new client, it reads from the pickle file and loads " + \
|
||||
"the fake filesystem into memory. By default this file " + \
|
||||
"is /opt/kippo/fs.pickle. Originally the script " + \
|
||||
"/opt/kippo/createfs.py was used to copy the filesystem " + \
|
||||
"is /opt/cowrie/data/fs.pickle. Originally the script " + \
|
||||
"/opt/cowrie/createfs.py was used to copy the filesystem " + \
|
||||
"of the existing computer. However, it quite difficult to " + \
|
||||
"edit the pickle file by hand.\n\nThis script strives to be " + \
|
||||
"a bash-like interface that allows users to modify " + \
|
||||
"existing fs pickle files. It supports many of the " + \
|
||||
"common bash commands and even handles relative file " + \
|
||||
"paths. Keep in mind that you need to restart the " + \
|
||||
"kippo process in order for the new file system to be " + \
|
||||
"cowrie process in order for the new file system to be " + \
|
||||
"reloaded into memory.\n\nDonovan Hubbard, Douglas Hubbard, " + \
|
||||
"March 2013\nVersion 1.0"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user