diff --git a/honeypots/__init__.py b/honeypots/__init__.py
index d6bffe3..df9d946 100644
--- a/honeypots/__init__.py
+++ b/honeypots/__init__.py
@@ -6,7 +6,6 @@
is_privileged,
clean_all,
close_port_wrapper,
- disable_logger,
get_free_port,
get_running_servers,
kill_server_wrapper,
@@ -78,7 +77,6 @@
"is_privileged",
"clean_all",
"close_port_wrapper",
- "disable_logger",
"get_free_port",
"get_running_servers",
"kill_server_wrapper",
diff --git a/honeypots/base_http_server.py b/honeypots/base_http_server.py
new file mode 100644
index 0000000..9207663
--- /dev/null
+++ b/honeypots/base_http_server.py
@@ -0,0 +1,123 @@
+from __future__ import annotations
+
+from abc import ABC
+from cgi import FieldStorage
+from contextlib import suppress
+from random import choice
+
+from twisted.web.resource import Resource
+
+from honeypots.base_server import BaseServer
+from honeypots.helper import load_template, get_headers_and_ip_from_request, check_bytes
+
+
+class BaseHttpServer(BaseServer, ABC):
+ def __init__(self, **kwargs):
+ super().__init__(**kwargs)
+ self.mocking_server = choice(
+ [
+ "Apache",
+ "nginx",
+ "Microsoft-IIS/7.5",
+ "Microsoft-HTTPAPI/2.0",
+ "Apache/2.2.15",
+ "SmartXFilter",
+ "Microsoft-IIS/8.5",
+ "Apache/2.4.6",
+ "Apache-Coyote/1.1",
+ "Microsoft-IIS/7.0",
+ "Apache/2.4.18",
+ "AkamaiGHost",
+ "Apache/2.2.25",
+ "Microsoft-IIS/10.0",
+ "Apache/2.2.3",
+ "nginx/1.12.1",
+ "Apache/2.4.29",
+ "cloudflare",
+ "Apache/2.2.22",
+ ]
+ )
+
+ class MainResource(Resource):
+ isLeaf = True
+ home_file = load_template("home.html")
+ login_file = load_template("login.html")
+
+ def __init__(self, *args, hp_server=None, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.hp_server = hp_server
+ self.headers = {}
+
+ def render(self, request):
+ client_ip, headers = get_headers_and_ip_from_request(request, self.hp_server.options)
+
+ with suppress(Exception):
+ log_data = {
+ "server": self.hp_server.NAME,
+ "action": "connection",
+ "src_ip": client_ip,
+ "src_port": request.getClientAddress().port,
+ "dest_ip": self.hp_server.ip,
+ "dest_port": self.hp_server.port,
+ }
+ if "capture_commands" in self.hp_server.options:
+ log_data["data"] = headers
+ self.hp_server.logs.info(log_data)
+
+ if self.hp_server.mocking_server != "":
+ request.responseHeaders.removeHeader("Server")
+ request.responseHeaders.addRawHeader("Server", self.hp_server.mocking_server)
+
+ if request.method in (b"GET", b"POST"):
+ self.hp_server.logs.info(
+ {
+ "server": self.hp_server.NAME,
+ "action": request.method.decode(),
+ "src_ip": client_ip,
+ "src_port": request.getClientAddress().port,
+ "dest_ip": self.hp_server.ip,
+ "dest_port": self.hp_server.port,
+ }
+ )
+
+ if request.method == b"GET":
+ if (
+ request.uri == b"/login.html"
+ and self.hp_server.username != ""
+ and self.hp_server.password != ""
+ ):
+ request.responseHeaders.addRawHeader(
+ "Content-Type", "text/html; charset=utf-8"
+ )
+ return self.login_file
+
+ request.responseHeaders.addRawHeader("Content-Type", "text/html; charset=utf-8")
+ return self.login_file
+
+ if request.method == b"POST":
+ self.headers = request.getAllHeaders()
+ if (
+ request.uri in (b"/login.html", b"/")
+ and self.hp_server.username != ""
+ and self.hp_server.password != ""
+ ):
+ form = FieldStorage(
+ fp=request.content,
+ headers=self.headers,
+ environ={
+ "REQUEST_METHOD": "POST",
+ "CONTENT_TYPE": self.headers.get(
+ b"content-type",
+ b"application/x-www-form-urlencoded",
+ ),
+ },
+ )
+ if "username" in form and "password" in form:
+ username = check_bytes(form["username"].value)
+ password = check_bytes(form["password"].value)
+ self.hp_server.log_login(
+ username, password, client_ip, request.getClientAddress().port
+ )
+
+ request.responseHeaders.addRawHeader("Content-Type", "text/html; charset=utf-8")
+ return self.home_file
diff --git a/honeypots/base_server.py b/honeypots/base_server.py
new file mode 100644
index 0000000..074fcbd
--- /dev/null
+++ b/honeypots/base_server.py
@@ -0,0 +1,133 @@
+from __future__ import annotations
+
+import inspect
+from abc import ABC, abstractmethod
+from os import getenv
+from shlex import split
+from subprocess import Popen
+from uuid import uuid4
+
+from honeypots.helper import (
+ setup_logger,
+ set_local_vars,
+ set_up_error_logging,
+ close_port_wrapper,
+ kill_server_wrapper,
+ get_free_port,
+ check_if_server_is_running,
+)
+
+
+class BaseServer(ABC):
+ NAME = "base"
+ DEFAULT_PORT = 0
+ DEFAULT_USERNAME = "test"
+ DEFAULT_PASSWORD = "test"
+
+ def __init__(self, **kwargs):
+ self.auto_disabled = None
+ self.process = None
+ self.uuid = f"honeypotslogger_{__class__.__name__}_{str(uuid4())[:8]}"
+ self.config = kwargs.get("config", "")
+ if self.config:
+ self.logs = setup_logger(__class__.__name__, self.uuid, self.config)
+ set_local_vars(self, self.config)
+ else:
+ self.logs = setup_logger(__class__.__name__, self.uuid, None)
+ self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0"
+ self.port = (
+ (kwargs.get("port", None) and int(kwargs.get("port", None)))
+ or (hasattr(self, "port") and self.port)
+ or self.DEFAULT_PORT
+ )
+ self.username = (
+ kwargs.get("username")
+ or (hasattr(self, "username") and self.username)
+ or self.DEFAULT_USERNAME
+ )
+ self.password = (
+ kwargs.get("password")
+ or (hasattr(self, "password") and self.password)
+ or self.DEFAULT_PASSWORD
+ )
+ self.options = (
+ kwargs.get("options", "")
+ or (hasattr(self, "options") and self.options)
+ or getenv("HONEYPOTS_OPTIONS", "")
+ or ""
+ )
+ self.logger = set_up_error_logging()
+
+ def close_port(self):
+ return close_port_wrapper(self.NAME, self.ip, self.port, self.logs)
+
+ def kill_server(self):
+ return kill_server_wrapper(self.NAME, self.uuid, self.process)
+
+ @abstractmethod
+ def server_main(self):
+ pass
+
+ def run_server(self, process: bool = False, auto: bool = False) -> bool | None:
+ status = "error"
+ run = False
+ if not process:
+ self.server_main()
+ return None
+
+ if auto and not self.auto_disabled:
+ port = get_free_port()
+ if port > 0:
+ self.port = port
+ run = True
+ elif self.close_port() and self.kill_server():
+ run = True
+
+ if run:
+ file = inspect.getfile(self.__class__)
+ command = (
+ f"python3 {file} --custom --ip {self.ip} " f"--port {self.port} --uuid {self.uuid}"
+ )
+ if self.options:
+ command += f" --options '{self.options}'"
+ if self.config:
+ command += f" --config '{self.config}'"
+ self.process = Popen(split(command))
+ if self.process.poll() is None and check_if_server_is_running(self.uuid):
+ status = "success"
+
+ self.logs.info(
+ {
+ "server": self.NAME,
+ "action": "process",
+ "status": status,
+ "src_ip": self.ip,
+ "src_port": self.port,
+ "dest_ip": self.ip,
+ "dest_port": self.port,
+ }
+ )
+
+ if status == "success":
+ return True
+ self.kill_server()
+ return False
+
+ def log_login(self, username: str, password: str, ip: str, port: int):
+ status = "success" if self._login_is_correct(username, password) else "failed"
+ self.logs.info(
+ {
+ "server": self.NAME,
+ "action": "login",
+ "status": status,
+ "src_ip": ip,
+ "src_port": port,
+ "username": username,
+ "password": password,
+ "dest_ip": self.ip,
+ "dest_port": self.port,
+ }
+ )
+
+ def _login_is_correct(self, username: str, password: str) -> bool:
+ return username == self.username and password == self.password
diff --git a/honeypots/data/home.html b/honeypots/data/home.html
new file mode 100644
index 0000000..c184ba4
--- /dev/null
+++ b/honeypots/data/home.html
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+ Login
+
+
+
+
+
+
+ We'll back soon..
+
+
+
+
+
diff --git a/honeypots/data/login.html b/honeypots/data/login.html
new file mode 100644
index 0000000..443dc34
--- /dev/null
+++ b/honeypots/data/login.html
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+ Login
+
+
+
+
+
+
diff --git a/honeypots/dhcp_server.py b/honeypots/dhcp_server.py
index 3a01a3d..8aabb9f 100644
--- a/honeypots/dhcp_server.py
+++ b/honeypots/dhcp_server.py
@@ -10,58 +10,27 @@
// -------------------------------------------------------------
"""
-from twisted.internet.protocol import DatagramProtocol
-from twisted.internet import reactor
-from struct import unpack, error as StructError
from socket import inet_aton
-from subprocess import Popen
-from os import path, getenv
+from struct import error as StructError, unpack
+
+from twisted.internet import reactor
+from twisted.internet.protocol import DatagramProtocol
+
+from honeypots.base_server import BaseServer
from honeypots.helper import (
- close_port_wrapper,
- get_free_port,
- kill_server_wrapper,
server_arguments,
- setup_logger,
- set_local_vars,
- check_if_server_is_running,
+ check_bytes,
)
-from uuid import uuid4
-class QDHCPServer:
- def __init__(self, **kwargs):
- self.auto_disabled = None
- self.process = None
- self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8]
- self.config = kwargs.get("config", "")
- if self.config:
- self.logs = setup_logger(__class__.__name__, self.uuid, self.config)
- set_local_vars(self, self.config)
- else:
- self.logs = setup_logger(__class__.__name__, self.uuid, None)
- self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0"
- self.port = (
- (kwargs.get("port", None) and int(kwargs.get("port", None)))
- or (hasattr(self, "port") and self.port)
- or 67
- )
- self.options = (
- kwargs.get("options", "")
- or (hasattr(self, "options") and self.options)
- or getenv("HONEYPOTS_OPTIONS", "")
- or ""
- )
+class QDHCPServer(BaseServer):
+ NAME = "dhcp_server"
+ DEFAULT_PORT = 67
- def dhcp_server_main(self):
+ def server_main(self):
_q_s = self
class CustomDatagramProtocolProtocol(DatagramProtocol):
- def check_bytes(self, string):
- if isinstance(string, bytes):
- return string.decode()
- else:
- return str(string)
-
def payload(self, value, message):
(
op,
@@ -114,7 +83,7 @@ def parse_options(self, raw):
tag_size -= 1
tag += chr(b)
if tag_size == 0:
- options.update({self.check_bytes(tag_name): self.check_bytes(tag)})
+ options.update({check_bytes(tag_name): check_bytes(tag)})
tag_name = None
tag_size = None
tag = ""
@@ -129,7 +98,7 @@ def datagramReceived(self, data, addr):
data.update({"mac_address": mac_address})
_q_s.logs.info(
{
- "server": "dhcp_server",
+ "server": _q_s.NAME,
"action": "query",
"status": "success",
"src_ip": addr[0],
@@ -145,67 +114,6 @@ def datagramReceived(self, data, addr):
)
reactor.run()
- def run_server(self, process=False, auto=False):
- status = "error"
- run = False
- if process:
- if auto and not self.auto_disabled:
- port = get_free_port()
- if port > 0:
- self.port = port
- run = True
- elif self.close_port() and self.kill_server():
- run = True
-
- if run:
- self.process = Popen(
- [
- "python3",
- path.realpath(__file__),
- "--custom",
- "--ip",
- str(self.ip),
- "--port",
- str(self.port),
- "--options",
- str(self.options),
- "--config",
- str(self.config),
- "--uuid",
- str(self.uuid),
- ]
- )
- if self.process.poll() is None and check_if_server_is_running(self.uuid):
- status = "success"
-
- self.logs.info(
- {
- "server": "dhcp_server",
- "action": "process",
- "status": status,
- "src_ip": self.ip,
- "src_port": self.port,
- "dest_ip": self.ip,
- "dest_port": self.port,
- }
- )
-
- if status == "success":
- return True
- else:
- self.kill_server()
- return False
- else:
- self.dhcp_server_main()
-
- def close_port(self):
- ret = close_port_wrapper("dhcp_server", self.ip, self.port, self.logs)
- return ret
-
- def kill_server(self):
- ret = kill_server_wrapper("dhcp_server", self.uuid, self.process)
- return ret
-
def test_server(self, ip=None, port=None):
pass
diff --git a/honeypots/dns_server.py b/honeypots/dns_server.py
index a05fcd4..48aaeb0 100644
--- a/honeypots/dns_server.py
+++ b/honeypots/dns_server.py
@@ -12,50 +12,27 @@
from __future__ import annotations
+from contextlib import suppress
+
+from twisted.internet import defer, reactor
from twisted.names import dns, error, client
from twisted.names.server import DNSServerFactory
-from twisted.internet import defer, reactor
-from subprocess import Popen
-from os import path, getenv
+
+from honeypots.base_server import BaseServer
from honeypots.helper import (
- close_port_wrapper,
- get_free_port,
- kill_server_wrapper,
server_arguments,
- setup_logger,
- set_local_vars,
- check_if_server_is_running,
)
-from uuid import uuid4
-from contextlib import suppress
-class QDNSServer:
+class QDNSServer(BaseServer):
+ NAME = "dns_server"
+ DEFAULT_PORT = 53
+
def __init__(self, **kwargs):
- self.auto_disabled = None
+ super().__init__(**kwargs)
self.resolver_addresses = [("8.8.8.8", 53)]
- self.process = None
- self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8]
- self.config = kwargs.get("config", "")
- if self.config:
- self.logs = setup_logger(__class__.__name__, self.uuid, self.config)
- set_local_vars(self, self.config)
- else:
- self.logs = setup_logger(__class__.__name__, self.uuid, None)
- self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0"
- self.port = (
- (kwargs.get("port", None) and int(kwargs.get("port", None)))
- or (hasattr(self, "port") and self.port)
- or 53
- )
- self.options = (
- kwargs.get("options", "")
- or (hasattr(self, "options") and self.options)
- or getenv("HONEYPOTS_OPTIONS", "")
- or ""
- )
-
- def dns_server_main(self):
+
+ def server_main(self):
_q_s = self
class CustomClientResolver(client.Resolver):
@@ -78,7 +55,7 @@ def gotResolverResponse(self, response, protocol, message, address):
for item in items:
_q_s.logs.info(
{
- "server": "dns_server",
+ "server": _q_s.NAME,
"action": "query",
"src_ip": src_ip,
"src_port": src_port,
@@ -93,7 +70,7 @@ class CustomDnsUdpProtocol(dns.DNSDatagramProtocol):
def datagramReceived(self, data: bytes, addr: tuple[str, int]):
_q_s.logs.info(
{
- "server": "dns_server",
+ "server": _q_s.NAME,
"action": "connection",
"src_ip": addr[0],
"src_port": addr[1],
@@ -111,68 +88,6 @@ def datagramReceived(self, data: bytes, addr: tuple[str, int]):
reactor.listenTCP(self.port, self.factory, interface=self.ip)
reactor.run()
- def run_server(self, process=False, auto=False):
- status = "error"
- run = False
- if process:
- if auto and not self.auto_disabled:
- port = get_free_port()
- if port > 0:
- self.port = port
- run = True
- elif self.close_port() and self.kill_server():
- run = True
-
- if run:
- self.process = Popen(
- [
- "python3",
- path.realpath(__file__),
- "--custom",
- "--ip",
- str(self.ip),
- "--port",
- str(self.port),
- "--options",
- str(self.options),
- "--config",
- str(self.config),
- "--uuid",
- str(self.uuid),
- ]
- )
- if self.process.poll() is None and check_if_server_is_running(self.uuid):
- status = "success"
-
- self.logs.info(
- {
- "server": "dns_server",
- "action": "process",
- "status": status,
- "src_ip": self.ip,
- "src_port": self.port,
- "dest_ip": self.ip,
- "dest_port": self.port,
- }
- )
-
- if status == "success":
- return True
- else:
- self.kill_server()
- return False
- else:
- self.dns_server_main()
- return None
-
- def close_port(self):
- ret = close_port_wrapper("dns_server", self.ip, self.port, self.logs)
- return ret
-
- def kill_server(self):
- ret = kill_server_wrapper("dns_server", self.uuid, self.process)
- return ret
-
def test_server(self, ip=None, port=None, domain=None):
with suppress(Exception):
from dns.resolver import Resolver
diff --git a/honeypots/elastic_server.py b/honeypots/elastic_server.py
index 4b6b105..d126a58 100644
--- a/honeypots/elastic_server.py
+++ b/honeypots/elastic_server.py
@@ -11,83 +11,27 @@
"""
from base64 import b64encode, b64decode
-from json import dumps
+from contextlib import suppress
from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
+from json import dumps
+from ssl import wrap_socket
from urllib.parse import urlparse
from zlib import compressobj, DEFLATED
-from subprocess import Popen
-from ssl import wrap_socket
-from uuid import uuid4
-from os import path, getenv
-from OpenSSL import crypto
-from tempfile import gettempdir, _get_candidate_names
+
+from honeypots.base_server import BaseServer
from honeypots.helper import (
- check_if_server_is_running,
- close_port_wrapper,
- get_free_port,
- kill_server_wrapper,
server_arguments,
- set_local_vars,
- setup_logger,
+ create_certificate,
+ check_bytes,
)
-from contextlib import suppress
-
-class QElasticServer:
- def __init__(self, **kwargs):
- self.auto_disabled = None
- self.key = path.join(gettempdir(), next(_get_candidate_names()))
- self.cert = path.join(gettempdir(), next(_get_candidate_names()))
- self.process = None
- self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8]
- self.config = kwargs.get("config", "")
- if self.config:
- self.logs = setup_logger(__class__.__name__, self.uuid, self.config)
- set_local_vars(self, self.config)
- else:
- self.logs = setup_logger(__class__.__name__, self.uuid, None)
- self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0"
- self.port = (
- (kwargs.get("port", None) and int(kwargs.get("port", None)))
- or (hasattr(self, "port") and self.port)
- or 9200
- )
- self.username = (
- kwargs.get("username", None)
- or (hasattr(self, "username") and self.username)
- or "elastic"
- )
- self.password = (
- kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test"
- )
- self.options = (
- kwargs.get("options", "")
- or (hasattr(self, "options") and self.options)
- or getenv("HONEYPOTS_OPTIONS", "")
- or ""
- )
- def CreateCert(self, host_name, key, cert):
- pk = crypto.PKey()
- pk.generate_key(crypto.TYPE_RSA, 2048)
- c = crypto.X509()
- c.get_subject().C = "US"
- c.get_subject().ST = "OR"
- c.get_subject().L = "None"
- c.get_subject().O = "None"
- c.get_subject().OU = "None"
- c.get_subject().CN = next(_get_candidate_names())
- c.set_serial_number(0)
- before, after = (0, 60 * 60 * 24 * 365 * 2)
- c.gmtime_adj_notBefore(before)
- c.gmtime_adj_notAfter(after)
- c.set_issuer(c.get_subject())
- c.set_pubkey(pk)
- c.sign(pk, "sha256")
- open(cert, "wb").write(crypto.dump_certificate(crypto.FILETYPE_PEM, c))
- open(key, "wb").write(crypto.dump_privatekey(crypto.FILETYPE_PEM, pk))
+class QElasticServer(BaseServer):
+ NAME = "elastic_server"
+ DEFAULT_PORT = 9200
+ DEFAULT_USERNAME = "elastic"
- def elastic_server_main(self):
+ def server_main(self):
_q_s = self
class CustomElasticServerHandler(SimpleHTTPRequestHandler):
@@ -97,19 +41,12 @@ class CustomElasticServerHandler(SimpleHTTPRequestHandler):
def _dump_headers(self):
headers = {}
with suppress(Exception):
-
- def check_bytes(string):
- if isinstance(string, bytes):
- return string.decode()
- else:
- return str(string)
-
for item, value in dict(self.headers).items():
headers.update({check_bytes(item): check_bytes(value)})
_q_s.logs.info(
{
- "server": "elastic_server",
+ "server": _q_s.NAME,
"action": "dump",
"data": check_bytes(self.raw_requestline),
"src_ip": self.client_address[0],
@@ -174,7 +111,7 @@ def do_GET(self):
if self.headers.get("Authorization") is None:
_q_s.logs.info(
{
- "server": "elastic_server",
+ "server": _q_s.NAME,
"action": "login",
"status": "failed",
"src_ip": self.client_address[0],
@@ -218,7 +155,7 @@ def do_GET(self):
extracted = ""
_q_s.logs.info(
{
- "server": "elastic_server",
+ "server": _q_s.NAME,
"action": "login",
"status": "success",
"src_ip": self.client_address[0],
@@ -401,7 +338,7 @@ def do_GET(self):
username, password = basic.split(":")
_q_s.logs.info(
{
- "server": "elastic_server",
+ "server": _q_s.NAME,
"action": "login",
"status": "failed",
"src_ip": self.client_address[0],
@@ -452,7 +389,7 @@ def log_message(self, format, *args):
def handle_one_request(self):
_q_s.logs.info(
{
- "server": "elastic_server",
+ "server": _q_s.NAME,
"action": "connection",
"src_ip": self.client_address[0],
"src_port": self.client_address[1],
@@ -474,84 +411,16 @@ def set_auth_key(self, username, password):
def get_auth_key(self):
return self.key
- server = CustomElasticServer((self.ip, self.port))
- server.set_auth_key(self.username, self.password)
- self.CreateCert("localhost", self.key, self.cert)
- server.socket = wrap_socket(
- server.socket,
- keyfile=self.key,
- certfile=self.cert,
- server_side=True,
- )
- server.serve_forever()
-
- def run_server(self, process=False, auto=False):
- status = "error"
- run = False
- if process:
- if auto and not self.auto_disabled:
- port = get_free_port()
- if port > 0:
- self.port = port
- run = True
- elif self.close_port() and self.kill_server():
- run = True
-
- if run:
- self.process = Popen(
- [
- "python3",
- path.realpath(__file__),
- "--custom",
- "--ip",
- str(self.ip),
- "--port",
- str(self.port),
- "--username",
- str(self.username),
- "--password",
- str(self.password),
- "--options",
- str(self.options),
- "--config",
- str(self.config),
- "--uuid",
- str(self.uuid),
- ]
- )
- if self.process.poll() is None and check_if_server_is_running(self.uuid):
- status = "success"
-
- self.logs.info(
- {
- "server": "elastic_server",
- "action": "process",
- "status": status,
- "src_ip": self.ip,
- "src_port": self.port,
- "username": self.username,
- "password": self.password,
- "dest_ip": self.ip,
- "dest_port": self.port,
- }
+ with create_certificate() as (cert, key):
+ server = CustomElasticServer((self.ip, self.port))
+ server.set_auth_key(self.username, self.password)
+ server.socket = wrap_socket(
+ server.socket,
+ keyfile=key,
+ certfile=cert,
+ server_side=True,
)
-
- if status == "success":
- return True
- else:
- self.kill_server()
- return False
- else:
- self.elastic_server_main()
- return None
-
- def close_port(self):
- ret = close_port_wrapper("elastic_server", self.ip, self.port, self.logs)
- return ret
-
- def kill_server(self):
- ret = kill_server_wrapper("elastic_server", self.uuid, self.process)
- return ret
+ server.serve_forever()
def test_server(self, ip=None, port=None, username=None, password=None):
with suppress(Exception):
diff --git a/honeypots/ftp_server.py b/honeypots/ftp_server.py
index f810312..826e5d0 100644
--- a/honeypots/ftp_server.py
+++ b/honeypots/ftp_server.py
@@ -10,6 +10,15 @@
// -------------------------------------------------------------
"""
+from contextlib import suppress
+from random import choice
+from tempfile import TemporaryDirectory
+
+from twisted.cred import portal, credentials
+from twisted.cred.checkers import ICredentialsChecker
+from twisted.cred.error import UnauthorizedLogin, UnhandledCredentials
+from twisted.cred.portal import Portal
+from twisted.internet import reactor, defer
from twisted.protocols.ftp import (
FTPAnonymousShell,
FTPFactory,
@@ -19,33 +28,22 @@
AuthorizationError,
USR_LOGGED_IN_PROCEED,
)
-from twisted.internet import reactor, defer
-from twisted.cred.portal import Portal
-from twisted.cred import portal, credentials
-from twisted.cred.error import UnauthorizedLogin, UnhandledCredentials
-from twisted.cred.checkers import ICredentialsChecker
-from zope.interface import implementer
from twisted.python import filepath
-from random import choice
-from subprocess import Popen
-from os import path, getenv
+from zope.interface import implementer
+
+from honeypots.base_server import BaseServer
from honeypots.helper import (
- close_port_wrapper,
- get_free_port,
- kill_server_wrapper,
server_arguments,
- setup_logger,
- set_local_vars,
- check_if_server_is_running,
+ check_bytes,
)
-from uuid import uuid4
-from contextlib import suppress
-from tempfile import TemporaryDirectory
-class QFTPServer:
+class QFTPServer(BaseServer):
+ NAME = "ftp_server"
+ DEFAULT_PORT = 21
+
def __init__(self, **kwargs):
- self.auto_disabled = None
+ super().__init__(**kwargs)
self.mocking_server = choice(
[
"ProFTPD 1.2.10",
@@ -56,35 +54,9 @@ def __init__(self, **kwargs):
"ProFTPD 1.2.8",
]
)
- self.process = None
- self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8]
- self.config = kwargs.get("config", "")
- if self.config:
- self.logs = setup_logger(__class__.__name__, self.uuid, self.config)
- set_local_vars(self, self.config)
- else:
- self.logs = setup_logger(__class__.__name__, self.uuid, None)
- self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0"
- self.port = (
- (kwargs.get("port", None) and int(kwargs.get("port", None)))
- or (hasattr(self, "port") and self.port)
- or 21
- )
- self.username = (
- kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test"
- )
- self.password = (
- kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test"
- )
- self.options = (
- kwargs.get("options", "")
- or (hasattr(self, "options") and self.options)
- or getenv("HONEYPOTS_OPTIONS", "")
- or ""
- )
self.temp_folder = TemporaryDirectory()
- def ftp_server_main(self):
+ def server_main(self):
_q_s = self
@implementer(portal.IRealm)
@@ -103,16 +75,10 @@ def requestAvatar(self, avatarId, mind, *interfaces):
class CustomAccess:
credentialInterfaces = (credentials.IAnonymous, credentials.IUsernamePassword)
- def check_bytes(self, string):
- if isinstance(string, bytes):
- return string.decode()
- else:
- return str(string)
-
def requestAvatarId(self, credentials):
with suppress(Exception):
- username = self.check_bytes(credentials.username)
- password = self.check_bytes(credentials.password)
+ username = check_bytes(credentials.username)
+ password = check_bytes(credentials.password)
if username == _q_s.username and password == _q_s.password:
username = _q_s.username
password = _q_s.password
@@ -120,16 +86,10 @@ def requestAvatarId(self, credentials):
return defer.fail(UnauthorizedLogin())
class CustomFTPProtocol(FTP):
- def check_bytes(self, string):
- if isinstance(string, bytes):
- return string.decode()
- else:
- return str(string)
-
def connectionMade(self):
_q_s.logs.info(
{
- "server": "ftp_server",
+ "server": _q_s.NAME,
"action": "connection",
"src_ip": self.transport.getPeer().host,
"src_port": self.transport.getPeer().port,
@@ -146,11 +106,11 @@ def processCommand(self, cmd, *params):
if "capture_commands" in _q_s.options:
_q_s.logs.info(
{
- "server": "ftp_server",
+ "server": _q_s.NAME,
"action": "command",
"data": {
- "cmd": self.check_bytes(cmd.upper()),
- "args": self.check_bytes(params),
+ "cmd": check_bytes(cmd.upper()),
+ "args": check_bytes(params),
},
"src_ip": self.transport.getPeer().host,
"src_port": self.transport.getPeer().port,
@@ -161,16 +121,14 @@ def processCommand(self, cmd, *params):
return super().processCommand(cmd, *params)
def ftp_PASS(self, password):
- username = self.check_bytes(self._user)
- password = self.check_bytes(password)
+ username = check_bytes(self._user)
+ password = check_bytes(password)
status = "failed"
if username == _q_s.username and password == _q_s.password:
- username = _q_s.username
- password = _q_s.password
status = "success"
_q_s.logs.info(
{
- "server": "ftp_server",
+ "server": _q_s.NAME,
"action": "login",
"status": status,
"src_ip": self.transport.getPeer().host,
@@ -214,74 +172,6 @@ def _ebLogin(failure):
reactor.listenTCP(port=self.port, factory=factory)
reactor.run()
- def run_server(self, process=False, auto=False):
- status = "error"
- run = False
- if process:
- if auto and not self.auto_disabled:
- port = get_free_port()
- if port > 0:
- self.port = port
- run = True
- elif self.close_port() and self.kill_server():
- run = True
-
- if run:
- self.process = Popen(
- [
- "python3",
- path.realpath(__file__),
- "--custom",
- "--ip",
- str(self.ip),
- "--port",
- str(self.port),
- "--username",
- str(self.username),
- "--password",
- str(self.password),
- "--options",
- str(self.options),
- "--config",
- str(self.config),
- "--uuid",
- str(self.uuid),
- ]
- )
- if self.process.poll() is None and check_if_server_is_running(self.uuid):
- status = "success"
-
- self.logs.info(
- {
- "server": "ftp_server",
- "action": "process",
- "status": status,
- "src_ip": self.ip,
- "src_port": self.port,
- "username": self.username,
- "password": self.password,
- "dest_ip": self.ip,
- "dest_port": self.port,
- }
- )
-
- if status == "success":
- return True
- else:
- self.kill_server()
- return False
- else:
- self.ftp_server_main()
- return None
-
- def close_port(self):
- ret = close_port_wrapper("ftp_server", self.ip, self.port, self.logs)
- return ret
-
- def kill_server(self):
- ret = kill_server_wrapper("ftp_server", self.uuid, self.process)
- return ret
-
def test_server(self, ip=None, port=None, username=None, password=None):
with suppress(Exception):
from ftplib import FTP as FFTP
diff --git a/honeypots/helper.py b/honeypots/helper.py
index ef48867..4c22c52 100644
--- a/honeypots/helper.py
+++ b/honeypots/helper.py
@@ -9,11 +9,13 @@
// contributors list qeeqbox/honeypots/graphs/contributors
// -------------------------------------------------------------
"""
+from __future__ import annotations
+
import logging
import sys
from argparse import ArgumentParser
from collections.abc import Mapping
-from contextlib import suppress
+from contextlib import suppress, contextmanager
from datetime import datetime
from json import dumps, JSONEncoder, load
from logging import DEBUG, Formatter, getLogger, Handler
@@ -24,10 +26,12 @@
from socket import AF_INET, SOCK_STREAM, socket
from sqlite3 import connect as sqlite3_connect
from sys import stdout
-from tempfile import _get_candidate_names, gettempdir
+from tempfile import _get_candidate_names, gettempdir, NamedTemporaryFile
from time import sleep
+from typing import Any, Iterator
from urllib.parse import urlparse
+from OpenSSL import crypto
from psutil import process_iter
from psycopg2 import connect as psycopg2_connect, sql
@@ -155,12 +159,6 @@ def get_running_servers():
return temp_list
-def disable_logger(logger_type, object):
- if logger_type == 1:
- temp_name = path.join(gettempdir(), next(_get_candidate_names()))
- object.startLogging(open(temp_name, "w"), setStdout=False)
-
-
def setup_logger(name, temp_name, config, drop=False):
logs = "terminal"
logs_location = ""
@@ -687,3 +685,60 @@ def server_arguments():
)
_server_parsergroupdef.add_argument("--uuid", type=str, help="unique id", required=False)
return _server_parser.parse_args()
+
+
+@contextmanager
+def create_certificate() -> Iterator[tuple[str, str]]:
+ pk = crypto.PKey()
+ pk.generate_key(crypto.TYPE_RSA, 2048)
+ certificate = crypto.X509()
+ certificate.get_subject().C = "US"
+ certificate.get_subject().ST = "OR"
+ certificate.get_subject().L = "None"
+ certificate.get_subject().O = "None"
+ certificate.get_subject().OU = "None"
+ certificate.get_subject().CN = next(_get_candidate_names())
+ certificate.set_serial_number(0)
+ before, after = (0, 60 * 60 * 24 * 365 * 2)
+ certificate.gmtime_adj_notBefore(before)
+ certificate.gmtime_adj_notAfter(after)
+ certificate.set_issuer(certificate.get_subject())
+ certificate.set_pubkey(pk)
+ certificate.sign(pk, "sha256")
+ with NamedTemporaryFile() as cert, NamedTemporaryFile() as key:
+ cert_path = Path(cert.name)
+ key_path = Path(key.name)
+ cert_path.write_bytes(crypto.dump_certificate(crypto.FILETYPE_PEM, certificate))
+ key_path.write_bytes(crypto.dump_privatekey(crypto.FILETYPE_PEM, pk))
+ yield cert.name, key.name
+
+
+def check_bytes(string: Any) -> str:
+ if isinstance(string, bytes):
+ return string.decode("utf-8", errors="replace")
+ return str(string)
+
+
+def load_template(filename: str) -> str:
+ file_path = Path(__file__).parent / "data" / filename
+ return file_path.read_text()
+
+
+def get_headers_and_ip_from_request(request, options):
+ headers = {}
+ client_ip = ""
+ with suppress(Exception):
+ for item, value in dict(request.requestHeaders.getAllRawHeaders()).items():
+ headers.update({check_bytes(item): ",".join(map(check_bytes, value))})
+ headers.update({"method": check_bytes(request.method)})
+ headers.update({"uri": check_bytes(request.uri)})
+ if "fix_get_client_ip" in options:
+ with suppress(Exception):
+ raw_headers = dict(request.requestHeaders.getAllRawHeaders())
+ if b"X-Forwarded-For" in raw_headers:
+ client_ip = check_bytes(raw_headers[b"X-Forwarded-For"][0])
+ elif b"X-Real-IP" in raw_headers:
+ client_ip = check_bytes(raw_headers[b"X-Real-IP"][0])
+ if client_ip == "":
+ client_ip = request.getClientAddress().host
+ return client_ip, headers
diff --git a/honeypots/http_proxy_server.py b/honeypots/http_proxy_server.py
index 66c63f2..fceca05 100644
--- a/honeypots/http_proxy_server.py
+++ b/honeypots/http_proxy_server.py
@@ -11,59 +11,30 @@
"""
from __future__ import annotations
+from contextlib import suppress
+from email.parser import BytesParser
from pathlib import Path
-from shlex import split
from dns.resolver import resolve as dsnquery
from twisted.internet import reactor
from twisted.internet.protocol import Protocol, Factory
-from subprocess import Popen
-from email.parser import BytesParser
-from os import getenv
+
+from honeypots.base_server import BaseServer
from honeypots.helper import (
- close_port_wrapper,
- get_free_port,
- kill_server_wrapper,
server_arguments,
- set_up_error_logging,
- setup_logger,
- set_local_vars,
- check_if_server_is_running,
+ load_template,
)
-from uuid import uuid4
-from contextlib import suppress
-
-DUMMY_TEMPLATE = (Path(__file__).parent / "data" / "dummy_page.html").read_text()
+DUMMY_TEMPLATE = load_template("dummy_page.html")
-class QHTTPProxyServer:
+class QHTTPProxyServer(BaseServer):
NAME = "http_proxy_server"
+ DEFAULT_PORT = 8080
def __init__(self, **kwargs):
- self.auto_disabled = None
- self.process = None
- self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8]
- self.config = kwargs.get("config", "")
self.template: str | None = None
- if self.config:
- self.logs = setup_logger(__class__.__name__, self.uuid, self.config)
- set_local_vars(self, self.config)
- else:
- self.logs = setup_logger(__class__.__name__, self.uuid, None)
- self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0"
- self.port = (
- (kwargs.get("port", None) and int(kwargs.get("port", None)))
- or (hasattr(self, "port") and self.port)
- or 8080
- )
- self.options = (
- kwargs.get("options", "")
- or (hasattr(self, "options") and self.options)
- or getenv("HONEYPOTS_OPTIONS", "")
- or ""
- )
- self.logger = set_up_error_logging()
+ super().__init__(**kwargs)
self.template_contents: str | None = self._load_template()
def _load_template(self) -> str | None:
@@ -78,7 +49,7 @@ def _load_template(self) -> str | None:
self.logger.error(f"[{self.NAME}]: Template file {self.template} not found")
return None
- def http_proxy_server_main(self):
+ def server_main(self):
_q_s = self
class CustomProtocolParent(Protocol):
@@ -135,54 +106,6 @@ def write(self, data):
reactor.listenTCP(port=self.port, factory=factory, interface=self.ip)
reactor.run()
- def run_server(self, process=False, auto=False) -> bool | None:
- status = "error"
- run = False
- if not process:
- self.http_proxy_server_main()
- return None
-
- if auto and not self.auto_disabled:
- port = get_free_port()
- if port > 0:
- self.port = port
- run = True
- elif self.close_port() and self.kill_server():
- run = True
-
- if run:
- self.process = Popen(
- split(
- f"python3 {Path(__file__)} --custom --ip {self.ip} --port {self.port} "
- f"--options '{self.options}' --config '{self.config}' --uuid {self.uuid}"
- )
- )
- if self.process.poll() is None and check_if_server_is_running(self.uuid):
- status = "success"
-
- self.logs.info(
- {
- "server": self.NAME,
- "action": "process",
- "status": status,
- "src_ip": self.ip,
- "src_port": self.port,
- "dest_ip": self.ip,
- "dest_port": self.port,
- }
- )
-
- if status == "success":
- return True
- self.kill_server()
- return False
-
- def close_port(self):
- return close_port_wrapper(self.NAME, self.ip, self.port, self.logs)
-
- def kill_server(self):
- return kill_server_wrapper(self.NAME, self.uuid, self.process)
-
def test_server(self, ip=None, port=None, domain=None):
with suppress(Exception):
from requests import get
diff --git a/honeypots/http_server.py b/honeypots/http_server.py
index 494b1c3..e58881b 100644
--- a/honeypots/http_server.py
+++ b/honeypots/http_server.py
@@ -10,349 +10,26 @@
// -------------------------------------------------------------
"""
-from cgi import FieldStorage
from contextlib import suppress
-from os import getenv, path
-from random import choice
-from subprocess import Popen
-from tempfile import _get_candidate_names, gettempdir
-from uuid import uuid4
from twisted.internet import reactor
-from twisted.web.resource import Resource
from twisted.web.server import Site
+from honeypots.base_http_server import BaseHttpServer
from honeypots.helper import (
- check_if_server_is_running,
- close_port_wrapper,
- get_free_port,
- kill_server_wrapper,
server_arguments,
- set_local_vars,
- setup_logger,
)
-class QHTTPServer:
- def __init__(self, **kwargs):
- self.auto_disabled = None
- self.key = path.join(gettempdir(), next(_get_candidate_names()))
- self.cert = path.join(gettempdir(), next(_get_candidate_names()))
- self.mocking_server = choice(
- [
- "Apache",
- "nginx",
- "Microsoft-IIS/7.5",
- "Microsoft-HTTPAPI/2.0",
- "Apache/2.2.15",
- "SmartXFilter",
- "Microsoft-IIS/8.5",
- "Apache/2.4.6",
- "Apache-Coyote/1.1",
- "Microsoft-IIS/7.0",
- "Apache/2.4.18",
- "AkamaiGHost",
- "Apache/2.2.25",
- "Microsoft-IIS/10.0",
- "Apache/2.2.3",
- "nginx/1.12.1",
- "Apache/2.4.29",
- "cloudflare",
- "Apache/2.2.22",
- ]
- )
- self.process = None
- self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8]
- self.config = kwargs.get("config", "")
- if self.config:
- self.logs = setup_logger(__class__.__name__, self.uuid, self.config)
- set_local_vars(self, self.config)
- else:
- self.logs = setup_logger(__class__.__name__, self.uuid, None)
- self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0"
- self.port = (
- (kwargs.get("port", None) and int(kwargs.get("port", None)))
- or (hasattr(self, "port") and self.port)
- or 80
- )
- self.username = (
- kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test"
- )
- self.password = (
- kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test"
- )
- self.options = (
- kwargs.get("options", "")
- or (hasattr(self, "options") and self.options)
- or getenv("HONEYPOTS_OPTIONS", "")
- or ""
- )
-
- def http_server_main(self):
- _q_s = self
-
- class MainResource(Resource):
- isLeaf = True
-
- home_file = b"""
-
-
-
-
-
-
- Login
-
-
-
-
-
-
- We'll back soon..
-
-
-
-
-"""
-
- login_file = b"""
-
-
-
-
-
- Login
-
-
-
-
-
-
-"""
-
- def check_bytes(self, string):
- if isinstance(string, bytes):
- return string.decode()
- else:
- return str(string)
-
- def render(self, request):
- headers = {}
- client_ip = ""
-
- with suppress(Exception):
-
- def check_bytes(string):
- if isinstance(string, bytes):
- return string.decode()
- else:
- return str(string)
-
- for item, value in dict(request.requestHeaders.getAllRawHeaders()).items():
- headers.update({check_bytes(item): ",".join(map(check_bytes, value))})
- headers.update({"method": check_bytes(request.method)})
- headers.update({"uri": check_bytes(request.uri)})
-
- if "fix_get_client_ip" in _q_s.options:
- with suppress(Exception):
- raw_headers = dict(request.requestHeaders.getAllRawHeaders())
- if b"X-Forwarded-For" in raw_headers:
- client_ip = check_bytes(raw_headers[b"X-Forwarded-For"][0])
- elif b"X-Real-IP" in raw_headers:
- client_ip = check_bytes(raw_headers[b"X-Real-IP"][0])
+class QHTTPServer(BaseHttpServer):
+ NAME = "http_server"
+ DEFAULT_PORT = 80
- if client_ip == "":
- client_ip = request.getClientAddress().host
-
- with suppress(Exception):
- if "capture_commands" in _q_s.options:
- _q_s.logs.info(
- {
- "server": "http_server",
- "action": "connection",
- "src_ip": client_ip,
- "src_port": request.getClientAddress().port,
- "dest_ip": _q_s.ip,
- "dest_port": _q_s.port,
- "data": headers,
- }
- )
- else:
- _q_s.logs.info(
- {
- "server": "http_server",
- "action": "connection",
- "src_ip": client_ip,
- "src_port": request.getClientAddress().port,
- "dest_ip": _q_s.ip,
- "dest_port": _q_s.port,
- }
- )
-
- if _q_s.mocking_server != "":
- request.responseHeaders.removeHeader("Server")
- request.responseHeaders.addRawHeader("Server", _q_s.mocking_server)
-
- if request.method == b"GET" or request.method == b"POST":
- _q_s.logs.info(
- {
- "server": "http_server",
- "action": request.method.decode(),
- "src_ip": client_ip,
- "src_port": request.getClientAddress().port,
- "dest_ip": _q_s.ip,
- "dest_port": _q_s.port,
- }
- )
-
- if request.method == b"GET":
- if request.uri == b"/login.html":
- if _q_s.username != "" and _q_s.password != "":
- request.responseHeaders.addRawHeader(
- "Content-Type", "text/html; charset=utf-8"
- )
- return self.login_file
-
- request.responseHeaders.addRawHeader(
- "Content-Type", "text/html; charset=utf-8"
- )
- return self.login_file
-
- elif request.method == b"POST":
- self.headers = request.getAllHeaders()
- if request.uri == b"/login.html" or b"/":
- if _q_s.username != "" and _q_s.password != "":
- form = FieldStorage(
- fp=request.content,
- headers=self.headers,
- environ={
- "REQUEST_METHOD": "POST",
- "CONTENT_TYPE": self.headers.get(
- b"content-type",
- b"application/x-www-form-urlencoded",
- ),
- },
- )
- if "username" in form and "password" in form:
- username = self.check_bytes(form["username"].value)
- password = self.check_bytes(form["password"].value)
- status = "failed"
- if username == _q_s.username and password == _q_s.password:
- username = _q_s.username
- password = _q_s.password
- status = "success"
- _q_s.logs.info(
- {
- "server": "http_server",
- "action": "login",
- "status": status,
- "src_ip": client_ip,
- "src_port": request.getClientAddress().port,
- "username": username,
- "password": password,
- "dest_ip": _q_s.ip,
- "dest_port": _q_s.port,
- }
- )
-
- request.responseHeaders.addRawHeader(
- "Content-Type", "text/html; charset=utf-8"
- )
- return self.home_file
- else:
- request.responseHeaders.addRawHeader(
- "Content-Type", "text/html; charset=utf-8"
- )
- return self.home_file
-
- reactor.listenTCP(self.port, Site(MainResource()))
+ def server_main(self):
+ resource = self.MainResource(hp_server=self)
+ reactor.listenTCP(self.port, Site(resource))
reactor.run()
- def run_server(self, process=False, auto=False):
- status = "error"
- run = False
- if process:
- if auto and not self.auto_disabled:
- port = get_free_port()
- if port > 0:
- self.port = port
- run = True
- elif self.close_port() and self.kill_server():
- run = True
-
- if run:
- self.process = Popen(
- [
- "python3",
- path.realpath(__file__),
- "--custom",
- "--ip",
- str(self.ip),
- "--port",
- str(self.port),
- "--username",
- str(self.username),
- "--password",
- str(self.password),
- "--options",
- str(self.options),
- "--config",
- str(self.config),
- "--uuid",
- str(self.uuid),
- ]
- )
- if self.process.poll() is None and check_if_server_is_running(self.uuid):
- status = "success"
-
- self.logs.info(
- {
- "server": "http_server",
- "action": "process",
- "status": status,
- "src_ip": self.ip,
- "src_port": self.port,
- "username": self.username,
- "password": self.password,
- "dest_ip": self.ip,
- "dest_port": self.port,
- }
- )
-
- if status == "success":
- return True
- else:
- self.kill_server()
- return False
- else:
- self.http_server_main()
-
- def close_port(self):
- ret = close_port_wrapper("http_server", self.ip, self.port, self.logs)
- return ret
-
- def kill_server(self):
- ret = kill_server_wrapper("http_server", self.uuid, self.process)
- return ret
-
def test_server(self, ip=None, port=None, username=None, password=None):
with suppress(Exception):
from requests import get, post
diff --git a/honeypots/https_server.py b/honeypots/https_server.py
index ec5e803..fd030f9 100644
--- a/honeypots/https_server.py
+++ b/honeypots/https_server.py
@@ -10,370 +10,28 @@
// -------------------------------------------------------------
"""
-from cgi import FieldStorage
from contextlib import suppress
-from os import getenv, path
-from random import choice
-from subprocess import Popen
-from tempfile import _get_candidate_names, gettempdir
-from uuid import uuid4
-from OpenSSL import crypto
from twisted.internet import reactor, ssl
-from twisted.web.resource import Resource
from twisted.web.server import Site
+from honeypots.base_http_server import BaseHttpServer
from honeypots.helper import (
- check_if_server_is_running,
- close_port_wrapper,
- get_free_port,
- kill_server_wrapper,
server_arguments,
- set_local_vars,
- setup_logger,
+ create_certificate,
)
-class QHTTPSServer:
- def __init__(self, **kwargs):
- self.auto_disabled = None
- self.key = path.join(gettempdir(), next(_get_candidate_names()))
- self.cert = path.join(gettempdir(), next(_get_candidate_names()))
- self.mocking_server = choice(
- [
- "Apache",
- "nginx",
- "Microsoft-IIS/7.5",
- "Microsoft-HTTPAPI/2.0",
- "Apache/2.2.15",
- "SmartXFilter",
- "Microsoft-IIS/8.5",
- "Apache/2.4.6",
- "Apache-Coyote/1.1",
- "Microsoft-IIS/7.0",
- "Apache/2.4.18",
- "AkamaiGHost",
- "Apache/2.2.25",
- "Microsoft-IIS/10.0",
- "Apache/2.2.3",
- "nginx/1.12.1",
- "Apache/2.4.29",
- "cloudflare",
- "Apache/2.2.22",
- ]
- )
- self.process = None
- self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8]
- self.config = kwargs.get("config", "")
- if self.config:
- self.logs = setup_logger(__class__.__name__, self.uuid, self.config)
- set_local_vars(self, self.config)
- else:
- self.logs = setup_logger(__class__.__name__, self.uuid, None)
- self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0"
- self.port = (
- (kwargs.get("port", None) and int(kwargs.get("port", None)))
- or (hasattr(self, "port") and self.port)
- or 443
- )
- self.username = (
- kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test"
- )
- self.password = (
- kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test"
- )
- self.options = (
- kwargs.get("options", "")
- or (hasattr(self, "options") and self.options)
- or getenv("HONEYPOTS_OPTIONS", "")
- or ""
- )
-
- def CreateCert(self, host_name, key, cert):
- pk = crypto.PKey()
- pk.generate_key(crypto.TYPE_RSA, 2048)
- c = crypto.X509()
- c.get_subject().C = "US"
- c.get_subject().ST = "OR"
- c.get_subject().L = "None"
- c.get_subject().O = "None"
- c.get_subject().OU = "None"
- c.get_subject().CN = next(_get_candidate_names())
- c.set_serial_number(0)
- before, after = (0, 60 * 60 * 24 * 365 * 2)
- c.gmtime_adj_notBefore(before)
- c.gmtime_adj_notAfter(after)
- c.set_issuer(c.get_subject())
- c.set_pubkey(pk)
- c.sign(pk, "sha256")
- open(cert, "wb").write(crypto.dump_certificate(crypto.FILETYPE_PEM, c))
- open(key, "wb").write(crypto.dump_privatekey(crypto.FILETYPE_PEM, pk))
-
- def https_server_main(self):
- _q_s = self
-
- class MainResource(Resource):
- isLeaf = True
- home_file = b"""
-
-
-
-
-
-
- Login
-
-
-
-
-
-
- We'll back soon..
-
-
-
-
-"""
-
- login_file = b"""
-
-
-
-
-
- Login
-
-
-
-
-
-
-"""
-
- def check_bytes(self, string):
- if isinstance(string, bytes):
- return string.decode()
- else:
- return str(string)
-
- def render(self, request):
- headers = {}
- client_ip = ""
-
- with suppress(Exception):
-
- def check_bytes(string):
- if isinstance(string, bytes):
- return string.decode()
- else:
- return str(string)
-
- for item, value in dict(request.requestHeaders.getAllRawHeaders()).items():
- headers.update({check_bytes(item): ",".join(map(check_bytes, value))})
- headers.update({"method": check_bytes(request.method)})
- headers.update({"uri": check_bytes(request.uri)})
-
- if "fix_get_client_ip" in _q_s.options:
- with suppress(Exception):
- raw_headers = dict(request.requestHeaders.getAllRawHeaders())
- if b"X-Forwarded-For" in raw_headers:
- client_ip = check_bytes(raw_headers[b"X-Forwarded-For"][0])
- elif b"X-Real-IP" in raw_headers:
- client_ip = check_bytes(raw_headers[b"X-Real-IP"][0])
-
- if client_ip == "":
- client_ip = request.getClientAddress().host
-
- with suppress(Exception):
- if "capture_commands" in _q_s.options:
- _q_s.logs.info(
- {
- "server": "https_server",
- "action": "connection",
- "src_ip": client_ip,
- "src_port": request.getClientAddress().port,
- "dest_ip": _q_s.ip,
- "dest_port": _q_s.port,
- "data": headers,
- }
- )
- else:
- _q_s.logs.info(
- {
- "server": "https_server",
- "action": "connection",
- "src_ip": client_ip,
- "src_port": request.getClientAddress().port,
- "dest_ip": _q_s.ip,
- "dest_port": _q_s.port,
- }
- )
-
- if _q_s.mocking_server != "":
- request.responseHeaders.removeHeader("Server")
- request.responseHeaders.addRawHeader("Server", _q_s.mocking_server)
-
- if request.method == b"GET" or request.method == b"POST":
- _q_s.logs.info(
- {
- "server": "https_server",
- "action": request.method.decode(),
- "src_ip": client_ip,
- "src_port": request.getClientAddress().port,
- "dest_ip": _q_s.ip,
- "dest_port": _q_s.port,
- }
- )
-
- if request.method == b"GET":
- if request.uri == b"/login.html":
- if _q_s.username != "" and _q_s.password != "":
- request.responseHeaders.addRawHeader(
- "Content-Type", "text/html; charset=utf-8"
- )
- return self.login_file
-
- request.responseHeaders.addRawHeader(
- "Content-Type", "text/html; charset=utf-8"
- )
- return self.login_file
-
- elif request.method == b"POST":
- self.headers = request.getAllHeaders()
- if request.uri == b"/login.html" or b"/":
- if _q_s.username != "" and _q_s.password != "":
- form = FieldStorage(
- fp=request.content,
- headers=self.headers,
- environ={
- "REQUEST_METHOD": "POST",
- "CONTENT_TYPE": self.headers.get(
- b"content-type",
- b"application/x-www-form-urlencoded",
- ),
- },
- )
- if "username" in form and "password" in form:
- username = self.check_bytes(form["username"].value)
- password = self.check_bytes(form["password"].value)
- status = "failed"
- if username == _q_s.username and password == _q_s.password:
- username = _q_s.username
- password = _q_s.password
- status = "success"
- _q_s.logs.info(
- {
- "server": "https_server",
- "action": "login",
- "status": status,
- "src_ip": client_ip,
- "src_port": request.getClientAddress().port,
- "username": username,
- "password": password,
- "dest_ip": _q_s.ip,
- "dest_port": _q_s.port,
- }
- )
-
- request.responseHeaders.addRawHeader(
- "Content-Type", "text/html; charset=utf-8"
- )
- return self.home_file
- else:
- request.responseHeaders.addRawHeader(
- "Content-Type", "text/html; charset=utf-8"
- )
- return self.home_file
-
- self.CreateCert("localhost", self.key, self.cert)
- ssl_context = ssl.DefaultOpenSSLContextFactory(self.key, self.cert)
- reactor.listenSSL(self.port, Site(MainResource()), ssl_context)
- reactor.run()
-
- def run_server(self, process=False, auto=False):
- status = "error"
- run = False
- if process:
- if auto and not self.auto_disabled:
- port = get_free_port()
- if port > 0:
- self.port = port
- run = True
- elif self.close_port() and self.kill_server():
- run = True
-
- if run:
- self.process = Popen(
- [
- "python3",
- path.realpath(__file__),
- "--custom",
- "--ip",
- str(self.ip),
- "--port",
- str(self.port),
- "--username",
- str(self.username),
- "--password",
- str(self.password),
- "--options",
- str(self.options),
- "--config",
- str(self.config),
- "--uuid",
- str(self.uuid),
- ]
- )
- if self.process.poll() is None and check_if_server_is_running(self.uuid):
- status = "success"
-
- self.logs.info(
- {
- "server": "https_server",
- "action": "process",
- "status": status,
- "src_ip": self.ip,
- "src_port": self.port,
- "username": self.username,
- "password": self.password,
- "dest_ip": self.ip,
- "dest_port": self.port,
- }
- )
-
- if status == "success":
- return True
- else:
- self.kill_server()
- return False
- else:
- self.https_server_main()
-
- def close_port(self):
- ret = close_port_wrapper("https_server", self.ip, self.port, self.logs)
- return ret
+class QHTTPSServer(BaseHttpServer):
+ NAME = "https_server"
+ DEFAULT_PORT = 443
- def kill_server(self):
- ret = kill_server_wrapper("https_server", self.uuid, self.process)
- return ret
+ def server_main(self):
+ resource = self.MainResource(hp_server=self)
+ with create_certificate() as (cert, key):
+ ssl_context = ssl.DefaultOpenSSLContextFactory(key, cert)
+ reactor.listenSSL(self.port, Site(resource), ssl_context)
+ reactor.run()
def test_server(self, ip=None, port=None, username=None, password=None):
with suppress(Exception):
diff --git a/honeypots/imap_server.py b/honeypots/imap_server.py
index 2e122d7..623b605 100644
--- a/honeypots/imap_server.py
+++ b/honeypots/imap_server.py
@@ -10,69 +10,40 @@
// -------------------------------------------------------------
"""
-from twisted.mail.imap4 import IMAP4Server
-from twisted.internet.protocol import Factory
-from twisted.internet import reactor
+from contextlib import suppress
from random import choice
+
from twisted import cred
-from subprocess import Popen
-from os import path, getenv
+from twisted.internet import reactor
+from twisted.internet.protocol import Factory
+from twisted.mail.imap4 import (
+ IMAP4Server,
+ IllegalClientResponse,
+ IllegalOperation,
+ IllegalMailboxEncoding,
+)
+
+from honeypots.base_server import BaseServer
from honeypots.helper import (
- check_if_server_is_running,
- close_port_wrapper,
- get_free_port,
- kill_server_wrapper,
server_arguments,
- set_local_vars,
- setup_logger,
+ check_bytes,
)
-from uuid import uuid4
-from contextlib import suppress
-class QIMAPServer:
+class QIMAPServer(BaseServer):
+ NAME = "imap_server"
+ DEFAULT_PORT = 143
+
def __init__(self, **kwargs):
- self.auto_disabled = None
+ super().__init__(**kwargs)
self.mocking_server = choice(
[b"OK Microsoft Exchange Server 2003 IMAP4rev1 server version 6.5.6944.0 DC9 ready"]
)
- self.process = None
- self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8]
- self.config = kwargs.get("config", "")
- if self.config:
- self.logs = setup_logger(__class__.__name__, self.uuid, self.config)
- set_local_vars(self, self.config)
- else:
- self.logs = setup_logger(__class__.__name__, self.uuid, None)
- self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0"
- self.port = (
- (kwargs.get("port", None) and int(kwargs.get("port", None)))
- or (hasattr(self, "port") and self.port)
- or 143
- )
- self.username = (
- kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test"
- )
- self.password = (
- kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test"
- )
- self.options = (
- kwargs.get("options", "")
- or (hasattr(self, "options") and self.options)
- or getenv("HONEYPOTS_OPTIONS", "")
- or ""
- )
- def imap_server_main(self):
+ def server_main(self):
_q_s = self
class CustomIMAP4Server(IMAP4Server):
- def check_bytes(self, string):
- if isinstance(string, bytes):
- return string.decode()
- else:
- return str(string)
-
def parse_command(self, line):
args = line.split(None, 2)
rest = None
@@ -95,12 +66,12 @@ def parse_command(self, line):
if "capture_commands" in _q_s.options:
_q_s.logs.info(
{
- "server": "imap_server",
+ "server": _q_s.NAME,
"action": "command",
"data": {
- "cmd": self.check_bytes(cmd),
- "tag": self.check_bytes(tag),
- "data": self.check_bytes(rest),
+ "cmd": check_bytes(cmd),
+ "tag": check_bytes(tag),
+ "data": check_bytes(rest),
},
"src_ip": self.transport.getPeer().host,
"src_port": self.transport.getPeer().port,
@@ -121,7 +92,7 @@ def parse_command(self, line):
def connectionMade(self):
_q_s.logs.info(
{
- "server": "imap_server",
+ "server": _q_s.NAME,
"action": "connection",
"src_ip": self.transport.getPeer().host,
"src_port": self.transport.getPeer().port,
@@ -132,8 +103,8 @@ def connectionMade(self):
self.sendPositiveResponse(message=_q_s.mocking_server)
def authenticateLogin(self, user, passwd):
- username = self.check_bytes(user)
- password = self.check_bytes(passwd)
+ username = check_bytes(user)
+ password = check_bytes(passwd)
status = "failed"
if username == _q_s.username and password == _q_s.password:
username = _q_s.username
@@ -141,7 +112,7 @@ def authenticateLogin(self, user, passwd):
status = "success"
_q_s.logs.info(
{
- "server": "imap_server",
+ "server": _q_s.NAME,
"action": "login",
"status": status,
"src_ip": self.transport.getPeer().host,
@@ -179,73 +150,6 @@ def buildProtocol(self, address):
reactor.listenTCP(port=self.port, factory=factory, interface=self.ip)
reactor.run()
- def run_server(self, process=False, auto=False):
- status = "error"
- run = False
- if process:
- if auto and not self.auto_disabled:
- port = get_free_port()
- if port > 0:
- self.port = port
- run = True
- elif self.close_port() and self.kill_server():
- run = True
-
- if run:
- self.process = Popen(
- [
- "python3",
- path.realpath(__file__),
- "--custom",
- "--ip",
- str(self.ip),
- "--port",
- str(self.port),
- "--username",
- str(self.username),
- "--password",
- str(self.password),
- "--options",
- str(self.options),
- "--config",
- str(self.config),
- "--uuid",
- str(self.uuid),
- ]
- )
- if self.process.poll() is None and check_if_server_is_running(self.uuid):
- status = "success"
-
- self.logs.info(
- {
- "server": "imap_server",
- "action": "process",
- "status": status,
- "src_ip": self.ip,
- "src_port": self.port,
- "username": self.username,
- "password": self.password,
- "dest_ip": self.ip,
- "dest_port": self.port,
- }
- )
-
- if status == "success":
- return True
- else:
- self.kill_server()
- return False
- else:
- self.imap_server_main()
-
- def close_port(self):
- ret = close_port_wrapper("imap_server", self.ip, self.port, self.logs)
- return ret
-
- def kill_server(self):
- ret = kill_server_wrapper("imap_server", self.uuid, self.process)
- return ret
-
def test_server(self, ip=None, port=None, username=None, password=None):
with suppress(Exception):
from imaplib import IMAP4
diff --git a/honeypots/ipp_server.py b/honeypots/ipp_server.py
index 4a2c9a5..6161c9e 100644
--- a/honeypots/ipp_server.py
+++ b/honeypots/ipp_server.py
@@ -9,57 +9,31 @@
// contributors list qeeqbox/honeypots/graphs/contributors
// -------------------------------------------------------------
"""
+from __future__ import annotations
from contextlib import suppress
-from os import getenv, path
from struct import unpack
-from subprocess import Popen
-from typing import Dict
-from uuid import uuid4
from twisted.internet import reactor
from twisted.web.resource import Resource
from twisted.web.server import Site
+from honeypots.base_server import BaseServer
from honeypots.helper import (
- check_if_server_is_running,
- close_port_wrapper,
- get_free_port,
- kill_server_wrapper,
server_arguments,
- set_local_vars,
- setup_logger,
+ check_bytes,
+ get_headers_and_ip_from_request,
)
STATUS_CODE_OK = b"\x00\x00"
STATUS_CODE_BAD_REQUEST = b"\x04\x00"
-class QIPPServer:
- def __init__(self, **kwargs):
- self.auto_disabled = None
- self.process = None
- self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8]
- self.config = kwargs.get("config", "")
- if self.config:
- self.logs = setup_logger(__class__.__name__, self.uuid, self.config)
- set_local_vars(self, self.config)
- else:
- self.logs = setup_logger(__class__.__name__, self.uuid, None)
- self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0"
- self.port = (
- (kwargs.get("port", None) and int(kwargs.get("port", None)))
- or (hasattr(self, "port") and self.port)
- or 631
- )
- self.options = (
- kwargs.get("options", "")
- or (hasattr(self, "options") and self.options)
- or getenv("HONEYPOTS_OPTIONS", "")
- or ""
- )
+class QIPPServer(BaseServer):
+ NAME = "ipp_server"
+ DEFAULT_PORT = 631
- def ipp_server_main(self):
+ def server_main(self):
_q_s = self
class MainResource(Resource):
@@ -210,64 +184,6 @@ class MainResource(Resource):
0x7F: "extension",
}
- status_codes = {
- 0x0000: "successful-ok",
- 0x0001: "successful-ok-ignored-or-substituted-attributes",
- 0x0002: "successful-ok-conflicting-attributes",
- 0x0003: "successful-ok-ignored-subscriptions",
- 0x0004: "ipp-indp-method",
- 0x0005: "successful-ok-too-many-events",
- 0x0006: "ipp-indp-method",
- 0x0007: "successful-ok-events-complete",
- 0x0300: "ipp-get-method",
- 0x0400: "client-error-bad-request",
- 0x0401: "client-error-forbidden",
- 0x0402: "client-error-not-authenticated",
- 0x0403: "client-error-not-authorized",
- 0x0404: "client-error-not-possible",
- 0x0405: "client-error-timeout",
- 0x0406: "client-error-not-found",
- 0x0407: "client-error-gone",
- 0x0408: "client-error-request-entity-too-large",
- 0x0409: "client-error-request-value-too-long",
- 0x040A: "client-error-document-format-not-supported",
- 0x040B: "client-error-attributes-or-values-not-supported",
- 0x040C: "client-error-uri-scheme-not-supported",
- 0x040D: "client-error-charset-not-supported",
- 0x040E: "client-error-conflicting-attributes",
- 0x040F: "client-error-compression-not-supported",
- 0x0410: "client-error-compression-error",
- 0x0411: "client-error-document-format-error",
- 0x0412: "client-error-document-access-error",
- 0x0413: "client-error-attributes-not-settable",
- 0x0414: "client-error-ignored-all-subscriptions",
- 0x0415: "client-error-too-many-subscriptions",
- 0x0416: "ipp-indp-method",
- 0x0417: "ipp-install",
- 0x0418: "client-error-document-password-error",
- 0x0419: "client-error-document-permission-error",
- 0x041A: "client-error-document-security-error",
- 0x041B: "client-error-document-unprintable-error",
- 0x041C: "client-error-account-info-needed",
- 0x041D: "client-error-account-closed",
- 0x041E: "client-error-account-limit-reached",
- 0x041F: "client-error-account-authorization-failed",
- 0x0420: "client-error-not-fetchable",
- 0x0500: "server-error-internal-error",
- 0x0501: "server-error-operation-not-supported",
- 0x0502: "server-error-service-unavailable",
- 0x0503: "server-error-version-not-supported",
- 0x0504: "server-error-device-error",
- 0x0505: "server-error-temporary-error",
- 0x0506: "server-error-not-accepting-jobs",
- 0x0507: "server-error-busy",
- 0x0508: "server-error-job-canceled",
- 0x0509: "server-error-multiple-document-jobs-not-supported",
- 0x050A: "server-error-printer-is-deactivated",
- 0x050B: "server-error-too-many-jobs",
- 0x050C: "server-error-too-many-documents",
- }
-
def get_uint8_t(self, index, data):
return index + 1, unpack("b", data[index : index + 1])[0]
@@ -280,74 +196,28 @@ def get_uint32_t(self, index, data):
def get_string(self, index, length, data):
return index + length, data[index : index + length]
- def check_bytes(self, string):
- if isinstance(string, bytes):
- return string.decode()
- else:
- return str(string)
-
def render_POST(self, request):
- headers = {}
- client_ip = ""
-
- with suppress(Exception):
-
- def check_bytes(string):
- if isinstance(string, bytes):
- return string.decode()
- else:
- return str(string)
-
- for item, value in dict(request.requestHeaders.getAllRawHeaders()).items():
- headers.update({check_bytes(item): ",".join(map(check_bytes, value))})
- headers.update({"method": check_bytes(request.method)})
- headers.update({"uri": check_bytes(request.uri)})
-
- if "fix_get_client_ip" in _q_s.options:
- with suppress(Exception):
- raw_headers = dict(request.requestHeaders.getAllRawHeaders())
- if b"X-Forwarded-For" in raw_headers:
- client_ip = check_bytes(raw_headers[b"X-Forwarded-For"][0])
- elif b"X-Real-IP" in raw_headers:
- client_ip = check_bytes(raw_headers[b"X-Real-IP"][0])
-
- if client_ip == "":
- client_ip = request.getClientAddress().host
+ client_ip, headers = get_headers_and_ip_from_request(request, _q_s.options)
with suppress(Exception):
+ log_data = {
+ "server": _q_s.NAME,
+ "action": "connection",
+ "src_ip": client_ip,
+ "src_port": request.getClientAddress().port,
+ "dest_ip": _q_s.ip,
+ "dest_port": _q_s.port,
+ }
if "capture_commands" in _q_s.options:
- _q_s.logs.info(
- {
- "server": "ipp_server",
- "action": "connection",
- "src_ip": client_ip,
- "src_port": request.getClientAddress().port,
- "dest_ip": _q_s.ip,
- "dest_port": _q_s.port,
- "data": headers,
- }
- )
- else:
- _q_s.logs.info(
- {
- "server": "ipp_server",
- "action": "connection",
- "src_ip": client_ip,
- "src_port": request.getClientAddress().port,
- "dest_ip": _q_s.ip,
- "dest_port": _q_s.port,
- }
- )
+ log_data["data"] = headers
+ _q_s.logs.info(log_data)
data = request.content.read()
response = ""
version = [0, 0]
- request_id = 0
- group = ""
groups = []
groups_parsed = ""
- operation = ""
status = "success"
with suppress(Exception):
@@ -363,7 +233,6 @@ def check_bytes(string):
if uint8_t in self.attribute_syntaxes:
while index < to_parse_len:
try:
- attribute = ""
value = ""
if self.attribute_syntaxes[uint8_t] == "integer":
index, attribute = self.get_uint32_t(index, data)
@@ -375,11 +244,9 @@ def check_bytes(string):
index, uint16_t = self.get_uint16_t(index, data)
index, value = self.get_string(index, uint16_t, data)
if attribute == b"":
- groups[-1][1].append(self.check_bytes(value))
+ groups[-1][1].append(check_bytes(value))
else:
- groups.append(
- [self.check_bytes(attribute), [self.check_bytes(value)]]
- )
+ groups.append([check_bytes(attribute), [check_bytes(value)]])
index, uint8_t = self.get_uint8_t(index, data)
if uint8_t in self.attribute_group_tags:
@@ -405,7 +272,7 @@ def check_bytes(string):
if len(response) > 0:
_q_s.logs.info(
{
- "server": "ipp_server",
+ "server": _q_s.NAME,
"action": "query",
"status": status,
"src_ip": client_ip,
@@ -426,93 +293,36 @@ def send_response(request: bytes, successful: bool) -> bytes:
attributes = attributes_dict_to_bytes(
{"attributes-charset": "utf-8", "attributes-natural-language": "en-us"}
)
- response = version + status_code + request_id + attributes
- return response
+ return version + status_code + request_id + attributes
reactor.listenTCP(self.port, Site(MainResource()))
reactor.run()
- def run_server(self, process=False, auto=False):
- status = "error"
- run = False
- if process:
- if auto and not self.auto_disabled:
- port = get_free_port()
- if port > 0:
- self.port = port
- run = True
- elif self.close_port() and self.kill_server():
- run = True
-
- if run:
- self.process = Popen(
- [
- "python3",
- path.realpath(__file__),
- "--custom",
- "--ip",
- str(self.ip),
- "--port",
- str(self.port),
- "--options",
- str(self.options),
- "--config",
- str(self.config),
- "--uuid",
- str(self.uuid),
- ]
- )
- if self.process.poll() is None and check_if_server_is_running(self.uuid):
- status = "success"
-
- self.logs.info(
- {
- "server": "ipp_server",
- "action": "process",
- "status": status,
- "src_ip": self.ip,
- "src_port": self.port,
- "dest_ip": self.ip,
- "dest_port": self.port,
- }
- )
-
- if status == "success":
- return True
- else:
- self.kill_server()
- return False
- else:
- self.ipp_server_main()
-
- def close_port(self):
- ret = close_port_wrapper("ipp_server", self.ip, self.port, self.logs)
- return ret
-
- def kill_server(self):
- ret = kill_server_wrapper("ipp_server", self.uuid, self.process)
- return ret
-
def test_server(self, ip=None, port=None):
- with suppress():
- from socket import socket, AF_INET, SOCK_STREAM
+ from socket import socket, AF_INET, SOCK_STREAM
- _ip = ip or self.ip
- _port = port or self.port
+ _ip = ip or self.ip
+ _port = port or self.port
- body = b"\x02\x00\x00\x0b\x00\x01/p\x01G\x00\x12attributes-charset\x00\x05utf-8H\x00\x1battributes-natural-language\x00\x02enE\x00\x0bprinter-uri\x00\x15ipp://127.0.0.1:631/D\x00\x14requested-attributes\x00\x03allD\x00\x00\x00\x12media-col-database\x03"
+ body = (
+ b"\x02\x00\x00\x0b\x00\x01/p\x01G\x00\x12attributes-charset\x00\x05utf-8H\x00\x1b"
+ b"attributes-natural-language\x00\x02enE\x00\x0bprinter-uri\x00\x15"
+ b"ipp://127.0.0.1:631/D\x00\x14requested-attributes\x00\x03allD\x00\x00\x00\x12"
+ b"media-col-database\x03"
+ )
- headers = f"""\
- POST / HTTP/1.1\r
- Content-Type: application/x-www-form-urlencoded\r
- Content-Length: {len(body)}\r
- Host: {_ip}:{_port}\r
- Connection: close\r
- \r\n""".encode()
+ headers = (
+ "POST / HTTP/1.1\r\n"
+ "Content-Type: application/x-www-form-urlencoded\r\n"
+ "Content-Length: {len(body)}\r\n"
+ f"Host: {_ip}:{_port}\r\n"
+ "Connection: close\r\n"
+ "\r\n"
+ )
- s = socket(AF_INET, SOCK_STREAM)
- s.connect((_ip, _port))
- s.sendall(headers + body)
+ s = socket(AF_INET, SOCK_STREAM)
+ s.connect((_ip, _port))
+ s.sendall(headers.encode() + body)
ATTRIBUTE_NAME_TO_VALUE_TAG = {
@@ -521,7 +331,7 @@ def test_server(self, ip=None, port=None):
}
-def attributes_dict_to_bytes(attributes: Dict[str, str]) -> bytes:
+def attributes_dict_to_bytes(attributes: dict[str, str]) -> bytes:
attributes_str = b"\x01" # start operation attributes
for key, value in attributes.items():
value_tag = ATTRIBUTE_NAME_TO_VALUE_TAG[key]
diff --git a/honeypots/irc_server.py b/honeypots/irc_server.py
index 9c86188..a8b9f42 100644
--- a/honeypots/irc_server.py
+++ b/honeypots/irc_server.py
@@ -10,59 +10,24 @@
// -------------------------------------------------------------
"""
-from twisted.internet.protocol import Factory
+from contextlib import suppress
+
from twisted.internet import reactor
+from twisted.internet.protocol import Factory
from twisted.words import service
-from subprocess import Popen
-from os import path, getenv
+
+from honeypots.base_server import BaseServer
from honeypots.helper import (
- close_port_wrapper,
- get_free_port,
- kill_server_wrapper,
server_arguments,
- set_up_error_logging,
- setup_logger,
- set_local_vars,
- check_if_server_is_running,
+ check_bytes,
)
-from uuid import uuid4
-from contextlib import suppress
-class QIRCServer:
+class QIRCServer(BaseServer):
NAME = "irc_server"
+ DEFAULT_PORT = 6667
- def __init__(self, **kwargs):
- self.auto_disabled = None
- self.process = None
- self.uuid = f"honeypotslogger_{__class__.__name__}_{str(uuid4())[:8]}"
- self.config = kwargs.get("config", "")
- if self.config:
- self.logs = setup_logger(__class__.__name__, self.uuid, self.config)
- set_local_vars(self, self.config)
- else:
- self.logs = setup_logger(__class__.__name__, self.uuid, None)
- self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0"
- self.port = (
- (kwargs.get("port", None) and int(kwargs.get("port", None)))
- or (hasattr(self, "port") and self.port)
- or 6667
- )
- self.username = (
- kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test"
- )
- self.password = (
- kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test"
- )
- self.options = (
- kwargs.get("options", "")
- or (hasattr(self, "options") and self.options)
- or getenv("HONEYPOTS_OPTIONS", "")
- or ""
- )
- self.logger = set_up_error_logging()
-
- def irc_server_main(self):
+ def server_main(self):
_q_s = self
class CustomIRCProtocol(service.IRCUser):
@@ -134,67 +99,6 @@ def irc_NICK(self, prefix, params):
reactor.listenTCP(port=self.port, factory=factory, interface=self.ip)
reactor.run()
- def run_server(self, process=False, auto=False):
- status = "error"
- run = False
- if process:
- if auto and not self.auto_disabled:
- port = get_free_port()
- if port > 0:
- self.port = port
- run = True
- elif self.close_port() and self.kill_server():
- run = True
-
- if run:
- self.process = Popen(
- [
- "python3",
- path.realpath(__file__),
- "--custom",
- "--ip",
- str(self.ip),
- "--port",
- str(self.port),
- "--options",
- str(self.options),
- "--config",
- str(self.config),
- "--uuid",
- str(self.uuid),
- ]
- )
- if self.process.poll() is None and check_if_server_is_running(self.uuid):
- status = "success"
-
- self.logs.info(
- {
- "server": self.NAME,
- "action": "process",
- "status": status,
- "src_ip": self.ip,
- "src_port": self.port,
- "dest_ip": self.ip,
- "dest_port": self.port,
- }
- )
-
- if status == "success":
- return True
- else:
- self.kill_server()
- return False
- else:
- self.irc_server_main()
-
- def close_port(self):
- ret = close_port_wrapper(self.NAME, self.ip, self.port, self.logs)
- return ret
-
- def kill_server(self):
- ret = kill_server_wrapper(self.NAME, self.uuid, self.process)
- return ret
-
def test_server(self, ip=None, port=None, username=None, password=None):
with suppress(Exception):
from warnings import filterwarnings
@@ -213,13 +117,6 @@ def test_server(self, ip=None, port=None, username=None, password=None):
c.close()
-def check_bytes(string):
- if isinstance(string, bytes):
- return string.decode(errors="replace")
- else:
- return str(string)
-
-
if __name__ == "__main__":
parsed = server_arguments()
if parsed.docker or parsed.aws or parsed.custom:
diff --git a/honeypots/ldap_server.py b/honeypots/ldap_server.py
index e625750..4a07c36 100644
--- a/honeypots/ldap_server.py
+++ b/honeypots/ldap_server.py
@@ -9,73 +9,37 @@
// contributors list qeeqbox/honeypots/graphs/contributors
// -------------------------------------------------------------
"""
+from __future__ import annotations
-from twisted.internet.protocol import Protocol, Factory
-from twisted.internet import reactor
-from subprocess import Popen
-from os import path, getenv
-from struct import unpack
from binascii import unhexlify
+from contextlib import suppress
+from struct import unpack
+
+from twisted.internet import reactor
+from twisted.internet.protocol import Protocol, Factory
+
+from honeypots.base_server import BaseServer
from honeypots.helper import (
- close_port_wrapper,
- get_free_port,
- kill_server_wrapper,
server_arguments,
- setup_logger,
- set_local_vars,
- check_if_server_is_running,
+ check_bytes,
)
-from uuid import uuid4
-from contextlib import suppress
-class QLDAPServer:
- def __init__(self, **kwargs):
- self.auto_disabled = None
- self.process = None
- self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8]
- self.config = kwargs.get("config", "")
- if self.config:
- self.logs = setup_logger(__class__.__name__, self.uuid, self.config)
- set_local_vars(self, self.config)
- else:
- self.logs = setup_logger(__class__.__name__, self.uuid, None)
- self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0"
- self.port = (
- (kwargs.get("port", None) and int(kwargs.get("port", None)))
- or (hasattr(self, "port") and self.port)
- or 389
- )
- self.username = (
- kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test"
- )
- self.password = (
- kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test"
- )
- self.options = (
- kwargs.get("options", "")
- or (hasattr(self, "options") and self.options)
- or getenv("HONEYPOTS_OPTIONS", "")
- or ""
- )
+class QLDAPServer(BaseServer):
+ NAME = "ldap_server"
+ DEFAULT_PORT = 389
- def ldap_server_main(self):
+ def server_main(self):
_q_s = self
class CustomLDAProtocol(Protocol):
_state = None
- def check_bytes(self, string):
- if isinstance(string, bytes):
- return string.decode()
- else:
- return str(string)
-
def connectionMade(self):
self._state = 1
_q_s.logs.info(
{
- "server": "ldap_server",
+ "server": _q_s.NAME,
"action": "connection",
"src_ip": self.transport.getPeer().host,
"src_port": self.transport.getPeer().port,
@@ -84,16 +48,13 @@ def connectionMade(self):
}
)
- def parse_ldap_packet(self, data):
+ @staticmethod
+ def parse_ldap_packet(data: bytes) -> tuple[str, str]:
# V
# 30[20] 0201[02] 60[1b] 0201[03] 04[0a] 7379736261636b757031 [80][0a] 7379736261636b757032
username = ""
password = ""
- username_start = 0
- username_end = 0
- password_start = 0
- password_end = 0
with suppress(Exception):
version = data.find(b"\x02\x01\x03")
if version > 0:
@@ -120,82 +81,41 @@ def parse_ldap_packet(self, data):
)
password = data[password_start:password_end]
- return username, password
+ return check_bytes(username), check_bytes(password)
def dataReceived(self, data):
if self._state == 1:
self._state = 2
- username, password = self.parse_ldap_packet(data)
- username = self.check_bytes(username)
- password = self.check_bytes(password)
- if username != "" or password != "":
- if username == _q_s.username and password == _q_s.password:
- _q_s.logs.info(
- {
- "server": "ldap_server",
- "action": "login",
- "status": "success",
- "src_ip": self.transport.getPeer().host,
- "src_port": self.transport.getPeer().port,
- "dest_ip": _q_s.ip,
- "dest_port": _q_s.port,
- "username": _q_s.username,
- "password": _q_s.password,
- }
- )
- else:
- _q_s.logs.info(
- {
- "server": "ldap_server",
- "action": "login",
- "status": "failed",
- "src_ip": self.transport.getPeer().host,
- "src_port": self.transport.getPeer().port,
- "dest_ip": _q_s.ip,
- "dest_port": _q_s.port,
- "username": username,
- "password": password,
- }
- )
+ self._check_login(data)
self.transport.write(unhexlify(b"300c02010165070a013204000400"))
elif self._state == 2:
self._state = 3
- username, password = self.parse_ldap_packet(data)
- username = self.check_bytes(username)
- password = self.check_bytes(password)
- if username != "" or password != "":
- if username == _q_s.username and password == _q_s.password:
- _q_s.logs.info(
- {
- "server": "ldap_server",
- "action": "login",
- "status": "success",
- "src_ip": self.transport.getPeer().host,
- "src_port": self.transport.getPeer().port,
- "dest_ip": _q_s.ip,
- "dest_port": _q_s.port,
- "username": _q_s.username,
- "password": _q_s.password,
- }
- )
- else:
- _q_s.logs.info(
- {
- "server": "ldap_server",
- "action": "login",
- "status": "failed",
- "src_ip": self.transport.getPeer().host,
- "src_port": self.transport.getPeer().port,
- "dest_ip": _q_s.ip,
- "dest_port": _q_s.port,
- "username": username,
- "password": password,
- }
- )
+ self._check_login(data)
self.transport.write(unhexlify(b"300c02010265070a013204000400"))
else:
self.transport.loseConnection()
+ def _check_login(self, data):
+ username, password = self.parse_ldap_packet(data)
+ if username != "" or password != "":
+ if username == _q_s.username and password == _q_s.password:
+ status = "success"
+ else:
+ status = "failed"
+ _q_s.logs.info(
+ {
+ "server": _q_s.NAME,
+ "action": "login",
+ "status": status,
+ "src_ip": self.transport.getPeer().host,
+ "src_port": self.transport.getPeer().port,
+ "dest_ip": _q_s.ip,
+ "dest_port": _q_s.port,
+ "username": username,
+ "password": password,
+ }
+ )
+
def connectionLost(self, reason):
self._state = None
@@ -204,73 +124,6 @@ def connectionLost(self, reason):
reactor.listenTCP(port=self.port, factory=factory, interface=self.ip)
reactor.run()
- def run_server(self, process=False, auto=False):
- status = "error"
- run = False
- if process:
- if auto and not self.auto_disabled:
- port = get_free_port()
- if port > 0:
- self.port = port
- run = True
- elif self.close_port() and self.kill_server():
- run = True
-
- if run:
- self.process = Popen(
- [
- "python3",
- path.realpath(__file__),
- "--custom",
- "--ip",
- str(self.ip),
- "--port",
- str(self.port),
- "--username",
- str(self.username),
- "--password",
- str(self.password),
- "--options",
- str(self.options),
- "--config",
- str(self.config),
- "--uuid",
- str(self.uuid),
- ]
- )
- if self.process.poll() is None and check_if_server_is_running(self.uuid):
- status = "success"
-
- self.logs.info(
- {
- "server": "ldap_server",
- "action": "process",
- "status": status,
- "src_ip": self.ip,
- "src_port": self.port,
- "username": self.username,
- "password": self.password,
- "dest_ip": self.ip,
- "dest_port": self.port,
- }
- )
-
- if status == "success":
- return True
- else:
- self.kill_server()
- return False
- else:
- self.ldap_server_main()
-
- def close_port(self):
- ret = close_port_wrapper("ldap_server", self.ip, self.port, self.logs)
- return ret
-
- def kill_server(self):
- ret = kill_server_wrapper("ldap_server", self.uuid, self.process)
- return ret
-
def test_server(self, ip=None, port=None, username=None, password=None):
with suppress(Exception):
from ldap3 import Server, Connection, ALL
diff --git a/honeypots/memcache_server.py b/honeypots/memcache_server.py
index 8aac179..c2f774c 100644
--- a/honeypots/memcache_server.py
+++ b/honeypots/memcache_server.py
@@ -11,51 +11,23 @@
"""
from contextlib import suppress
-from os import getenv, path
from random import randint, uniform
-from subprocess import Popen
from time import time
-from uuid import uuid4
from twisted.internet import reactor
from twisted.internet.protocol import Factory, Protocol
+from honeypots.base_server import BaseServer
from honeypots.helper import (
- check_if_server_is_running,
- close_port_wrapper,
- get_free_port,
- kill_server_wrapper,
server_arguments,
- set_local_vars,
- setup_logger,
)
-class QMemcacheServer:
- def __init__(self, **kwargs):
- self.auto_disabled = None
- self.process = None
- self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8]
- self.config = kwargs.get("config", "")
- if self.config:
- self.logs = setup_logger(__class__.__name__, self.uuid, self.config)
- set_local_vars(self, self.config)
- else:
- self.logs = setup_logger(__class__.__name__, self.uuid, None)
- self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0"
- self.port = (
- (kwargs.get("port", None) and int(kwargs.get("port", None)))
- or (hasattr(self, "port") and self.port)
- or 11211
- )
- self.options = (
- kwargs.get("options", "")
- or (hasattr(self, "options") and self.options)
- or getenv("HONEYPOTS_OPTIONS", "")
- or ""
- )
+class QMemcacheServer(BaseServer):
+ NAME = "memcache_server"
+ DEFAULT_PORT = 11211
- def memcache_server_main(self):
+ def server_main(self):
_q_s = self
class CustomRedisProtocol(Protocol):
@@ -166,7 +138,7 @@ def get_key(self, key):
def connectionMade(self):
_q_s.logs.info(
{
- "server": "memcache_server",
+ "server": _q_s.NAME,
"action": "connection",
"src_ip": self.transport.getPeer().host,
"src_port": self.transport.getPeer().port,
@@ -192,7 +164,7 @@ def dataReceived(self, data):
if _data[0] != b"":
_q_s.logs.info(
{
- "server": "memcache_server",
+ "server": _q_s.NAME,
"action": _data[0].decode(),
"src_ip": self.transport.getPeer().host,
"src_port": self.transport.getPeer().port,
@@ -207,67 +179,6 @@ def dataReceived(self, data):
reactor.listenTCP(port=self.port, factory=factory, interface=self.ip)
reactor.run()
- def run_server(self, process=False, auto=False):
- status = "error"
- run = False
- if process:
- if auto and not self.auto_disabled:
- port = get_free_port()
- if port > 0:
- self.port = port
- run = True
- elif self.close_port() and self.kill_server():
- run = True
-
- if run:
- self.process = Popen(
- [
- "python3",
- path.realpath(__file__),
- "--custom",
- "--ip",
- str(self.ip),
- "--port",
- str(self.port),
- "--options",
- str(self.options),
- "--config",
- str(self.config),
- "--uuid",
- str(self.uuid),
- ]
- )
- if self.process.poll() is None and check_if_server_is_running(self.uuid):
- status = "success"
-
- self.logs.info(
- {
- "server": "memcache_server",
- "action": "process",
- "status": status,
- "src_ip": self.ip,
- "src_port": self.port,
- "dest_ip": self.ip,
- "dest_port": self.port,
- }
- )
-
- if status == "success":
- return True
- else:
- self.kill_server()
- return False
- else:
- self.memcache_server_main()
-
- def close_port(self):
- ret = close_port_wrapper("memcache_server", self.ip, self.port, self.logs)
- return ret
-
- def kill_server(self):
- ret = kill_server_wrapper("memcache_server", self.uuid, self.process)
- return ret
-
def test_server(self, ip=None, port=None, username=None, password=None):
with suppress(Exception):
from warnings import filterwarnings
diff --git a/honeypots/mssql_server.py b/honeypots/mssql_server.py
index 8b0e0e9..8564a4b 100644
--- a/honeypots/mssql_server.py
+++ b/honeypots/mssql_server.py
@@ -12,68 +12,32 @@
from binascii import hexlify, unhexlify
from contextlib import suppress
-from os import getenv, path
from struct import pack, unpack
-from subprocess import Popen
-from uuid import uuid4
from twisted.internet import reactor
from twisted.internet.protocol import Factory, Protocol
+from honeypots.base_server import BaseServer
from honeypots.helper import (
- check_if_server_is_running,
- close_port_wrapper,
- get_free_port,
- kill_server_wrapper,
server_arguments,
- set_local_vars,
- setup_logger,
+ check_bytes,
)
-class QMSSQLServer:
+class QMSSQLServer(BaseServer):
+ NAME = "mssql_server"
+ DEFAULT_PORT = 1433
+
def __init__(self, **kwargs):
- self.auto_disabled = None
+ super().__init__(**kwargs)
self.file_name = None
- self.process = None
- self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8]
- self.config = kwargs.get("config", "")
- if self.config:
- self.logs = setup_logger(__class__.__name__, self.uuid, self.config)
- set_local_vars(self, self.config)
- else:
- self.logs = setup_logger(__class__.__name__, self.uuid, None)
- self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0"
- self.port = (
- (kwargs.get("port", None) and int(kwargs.get("port", None)))
- or (hasattr(self, "port") and self.port)
- or 1433
- )
- self.username = (
- kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test"
- )
- self.password = (
- kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test"
- )
- self.options = (
- kwargs.get("options", "")
- or (hasattr(self, "options") and self.options)
- or getenv("HONEYPOTS_OPTIONS", "")
- or ""
- )
- def mssql_server_main(self):
+ def server_main(self):
_q_s = self
class CustomMSSQLProtocol(Protocol):
_state = None
- def check_bytes(self, string):
- if isinstance(string, bytes):
- return string.decode()
- else:
- return str(string)
-
def create_payload(self, server_name=b"", token_error_msg=b"", error_code=2):
ret = "040100c000350100aaa80002000000010e440041006e0020006500720072006f007200200068006100730020006f00630063007500720072006500640020007700680069006c0065002000650073007400610062006c0069007300680069006e00670020006100200063006f006e006e0065006300740069006f006e00200074006f00200074006800650020007300650072007600650072002e00095200260044006200610063006b00750070000001000000fd020000000000000000000000"
with suppress(Exception):
@@ -117,7 +81,7 @@ def connectionMade(self):
self._state = 1
_q_s.logs.info(
{
- "server": "mssql_server",
+ "server": _q_s.NAME,
"action": "connection",
"src_ip": self.transport.getPeer().host,
"src_port": self.transport.getPeer().port,
@@ -152,8 +116,8 @@ def dataReceived(self, data):
password_decrypted += chr(
((x ^ 0xA5) & 0x0F) << 4 | ((x ^ 0xA5) & 0xF0) >> 4
)
- username = self.check_bytes(username)
- password = self.check_bytes(password_decrypted)
+ username = check_bytes(username)
+ password = check_bytes(password_decrypted)
status = "failed"
if username == _q_s.username and password == _q_s.password:
username = _q_s.username
@@ -161,7 +125,7 @@ def dataReceived(self, data):
status = "success"
_q_s.logs.info(
{
- "server": "mssql_server",
+ "server": _q_s.NAME,
"action": "login",
"status": status,
"src_ip": self.transport.getPeer().host,
@@ -191,73 +155,6 @@ def connectionLost(self, reason):
reactor.listenTCP(port=self.port, factory=factory, interface=self.ip)
reactor.run()
- def run_server(self, process=False, auto=False):
- status = "error"
- run = False
- if process:
- if auto and not self.auto_disabled:
- port = get_free_port()
- if port > 0:
- self.port = port
- run = True
- elif self.close_port() and self.kill_server():
- run = True
-
- if run:
- self.process = Popen(
- [
- "python3",
- path.realpath(__file__),
- "--custom",
- "--ip",
- str(self.ip),
- "--port",
- str(self.port),
- "--username",
- str(self.username),
- "--password",
- str(self.password),
- "--options",
- str(self.options),
- "--config",
- str(self.config),
- "--uuid",
- str(self.uuid),
- ]
- )
- if self.process.poll() is None and check_if_server_is_running(self.uuid):
- status = "success"
-
- self.logs.info(
- {
- "server": "mssql_server",
- "action": "process",
- "status": status,
- "src_ip": self.ip,
- "src_port": self.port,
- "username": self.username,
- "password": self.password,
- "dest_ip": self.ip,
- "dest_port": self.port,
- }
- )
-
- if status == "success":
- return True
- else:
- self.kill_server()
- return False
- else:
- self.mssql_server_main()
-
- def close_port(self):
- ret = close_port_wrapper("mssql_server", self.ip, self.port, self.logs)
- return ret
-
- def kill_server(self):
- ret = kill_server_wrapper("mssql_server", self.uuid, self.process)
- return ret
-
def test_server(self, ip=None, port=None, username=None, password=None):
with suppress(Exception):
from pymssql import connect as pconnect
diff --git a/honeypots/mysql_server.py b/honeypots/mysql_server.py
index 8742d71..006b081 100644
--- a/honeypots/mysql_server.py
+++ b/honeypots/mysql_server.py
@@ -12,54 +12,24 @@
from contextlib import suppress
from hashlib import sha1
-from os import getenv, path
from struct import pack
-from subprocess import Popen
-from uuid import uuid4
from twisted.internet import reactor
from twisted.internet.protocol import Factory, Protocol
+from honeypots.base_server import BaseServer
from honeypots.helper import (
- check_if_server_is_running,
- close_port_wrapper,
- get_free_port,
- kill_server_wrapper,
server_arguments,
- set_local_vars,
- setup_logger,
+ check_bytes,
)
-class QMysqlServer:
+class QMysqlServer(BaseServer):
+ NAME = "mysql_server"
+ DEFAULT_PORT = 3306
+
def __init__(self, **kwargs):
- self.auto_disabled = None
- self.process = None
- self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8]
- self.config = kwargs.get("config", "")
- if self.config:
- self.logs = setup_logger(__class__.__name__, self.uuid, self.config)
- set_local_vars(self, self.config)
- else:
- self.logs = setup_logger(__class__.__name__, self.uuid, None)
- self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0"
- self.port = (
- (kwargs.get("port", None) and int(kwargs.get("port", None)))
- or (hasattr(self, "port") and self.port)
- or 3306
- )
- self.username = (
- kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test"
- )
- self.password = (
- kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test"
- )
- self.options = (
- kwargs.get("options", "")
- or (hasattr(self, "options") and self.options)
- or getenv("HONEYPOTS_OPTIONS", "")
- or ""
- )
+ super().__init__(**kwargs)
self.words = [self.password.encode()]
def load_words(
@@ -150,26 +120,18 @@ def decode(self, hash):
return temp
return None
- def mysql_server_main(self):
+ def server_main(self):
_q_s = self
class CustomMysqlProtocol(Protocol):
_state = None
- def check_bytes(self, string):
- with suppress(Exception):
- if isinstance(string, bytes):
- return string.decode("utf-8", "ignore")
- else:
- return str(string)
- return string
-
def connectionMade(self):
self._state = 1
self.transport.write(_q_s.greeting())
_q_s.logs.info(
{
- "server": "mysql_server",
+ "server": _q_s.NAME,
"action": "connection",
"src_ip": self.transport.getPeer().host,
"src_port": self.transport.getPeer().port,
@@ -183,13 +145,13 @@ def dataReceived(self, data):
if self._state == 1:
ret_access_denied = False
username, password, good = _q_s.parse_data(data)
- username = self.check_bytes(username)
+ username = check_bytes(username)
status = "failed"
if good:
if password:
password_decoded = _q_s.decode(password)
if password_decoded is not None and username == _q_s.username:
- password = self.check_bytes(password_decoded)
+ password = check_bytes(password_decoded)
status = "success"
else:
password = password.hex()
@@ -199,7 +161,7 @@ def dataReceived(self, data):
password = ":".join(hex(c)[2:] for c in data)
_q_s.logs.info(
{
- "server": "mysql_server",
+ "server": _q_s.NAME,
"action": "login",
"status": status,
"src_ip": self.transport.getPeer().host,
@@ -229,73 +191,6 @@ def connectionLost(self, reason):
reactor.listenTCP(port=self.port, factory=factory, interface=self.ip)
reactor.run()
- def run_server(self, process=False, auto=False):
- status = "error"
- run = False
- if process:
- if auto and not self.auto_disabled:
- port = get_free_port()
- if port > 0:
- self.port = port
- run = True
- elif self.close_port() and self.kill_server():
- run = True
-
- if run:
- self.process = Popen(
- [
- "python3",
- path.realpath(__file__),
- "--custom",
- "--ip",
- str(self.ip),
- "--port",
- str(self.port),
- "--username",
- str(self.username),
- "--password",
- str(self.password),
- "--options",
- str(self.options),
- "--config",
- str(self.config),
- "--uuid",
- str(self.uuid),
- ]
- )
- if self.process.poll() is None and check_if_server_is_running(self.uuid):
- status = "success"
-
- self.logs.info(
- {
- "server": "mysql_server",
- "action": "process",
- "status": status,
- "src_ip": self.ip,
- "src_port": self.port,
- "username": self.username,
- "password": self.password,
- "dest_ip": self.ip,
- "dest_port": self.port,
- }
- )
-
- if status == "success":
- return True
- else:
- self.kill_server()
- return False
- else:
- self.mysql_server_main()
-
- def close_port(self):
- ret = close_port_wrapper("mysql_server", self.ip, self.port, self.logs)
- return ret
-
- def kill_server(self):
- ret = kill_server_wrapper("mysql_server", self.uuid, self.process)
- return ret
-
def test_server(self, ip=None, port=None, username=None, password=None):
with suppress(Exception):
from mysql.connector import connect as mysqlconnect
diff --git a/honeypots/ntp_server.py b/honeypots/ntp_server.py
index d6894d1..0c84352 100644
--- a/honeypots/ntp_server.py
+++ b/honeypots/ntp_server.py
@@ -11,57 +11,23 @@
"""
import struct
from contextlib import suppress
-from os import getenv, path
from struct import pack, unpack
-from subprocess import Popen
from time import time
-from uuid import uuid4
from twisted.internet import reactor
from twisted.internet.protocol import DatagramProtocol
+from honeypots.base_server import BaseServer
from honeypots.helper import (
- check_if_server_is_running,
- close_port_wrapper,
- get_free_port,
- kill_server_wrapper,
server_arguments,
- set_local_vars,
- setup_logger,
)
-class QNTPServer:
- def __init__(self, **kwargs):
- self.auto_disabled = None
- self.process = None
- self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8]
- self.config = kwargs.get("config", "")
- if self.config:
- self.logs = setup_logger(__class__.__name__, self.uuid, self.config)
- set_local_vars(self, self.config)
- else:
- self.logs = setup_logger(__class__.__name__, self.uuid, None)
- self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0"
- self.port = (
- (kwargs.get("port", None) and int(kwargs.get("port", None)))
- or (hasattr(self, "port") and self.port)
- or 123
- )
- self.username = (
- kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test"
- )
- self.password = (
- kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test"
- )
- self.options = (
- kwargs.get("options", "")
- or (hasattr(self, "options") and self.options)
- or getenv("HONEYPOTS_OPTIONS", "")
- or ""
- )
+class QNTPServer(BaseServer):
+ NAME = "ntp_server"
+ DEFAULT_PORT = 123
- def ntp_server_main(self):
+ def server_main(self):
_q_s = self
class CustomDatagramProtocolProtocol(DatagramProtocol):
@@ -80,7 +46,7 @@ def datagramReceived(self, data, addr):
mode = "UnKnown"
_q_s.logs.info(
{
- "server": "ntp_server",
+ "server": _q_s.NAME,
"action": "connection",
"src_ip": addr[0],
"src_port": addr[1],
@@ -111,7 +77,7 @@ def datagramReceived(self, data, addr):
_q_s.logs.info(
{
- "server": "ntp_server",
+ "server": _q_s.NAME,
"action": "query",
"status": status,
"src_ip": addr[0],
@@ -127,67 +93,6 @@ def datagramReceived(self, data, addr):
)
reactor.run()
- def run_server(self, process=False, auto=False):
- status = "error"
- run = False
- if process:
- if auto and not self.auto_disabled:
- port = get_free_port()
- if port > 0:
- self.port = port
- run = True
- elif self.close_port() and self.kill_server():
- run = True
-
- if run:
- self.process = Popen(
- [
- "python3",
- path.realpath(__file__),
- "--custom",
- "--ip",
- str(self.ip),
- "--port",
- str(self.port),
- "--options",
- str(self.options),
- "--config",
- str(self.config),
- "--uuid",
- str(self.uuid),
- ]
- )
- if self.process.poll() is None and check_if_server_is_running(self.uuid):
- status = "success"
-
- self.logs.info(
- {
- "server": "ntp_server",
- "action": "process",
- "status": status,
- "src_ip": self.ip,
- "src_port": self.port,
- "dest_ip": self.ip,
- "dest_port": self.port,
- }
- )
-
- if status == "success":
- return True
- else:
- self.kill_server()
- return False
- else:
- self.ntp_server_main()
-
- def close_port(self):
- ret = close_port_wrapper("ntp_server", self.ip, self.port, self.logs)
- return ret
-
- def kill_server(self):
- ret = kill_server_wrapper("ntp_server", self.uuid, self.process)
- return ret
-
def test_server(self, ip=None, port=None, username=None, password=None):
with suppress(Exception):
from warnings import filterwarnings
diff --git a/honeypots/oracle_server.py b/honeypots/oracle_server.py
index 803cbfa..ed8fff5 100644
--- a/honeypots/oracle_server.py
+++ b/honeypots/oracle_server.py
@@ -11,57 +11,23 @@
"""
from contextlib import suppress
-from os import getenv, path
from re import findall
from struct import unpack
-from subprocess import Popen
-from uuid import uuid4
from twisted.internet import reactor
from twisted.internet.protocol import Factory, Protocol
+from honeypots.base_server import BaseServer
from honeypots.helper import (
- check_if_server_is_running,
- close_port_wrapper,
- get_free_port,
- kill_server_wrapper,
server_arguments,
- set_local_vars,
- setup_logger,
)
-class QOracleServer:
- def __init__(self, **kwargs):
- self.auto_disabled = None
- self.process = None
- self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8]
- self.config = kwargs.get("config", "")
- if self.config:
- self.logs = setup_logger(__class__.__name__, self.uuid, self.config)
- set_local_vars(self, self.config)
- else:
- self.logs = setup_logger(__class__.__name__, self.uuid, None)
- self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0"
- self.port = (
- (kwargs.get("port", None) and int(kwargs.get("port", None)))
- or (hasattr(self, "port") and self.port)
- or 1521
- )
- self.username = (
- kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test"
- )
- self.password = (
- kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test"
- )
- self.options = (
- kwargs.get("options", "")
- or (hasattr(self, "options") and self.options)
- or getenv("HONEYPOTS_OPTIONS", "")
- or ""
- )
+class QOracleServer(BaseServer):
+ NAME = "oracle_server"
+ DEFAULT_PORT = 1521
- def oracle_server_main(self):
+ def server_main(self):
_q_s = self
class CustomRedisProtocol(Protocol):
@@ -106,7 +72,7 @@ def parse_payload(self, data):
def connectionMade(self):
_q_s.logs.info(
{
- "server": "oracle_server",
+ "server": _q_s.NAME,
"action": "connection",
"src_ip": self.transport.getPeer().host,
"src_port": self.transport.getPeer().port,
@@ -120,7 +86,7 @@ def dataReceived(self, data):
if service_name or program or local_user:
_q_s.logs.info(
{
- "server": "oracle_server",
+ "server": _q_s.NAME,
"action": "login",
"src_ip": self.transport.getPeer().host,
"src_port": self.transport.getPeer().port,
@@ -141,67 +107,6 @@ def dataReceived(self, data):
reactor.listenTCP(port=self.port, factory=factory, interface=self.ip)
reactor.run()
- def run_server(self, process=False, auto=False):
- status = "error"
- run = False
- if process:
- if auto and not self.auto_disabled:
- port = get_free_port()
- if port > 0:
- self.port = port
- run = True
- elif self.close_port() and self.kill_server():
- run = True
-
- if run:
- self.process = Popen(
- [
- "python3",
- path.realpath(__file__),
- "--custom",
- "--ip",
- str(self.ip),
- "--port",
- str(self.port),
- "--options",
- str(self.options),
- "--config",
- str(self.config),
- "--uuid",
- str(self.uuid),
- ]
- )
- if self.process.poll() is None and check_if_server_is_running(self.uuid):
- status = "success"
-
- self.logs.info(
- {
- "server": "oracle_server",
- "action": "process",
- "status": status,
- "src_ip": self.ip,
- "src_port": self.port,
- "dest_ip": self.ip,
- "dest_port": self.port,
- }
- )
-
- if status == "success":
- return True
- else:
- self.kill_server()
- return False
- else:
- self.oracle_server_main()
-
- def close_port(self):
- ret = close_port_wrapper("oracle_server", self.ip, self.port, self.logs)
- return ret
-
- def kill_server(self):
- ret = kill_server_wrapper("oracle_server", self.uuid, self.process)
- return ret
-
def test_server(self, ip=None, port=None, username=None, password=None):
with suppress(Exception):
from warnings import filterwarnings
diff --git a/honeypots/pjl_server.py b/honeypots/pjl_server.py
index c7dd6bd..ab9b27c 100644
--- a/honeypots/pjl_server.py
+++ b/honeypots/pjl_server.py
@@ -11,48 +11,24 @@
"""
from contextlib import suppress
-from os import getenv, path
-from subprocess import Popen
-from uuid import uuid4
from twisted.internet import reactor
from twisted.internet.protocol import Factory, Protocol
+from honeypots.base_server import BaseServer
from honeypots.helper import (
- check_if_server_is_running,
- close_port_wrapper,
- get_free_port,
- kill_server_wrapper,
server_arguments,
- set_local_vars,
- setup_logger,
+ check_bytes,
)
-class QPJLServer:
+class QPJLServer(BaseServer):
+ NAME = "pjl_server"
+ DEFAULT_PORT = 9100
+
def __init__(self, **kwargs):
- self.auto_disabled = None
- self.process = None
+ super().__init__(**kwargs)
self.printer = b"Brother HL-L2360"
- self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8]
- self.config = kwargs.get("config", "")
- if self.config:
- self.logs = setup_logger(__class__.__name__, self.uuid, self.config)
- set_local_vars(self, self.config)
- else:
- self.logs = setup_logger(__class__.__name__, self.uuid, None)
- self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0"
- self.port = (
- (kwargs.get("port", None) and int(kwargs.get("port", None)))
- or (hasattr(self, "port") and self.port)
- or 9100
- )
- self.options = (
- kwargs.get("options", "")
- or (hasattr(self, "options") and self.options)
- or getenv("HONEYPOTS_OPTIONS", "")
- or ""
- )
self.template = {
"ProductName": "Brother HL-L2360",
"FormatterNumber": "Q910CHL",
@@ -72,23 +48,17 @@ def __init__(self, **kwargs):
"HWAddress": "0025B395EA01",
}
- def pjl_server_main(self):
+ def server_main(self):
_q_s = self
class Custompjlrotocol(Protocol):
_state = None
- def check_bytes(self, string):
- if isinstance(string, bytes):
- return string.decode(errors="replace")
- else:
- return str(string)
-
def connectionMade(self):
self._state = 1
_q_s.logs.info(
{
- "server": "pjl_server",
+ "server": _q_s.NAME,
"action": "connection",
"src_ip": self.transport.getPeer().host,
"src_port": self.transport.getPeer().port,
@@ -109,14 +79,14 @@ def dataReceived(self, data):
self.transport.write(prodinfo.encode("utf-8") + b"\x1b")
_q_s.logs.info(
{
- "server": "pjl_server",
+ "server": _q_s.NAME,
"action": "query",
"status": "success",
"src_ip": self.transport.getPeer().host,
"src_port": self.transport.getPeer().port,
"dest_ip": _q_s.ip,
"dest_port": _q_s.port,
- "data": {"command": self.check_bytes(data)},
+ "data": {"command": check_bytes(data)},
}
)
self.transport.loseConnection()
@@ -129,67 +99,6 @@ def connectionLost(self, reason):
reactor.listenTCP(port=self.port, factory=factory, interface=self.ip)
reactor.run()
- def run_server(self, process=False, auto=False):
- status = "error"
- run = False
- if process:
- if auto and not self.auto_disabled:
- port = get_free_port()
- if port > 0:
- self.port = port
- run = True
- elif self.close_port() and self.kill_server():
- run = True
-
- if run:
- self.process = Popen(
- [
- "python3",
- path.realpath(__file__),
- "--custom",
- "--ip",
- str(self.ip),
- "--port",
- str(self.port),
- "--options",
- str(self.options),
- "--config",
- str(self.config),
- "--uuid",
- str(self.uuid),
- ]
- )
- if self.process.poll() is None and check_if_server_is_running(self.uuid):
- status = "success"
-
- self.logs.info(
- {
- "server": "pjl_server",
- "action": "process",
- "status": status,
- "src_ip": self.ip,
- "src_port": self.port,
- "dest_ip": self.ip,
- "dest_port": self.port,
- }
- )
-
- if status == "success":
- return True
- else:
- self.kill_server()
- return False
- else:
- self.pjl_server_main()
-
- def close_port(self):
- ret = close_port_wrapper("pjl_server", self.ip, self.port, self.logs)
- return ret
-
- def kill_server(self):
- ret = kill_server_wrapper("pjl_server", self.uuid, self.process)
- return ret
-
def test_server(self, ip=None, port=None, username=None, password=None):
with suppress(Exception):
from warnings import filterwarnings
diff --git a/honeypots/pop3_server.py b/honeypots/pop3_server.py
index 09ffaee..380a42b 100644
--- a/honeypots/pop3_server.py
+++ b/honeypots/pop3_server.py
@@ -10,74 +10,38 @@
// -------------------------------------------------------------
"""
from contextlib import suppress
-from os import getenv, path
from random import choice
-from subprocess import Popen
from typing import Tuple
-from uuid import uuid4
from twisted.internet import reactor
from twisted.internet.protocol import Factory
from twisted.mail.pop3 import POP3, POP3Error
+from honeypots.base_server import BaseServer
from honeypots.helper import (
- check_if_server_is_running,
- close_port_wrapper,
- get_free_port,
- kill_server_wrapper,
server_arguments,
- set_local_vars,
- setup_logger,
+ check_bytes,
)
-class QPOP3Server:
+class QPOP3Server(BaseServer):
+ NAME = "pop3_server"
+ DEFAULT_PORT = 110
+
def __init__(self, **kwargs):
- self.auto_disabled = None
+ super().__init__(**kwargs)
self.mocking_server = choice(["Microsoft Exchange POP3 service is ready"])
- self.process = None
- self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8]
- self.config = kwargs.get("config", "")
- if self.config:
- self.logs = setup_logger(__class__.__name__, self.uuid, self.config)
- set_local_vars(self, self.config)
- else:
- self.logs = setup_logger(__class__.__name__, self.uuid, None)
- self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0"
- self.port = (
- (kwargs.get("port", None) and int(kwargs.get("port", None)))
- or (hasattr(self, "port") and self.port)
- or 110
- )
- self.username = (
- kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test"
- )
- self.password = (
- kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test"
- )
- self.options = (
- kwargs.get("options", "")
- or (hasattr(self, "options") and self.options)
- or getenv("HONEYPOTS_OPTIONS", "")
- or ""
- )
- def pop3_server_main(self):
+ def server_main(self):
_q_s = self
class CustomPOP3Protocol(POP3):
self._user = None
- def check_bytes(self, string):
- if isinstance(string, bytes):
- return string.decode()
- else:
- return str(string)
-
def connectionMade(self):
_q_s.logs.info(
{
- "server": "pop3_server",
+ "server": _q_s.NAME,
"action": "connection",
"src_ip": self.transport.getPeer().host,
"src_port": self.transport.getPeer().port,
@@ -93,11 +57,11 @@ def processCommand(self, command: bytes, *args):
if "capture_commands" in _q_s.options:
_q_s.logs.info(
{
- "server": "pop3_server",
+ "server": _q_s.NAME,
"action": "command",
"data": {
- "cmd": self.check_bytes(command),
- "args": self.check_bytes(b" ".join(args)),
+ "cmd": check_bytes(command),
+ "args": check_bytes(b" ".join(args)),
},
"src_ip": self.transport.getPeer().host,
"src_port": self.transport.getPeer().port,
@@ -120,7 +84,7 @@ def processCommand(self, command: bytes, *args):
authCmd = command in self.AUTH_CMDS
if not self.mbox and not authCmd:
raise POP3Error(b"not authenticated yet: cannot do " + command)
- f = getattr(self, f"do_{self.check_bytes(command)}", None)
+ f = getattr(self, f"do_{check_bytes(command)}", None)
if f:
return f(*args)
raise POP3Error(b"Unknown protocol command: " + command)
@@ -131,8 +95,8 @@ def do_USER(self, user):
def do_PASS(self, password: bytes, *words: Tuple[bytes]):
if self._user:
- username = self.check_bytes(self._user)
- password = self.check_bytes(b" ".join((password,) + words))
+ username = check_bytes(self._user)
+ password = check_bytes(b" ".join((password,) + words))
status = "failed"
if username == _q_s.username and password == _q_s.password:
username = _q_s.username
@@ -140,7 +104,7 @@ def do_PASS(self, password: bytes, *words: Tuple[bytes]):
status = "success"
_q_s.logs.info(
{
- "server": "pop3_server",
+ "server": _q_s.NAME,
"action": "login",
"status": status,
"src_ip": self.transport.getPeer().host,
@@ -171,73 +135,6 @@ def buildProtocol(self, address):
reactor.listenTCP(port=self.port, factory=factory, interface=self.ip)
reactor.run()
- def run_server(self, process=False, auto=False):
- status = "error"
- run = False
- if process:
- if auto and not self.auto_disabled:
- port = get_free_port()
- if port > 0:
- self.port = port
- run = True
- elif self.close_port() and self.kill_server():
- run = True
-
- if run:
- self.process = Popen(
- [
- "python3",
- path.realpath(__file__),
- "--custom",
- "--ip",
- str(self.ip),
- "--port",
- str(self.port),
- "--username",
- str(self.username),
- "--password",
- str(self.password),
- "--options",
- str(self.options),
- "--config",
- str(self.config),
- "--uuid",
- str(self.uuid),
- ]
- )
- if self.process.poll() is None and check_if_server_is_running(self.uuid):
- status = "success"
-
- self.logs.info(
- {
- "server": "pop3_server",
- "action": "process",
- "status": status,
- "src_ip": self.ip,
- "src_port": self.port,
- "username": self.username,
- "password": self.password,
- "dest_ip": self.ip,
- "dest_port": self.port,
- }
- )
-
- if status == "success":
- return True
- else:
- self.kill_server()
- return False
- else:
- self.pop3_server_main()
-
- def close_port(self):
- ret = close_port_wrapper("pop3_server", self.ip, self.port, self.logs)
- return ret
-
- def kill_server(self):
- ret = kill_server_wrapper("pop3_server", self.uuid, self.process)
- return ret
-
def test_server(self, ip=None, port=None, username=None, password=None):
with suppress(Exception):
from poplib import POP3 as poplibPOP3
diff --git a/honeypots/postgres_server.py b/honeypots/postgres_server.py
index d0dd44c..2b84d25 100644
--- a/honeypots/postgres_server.py
+++ b/honeypots/postgres_server.py
@@ -11,68 +11,29 @@
"""
from contextlib import suppress
-from os import getenv, path
from struct import unpack
-from subprocess import Popen
-from uuid import uuid4
from twisted.internet import reactor
from twisted.internet.protocol import Factory, Protocol
+from honeypots.base_server import BaseServer
from honeypots.helper import (
- check_if_server_is_running,
- close_port_wrapper,
- get_free_port,
- kill_server_wrapper,
server_arguments,
- set_local_vars,
- setup_logger,
+ check_bytes,
)
-class QPostgresServer:
- def __init__(self, **kwargs):
- self.auto_disabled = None
- self.process = None
- self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8]
- self.config = kwargs.get("config", "")
- if self.config:
- self.logs = setup_logger(__class__.__name__, self.uuid, self.config)
- set_local_vars(self, self.config)
- else:
- self.logs = setup_logger(__class__.__name__, self.uuid, None)
- self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0"
- self.port = (
- (kwargs.get("port", None) and int(kwargs.get("port", None)))
- or (hasattr(self, "port") and self.port)
- or 5432
- )
- self.username = (
- kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test"
- )
- self.password = (
- kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test"
- )
- self.options = (
- kwargs.get("options", "")
- or (hasattr(self, "options") and self.options)
- or getenv("HONEYPOTS_OPTIONS", "")
- or ""
- )
+class QPostgresServer(BaseServer):
+ NAME = "postgres_server"
+ DEFAULT_PORT = 5432
- def postgres_server_main(self):
+ def server_main(self):
_q_s = self
class CustomPostgresProtocol(Protocol):
_state = None
_variables = {}
- def check_bytes(self, string):
- if isinstance(string, bytes):
- return string.decode()
- else:
- return str(string)
-
def read_data_custom(self, data):
_data = data.decode("utf-8")
length = unpack("!I", data[0:4])
@@ -88,7 +49,7 @@ def connectionMade(self):
self._variables = {}
_q_s.logs.info(
{
- "server": "postgres_server",
+ "server": _q_s.NAME,
"action": "connection",
"src_ip": self.transport.getPeer().host,
"src_port": self.transport.getPeer().port,
@@ -108,8 +69,8 @@ def dataReceived(self, data):
elif self._state == 3:
if data[0] == 112 and "user" in self._variables:
self.read_password_custom(data)
- username = self.check_bytes(self._variables["user"])
- password = self.check_bytes(self._variables["password"])
+ username = check_bytes(self._variables["user"])
+ password = check_bytes(self._variables["password"])
status = "failed"
if username == _q_s.username and password == _q_s.password:
username = _q_s.username
@@ -117,7 +78,7 @@ def dataReceived(self, data):
status = "success"
_q_s.logs.info(
{
- "server": "postgres_server",
+ "server": _q_s.NAME,
"action": "login",
"status": status,
"src_ip": self.transport.getPeer().host,
@@ -142,73 +103,6 @@ def connectionLost(self, reason):
reactor.listenTCP(port=self.port, factory=factory, interface=self.ip)
reactor.run()
- def run_server(self, process=False, auto=False):
- status = "error"
- run = False
- if process:
- if auto and not self.auto_disabled:
- port = get_free_port()
- if port > 0:
- self.port = port
- run = True
- elif self.close_port() and self.kill_server():
- run = True
-
- if run:
- self.process = Popen(
- [
- "python3",
- path.realpath(__file__),
- "--custom",
- "--ip",
- str(self.ip),
- "--port",
- str(self.port),
- "--username",
- str(self.username),
- "--password",
- str(self.password),
- "--options",
- str(self.options),
- "--config",
- str(self.config),
- "--uuid",
- str(self.uuid),
- ]
- )
- if self.process.poll() is None and check_if_server_is_running(self.uuid):
- status = "success"
-
- self.logs.info(
- {
- "server": "postgres_server",
- "action": "process",
- "status": status,
- "src_ip": self.ip,
- "src_port": self.port,
- "username": self.username,
- "password": self.password,
- "dest_ip": self.ip,
- "dest_port": self.port,
- }
- )
-
- if status == "success":
- return True
- else:
- self.kill_server()
- return False
- else:
- self.postgres_server_main()
-
- def close_port(self):
- ret = close_port_wrapper("postgres_server", self.ip, self.port, self.logs)
- return ret
-
- def kill_server(self):
- ret = kill_server_wrapper("postgres_server", self.uuid, self.process)
- return ret
-
def test_server(self, ip=None, port=None, username=None, password=None):
with suppress(Exception):
from psycopg2 import connect
diff --git a/honeypots/rdp_server.py b/honeypots/rdp_server.py
index 31a5bb2..95920ad 100644
--- a/honeypots/rdp_server.py
+++ b/honeypots/rdp_server.py
@@ -10,82 +10,30 @@
// -------------------------------------------------------------
"""
+from contextlib import suppress
from socket import socket, SHUT_RDWR, AF_INET, SOCK_STREAM, SOL_SOCKET, SO_REUSEADDR
from ssl import SSLContext, PROTOCOL_TLSv1_2, CERT_NONE
-from subprocess import Popen
-from os import path, getenv
+from struct import unpack
+from threading import Thread
+
+from honeypots.base_server import BaseServer
from honeypots.helper import (
- check_if_server_is_running,
- close_port_wrapper,
- get_free_port,
- kill_server_wrapper,
server_arguments,
- set_local_vars,
- setup_logger,
+ create_certificate,
+ check_bytes,
)
-from uuid import uuid4
-from contextlib import suppress
-from threading import Thread
-from struct import unpack
-from OpenSSL import crypto
-from tempfile import gettempdir, _get_candidate_names
-class QRDPServer:
+class QRDPServer(BaseServer):
+ NAME = "rdp_server"
+ DEFAULT_PORT = 3389
+
def __init__(self, **kwargs):
- self.auto_disabled = None
- self.process = None
- self.key = path.join(gettempdir(), next(_get_candidate_names()))
- self.cert = path.join(gettempdir(), next(_get_candidate_names()))
- self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8]
- self.config = kwargs.get("config", "")
- if self.config:
- self.logs = setup_logger(__class__.__name__, self.uuid, self.config)
- set_local_vars(self, self.config)
- else:
- self.logs = setup_logger(__class__.__name__, self.uuid, None)
- self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0"
- self.port = (
- (kwargs.get("port", None) and int(kwargs.get("port", None)))
- or (hasattr(self, "port") and self.port)
- or 3389
- )
- self.username = (
- kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test"
- )
- self.password = (
- kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test"
- )
- self.options = (
- kwargs.get("options", "")
- or (hasattr(self, "options") and self.options)
- or getenv("HONEYPOTS_OPTIONS", "")
- or ""
- )
+ super().__init__(**kwargs)
- def rdp_server_main(self):
+ def server_main(self):
_q_s = self
- def CreateCert(host_name, key, cert):
- pk = crypto.PKey()
- pk.generate_key(crypto.TYPE_RSA, 2048)
- c = crypto.X509()
- c.get_subject().C = "US"
- c.get_subject().ST = "OR"
- c.get_subject().L = "None"
- c.get_subject().O = "None"
- c.get_subject().OU = "None"
- c.get_subject().CN = next(_get_candidate_names())
- c.set_serial_number(0)
- before, after = (0, 60 * 60 * 24 * 365 * 2)
- c.gmtime_adj_notBefore(before)
- c.gmtime_adj_notAfter(after)
- c.set_issuer(c.get_subject())
- c.set_pubkey(pk)
- c.sign(pk, "sha256")
- open(cert, "wb").write(crypto.dump_certificate(crypto.FILETYPE_PEM, c))
- open(key, "wb").write(crypto.dump_privatekey(crypto.FILETYPE_PEM, pk))
-
class ConnectionHandle(Thread):
def __init__(self, sock, key, cert):
super(ConnectionHandle, self).__init__()
@@ -93,12 +41,6 @@ def __init__(self, sock, key, cert):
self.key = key
self.cert = cert
- def check_bytes(self, string):
- if isinstance(string, bytes):
- return string.decode()
- else:
- return str(string)
-
def get_value(self, length, data):
with suppress(Exception):
var = b""
@@ -107,25 +49,15 @@ def get_value(self, length, data):
break
if _ == 0:
continue
- else:
- var += bytes([_])
+ var += bytes([_])
if length / 2 == len(var):
return var
return b""
- def extract_cookie(self, data):
- cookie = b""
- with suppress(Exception):
- for idx, _ in enumerate(data):
- if _ == 13 and data[idx + 1] == 10:
- break
- else:
- cookie += bytes([_])
- return cookie
+ def extract_cookie(self, data: bytes) -> bytes:
+ return data[: data.find(b"\r\n")]
- def extract_creds(self, data):
- user = ""
- password = ""
+ def extract_creds(self, data: bytes):
with suppress(Exception):
(
flag,
@@ -160,7 +92,7 @@ def run(self):
with suppress(Exception):
_q_s.logs.info(
{
- "server": "rdp_server",
+ "server": _q_s.NAME,
"action": "connection",
"src_ip": self.sock.getpeername()[0],
"src_port": self.sock.getpeername()[1],
@@ -172,11 +104,10 @@ def run(self):
data = self.sock.recv(1024)
if b"Cookie" in data:
- cookie = self.extract_cookie(data[11:])
- cookie = self.check_bytes(cookie)
+ cookie = self.extract_cookie(data[11:]).decode(errors="replace")
_q_s.logs.info(
{
- "server": "rdp_server",
+ "server": _q_s.NAME,
"action": "stshash",
"mstshash": "success",
"src_ip": self.sock.getpeername()[0],
@@ -257,19 +188,15 @@ def run(self):
data = self.sock.recv(1024)
if len(data) > 14:
if data[15] == 64:
- username = ""
- password = ""
status = "failed"
username, password = self.extract_creds(data)
- username = self.check_bytes(username)
- password = self.check_bytes(password)
+ username = check_bytes(username)
+ password = check_bytes(password)
if username == _q_s.username and password == _q_s.password:
- username = _q_s.username
- password = _q_s.password
status = "success"
_q_s.logs.info(
{
- "server": "rdp_server",
+ "server": _q_s.NAME,
"action": "login",
"status": status,
"src_ip": self.sock.getpeername()[0],
@@ -299,84 +226,17 @@ def run(self):
with suppress(Exception):
self.sock.close()
- CreateCert("localhost", self.key, self.cert)
rpdserver = socket(AF_INET, SOCK_STREAM)
rpdserver.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
rpdserver.bind((self.ip, self.port))
rpdserver.listen()
- while True:
- with suppress(Exception):
- client, addr = rpdserver.accept()
- client.settimeout(10.0)
- ConnectionHandle(client, self.key, self.cert).start()
-
- def run_server(self, process=False, auto=False):
- status = "error"
- run = False
- if process:
- if auto and not self.auto_disabled:
- port = get_free_port()
- if port > 0:
- self.port = port
- run = True
- elif self.close_port() and self.kill_server():
- run = True
-
- if run:
- self.process = Popen(
- [
- "python3",
- path.realpath(__file__),
- "--custom",
- "--ip",
- str(self.ip),
- "--port",
- str(self.port),
- "--username",
- str(self.username),
- "--password",
- str(self.password),
- "--options",
- str(self.options),
- "--config",
- str(self.config),
- "--uuid",
- str(self.uuid),
- ]
- )
- if self.process.poll() is None and check_if_server_is_running(self.uuid):
- status = "success"
-
- self.logs.info(
- {
- "server": "rdp_server",
- "action": "process",
- "status": status,
- "src_ip": self.ip,
- "src_port": self.port,
- "username": self.username,
- "password": self.password,
- "dest_ip": self.ip,
- "dest_port": self.port,
- }
- )
-
- if status == "success":
- return True
- else:
- self.kill_server()
- return False
- else:
- self.rdp_server_main()
-
- def close_port(self):
- ret = close_port_wrapper("rdp_server", self.ip, self.port, self.logs)
- return ret
-
- def kill_server(self):
- ret = kill_server_wrapper("rdp_server", self.uuid, self.process)
- return ret
+ with create_certificate() as (cert, key):
+ while True:
+ with suppress(Exception):
+ client, addr = rpdserver.accept()
+ client.settimeout(10.0)
+ ConnectionHandle(client, key, cert).start()
def test_server(self, ip=None, port=None):
with suppress(Exception):
diff --git a/honeypots/redis_server.py b/honeypots/redis_server.py
index c691ea3..ea39566 100644
--- a/honeypots/redis_server.py
+++ b/honeypots/redis_server.py
@@ -11,64 +11,25 @@
"""
from contextlib import suppress
-from os import getenv, path
-from subprocess import Popen
-from uuid import uuid4
from twisted.internet import reactor
from twisted.internet.protocol import Factory, Protocol
+from honeypots.base_server import BaseServer
from honeypots.helper import (
- check_if_server_is_running,
- close_port_wrapper,
- get_free_port,
- kill_server_wrapper,
server_arguments,
- set_local_vars,
- setup_logger,
+ check_bytes,
)
-class QRedisServer:
- def __init__(self, **kwargs):
- self.auto_disabled = None
- self.process = None
- self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8]
- self.config = kwargs.get("config", "")
- if self.config:
- self.logs = setup_logger(__class__.__name__, self.uuid, self.config)
- set_local_vars(self, self.config)
- else:
- self.logs = setup_logger(__class__.__name__, self.uuid, None)
- self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0"
- self.port = (
- (kwargs.get("port", None) and int(kwargs.get("port", None)))
- or (hasattr(self, "port") and self.port)
- or 6379
- )
- self.username = (
- kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test"
- )
- self.password = (
- kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test"
- )
- self.options = (
- kwargs.get("options", "")
- or (hasattr(self, "options") and self.options)
- or getenv("HONEYPOTS_OPTIONS", "")
- or ""
- )
+class QRedisServer(BaseServer):
+ NAME = "redis_server"
+ DEFAULT_PORT = 6379
- def redis_server_main(self):
+ def server_main(self):
_q_s = self
class CustomRedisProtocol(Protocol):
- def check_bytes(self, string):
- if isinstance(string, bytes):
- return string.decode()
- else:
- return str(string)
-
def get_command(self, data):
with suppress(Exception):
_data = data.decode("utf-8").split("\x0d\x0a")
@@ -97,8 +58,8 @@ def parse_data(self, c, data):
if _data[0::2][_][0] == "$" and len(_data[1::2][_]) == int(_data[0::2][_][1]):
password = _data[1::2][_]
if c == 2 or c == 1:
- username = self.check_bytes(username)
- password = self.check_bytes(password)
+ username = check_bytes(username)
+ password = check_bytes(password)
status = "failed"
if username == _q_s.username and password == _q_s.password:
username = _q_s.username
@@ -106,7 +67,7 @@ def parse_data(self, c, data):
status = "success"
_q_s.logs.info(
{
- "server": "redis_server",
+ "server": _q_s.NAME,
"action": "login",
"status": status,
"src_ip": self.transport.getPeer().host,
@@ -123,7 +84,7 @@ def connectionMade(self):
self._variables = {}
_q_s.logs.info(
{
- "server": "redis_server",
+ "server": _q_s.NAME,
"action": "connection",
"src_ip": self.transport.getPeer().host,
"src_port": self.transport.getPeer().port,
@@ -146,73 +107,6 @@ def dataReceived(self, data):
reactor.listenTCP(port=self.port, factory=factory, interface=self.ip)
reactor.run()
- def run_server(self, process=False, auto=False):
- status = "error"
- run = False
- if process:
- if auto and not self.auto_disabled:
- port = get_free_port()
- if port > 0:
- self.port = port
- run = True
- elif self.close_port() and self.kill_server():
- run = True
-
- if run:
- self.process = Popen(
- [
- "python3",
- path.realpath(__file__),
- "--custom",
- "--ip",
- str(self.ip),
- "--port",
- str(self.port),
- "--username",
- str(self.username),
- "--password",
- str(self.password),
- "--options",
- str(self.options),
- "--config",
- str(self.config),
- "--uuid",
- str(self.uuid),
- ]
- )
- if self.process.poll() is None and check_if_server_is_running(self.uuid):
- status = "success"
-
- self.logs.info(
- {
- "server": "redis_server",
- "action": "process",
- "status": status,
- "src_ip": self.ip,
- "src_port": self.port,
- "username": self.username,
- "password": self.password,
- "dest_ip": self.ip,
- "dest_port": self.port,
- }
- )
-
- if status == "success":
- return True
- else:
- self.kill_server()
- return False
- else:
- self.redis_server_main()
-
- def close_port(self):
- ret = close_port_wrapper("redis_server", self.ip, self.port, self.logs)
- return ret
-
- def kill_server(self):
- ret = kill_server_wrapper("redis_server", self.uuid, self.process)
- return ret
-
def test_server(self, ip=None, port=None, username=None, password=None):
with suppress(Exception):
from redis import StrictRedis
diff --git a/honeypots/sip_server.py b/honeypots/sip_server.py
index b0a345a..cbdf9de 100644
--- a/honeypots/sip_server.py
+++ b/honeypots/sip_server.py
@@ -11,55 +11,22 @@
"""
from contextlib import suppress
-from os import getenv, path
-from subprocess import Popen
-from uuid import uuid4
from twisted.internet import reactor
from twisted.protocols.sip import Base
+from honeypots.base_server import BaseServer
from honeypots.helper import (
- check_if_server_is_running,
- close_port_wrapper,
- get_free_port,
- kill_server_wrapper,
server_arguments,
- set_local_vars,
- setup_logger,
+ check_bytes,
)
-class QSIPServer:
- def __init__(self, **kwargs):
- self.auto_disabled = None
- self.process = None
- self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8]
- self.config = kwargs.get("config", "")
- if self.config:
- self.logs = setup_logger(__class__.__name__, self.uuid, self.config)
- set_local_vars(self, self.config)
- else:
- self.logs = setup_logger(__class__.__name__, self.uuid, None)
- self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0"
- self.port = (
- (kwargs.get("port", None) and int(kwargs.get("port", None)))
- or (hasattr(self, "port") and self.port)
- or 5060
- )
- self.username = (
- kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test"
- )
- self.password = (
- kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test"
- )
- self.options = (
- kwargs.get("options", "")
- or (hasattr(self, "options") and self.options)
- or getenv("HONEYPOTS_OPTIONS", "")
- or ""
- )
+class QSIPServer(BaseServer):
+ NAME = "sip_server"
+ DEFAULT_PORT = 5060
- def sip_server_main(self):
+ def server_main(self):
_q_s = self
class CustomSIPServer(Base):
@@ -68,25 +35,19 @@ def handle_request(self, message, addr):
_q_s.logs.info(
{
- "server": "sip_server",
+ "server": _q_s.NAME,
"action": "connection",
"src_ip": addr[0],
"src_port": addr[1],
}
)
- def check_bytes(string):
- if isinstance(string, bytes):
- return string.decode()
- else:
- return str(string)
-
for item, value in message.headers.items():
headers.update({check_bytes(item): ",".join(map(check_bytes, value))})
_q_s.logs.info(
{
- "server": "sip_server",
+ "server": _q_s.NAME,
"action": "request",
"src_ip": addr[0],
"src_port": addr[1],
@@ -100,67 +61,6 @@ def check_bytes(string):
reactor.listenUDP(port=self.port, protocol=CustomSIPServer(), interface=self.ip)
reactor.run()
- def run_server(self, process=False, auto=False):
- status = "error"
- run = False
- if process:
- if auto and not self.auto_disabled:
- port = get_free_port()
- if port > 0:
- self.port = port
- run = True
- elif self.close_port() and self.kill_server():
- run = True
-
- if run:
- self.process = Popen(
- [
- "python3",
- path.realpath(__file__),
- "--custom",
- "--ip",
- str(self.ip),
- "--port",
- str(self.port),
- "--options",
- str(self.options),
- "--config",
- str(self.config),
- "--uuid",
- str(self.uuid),
- ]
- )
- if self.process.poll() is None and check_if_server_is_running(self.uuid):
- status = "success"
-
- self.logs.info(
- {
- "server": "sip_server",
- "action": "process",
- "status": status,
- "src_ip": self.ip,
- "src_port": self.port,
- "dest_ip": self.ip,
- "dest_port": self.port,
- }
- )
-
- if status == "success":
- return True
- else:
- self.kill_server()
- return False
- else:
- self.sip_server_main()
-
- def close_port(self):
- ret = close_port_wrapper("sip_server", self.ip, self.port, self.logs)
- return ret
-
- def kill_server(self):
- ret = kill_server_wrapper("sip_server", self.uuid, self.process)
- return ret
-
def test_server(self, ip=None, port=None, username=None, password=None):
with suppress(Exception):
from socket import socket, AF_INET, SOCK_DGRAM, IPPROTO_UDP
diff --git a/honeypots/smb_server.py b/honeypots/smb_server.py
index e56ab86..92177ec 100644
--- a/honeypots/smb_server.py
+++ b/honeypots/smb_server.py
@@ -12,102 +12,72 @@
from contextlib import suppress
from logging import DEBUG, getLogger, StreamHandler
-from os import getenv, path
+from os import path
from random import randint
from shutil import rmtree
-from subprocess import Popen
from tempfile import mkdtemp
from threading import current_thread
from time import sleep
-from uuid import uuid4
from impacket import smbserver
from impacket.ntlm import compute_lmhash, compute_nthash
from six.moves import socketserver
+from honeypots.base_server import BaseServer
from honeypots.helper import (
- check_if_server_is_running,
- close_port_wrapper,
- get_free_port,
- kill_server_wrapper,
server_arguments,
- set_local_vars,
- setup_logger,
)
-class QSMBServer:
+class QSMBServer(BaseServer):
+ NAME = "smb_server"
+ DEFAULT_PORT = 445
+
def __init__(self, **kwargs):
- self.auto_disabled = None
- self.process = None
- self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8]
+ super().__init__(**kwargs)
self.folders = ""
- self.config = kwargs.get("config", "")
- if self.config:
- self.logs = setup_logger(__class__.__name__, self.uuid, self.config)
- set_local_vars(self, self.config)
- else:
- self.logs = setup_logger(__class__.__name__, self.uuid, None)
- self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0"
- self.port = (
- (kwargs.get("port", None) and int(kwargs.get("port", None)))
- or (hasattr(self, "port") and self.port)
- or 445
- )
- self.username = (
- kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test"
- )
- self.password = (
- kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test"
- )
- self.options = (
- kwargs.get("options", "")
- or (hasattr(self, "options") and self.options)
- or getenv("HONEYPOTS_OPTIONS", "")
- or ""
- )
- def smb_server_main(self):
+ def server_main(self):
_q_s = self
class Logger:
def write(self, message):
- with suppress(Exception):
- temp = current_thread().name
- if temp.startswith("thread_"):
- ip = temp.split("_")[1]
- port = temp.split("_")[2]
- if (
- "Incoming connection" in message.strip()
- or "AUTHENTICATE_MESSAGE" in message.strip()
- or "authenticated successfully" in message.strip()
- ):
+ temp = current_thread().name
+ if temp.startswith("thread_"):
+ ip = temp.split("_")[1]
+ port = temp.split("_")[2]
+ if (
+ "Incoming connection" in message.strip()
+ or "AUTHENTICATE_MESSAGE" in message.strip()
+ or "authenticated successfully" in message.strip()
+ ):
+ _q_s.logs.info(
+ {
+ "server": _q_s.NAME,
+ "action": "connection",
+ "data": message.strip(),
+ "src_ip": ip,
+ "src_port": port,
+ "dest_ip": _q_s.ip,
+ "dest_port": _q_s.port,
+ }
+ )
+ elif ":aaaaaaaaaaaaaaaa:" in message.strip():
+ parsed = message.strip().split(":")
+ if len(parsed) == 6:
+ username, _, _, _, nt_res_1, nt_res_2 = parsed
_q_s.logs.info(
{
- "server": "smb_server",
- "action": "connection",
- "data": message.strip(),
+ "server": _q_s.NAME,
+ "action": "login",
+ "username": username,
"src_ip": ip,
"src_port": port,
"dest_ip": _q_s.ip,
"dest_port": _q_s.port,
+ "data": {"nt_data_1": nt_res_1, "nt_data_2": nt_res_2},
}
)
- elif ":4141414141414141:" in message.strip():
- parsed = message.strip().split(":")
- if len(parsed) > 2:
- _q_s.logs.info(
- {
- "server": "smb_server",
- "action": "login",
- "workstation": parsed[0],
- "test": parsed[1],
- "src_ip": ip,
- "src_port": port,
- "dest_ip": _q_s.ip,
- "dest_port": _q_s.port,
- }
- )
class SMBSERVERHandler(smbserver.SMBSERVERHandler):
def __init__(self, request, client_address, server, select_poll=False):
@@ -166,73 +136,6 @@ def start(self):
server.start()
rmtree(dirpath)
- def run_server(self, process=False, auto=False):
- status = "error"
- run = False
- if process:
- if auto and not self.auto_disabled:
- port = get_free_port()
- if port > 0:
- self.port = port
- run = True
- elif self.close_port() and self.kill_server():
- run = True
-
- if run:
- self.process = Popen(
- [
- "python3",
- path.realpath(__file__),
- "--custom",
- "--ip",
- str(self.ip),
- "--port",
- str(self.port),
- "--username",
- str(self.username),
- "--password",
- str(self.password),
- "--options",
- str(self.options),
- "--config",
- str(self.config),
- "--uuid",
- str(self.uuid),
- ]
- )
- if self.process.poll() is None and check_if_server_is_running(self.uuid):
- status = "success"
-
- self.logs.info(
- {
- "server": "smb_server",
- "action": "process",
- "status": status,
- "src_ip": self.ip,
- "src_port": self.port,
- "username": self.username,
- "password": self.password,
- "dest_ip": self.ip,
- "dest_port": self.port,
- }
- )
-
- if status == "success":
- return True
- else:
- self.kill_server()
- return False
- else:
- self.smb_server_main()
-
- def close_port(self):
- ret = close_port_wrapper("smb_server", self.ip, self.port, self.logs)
- return ret
-
- def kill_server(self):
- ret = kill_server_wrapper("smb_server", self.uuid, self.process)
- return ret
-
def test_server(self, ip=None, port=None, username=None, password=None):
with suppress(Exception):
from impacket.smbconnection import SMBConnection
diff --git a/honeypots/smtp_server.py b/honeypots/smtp_server.py
index d04b00a..c92da1b 100644
--- a/honeypots/smtp_server.py
+++ b/honeypots/smtp_server.py
@@ -10,55 +10,22 @@
// -------------------------------------------------------------
"""
-from smtpd import SMTPChannel, SMTPServer
from asyncore import loop
from base64 import b64decode
-from os import path, getenv
-from subprocess import Popen
+from contextlib import suppress
+from smtpd import SMTPChannel, SMTPServer
+
+from honeypots.base_server import BaseServer
from honeypots.helper import (
- check_if_server_is_running,
- close_port_wrapper,
- get_free_port,
- kill_server_wrapper,
server_arguments,
- set_local_vars,
- setup_logger,
)
-from uuid import uuid4
-from contextlib import suppress
-class QSMTPServer:
- def __init__(self, **kwargs):
- self.auto_disabled = None
- self.process = None
- self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8]
- self.config = kwargs.get("config", "")
- if self.config:
- self.logs = setup_logger(__class__.__name__, self.uuid, self.config)
- set_local_vars(self, self.config)
- else:
- self.logs = setup_logger(__class__.__name__, self.uuid, None)
- self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0"
- self.port = (
- (kwargs.get("port", None) and int(kwargs.get("port", None)))
- or (hasattr(self, "port") and self.port)
- or 25
- )
- self.username = (
- kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test"
- )
- self.password = (
- kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test"
- )
- self.options = (
- kwargs.get("options", "")
- or (hasattr(self, "options") and self.options)
- or getenv("HONEYPOTS_OPTIONS", "")
- or ""
- )
+class QSMTPServer(BaseServer):
+ NAME = "smtp_server"
+ DEFAULT_PORT = 25
- def smtp_server_main(self):
+ def server_main(self):
_q_s = self
class CustomSMTPChannel(SMTPChannel):
@@ -78,7 +45,7 @@ def found_terminator(self):
if command != "HELO" and command != "EHLO":
_q_s.logs.info(
{
- "server": "smtp_server",
+ "server": _q_s.NAME,
"action": "connection",
"src_ip": self.addr[0],
"src_port": self.addr[1],
@@ -92,7 +59,7 @@ def found_terminator(self):
def smtp_EHLO(self, arg):
_q_s.logs.info(
{
- "server": "smtp_server",
+ "server": _q_s.NAME,
"action": "connection",
"src_ip": self.addr[0],
"src_port": self.addr[1],
@@ -124,7 +91,7 @@ def smtp_AUTH(self, arg):
status = "success"
_q_s.logs.info(
{
- "server": "smtp_server",
+ "server": _q_s.NAME,
"action": "login",
"status": status,
"src_ip": self.addr[0],
@@ -151,7 +118,7 @@ def handle_accept(self):
conn, addr = self.accept()
_q_s.logs.info(
{
- "server": "smtp_server",
+ "server": _q_s.NAME,
"action": "connection",
"src_ip": addr[0],
"src_port": addr[1],
@@ -164,73 +131,6 @@ def handle_accept(self):
CustomSMTPServer((self.ip, self.port), None)
loop(timeout=1.1, use_poll=True)
- def run_server(self, process=False, auto=False):
- status = "error"
- run = False
- if process:
- if auto and not self.auto_disabled:
- port = get_free_port()
- if port > 0:
- self.port = port
- run = True
- elif self.close_port() and self.kill_server():
- run = True
-
- if run:
- self.process = Popen(
- [
- "python3",
- path.realpath(__file__),
- "--custom",
- "--ip",
- str(self.ip),
- "--port",
- str(self.port),
- "--username",
- str(self.username),
- "--password",
- str(self.password),
- "--options",
- str(self.options),
- "--config",
- str(self.config),
- "--uuid",
- str(self.uuid),
- ]
- )
- if self.process.poll() is None and check_if_server_is_running(self.uuid):
- status = "success"
-
- self.logs.info(
- {
- "server": "smtp_server",
- "action": "process",
- "status": status,
- "src_ip": self.ip,
- "src_port": self.port,
- "username": self.username,
- "password": self.password,
- "dest_ip": self.ip,
- "dest_port": self.port,
- }
- )
-
- if status == "success":
- return True
- else:
- self.kill_server()
- return False
- else:
- self.smtp_server_main()
-
- def close_port(self):
- ret = close_port_wrapper("smtp_server", self.ip, self.port, self.logs)
- return ret
-
- def kill_server(self):
- ret = kill_server_wrapper("smtp_server", self.uuid, self.process)
- return ret
-
def test_server(self, ip=None, port=None, username=None, password=None):
with suppress(Exception):
from smtplib import SMTP
diff --git a/honeypots/snmp_server.py b/honeypots/snmp_server.py
index aaee93d..5d72b3b 100644
--- a/honeypots/snmp_server.py
+++ b/honeypots/snmp_server.py
@@ -9,56 +9,27 @@
// contributors list qeeqbox/honeypots/graphs/contributors
// -------------------------------------------------------------
"""
+from contextlib import suppress
from warnings import filterwarnings
+
from cryptography.utils import CryptographyDeprecationWarning
filterwarnings(action="ignore", category=CryptographyDeprecationWarning)
-
-from contextlib import suppress
-from os import getenv, path
-from subprocess import Popen
-from uuid import uuid4
-
from scapy.all import SNMP
from twisted.internet import reactor
from twisted.internet.protocol import DatagramProtocol
+from honeypots.base_server import BaseServer
from honeypots.helper import (
- check_if_server_is_running,
- close_port_wrapper,
- get_free_port,
- kill_server_wrapper,
server_arguments,
- set_local_vars,
- setup_logger,
)
-class QSNMPServer:
- def __init__(self, **kwargs):
- self.auto_disabled = None
- self.process = None
- self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8]
- self.config = kwargs.get("config", "")
- if self.config:
- self.logs = setup_logger(__class__.__name__, self.uuid, self.config)
- set_local_vars(self, self.config)
- else:
- self.logs = setup_logger(__class__.__name__, self.uuid, None)
- self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0"
- self.port = (
- (kwargs.get("port", None) and int(kwargs.get("port", None)))
- or (hasattr(self, "port") and self.port)
- or 161
- )
- self.options = (
- kwargs.get("options", "")
- or (hasattr(self, "options") and self.options)
- or getenv("HONEYPOTS_OPTIONS", "")
- or ""
- )
+class QSNMPServer(BaseServer):
+ NAME = "snmp_server"
+ DEFAULT_PORT = 161
- def snmp_server_main(self):
+ def server_main(self):
_q_s = self
class CustomDatagramProtocolProtocol(DatagramProtocol):
@@ -76,7 +47,7 @@ def parse_snmp(self, data):
def datagramReceived(self, data, addr):
_q_s.logs.info(
{
- "server": "snmp_server",
+ "server": _q_s.NAME,
"action": "connection",
"status": "fail",
"src_ip": addr[0],
@@ -89,7 +60,7 @@ def datagramReceived(self, data, addr):
if version or community or oids:
_q_s.logs.info(
{
- "server": "snmp_server",
+ "server": _q_s.NAME,
"action": "query",
"status": "success",
"src_ip": addr[0],
@@ -106,67 +77,6 @@ def datagramReceived(self, data, addr):
)
reactor.run()
- def run_server(self, process=False, auto=False):
- status = "error"
- run = False
- if process:
- if auto and not self.auto_disabled:
- port = get_free_port()
- if port > 0:
- self.port = port
- run = True
- elif self.close_port() and self.kill_server():
- run = True
-
- if run:
- self.process = Popen(
- [
- "python3",
- path.realpath(__file__),
- "--custom",
- "--ip",
- str(self.ip),
- "--port",
- str(self.port),
- "--options",
- str(self.options),
- "--config",
- str(self.config),
- "--uuid",
- str(self.uuid),
- ]
- )
- if self.process.poll() is None and check_if_server_is_running(self.uuid):
- status = "success"
-
- self.logs.info(
- {
- "server": "snmp_server",
- "action": "process",
- "status": status,
- "src_ip": self.ip,
- "src_port": self.port,
- "dest_ip": self.ip,
- "dest_port": self.port,
- }
- )
-
- if status == "success":
- return True
- else:
- self.kill_server()
- return False
- else:
- self.snmp_server_main()
-
- def close_port(self):
- ret = close_port_wrapper("snmp_server", self.ip, self.port, self.logs)
- return ret
-
- def kill_server(self):
- ret = kill_server_wrapper("snmp_server", self.uuid, self.process)
- return ret
-
def test_server(self, ip=None, port=None, username=None, password=None):
with suppress(Exception):
from pysnmp.hlapi import (
diff --git a/honeypots/socks5_server.py b/honeypots/socks5_server.py
index fa0a9ff..ca026e1 100644
--- a/honeypots/socks5_server.py
+++ b/honeypots/socks5_server.py
@@ -10,68 +10,25 @@
// -------------------------------------------------------------
"""
import struct
+from contextlib import suppress
from socketserver import TCPServer, StreamRequestHandler, ThreadingMixIn
from struct import unpack
-from os import path, getenv
-from subprocess import Popen
-from honeypots import set_up_error_logging
+from honeypots.base_server import BaseServer
from honeypots.helper import (
- check_if_server_is_running,
- close_port_wrapper,
- get_free_port,
- kill_server_wrapper,
server_arguments,
- set_local_vars,
- setup_logger,
+ check_bytes,
)
-from uuid import uuid4
-from contextlib import suppress
-class QSOCKS5Server:
+class QSOCKS5Server(BaseServer):
NAME = "socks5_server"
+ DEFAULT_PORT = 1080
- def __init__(self, **kwargs):
- self.auto_disabled = None
- self.process = None
- self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8]
- self.config = kwargs.get("config", "")
- if self.config:
- self.logs = setup_logger(__class__.__name__, self.uuid, self.config)
- set_local_vars(self, self.config)
- else:
- self.logs = setup_logger(__class__.__name__, self.uuid, None)
- self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0"
- self.port = (
- (kwargs.get("port", None) and int(kwargs.get("port", None)))
- or (hasattr(self, "port") and self.port)
- or 1080
- )
- self.username = (
- kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test"
- )
- self.password = (
- kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test"
- )
- self.options = (
- kwargs.get("options", "")
- or (hasattr(self, "options") and self.options)
- or getenv("HONEYPOTS_OPTIONS", "")
- or ""
- )
- self.logger = set_up_error_logging()
-
- def socks5_server_main(self):
+ def server_main(self):
_q_s = self
class CustomStreamRequestHandler(StreamRequestHandler):
- def check_bytes(self, string):
- if isinstance(string, bytes):
- return string.decode()
- else:
- return str(string)
-
def handle(self):
src_ip, src_port = self.client_address
_q_s.logs.info(
@@ -91,11 +48,9 @@ def handle(self):
self.connection.sendall(b"\x05\x02")
if 1 in unpack("B", self.connection.recv(1)):
_len = ord(self.connection.recv(1))
- username = self.connection.recv(_len)
+ username = check_bytes(self.connection.recv(_len))
_len = ord(self.connection.recv(1))
- password = self.connection.recv(_len)
- username = self.check_bytes(username)
- password = self.check_bytes(password)
+ password = check_bytes(self.connection.recv(_len))
status = "failed"
if username == _q_s.username and password == _q_s.password:
status = "success"
@@ -128,73 +83,6 @@ class ThreadingTCPServer(ThreadingMixIn, TCPServer):
server = ThreadingTCPServer((self.ip, self.port), CustomStreamRequestHandler)
server.serve_forever()
- def run_server(self, process=False, auto=False):
- status = "error"
- run = False
- if process:
- if auto and not self.auto_disabled:
- port = get_free_port()
- if port > 0:
- self.port = port
- run = True
- elif self.close_port() and self.kill_server():
- run = True
-
- if run:
- self.process = Popen(
- [
- "python3",
- path.realpath(__file__),
- "--custom",
- "--ip",
- str(self.ip),
- "--port",
- str(self.port),
- "--username",
- str(self.username),
- "--password",
- str(self.password),
- "--options",
- str(self.options),
- "--config",
- str(self.config),
- "--uuid",
- str(self.uuid),
- ]
- )
- if self.process.poll() is None and check_if_server_is_running(self.uuid):
- status = "success"
-
- self.logs.info(
- {
- "server": self.NAME,
- "action": "process",
- "status": status,
- "src_ip": self.ip,
- "src_port": self.port,
- "username": self.username,
- "password": self.password,
- "dest_ip": self.ip,
- "dest_port": self.port,
- }
- )
-
- if status == "success":
- return True
- else:
- self.kill_server()
- return False
- else:
- self.socks5_server_main()
-
- def close_port(self):
- ret = close_port_wrapper(self.NAME, self.ip, self.port, self.logs)
- return ret
-
- def kill_server(self):
- ret = kill_server_wrapper(self.NAME, self.uuid, self.process)
- return ret
-
def test_server(self, ip=None, port=None, username=None, password=None):
with suppress(Exception):
from requests import get
diff --git a/honeypots/ssh_server.py b/honeypots/ssh_server.py
index 6acbd0f..198aa2a 100644
--- a/honeypots/ssh_server.py
+++ b/honeypots/ssh_server.py
@@ -10,74 +10,43 @@
// -------------------------------------------------------------
"""
+from _thread import start_new_thread
+from binascii import hexlify
+from contextlib import suppress
+from io import StringIO
+from random import choice
+from re import compile as rcompile
+from socket import socket, AF_INET, SOCK_STREAM, SOL_SOCKET, SO_REUSEADDR
+from threading import Event
+from time import time
+
from paramiko import (
RSAKey,
ServerInterface,
Transport,
- OPEN_SUCCEEDED,
AUTH_SUCCESSFUL,
OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED,
OPEN_SUCCEEDED,
AUTH_FAILED,
)
-from socket import socket, AF_INET, SOCK_STREAM, SOL_SOCKET, SO_REUSEADDR
-from _thread import start_new_thread
-from io import StringIO
-from random import choice
-from subprocess import Popen
-from os import path, getenv
-
from paramiko.ssh_exception import SSHException
+from honeypots.base_server import BaseServer
from honeypots.helper import (
- check_if_server_is_running,
- close_port_wrapper,
- get_free_port,
- kill_server_wrapper,
server_arguments,
- set_local_vars,
- setup_logger,
+ check_bytes,
)
-from uuid import uuid4
-from contextlib import suppress
-from re import compile as rcompile
-from time import time
-from threading import Event
-from binascii import hexlify
-class QSSHServer:
+class QSSHServer(BaseServer):
+ NAME = "ssh_server"
+ DEFAULT_PORT = 22
+
def __init__(self, **kwargs):
- self.auto_disabled = None
+ super().__init__(**kwargs)
self.mocking_server = choice(
["OpenSSH 7.5", "OpenSSH 7.3", "Serv-U SSH Server 15.1.1.108", "OpenSSH 6.4"]
)
- self.process = None
- self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8]
- self.config = kwargs.get("config", "")
- if self.config:
- self.logs = setup_logger(__class__.__name__, self.uuid, self.config)
- set_local_vars(self, self.config)
- else:
- self.logs = setup_logger(__class__.__name__, self.uuid, None)
- self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0"
- self.port = (
- (kwargs.get("port", None) and int(kwargs.get("port", None)))
- or (hasattr(self, "port") and self.port)
- or 22
- )
- self.username = (
- kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test"
- )
- self.password = (
- kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test"
- )
- self.options = (
- kwargs.get("options", "")
- or (hasattr(self, "options") and self.options)
- or getenv("HONEYPOTS_OPTIONS", "")
- or ""
- )
self.ansi = rcompile(r"(?:\x1B[@-_]|[\x80-\x9F])[0-?]*[ -/]*[@-~]")
def generate_pub_pri_keys(self):
@@ -88,7 +57,7 @@ def generate_pub_pri_keys(self):
return key.get_base64(), string_io.getvalue()
return None, None
- def ssh_server_main(self):
+ def server_main(self):
_q_s = self
class SSHHandle(ServerInterface):
@@ -96,13 +65,6 @@ def __init__(self, ip, port):
self.ip = ip
self.port = port
self.event = Event()
- # ServerInterface.__init__(self)
-
- def check_bytes(self, string):
- if isinstance(string, bytes):
- return string.decode()
- else:
- return str(string)
def check_channel_request(self, kind, chanid):
if kind == "session":
@@ -110,8 +72,8 @@ def check_channel_request(self, kind, chanid):
return OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED
def check_auth_password(self, username, password):
- username = self.check_bytes(username)
- password = self.check_bytes(password)
+ username = check_bytes(username)
+ password = check_bytes(password)
status = "failed"
if username == _q_s.username and password == _q_s.password:
username = _q_s.username
@@ -120,7 +82,7 @@ def check_auth_password(self, username, password):
if status == "success":
_q_s.logs.info(
{
- "server": "ssh_server",
+ "server": _q_s.NAME,
"action": "login",
"status": status,
"src_ip": self.ip,
@@ -134,7 +96,7 @@ def check_auth_password(self, username, password):
return AUTH_SUCCESSFUL
_q_s.logs.info(
{
- "server": "ssh_server",
+ "server": _q_s.NAME,
"action": "login",
"status": status,
"src_ip": self.ip,
@@ -151,13 +113,13 @@ def check_channel_exec_request(self, channel, command):
if "capture_commands" in _q_s.options:
_q_s.logs.info(
{
- "server": "ssh_server",
+ "server": _q_s.NAME,
"action": "command",
"src_ip": self.ip,
"src_port": self.port,
"dest_ip": _q_s.ip,
"dest_port": _q_s.port,
- "data": {"command": self.check_bytes(command)},
+ "data": {"command": check_bytes(command)},
}
)
self.event.set()
@@ -169,14 +131,14 @@ def get_allowed_auths(self, username):
def check_auth_publickey(self, username, key):
_q_s.logs.info(
{
- "server": "ssh_server",
+ "server": _q_s.NAME,
"action": "login",
"src_ip": self.ip,
"src_port": self.port,
"dest_ip": _q_s.ip,
"dest_port": _q_s.port,
- "username": self.check_bytes(username),
- "key_fingerprint": self.check_bytes(hexlify(key.get_fingerprint())),
+ "username": check_bytes(username),
+ "key_fingerprint": check_bytes(hexlify(key.get_fingerprint())),
}
)
return AUTH_SUCCESSFUL
@@ -198,7 +160,7 @@ def ConnectionHandle(client, priv):
ip, port = client.getpeername()
_q_s.logs.info(
{
- "server": "ssh_server",
+ "server": _q_s.NAME,
"action": "connection",
"src_ip": ip,
"src_port": port,
@@ -216,11 +178,11 @@ def ConnectionHandle(client, priv):
conn = t.accept(30)
if "interactive" in _q_s.options and conn is not None:
conn.send(
- "Welcome to Ubuntu 20.04.4 LTS (GNU/Linux 5.10.60.1-microsoft-standard-WSL2 x86_64)\r\n\r\n"
+ b"Welcome to Ubuntu 20.04.4 LTS (GNU/Linux 5.10.60.1-microsoft-standard-WSL2 x86_64)\r\n\r\n"
)
current_time = time()
while True and time() < current_time + 10:
- conn.send("/$ ")
+ conn.send(b"/$ ")
line = ""
while (
not line.endswith("\x0d")
@@ -231,12 +193,12 @@ def ConnectionHandle(client, priv):
recv = conn.recv(1).decode()
conn.settimeout(None)
if _q_s.ansi.match(recv) is None and recv != "\x7f":
- conn.send(recv)
+ conn.send(recv.encode())
line += recv
line = line.rstrip()
_q_s.logs.info(
{
- "server": "ssh_server",
+ "server": _q_s.NAME,
"action": "interactive",
"src_ip": ip,
"src_port": port,
@@ -247,16 +209,18 @@ def ConnectionHandle(client, priv):
)
if line == "ls":
conn.send(
- "\r\nbin cdrom etc lib lib64 lost+found mnt proc run snap swapfile tmp var boot dev home lib32 libx32 media opt root sbin srv sys usr\r\n"
+ b"\r\nbin cdrom etc lib lib64 lost+found mnt proc run snap "
+ b"swapfile tmp var boot dev home lib32 libx32 media opt root "
+ b"sbin srv sys usr\r\n"
)
elif line == "pwd":
- conn.send("\r\n/\r\n")
+ conn.send(b"\r\n/\r\n")
elif line == "whoami":
- conn.send("\r\nroot\r\n")
+ conn.send(b"\r\nroot\r\n")
elif line == "exit":
break
else:
- conn.send(f"\r\n{line}: command not found\r\n")
+ conn.send(f"\r\n{line}: command not found\r\n".encode())
with suppress(Exception):
sshhandle.event.wait(2)
with suppress(Exception):
@@ -280,73 +244,6 @@ def ConnectionHandle(client, priv):
),
)
- def run_server(self, process=False, auto=False):
- status = "error"
- run = False
- if process:
- if auto and not self.auto_disabled:
- port = get_free_port()
- if port > 0:
- self.port = port
- run = True
- elif self.close_port() and self.kill_server():
- run = True
-
- if run:
- self.process = Popen(
- [
- "python3",
- path.realpath(__file__),
- "--custom",
- "--ip",
- str(self.ip),
- "--port",
- str(self.port),
- "--username",
- str(self.username),
- "--password",
- str(self.password),
- "--options",
- str(self.options),
- "--config",
- str(self.config),
- "--uuid",
- str(self.uuid),
- ]
- )
- if self.process.poll() is None and check_if_server_is_running(self.uuid):
- status = "success"
-
- self.logs.info(
- {
- "server": "ssh_server",
- "action": "process",
- "status": status,
- "src_ip": self.ip,
- "src_port": self.port,
- "username": self.username,
- "password": self.password,
- "dest_ip": self.ip,
- "dest_port": self.port,
- }
- )
-
- if status == "success":
- return True
- else:
- self.kill_server()
- return False
- else:
- self.ssh_server_main()
-
- def close_port(self):
- ret = close_port_wrapper("ssh_server", self.ip, self.port, self.logs)
- return ret
-
- def kill_server(self):
- ret = kill_server_wrapper("ssh_server", self.uuid, self.process)
- return ret
-
def test_server(self, ip=None, port=None, username=None, password=None):
from paramiko import SSHClient, AutoAddPolicy
diff --git a/honeypots/telnet_server.py b/honeypots/telnet_server.py
index ae35e12..ac46d1b 100644
--- a/honeypots/telnet_server.py
+++ b/honeypots/telnet_server.py
@@ -10,60 +10,32 @@
// -------------------------------------------------------------
"""
+from contextlib import suppress
+
from twisted.conch.telnet import TelnetProtocol, TelnetTransport
-from twisted.internet.protocol import Factory
from twisted.internet import reactor
-from subprocess import Popen
-from os import path, getenv
+from twisted.internet.protocol import Factory
+
+from honeypots.base_server import BaseServer
from honeypots.helper import (
- close_port_wrapper,
- get_free_port,
- kill_server_wrapper,
server_arguments,
- setup_logger,
- set_local_vars,
- check_if_server_is_running,
+ check_bytes,
)
-from uuid import uuid4
-from contextlib import suppress
-class QTelnetServer:
+class QTelnetServer(BaseServer):
+ NAME = "telnet_server"
+ DEFAULT_PORT = 23
+
def __init__(self, **kwargs):
- self.auto_disabled = None
+ super().__init__(**kwargs)
self.random_servers = [
"Ubuntu 18.04 LTS",
"Ubuntu 16.04.3 LTS",
"Welcome to Microsoft Telnet Server.",
]
- self.process = None
- self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8]
- self.config = kwargs.get("config", "")
- if self.config:
- self.logs = setup_logger(__class__.__name__, self.uuid, self.config)
- set_local_vars(self, self.config)
- else:
- self.logs = setup_logger(__class__.__name__, self.uuid, None)
- self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0"
- self.port = (
- (kwargs.get("port", None) and int(kwargs.get("port", None)))
- or (hasattr(self, "port") and self.port)
- or 23
- )
- self.username = (
- kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test"
- )
- self.password = (
- kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test"
- )
- self.options = (
- kwargs.get("options", "")
- or (hasattr(self, "options") and self.options)
- or getenv("HONEYPOTS_OPTIONS", "")
- or ""
- )
- def telent_server_main(self):
+ def server_main(self):
_q_s = self
class CustomTelnetProtocol(TelnetProtocol):
@@ -71,12 +43,6 @@ class CustomTelnetProtocol(TelnetProtocol):
_user = None
_pass = None
- def check_bytes(self, string):
- if isinstance(string, bytes):
- return string.decode()
- else:
- return str(string)
-
def connectionMade(self):
self._state = None
self._user = None
@@ -85,7 +51,7 @@ def connectionMade(self):
self._state = b"Username"
_q_s.logs.info(
{
- "server": "telnet_server",
+ "server": _q_s.NAME,
"action": "connection",
"src_ip": self.transport.getPeer().host,
"src_port": self.transport.getPeer().port,
@@ -101,17 +67,15 @@ def dataReceived(self, data):
self._state = b"Password"
self.transport.write(b"Password: ")
elif self._state == b"Password":
- username = self.check_bytes(self._user)
- password = self.check_bytes(data)
+ username = check_bytes(self._user)
+ password = check_bytes(data)
status = "failed"
# may need decode
if username == _q_s.username and password == _q_s.password:
- username = _q_s.username
- password = _q_s.password
status = "success"
_q_s.logs.info(
{
- "server": "telnet_server",
+ "server": _q_s.NAME,
"action": "login",
"status": status,
"src_ip": self.transport.getPeer().host,
@@ -136,73 +100,6 @@ def connectionLost(self, reason):
reactor.listenTCP(port=self.port, factory=factory, interface=self.ip)
reactor.run()
- def run_server(self, process=False, auto=False):
- status = "error"
- run = False
- if process:
- if auto and not self.auto_disabled:
- port = get_free_port()
- if port > 0:
- self.port = port
- run = True
- elif self.close_port() and self.kill_server():
- run = True
-
- if run:
- self.process = Popen(
- [
- "python3",
- path.realpath(__file__),
- "--custom",
- "--ip",
- str(self.ip),
- "--port",
- str(self.port),
- "--username",
- str(self.username),
- "--password",
- str(self.password),
- "--options",
- str(self.options),
- "--config",
- str(self.config),
- "--uuid",
- str(self.uuid),
- ]
- )
- if self.process.poll() is None and check_if_server_is_running(self.uuid):
- status = "success"
-
- self.logs.info(
- {
- "server": "telnet_server",
- "action": "process",
- "status": status,
- "src_ip": self.ip,
- "src_port": self.port,
- "username": self.username,
- "password": self.password,
- "dest_ip": self.ip,
- "dest_port": self.port,
- }
- )
-
- if status == "success":
- return True
- else:
- self.kill_server()
- return False
- else:
- self.telent_server_main()
-
- def close_port(self):
- ret = close_port_wrapper("telnet_server", self.ip, self.port, self.logs)
- return ret
-
- def kill_server(self):
- ret = kill_server_wrapper("telnet_server", self.uuid, self.process)
- return ret
-
def test_server(self, ip=None, port=None, username=None, password=None):
with suppress(Exception):
from telnetlib import Telnet as TTelnet
diff --git a/honeypots/vnc_server.py b/honeypots/vnc_server.py
index ad7d99b..7a80b99 100644
--- a/honeypots/vnc_server.py
+++ b/honeypots/vnc_server.py
@@ -12,56 +12,26 @@
from binascii import unhexlify
from contextlib import suppress
-from os import getenv, path
-from subprocess import Popen
-from uuid import uuid4
from Crypto.Cipher import DES
from twisted.internet import reactor
from twisted.internet.protocol import Factory, Protocol
+from honeypots.base_server import BaseServer
from honeypots.helper import (
- check_if_server_is_running,
- close_port_wrapper,
- get_free_port,
- kill_server_wrapper,
server_arguments,
- set_local_vars,
- setup_logger,
+ check_bytes,
)
-class QVNCServer:
+class QVNCServer(BaseServer):
+ NAME = "vnc_server"
+ DEFAULT_PORT = 5900
+
def __init__(self, **kwargs):
- self.auto_disabled = None
+ super().__init__(**kwargs)
self.challenge = unhexlify("00000000901234567890123456789012")
self.words = ["test"]
- self.process = None
- self.uuid = "honeypotslogger" + "_" + __class__.__name__ + "_" + str(uuid4())[:8]
- self.config = kwargs.get("config", "")
- if self.config:
- self.logs = setup_logger(__class__.__name__, self.uuid, self.config)
- set_local_vars(self, self.config)
- else:
- self.logs = setup_logger(__class__.__name__, self.uuid, None)
- self.ip = kwargs.get("ip", None) or (hasattr(self, "ip") and self.ip) or "0.0.0.0"
- self.port = (
- (kwargs.get("port", None) and int(kwargs.get("port", None)))
- or (hasattr(self, "port") and self.port)
- or 5900
- )
- self.username = (
- kwargs.get("username", None) or (hasattr(self, "username") and self.username) or "test"
- )
- self.password = (
- kwargs.get("password", None) or (hasattr(self, "password") and self.password) or "test"
- )
- self.options = (
- kwargs.get("options", "")
- or (hasattr(self, "options") and self.options)
- or getenv("HONEYPOTS_OPTIONS", "")
- or ""
- )
def load_words(
self,
@@ -82,24 +52,18 @@ def decode(self, c, r):
return temp
return None
- def vnc_server_main(self):
+ def server_main(self):
_q_s = self
class CustomVNCProtocol(Protocol):
_state = None
- def check_bytes(self, string):
- if isinstance(string, bytes):
- return string.decode()
- else:
- return str(string)
-
def connectionMade(self):
self.transport.write(b"RFB 003.008\n")
self._state = 1
_q_s.logs.info(
{
- "server": "vnc_server",
+ "server": _q_s.NAME,
"action": "connection",
"src_ip": self.transport.getPeer().host,
"src_port": self.transport.getPeer().port,
@@ -119,21 +83,19 @@ def dataReceived(self, data):
self.transport.write(_q_s.challenge)
elif self._state == 3:
with suppress(Exception):
- username = self.check_bytes(_q_s.decode(_q_s.challenge, data.hex()))
- password = self.check_bytes(data)
+ username = check_bytes(_q_s.decode(_q_s.challenge, data.hex()))
+ password = check_bytes(data)
status = "failed"
# may need decode
if username == _q_s.username and password == _q_s.password:
- username = _q_s.username
- password = _q_s.password
status = "success"
else:
password = data.hex()
_q_s.logs.info(
{
- "server": "vnc_server",
+ "server": _q_s.NAME,
"action": "login",
- status: "failed",
+ "status": status,
"src_ip": self.transport.getPeer().host,
"src_port": self.transport.getPeer().port,
"dest_ip": _q_s.ip,
@@ -154,73 +116,6 @@ def connectionLost(self, reason):
reactor.listenTCP(port=self.port, factory=factory, interface=self.ip)
reactor.run()
- def run_server(self, process=False, auto=False):
- status = "error"
- run = False
- if process:
- if auto and not self.auto_disabled:
- port = get_free_port()
- if port > 0:
- self.port = port
- run = True
- elif self.close_port() and self.kill_server():
- run = True
-
- if run:
- self.process = Popen(
- [
- "python3",
- path.realpath(__file__),
- "--custom",
- "--ip",
- str(self.ip),
- "--port",
- str(self.port),
- "--username",
- str(self.username),
- "--password",
- str(self.password),
- "--options",
- str(self.options),
- "--config",
- str(self.config),
- "--uuid",
- str(self.uuid),
- ]
- )
- if self.process.poll() is None and check_if_server_is_running(self.uuid):
- status = "success"
-
- self.logs.info(
- {
- "server": "vnc_server",
- "action": "process",
- "status": status,
- "src_ip": self.ip,
- "src_port": self.port,
- "username": self.username,
- "password": self.password,
- "dest_ip": self.ip,
- "dest_port": self.port,
- }
- )
-
- if status == "success":
- return True
- else:
- self.kill_server()
- return False
- else:
- self.vnc_server_main()
-
- def close_port(self):
- ret = close_port_wrapper("vnc_server", self.ip, self.port, self.logs)
- return ret
-
- def kill_server(self):
- ret = kill_server_wrapper("vnc_server", self.uuid, self.process)
- return ret
-
def test_server(self, ip=None, port=None, username=None, password=None):
with suppress(Exception):
ip or self.ip
diff --git a/tests/test_smb_server.py b/tests/test_smb_server.py
index 17a2711..542a4cc 100644
--- a/tests/test_smb_server.py
+++ b/tests/test_smb_server.py
@@ -27,12 +27,15 @@ def test_smb_server(server_logs):
smb_client.login(USERNAME, PASSWORD)
smb_client.close()
- logs = load_logs_from_file(server_logs)
+ *connects, login = load_logs_from_file(server_logs)
- assert len(logs) == 3
- for entry in logs:
+ assert len(connects) == 3
+ for entry in connects:
assert_connect_is_logged(entry, PORT)
- assert "Incoming connection" in logs[0]["data"]
- assert "AUTHENTICATE_MESSAGE" in logs[1]["data"]
- assert "authenticated successfully" in logs[2]["data"]
+ assert "Incoming connection" in connects[0]["data"]
+ assert "AUTHENTICATE_MESSAGE" in connects[1]["data"]
+ assert "authenticated successfully" in connects[2]["data"]
+
+ assert login["action"] == "login"
+ assert login["username"] == USERNAME
diff --git a/tests/test_ssh_server.py b/tests/test_ssh_server.py
index 98b3162..df66238 100644
--- a/tests/test_ssh_server.py
+++ b/tests/test_ssh_server.py
@@ -33,13 +33,16 @@ def test_ssh_server(server_logs):
ssh = SSHClient()
ssh.set_missing_host_key_policy(AutoAddPolicy())
ssh.connect(IP, port=PORT, username=USERNAME, password=PASSWORD)
+ ssh.exec_command("ls")
ssh.close()
logs = load_logs_from_file(server_logs)
- assert len(logs) == 2
- connect, login = logs
+ assert len(logs) == 3
+ connect, login, command = logs
assert_connect_is_logged(connect, str(PORT))
+ assert command["action"] == "command"
+ assert command["data"] == {"command": "ls"}
assert login["action"] == "login"
assert login["username"] == USERNAME
diff --git a/tests/test_vnc_server.py b/tests/test_vnc_server.py
index 632b6dc..b118a05 100644
--- a/tests/test_vnc_server.py
+++ b/tests/test_vnc_server.py
@@ -32,5 +32,9 @@ def test_vnc_server(server_logs):
logs = load_logs_from_file(server_logs)
- assert len(logs) == 1
- assert_connect_is_logged(logs[0], PORT)
+ assert len(logs) == 2
+ connection, login = logs
+ assert_connect_is_logged(connection, PORT)
+ assert login["action"] == "login"
+ assert login["username"] == "None" # FixMe: seems to be "None" even with a user
+ assert login["password"] # we can't check the PW because it is encrypted