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:
|
||||
# KERN, USER, MAIL, DAEMON, AUTH, LPR, NEWS, UUCP, CRON, SYSLOG and LOCAL0 to LOCAL7.
|
||||
#
|
||||
# Format can be:
|
||||
# text, cef
|
||||
#
|
||||
#[output_localsyslog]
|
||||
#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)
|
||||
|
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
|
||||
if ev['eventid'] == 'cowrie.session.connect':
|
||||
self.sessions[sessionno] = ev['id']
|
||||
self.sessions[sessionno] = ev['session']
|
||||
self.ips[sessionno] = ev['src_ip']
|
||||
del ev['id']
|
||||
|
||||
ev['session'] = self.sessions[sessionno]
|
||||
else:
|
||||
ev['session'] = self.sessions[sessionno]
|
||||
|
||||
self.write(ev)
|
||||
|
||||
|
@ -30,6 +30,7 @@ import syslog
|
||||
import twisted.python.syslog
|
||||
|
||||
import cowrie.core.output
|
||||
import cowrie.core.cef
|
||||
|
||||
class Output(cowrie.core.output.Output):
|
||||
|
||||
@ -38,6 +39,7 @@ class Output(cowrie.core.output.Output):
|
||||
"""
|
||||
cowrie.core.output.Output.__init__(self, cfg)
|
||||
facilityString = cfg.get('output_localsyslog', 'facility')
|
||||
self.format = cfg.get('output_localsyslog', 'format')
|
||||
self.facility = vars(syslog)['LOG_' + facilityString]
|
||||
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):
|
||||
"""
|
||||
"""
|
||||
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]
|
||||
|
||||
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,
|
||||
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.currentEncryptions = transport.SSHCiphers('none', 'none', 'none', 'none')
|
||||
|
Reference in New Issue
Block a user