This commit is contained in:
Michel Oosterhof
2017-02-18 23:35:43 +04:00
9 changed files with 145 additions and 50 deletions

View File

@ -83,6 +83,13 @@ txtcmds_path = txtcmds
#download_limit_size = 10485760 #download_limit_size = 10485760
# TTY logging will log a transcript of the complete terminal interaction in UML
# compatible format.
# (default: true)
ttylog = true
# ============================================================================ # ============================================================================
# Network Specific Options # Network Specific Options
# ============================================================================ # ============================================================================
@ -154,7 +161,8 @@ auth_class = UserDB
# ============================================================================ # ============================================================================
# SSH Specific Options # Historical SSH Specific Options
# historical options in [honeypot] that have not yet been moved to [ssh]
# ============================================================================ # ============================================================================
@ -233,14 +241,23 @@ forward_redirect_25 = 127.0.0.1:12525
forward_redirect_587 = 127.0.0.1:12525 forward_redirect_587 = 127.0.0.1:12525
# ============================================================================
# SSH Specific Options
# ============================================================================
[ssh] [ssh]
# Enable SSH support, enabled by default # Enable SSH support
# (default: true)
enabled = true enabled = true
# Enable SSH direct-tcpip forwarding, enabled by default
# Enable SSH direct-tcpip forwarding
# (default: true)
forwarding = true forwarding = true
# ============================================================================ # ============================================================================
# Telnet Specific Options # Telnet Specific Options
# ============================================================================ # ============================================================================
@ -266,6 +283,7 @@ enabled = false
#reported_port = 23 #reported_port = 23
# ============================================================================ # ============================================================================
# Database logging Specific Options # Database logging Specific Options
# ============================================================================ # ============================================================================

View File

@ -314,7 +314,8 @@ Options: (H) means HTTP/HTTPS only, (F) means FTP only
log.msg("there's no file " + self.safeoutfile) log.msg("there's no file " + self.safeoutfile)
self.exit() self.exit()
shasum = hashlib.sha256(open(self.safeoutfile, 'rb').read()).hexdigest() with open(self.safeoutfile, 'rb') as f:
shasum = hashlib.sha256(f.read()).hexdigest()
hashPath = os.path.join(self.download_path, shasum) hashPath = os.path.join(self.download_path, shasum)
# If we have content already, delete temp file # If we have content already, delete temp file
@ -343,9 +344,7 @@ Options: (H) means HTTP/HTTPS only, (F) means FTP only
# self.safeoutfile = hashPath # self.safeoutfile = hashPath
# Update the honeyfs to point to downloaded file # Update the honeyfs to point to downloaded file
if outfile is not None: self.fs.update_realfile(self.fs.getfile(outfile), hashPath)
f = self.fs.getfile(outfile)
f[A_REALFILE] = hashPath
self.exit() self.exit()

View File

@ -104,6 +104,7 @@ Download a file via FTP
result = self.ftp_download(self.safeoutfile) result = self.ftp_download(self.safeoutfile)
if not result: if not result:
self.safeoutfile = None
self.exit() self.exit()
return return
@ -112,7 +113,8 @@ Download a file via FTP
self.exit() self.exit()
return return
shasum = hashlib.sha256(open(self.safeoutfile, 'rb').read()).hexdigest() with open(self.safeoutfile, 'rb') as f:
shasum = hashlib.sha256(f.read()).hexdigest()
hash_path = os.path.join(self.download_path, shasum) hash_path = os.path.join(self.download_path, shasum)
# If we have content already, delete temp file # If we have content already, delete temp file
@ -120,7 +122,7 @@ Download a file via FTP
os.rename(self.safeoutfile, hash_path) os.rename(self.safeoutfile, hash_path)
else: else:
os.remove(self.safeoutfile) os.remove(self.safeoutfile)
os.symlink( shasum, self.safeoutfile ) log.msg("Not storing duplicate content " + shasum)
log.msg(eventid='cowrie.session.file_download', log.msg(eventid='cowrie.session.file_download',
format='Downloaded URL (%(url)s) with SHA-256 %(shasum)s to %(outfile)s', format='Downloaded URL (%(url)s) with SHA-256 %(shasum)s to %(outfile)s',
@ -128,10 +130,13 @@ Download a file via FTP
outfile=hash_path, outfile=hash_path,
shasum=shasum) shasum=shasum)
# Update the honeyfs to point to downloaded file # Link friendly name to hash
self.fs.mkfile(fakeoutfile, 0, 0, os.path.getsize(hash_path), 33188) os.symlink(shasum, self.safeoutfile)
self.fs.update_realfile(self.fs.getfile(fakeoutfile), hash_path)
self.safeoutfile = None
# Update the honeyfs to point to downloaded file
self.fs.update_realfile(self.fs.getfile(fakeoutfile), hash_path)
self.exit() self.exit()
def ftp_download(self, safeoutfile): def ftp_download(self, safeoutfile):

