mirror of
https://github.com/cowrie/cowrie.git
synced 2025-07-01 18:07:27 -04:00
CEF / textlog output module
This commit is contained in:
@ -288,8 +288,24 @@ logfile = log/cowrie.json
|
|||||||
# Facility can be:
|
# Facility can be:
|
||||||
# KERN, USER, MAIL, DAEMON, AUTH, LPR, NEWS, UUCP, CRON, SYSLOG and LOCAL0 to LOCAL7.
|
# KERN, USER, MAIL, DAEMON, AUTH, LPR, NEWS, UUCP, CRON, SYSLOG and LOCAL0 to LOCAL7.
|
||||||
#
|
#
|
||||||
|
# Format can be:
|
||||||
|
# text, cef
|
||||||
|
#
|
||||||
#[output_localsyslog]
|
#[output_localsyslog]
|
||||||
#facility = USER
|
#facility = USER
|
||||||
|
#format = text
|
||||||
|
|
||||||
|
|
||||||
|
# Text output
|
||||||
|
#
|
||||||
|
# This writes log entries to a text file
|
||||||
|
#
|
||||||
|
# Format can be:
|
||||||
|
# text, cef
|
||||||
|
#
|
||||||
|
#[output_textlog]
|
||||||
|
#logfile = log/cowrie.textlog
|
||||||
|
#format = text
|
||||||
|
|
||||||
|
|
||||||
# MySQL logging module (output)
|
# MySQL logging module (output)
|
||||||
|
111
cowrie/core/cef.py
Normal file
111
cowrie/core/cef.py
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
"""
|
||||||
|
This module contains ...
|
||||||
|
"""
|
||||||
|
|
||||||
|
from twisted.python import log
|
||||||
|
|
||||||
|
# cowrie.client.fingerprint
|
||||||
|
# cowrie.client.size
|
||||||
|
# cowrie.client.var
|
||||||
|
# cowrie.client.version
|
||||||
|
# cowrie.command.failed
|
||||||
|
# cowrie.command.success
|
||||||
|
# cowrie.direct-tcpip.data
|
||||||
|
# cowrie.direct-tcpip.request
|
||||||
|
# cowrie.log.closed
|
||||||
|
# cowrie.log.open
|
||||||
|
# cowrie.login.failed
|
||||||
|
# cowrie.login.success
|
||||||
|
# cowrie.session.closed
|
||||||
|
# cowrie.session.connect
|
||||||
|
# cowrie.session.file_download
|
||||||
|
# cowrie.session.file_upload
|
||||||
|
|
||||||
|
def formatCef(logentry):
|
||||||
|
"""
|
||||||
|
Take logentry and turn into CEF string
|
||||||
|
"""
|
||||||
|
# Jan 18 11:07:53 host CEF:Version|Device Vendor|Device Product|Device Version|Signature ID|Name|Severity|[Extension]
|
||||||
|
cefVendor = "Cowrie"
|
||||||
|
cefProduct = "Cowrie"
|
||||||
|
cefVersion = "1.0"
|
||||||
|
cefSignature = logentry["eventid"]
|
||||||
|
cefName = logentry["eventid"]
|
||||||
|
cefSeverity = "5"
|
||||||
|
|
||||||
|
cefExtensions = {
|
||||||
|
'app': 'SSHv2',
|
||||||
|
'destinationServicename': 'sshd',
|
||||||
|
'deviceExternalId': logentry['sensor'],
|
||||||
|
'msg': log.textFromEventDict(logentry),
|
||||||
|
'src' : logentry['src_ip'],
|
||||||
|
'proto': 'tcp'
|
||||||
|
}
|
||||||
|
|
||||||
|
if logentry['eventid'] == 'cowrie.session.connect':
|
||||||
|
cefExtensions['spt'] = logentry['src_port']
|
||||||
|
cefExtensions['dpt'] = logentry['dst_port']
|
||||||
|
cefExtensions['src'] = logentry['src_ip']
|
||||||
|
cefExtensions['dst'] = logentry['dst_ip']
|
||||||
|
elif logentry['eventid'] == 'cowrie.login.success':
|
||||||
|
cefExtensions['duser'] = logentry['username']
|
||||||
|
cefExtensions['outcome'] = 'success'
|
||||||
|
elif logentry['eventid'] == 'cowrie.login.failed':
|
||||||
|
cefExtensions['duser'] = logentry['username']
|
||||||
|
cefExtensions['outcome'] = 'failed'
|
||||||
|
elif logentry['eventid'] == 'cowrie.file.file_download':
|
||||||
|
cefExtensions['filehash'] = logentry['filehash']
|
||||||
|
cefExtensions['filePath'] = logentry['filename']
|
||||||
|
cefExtensions['fsize'] = logentry['size']
|
||||||
|
elif logentry['eventid'] == 'cowrie.file.file_upload':
|
||||||
|
cefExtensions['filehash'] = logentry['filehash']
|
||||||
|
cefExtensions['filePath'] = logentry['filename']
|
||||||
|
cefExtensions['fsize'] = logentry['size']
|
||||||
|
|
||||||
|
# 'out' 'outcome' request, rt
|
||||||
|
|
||||||
|
cefList = []
|
||||||
|
for key in cefExtensions.keys():
|
||||||
|
value = str(cefExtensions[key]).replace(' ', '\ ')
|
||||||
|
cefList.append(key+"="+value)
|
||||||
|
cefExtension = ' '.join(cefList)
|
||||||
|
|
||||||
|
cefString = "CEF:0|" + \
|
||||||
|
cefVendor + "|" + \
|
||||||
|
cefProduct + "|" + \
|
||||||
|
cefVersion + "|" + \
|
||||||
|
cefSignature + "|" + \
|
||||||
|
cefName + "|" + \
|
||||||
|
cefSeverity + "|" + \
|
||||||
|
cefExtension
|
||||||
|
|
||||||
|
return cefString
|
||||||
|
|
@ -158,11 +158,10 @@ class Output(object):
|
|||||||
|
|
||||||
# Connection event is special. adds to session list
|
# Connection event is special. adds to session list
|
||||||
if ev['eventid'] == 'cowrie.session.connect':
|
if ev['eventid'] == 'cowrie.session.connect':
|
||||||
self.sessions[sessionno] = ev['id']
|
self.sessions[sessionno] = ev['session']
|
||||||
self.ips[sessionno] = ev['src_ip']
|
self.ips[sessionno] = ev['src_ip']
|
||||||
del ev['id']
|
else:
|
||||||
|
ev['session'] = self.sessions[sessionno]
|
||||||
ev['session'] = self.sessions[sessionno]
|
|
||||||
|
|
||||||
self.write(ev)
|
self.write(ev)
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ import syslog
|
|||||||
import twisted.python.syslog
|
import twisted.python.syslog
|
||||||
|
|
||||||
import cowrie.core.output
|
import cowrie.core.output
|
||||||
|
import cowrie.core.cef
|
||||||
|
|
||||||
class Output(cowrie.core.output.Output):
|
class Output(cowrie.core.output.Output):
|
||||||
|
|
||||||
@ -38,6 +39,7 @@ class Output(cowrie.core.output.Output):
|
|||||||
"""
|
"""
|
||||||
cowrie.core.output.Output.__init__(self, cfg)
|
cowrie.core.output.Output.__init__(self, cfg)
|
||||||
facilityString = cfg.get('output_localsyslog', 'facility')
|
facilityString = cfg.get('output_localsyslog', 'facility')
|
||||||
|
self.format = cfg.get('output_localsyslog', 'format')
|
||||||
self.facility = vars(syslog)['LOG_' + facilityString]
|
self.facility = vars(syslog)['LOG_' + facilityString]
|
||||||
self.syslog = twisted.python.syslog.SyslogObserver(prefix='cowrie', facility=self.facility)
|
self.syslog = twisted.python.syslog.SyslogObserver(prefix='cowrie', facility=self.facility)
|
||||||
|
|
||||||
@ -57,5 +59,8 @@ class Output(cowrie.core.output.Output):
|
|||||||
def write(self, logentry):
|
def write(self, logentry):
|
||||||
"""
|
"""
|
||||||
"""
|
"""
|
||||||
self.syslog.emit(logentry)
|
if self.format == 'cef':
|
||||||
|
self.syslog.emit(cowrie.core.cef.formatCef(logentry))
|
||||||
|
else:
|
||||||
|
self.syslog.emit(logentry)
|
||||||
|
|
||||||
|
62
cowrie/output/textlog.py
Normal file
62
cowrie/output/textlog.py
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
# 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 cowrie.core.output
|
||||||
|
import cowrie.core.cef
|
||||||
|
|
||||||
|
class Output(cowrie.core.output.Output):
|
||||||
|
|
||||||
|
def __init__(self, cfg):
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
cowrie.core.output.Output.__init__(self, cfg)
|
||||||
|
self.format = cfg.get('output_textlog', 'format')
|
||||||
|
self.outfile = file(cfg.get('output_textlog', 'logfile'), 'a')
|
||||||
|
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def write(self, logentry):
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
if self.format == 'cef':
|
||||||
|
self.outfile.write(cowrie.core.cef.formatCef(logentry)+'\n')
|
||||||
|
self.outfile.flush()
|
||||||
|
else:
|
||||||
|
self.outfile.write(logentry["message"])
|
||||||
|
|
@ -171,10 +171,10 @@ class HoneyPotTransport(transport.SSHServerTransport, TimeoutMixin):
|
|||||||
self.transportId = uuid.uuid4().hex[:8]
|
self.transportId = uuid.uuid4().hex[:8]
|
||||||
|
|
||||||
log.msg(eventid='cowrie.session.connect',
|
log.msg(eventid='cowrie.session.connect',
|
||||||
format='New connection: %(src_ip)s:%(src_port)s (%(dst_ip)s:%(dst_port)s) [session: %(sessionno)s]',
|
format='New connection: %(src_ip)s:%(src_port)s (%(dst_ip)s:%(dst_port)s) [session: %(session)s]',
|
||||||
src_ip=self.transport.getPeer().host, src_port=self.transport.getPeer().port,
|
src_ip=self.transport.getPeer().host, src_port=self.transport.getPeer().port,
|
||||||
dst_ip=self.transport.getHost().host, dst_port=self.transport.getHost().port,
|
dst_ip=self.transport.getHost().host, dst_port=self.transport.getHost().port,
|
||||||
id=self.transportId, sessionno=self.transport.sessionno)
|
session=self.transportId, sessionno=self.transport.sessionno)
|
||||||
|
|
||||||
self.transport.write('{}\r\n'.format(self.ourVersionString))
|
self.transport.write('{}\r\n'.format(self.ourVersionString))
|
||||||
self.currentEncryptions = transport.SSHCiphers('none', 'none', 'none', 'none')
|
self.currentEncryptions = transport.SSHCiphers('none', 'none', 'none', 'none')
|
||||||
|
Reference in New Issue
Block a user