From 1a462eafe6e97ba04a920f0fbfedef29962b31b9 Mon Sep 17 00:00:00 2001 From: Simon Whittaker Date: Tue, 20 Dec 2016 07:15:28 +0000 Subject: [PATCH] Documentation and start script changes to assist with supervisord usage (#346) * * Updating start script to run in the foreground when using supervisord. * Update install documentation to reference use of supervisord and install on OSX * Updating index of INSTALL.md to with reference to supervisord * Adding slack output and db * Restoring start.sh back to default of AUTHBIND_ENABLED=no and DAEMONIZE=no * Updating with pretty formatting of json dump --- INSTALL.md | 31 ++++++++++++++++ cowrie.cfg.dist | 14 ++++++++ cowrie/dblog/slack.py | 57 ++++++++++++++++++++++++++++++ cowrie/output/slack.py | 80 ++++++++++++++++++++++++++++++++++++++++++ start.sh | 10 +++--- 5 files changed, 188 insertions(+), 4 deletions(-) create mode 100644 cowrie/dblog/slack.py create mode 100644 cowrie/output/slack.py diff --git a/INSTALL.md b/INSTALL.md index 5c4bdad..d11ca17 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -9,7 +9,9 @@ * [Step 5: Generate a DSA key](#step-5-generate-a-dsa-key) * [Step 6: Turning on cowrie](#step-6-turning-on-cowrie) * [Step 7: Port redirection (optional)](#step-7-port-redirection-optional) +* [Running within supervisord(optional)](#running-using-supervisord) * [Troubleshooting](#troubleshooting) +* [Installing on OSX for development](#installing-on-osx-for-development) ## Step 1: Install dependencies @@ -152,6 +154,25 @@ $ sudo chmod 770 /etc/authbind/byport/23 * Edit start.sh and modify the AUTHBIND_ENABLED setting * Change listen_port to 22 in cowrie.cfg +## Running using Supervisord +On Debian, put the below in /etc/supervisor/conf.d/cowrie.conf +``` +[program:cowrie] +command=/home/cowrie/cowrie/start.sh cowrie-env +directory=/home/cowrie/cowrie/ +user=cowrie +autorestart=true +redirect_stderr=true +``` +Update the start.sh script, change: + ``` + DAEMONIZE="" + ``` + to: + ``` + DAEMONIZE="-n" + ``` + ## Troubleshooting * For some versions of Twisted you may receive the following error messages: @@ -185,3 +206,13 @@ double check that your PYTHONPATH is set to the source code directory. To make Cowrie logfiles public readable, change the ```--umask 0077``` option in start.sh into ```--umask 0022``` +## Installing on OSX for development + +gmpy2 requires a number of libraries which are not included by default with Sierra and must be installed, suggested method is by using [homebrew](http://brew.sh/) + +``` +brew install gmp +brew install mpfr +brew install mpc +brew install libmpc +``` \ No newline at end of file diff --git a/cowrie.cfg.dist b/cowrie.cfg.dist index e6e33d9..ba39b83 100644 --- a/cowrie.cfg.dist +++ b/cowrie.cfg.dist @@ -295,6 +295,13 @@ enabled = false #signal_clientversion = cowrie-events #debug=true +# Slack Logging +# Log to an slack channel. +# +#[database_slack] +#channel = channel_that_events_should_be_posted_in +#token = slack_token_for_your_bot +#debug=true # ============================================================================ @@ -432,6 +439,13 @@ logfile = log/cowrie.json #api_key = 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef # +#[output_slack] +# This will produce a _lot_ of messages - you have been warned.... +#channel = channel_that_events_should_be_posted_in +#token = slack_token_for_your_bot +##debug=true + + # https://csirtg.io # You must signup for an api key. # diff --git a/cowrie/dblog/slack.py b/cowrie/dblog/slack.py new file mode 100644 index 0000000..5b85470 --- /dev/null +++ b/cowrie/dblog/slack.py @@ -0,0 +1,57 @@ +from slackclient import SlackClient +import sys +import os +from cowrie.core import dblog +import time +import uuid + +class DBLogger(dblog.DBLogger): + def start(self, cfg): + self.slack_channel = cfg.get('database_slack', 'channel') + #self.slack_token = os.environ["SLACK_API_TOKEN"] + self.slack_token = cfg.get('database_slack', 'token') + + def write(self, session, msg): + self.sc = SlackClient(self.slack_token) + self.sc.api_call( + "chat.postMessage", + channel=self.slack_channel, + text="%s %s %s"%(time.strftime('%Y-%m-%d %H:%M:%S'),session,msg) + ) + + def createSession(self, peerIP, peerPort, hostIP, hostPort): + sid = uuid.uuid4().hex + sensorname = self.getSensor() or hostIP + self.write(sid, 'New connection: %s:%s' % (peerIP, peerPort)) + return sid + + def handleConnectionLost(self, session, args): + self.write(session, 'Connection lost') + + def handleLoginFailed(self, session, args): + self.write(session, 'Login failed [%s/%s]' % \ + (args['username'], args['password'])) + + def handleLoginSucceeded(self, session, args): + self.write(session, 'Login succeeded [%s/%s]' % \ + (args['username'], args['password'])) + + def handleCommand(self, session, args): + self.write(session, 'Command [%s]' % (args['input'],)) + + def handleUnknownCommand(self, session, args): + self.write(session, 'Unknown command [%s]' % (args['input'],)) + + def handleInput(self, session, args): + self.write(session, 'Input [%s] @%s' % (args['input'], args['realm'])) + + def handleTerminalSize(self, session, args): + self.write(session, 'Terminal size: %sx%s' % \ + (args['width'], args['height'])) + + def handleClientVersion(self, session, args): + self.write(session, 'Client version: [%s]' % (args['version'],)) + + def handleFileDownload(self, session, args): + self.write(session, 'File download: [%s] -> %s with SHA-256 %s' % \ + (args['url'], args['outfile'], args['shasum'])) diff --git a/cowrie/output/slack.py b/cowrie/output/slack.py new file mode 100644 index 0000000..4f4b9e6 --- /dev/null +++ b/cowrie/output/slack.py @@ -0,0 +1,80 @@ +# Copyright (c) 2015 Michel Oosterhof +# 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. + +""" +Docstring +""" + +import json +import os + +import twisted.python.logfile + +import cowrie.core.output +from slackclient import SlackClient +import time + + +class Output(cowrie.core.output.Output): + """ + Docstring class + """ + + def __init__(self, cfg): + cowrie.core.output.Output.__init__(self, cfg) + self.slack_channel = cfg.get('output_slack', 'channel') + self.slack_token = cfg.get('output_slack', 'token') + + + def start(self): + """ + """ + pass + + + def stop(self): + """ + """ + pass + + + def write(self, logentry): + """ + """ + for i in list(logentry.keys()): + # Remove twisted 15 legacy keys + if i.startswith('log_'): + del logentry[i] + + self.sc = SlackClient(self.slack_token) + self.sc.api_call( + "chat.postMessage", + channel=self.slack_channel, + text="%s %s" % (time.strftime('%Y-%m-%d %H:%M:%S'), json.dumps(logentry, indent=4, sort_keys=True)) + ) + diff --git a/start.sh b/start.sh index 1754296..6519026 100755 --- a/start.sh +++ b/start.sh @@ -3,6 +3,8 @@ AUTHBIND_ENABLED=no COWRIEDIR=$(dirname $0) PIDFILE="var/run/cowrie.pid" export PYTHONPATH=${PYTHONPATH}:${COWRIEDIR} +#Change the below to -n to disable daemonizing (for instance when using supervisor) +DAEMONIZE="" set -e cd ${COWRIEDIR} @@ -27,10 +29,10 @@ then . $VENV/bin/activate fi -echo "Starting cowrie with extra arguments [$XARGS] ..." +echo "Starting cowrie with extra arguments [$XARGS $DAEMONIZE] ..." if [ $AUTHBIND_ENABLED = "no" ] then - twistd $XARGS -l log/cowrie.log --umask 0077 --pidfile ${PIDFILE} cowrie + twistd $XARGS $DAEMONIZE -l log/cowrie.log --umask 0077 --pidfile ${PIDFILE} cowrie else - authbind --deep twistd $XARGS -l log/cowrie.log --umask 0077 --pidfile cowrie.pid cowrie -fi + authbind --deep twistd $DAEMONIZE $XARGS -l log/cowrie.log --umask 0077 --pidfile cowrie.pid cowrie +fi \ No newline at end of file