View File

@ -28,6 +28,8 @@
import getopt import getopt
from twisted.python import log
from cowrie.core.honeypot import HoneyPotCommand from cowrie.core.honeypot import HoneyPotCommand
commands = {} commands = {}

View File

@ -62,8 +62,10 @@ class command_tftp(HoneyPotCommand):
re.sub('[^A-Za-z0-9]', '_', self.file_to_get)) re.sub('[^A-Za-z0-9]', '_', self.file_to_get))
self.safeoutfile = os.path.join(self.download_path, tmp_fname) self.safeoutfile = os.path.join(self.download_path, tmp_fname)
with tftpy.TftpClient(self.hostname, int(self.port)) as tclient: tclient = None
try: try:
tclient = tftpy.TftpClient(self.hostname, int(self.port))
tclient.download(self.file_to_get, self.safeoutfile, progresshook) tclient.download(self.file_to_get, self.safeoutfile, progresshook)
self.file_to_get = self.fs.resolve_path(self.file_to_get, self.protocol.cwd) self.file_to_get = self.fs.resolve_path(self.file_to_get, self.protocol.cwd)
if hasattr(tclient.context, 'metrics'): if hasattr(tclient.context, 'metrics'):
@ -72,7 +74,8 @@ class command_tftp(HoneyPotCommand):
self.fs.mkfile(self.file_to_get, 0, 0, 0, 33188) self.fs.mkfile(self.file_to_get, 0, 0, 0, 33188)
self.fs.update_realfile(self.fs.getfile(self.file_to_get), self.safeoutfile) self.fs.update_realfile(self.fs.getfile(self.file_to_get), self.safeoutfile)
except tftpy.TftpException, err: except tftpy.TftpException, err:
pass if tclient and tclient.context and not tclient.context.fileobj.closed:
tclient.context.fileobj.close()
if os.path.exists(self.safeoutfile): if os.path.exists(self.safeoutfile):
@ -103,11 +106,11 @@ class command_tftp(HoneyPotCommand):
# Link friendly name to hash # Link friendly name to hash
os.symlink(shasum, self.safeoutfile) os.symlink(shasum, self.safeoutfile)
self.safeoutfile = None
# Update the honeyfs to point to downloaded file # Update the honeyfs to point to downloaded file
f = self.fs.getfile(self.file_to_get) self.fs.update_realfile(self.fs.getfile(self.file_to_get), hash_path)
f[A_REALFILE] = hash_path self.exit()
def start(self): def start(self):

View File

@ -218,12 +218,10 @@ class command_wget(HoneyPotCommand):
# Link friendly name to hash # Link friendly name to hash
os.symlink(shasum, self.safeoutfile) os.symlink(shasum, self.safeoutfile)
# FIXME: is this necessary? self.safeoutfile = None
# self.safeoutfile = hash_path
# Update the honeyfs to point to downloaded file # Update the honeyfs to point to downloaded file
f = self.fs.getfile(outfile) self.fs.update_realfile(self.fs.getfile(outfile), hash_path)
f[A_REALFILE] = hash_path
self.exit() self.exit()

View File

