diff --git a/README.md b/README.md index d0286ba..88af466 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,14 @@ port = 10000 identity = shockpot secret = secret channel = shockpot.events + +[postgresql] +enabled = True +database = $POSTGRES_NAME +user = $POSTGRES_USER +password = $POSTGRES_PASS +host = $POSTGRES_HOST +port = $POSTGRES_PORT ``` ## Running @@ -42,7 +50,7 @@ python shockpot.py ## Deployment -See the [wiki](https://github.com/threatstream/shockpot/wiki). +See the [https://github.com/threatstream/shockpot/wiki](https://github.com/threatstream/shockpot/wiki). ## LICENSE diff --git a/requirements.txt b/requirements.txt index 10ede8c..8f4034f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ bottle==0.12.7 -e git+https://github.com/threatstream/hpfeeds/#egg=hpfeeds-dev requests==2.4.1 +psycopg2 diff --git a/shockpot.py b/shockpot.py index 76ea67f..a7d0c1b 100644 --- a/shockpot.py +++ b/shockpot.py @@ -7,6 +7,7 @@ from bottle import request, response import json from util import get_hpfeeds_client, get_ext_ip +from util import get_postgresql_handler from commands import perform_commands import re import datetime @@ -25,6 +26,7 @@ LOGGER.info( 'Loading config file shockpot.conf ...') app.config.load_config('shockpot.conf') hpclient = get_hpfeeds_client(app.config) +dbh = get_postgresql_handler(app.config) public_ip = None if app.config['fetch_public_ip.enabled'].lower() == 'true': @@ -67,11 +69,17 @@ def get_request_record(): def log_request(record): global hpclient + global dbh req = json.dumps(record) LOGGER.info(req) if hpclient and record['is_shellshock']: hpclient.publish(app.config['hpfeeds.channel'], req) + if dbh and record['is_shellshock']: + cursor = dbh.cursor() + cursor.execute("INSERT INTO connections (method, url, path, query_string, headers, source_ip, source_port, dest_host, dest_port, is_shellshock, command, command_data, timestamp) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)", + (record['method'], record['url'], record['path'], record['query_string'], str(record['headers']), record['source_ip'],request.environ.get('REMOTE_PORT'), record['dest_host'], record['dest_port'], record['is_shellshock'], record['command'], record['command_data'], record['timestamp']) ) + dbh.commit() @app.route('/') @app.route('/') diff --git a/util.py b/util.py index 3aca2bb..e23a625 100644 --- a/util.py +++ b/util.py @@ -1,5 +1,6 @@ import hpfeeds from logger import LOGGER +import psycopg2 import socket import requests from requests.exceptions import Timeout, ConnectionError @@ -22,6 +23,34 @@ def get_hpfeeds_client(config): LOGGER.info( 'hpfeeds is disabled') return hpc +def get_postgresql_handler(config): + dbh = None + if config['postgresql.enabled'].lower() == 'true': + LOGGER.info('postgresql enabled, creating connection to {}:{}'.format(config['postgresql.host'], config['postgresql.port'])) + dbh = psycopg2.connect(database=config['postgresql.database'], user=config['postgresql.user'], password=config['postgresql.password'], host=config['postgresql.host'], port=config['postgresql.port']) + cursor = dbh.cursor() + cursor.execute("""CREATE TABLE IF NOT EXISTS + connections ( + connection SERIAL PRIMARY KEY, + method TEXT, + url TEXT, + path TEXT, + query_string TEXT, + headers TEXT, + source_ip TEXT, + source_port INTEGER, + dest_host TEXT, + dest_port INTEGER, + is_shellshock TEXT, + command TEXT, + command_data TEXT, + timestamp INTEGER + );""") + dbh.commit() + else: + LOGGER.info( 'postgresql is disabled') + return dbh + def valid_ip(ip): try: socket.inet_aton(ip)