diff --git a/docker/ciscoasa/Dockerfile b/docker/ciscoasa/Dockerfile index b457ec2b..b7f8819d 100644 --- a/docker/ciscoasa/Dockerfile +++ b/docker/ciscoasa/Dockerfile @@ -21,7 +21,7 @@ RUN apk -U upgrade && \ # Get and install packages mkdir -p /opt/ && \ cd /opt/ && \ - git clone --depth=1 https://github.com/cymmetria/ciscoasa_honeypot && \ + git clone --depth=1 https://github.com/vorband/ciscoasa_honeypot && \ cd ciscoasa_honeypot && \ pip3 install --no-cache-dir --upgrade pip && \ pip3 install --no-cache-dir -r requirements.txt && \ diff --git a/docker/ciscoasa/dist/asa_server.py b/docker/ciscoasa/dist/asa_server.py index 11fa1bf1..e1883870 100644 --- a/docker/ciscoasa/dist/asa_server.py +++ b/docker/ciscoasa/dist/asa_server.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- import os -import datetime +import time import socket import logging logging.basicConfig(format='%(message)s') @@ -12,11 +12,36 @@ from http.server import HTTPServer from socketserver import ThreadingMixIn from http.server import SimpleHTTPRequestHandler import ike_server +import datetime class NonBlockingHTTPServer(ThreadingMixIn, HTTPServer): pass +class hpflogger: + def __init__(self, hpfserver, hpfport, hpfident, hpfsecret, hpfchannel, serverid, verbose): + self.hpfserver=hpfserver + self.hpfport=hpfport + self.hpfident=hpfident + self.hpfsecret=hpfsecret + self.hpfchannel=hpfchannel + self.serverid=serverid + self.hpc=None + self.verbose=verbose + if (self.hpfserver and self.hpfport and self.hpfident and self.hpfport and self.hpfchannel and self.serverid): + import hpfeeds + try: + self.hpc = hpfeeds.new(self.hpfserver, self.hpfport, self.hpfident, self.hpfsecret) + logger.debug("Logging to hpfeeds using server: {0}, channel {1}.".format(self.hpfserver, self.hpfchannel)) + except (hpfeeds.FeedException, socket.error, hpfeeds.Disconnect): + logger.critical("hpfeeds connection not successful") + + def log(self, level, message): + if self.hpc: + if level in ['debug', 'info'] and not self.verbose: + return + self.hpc.publish(self.hpfchannel, "["+self.serverid+"] ["+level+"] ["+datetime.datetime.now().isoformat() +"] " + str(message)) + def header_split(h): return [list(map(str.strip, l.split(': ', 1))) for l in h.strip().splitlines()] @@ -24,6 +49,7 @@ def header_split(h): class WebLogicHandler(SimpleHTTPRequestHandler): logger = None + hpfl = None protocol_version = "HTTP/1.1" @@ -153,6 +179,10 @@ class WebLogicHandler(SimpleHTTPRequestHandler): (datetime.datetime.now().isoformat(), self.client_address[0], format % args)) + self.hpfl.log('debug', "%s - - [%s] %s" % + (self.client_address[0], + self.log_date_time_string(), + format % args)) def handle_one_request(self): """Handle a single HTTP request. @@ -203,18 +233,37 @@ if __name__ == '__main__': @click.option('-c', '--cert', default=None, help='Certificate File Path (will generate self signed ' 'cert if not supplied)') @click.option('-v', '--verbose', default=False, help='Verbose logging', is_flag=True) - def start(host, port, ike_port, enable_ssl, cert, verbose): + + # hpfeeds options + @click.option('--hpfserver', default=os.environ.get('HPFEEDS_SERVER'), help='HPFeeds Server') + @click.option('--hpfport', default=os.environ.get('HPFEEDS_PORT'), help='HPFeeds Port', type=click.INT) + @click.option('--hpfident', default=os.environ.get('HPFEEDS_IDENT'), help='HPFeeds Ident') + @click.option('--hpfsecret', default=os.environ.get('HPFEEDS_SECRET'), help='HPFeeds Secret') + @click.option('--hpfchannel', default=os.environ.get('HPFEEDS_CHANNEL'), help='HPFeeds Channel') + @click.option('--serverid', default=os.environ.get('SERVERID'), help='Verbose logging') + + + def start(host, port, ike_port, enable_ssl, cert, verbose, hpfserver, hpfport, hpfident, hpfsecret, hpfchannel, serverid): """ A low interaction honeypot for the Cisco ASA component capable of detecting CVE-2018-0101, a DoS and remote code execution vulnerability """ + + hpfl=hpflogger(hpfserver, hpfport, hpfident, hpfsecret, hpfchannel, serverid, verbose) + def alert(cls, host, port, payloads): logger.critical({ - 'timestamp': datetime.datetime.utcnow().isoformat(), - 'src_ip': host, - 'src_port': port, - 'payload_printable': payloads, + 'timestamp': datetime.datetime.utcnow().isoformat(), + 'src_ip': host, + 'src_port': port, + 'payload_printable': payloads, }) + #log to hpfeeds + hpfl.log("critical", { + 'src': host, + 'spt': port, + 'data': payloads, + }) if verbose: logger.setLevel(logging.DEBUG) @@ -222,14 +271,15 @@ if __name__ == '__main__': requestHandler = WebLogicHandler requestHandler.alert_function = alert requestHandler.logger = logger + requestHandler.hpfl = hpfl def log_date_time_string(): """Return the current time formatted for logging.""" - now = datetime.datetime.utcnow().isoformat() + now = datetime.datetime.now().isoformat() return now def ike(): - ike_server.start(host, ike_port, alert, logger) + ike_server.start(host, ike_port, alert, logger, hpfl) t = threading.Thread(target=ike) t.daemon = True t.start() @@ -243,11 +293,15 @@ if __name__ == '__main__': httpd.socket = ssl.wrap_socket(httpd.socket, certfile=cert, server_side=True) logger.info('Starting server on port {:d}/tcp, use to stop'.format(port)) + hpfl.log('info', 'Starting server on port {:d}/tcp, use to stop'.format(port)) + try: httpd.serve_forever() except KeyboardInterrupt: pass logger.info('Stopping server.') + hpfl.log('info', 'Stopping server.') + httpd.server_close() start()