@ -31,6 +31,11 @@ class LoggingServerProtocol(insults.ServerProtocol):
self.ttylogPath = cfg.get('honeypot', 'log_path') self.ttylogPath = cfg.get('honeypot', 'log_path')
self.downloadPath = cfg.get('honeypot', 'download_path') self.downloadPath = cfg.get('honeypot', 'download_path')
try:
self.ttylogEnabled = cfg.getboolean('honeypot', 'ttylog')
except:
self.ttylogEnabled = True
self.redirFiles = set() self.redirFiles = set()
try: try:
@ -44,24 +49,28 @@ class LoggingServerProtocol(insults.ServerProtocol):
else: else:
self.type = 'i' # Interactive self.type = 'i' # Interactive
def getSessionId(self): def getSessionId(self):
"""
"""
transportId = self.transport.session.conn.transport.transportId transportId = self.transport.session.conn.transport.transportId
channelId = self.transport.session.id channelId = self.transport.session.id
return (transportId, channelId) return (transportId, channelId)
def connectionMade(self): def connectionMade(self):
""" """
""" """
transportId, channelId = self.getSessionId() transportId, channelId = self.getSessionId()
self.startTime = time.time() self.startTime = time.time()
if self.ttylogEnabled:
self.ttylogFile = '%s/tty/%s-%s-%s%s.log' % \ self.ttylogFile = '%s/tty/%s-%s-%s%s.log' % \
(self.ttylogPath, time.strftime('%Y%m%d-%H%M%S'), (self.ttylogPath, time.strftime('%Y%m%d-%H%M%S'),
transportId, channelId, self.type) transportId, channelId, self.type)
ttylog.ttylog_open(self.ttylogFile, self.startTime) ttylog.ttylog_open(self.ttylogFile, self.startTime)
self.ttylogOpen = True self.ttylogOpen = True
self.ttylogSize = 0 self.ttylogSize = 0
log.msg(eventid='cowrie.log.open', log.msg(eventid='cowrie.log.open',
ttylog=self.ttylogFile, ttylog=self.ttylogFile,
format='Opening TTY Log: %(ttylog)s') format='Opening TTY Log: %(ttylog)s')
@ -82,7 +91,7 @@ class LoggingServerProtocol(insults.ServerProtocol):
""" """
Output sent back to user Output sent back to user
""" """
if self.ttylogOpen: if self.ttylogEnabled and self.ttylogOpen:
ttylog.ttylog_write(self.ttylogFile, len(bytes), ttylog.ttylog_write(self.ttylogFile, len(bytes),
ttylog.TYPE_OUTPUT, time.time(), bytes) ttylog.TYPE_OUTPUT, time.time(), bytes)
self.ttylogSize += len(bytes) self.ttylogSize += len(bytes)
@ -105,7 +114,7 @@ class LoggingServerProtocol(insults.ServerProtocol):
if self.stdinlogOpen: if self.stdinlogOpen:
with open(self.stdinlogFile, 'ab') as f: with open(self.stdinlogFile, 'ab') as f:
f.write(data) f.write(data)
elif self.ttylogOpen: elif self.ttylogEnabled and self.ttylogOpen:
ttylog.ttylog_write(self.ttylogFile, len(data), ttylog.ttylog_write(self.ttylogFile, len(data),
ttylog.TYPE_INPUT, time.time(), data) ttylog.TYPE_INPUT, time.time(), data)
@ -181,8 +190,7 @@ class LoggingServerProtocol(insults.ServerProtocol):
pass pass
self.redirFiles.clear() self.redirFiles.clear()
if self.ttylogOpen: if self.ttylogEnabled and self.ttylogOpen:
# TODO: Add session duration to this entry
log.msg(eventid='cowrie.log.closed', log.msg(eventid='cowrie.log.closed',
format='Closing TTY Log: %(ttylog)s after %(duration)d seconds', format='Closing TTY Log: %(ttylog)s after %(duration)d seconds',
ttylog=self.ttylogFile, ttylog=self.ttylogFile,
@ -193,6 +201,8 @@ class LoggingServerProtocol(insults.ServerProtocol):
insults.ServerProtocol.connectionLost(self, reason) insults.ServerProtocol.connectionLost(self, reason)
class LoggingTelnetServerProtocol(LoggingServerProtocol): class LoggingTelnetServerProtocol(LoggingServerProtocol):
""" """
Wrap LoggingServerProtocol with single method to fetch session id for Telnet Wrap LoggingServerProtocol with single method to fetch session id for Telnet

55
doc/graylog/README.md Normal file
View File

@ -0,0 +1,55 @@
# How to process Cowrie output into Graylog
## Prerequisites
* Working Cowrie installation
* Working Graylog installation
## Cowrie Configuration
* Open the Cowrie configuration file and uncomment these 3 lines.
```
[output_localsyslog]
facility = USER
format = text
```
* Restart Cowrie
## Graylog Configuration
* Open the Graylog web interface and click on the **System** drop-down in the top menu. From the drop-down menu select **Inputs**. Select **Syslog UDP** from the drop-down menu and click the **Launch new input** button. In the modal dialog enter the following information.
**Title:** Cowrie
**Port:** 8514
**Bind address:** 127.0.0.1
* Then click **Launch.**
## Syslog Configuration
* Create a rsyslog configuration file in /etc/rsyslog.d
```
$ sudo nano /etc/rsyslog.d/85-graylog.conf
```
* Add the following lines to the file
```
$template GRAYLOGRFC5424,"<%pri%>%protocol-version% %timestamp:::date-rfc3339% %HOSTNAME% %app-name% %procid% %msg%\n"
*.* @127.0.0.1:8514;GRAYLOGRFC5424
```
* Save and quit.
* Restart rsyslog
```
$ sudo service rsyslog restart
```

View File

@ -3,6 +3,11 @@ cryptography
configparser configparser
pyopenssl pyopenssl
gmpy2 gmpy2
pyparsing
packaging
appdirs
pyasn1_modules
attrs
service_identity service_identity
pycrypto pycrypto
python-dateutil python-dateutil