From 16aca9bba63a56eacde2eb0b9cb4d00b876f1f00 Mon Sep 17 00:00:00 2001 From: Phillip Tarrant Date: Fri, 26 Dec 2025 07:53:05 -0600 Subject: [PATCH 1/2] Add configurable HTTP Server header for deception Add SERVER_HEADER environment variable to customize the HTTP Server response header, defaulting to Apache/2.2.22 (Ubuntu). This allows the honeypot to masquerade as different web servers to attract attackers. - Add server_header field to Config dataclass - Override version_string() in Handler to return configured header - Update documentation and all deployment configs --- README.md | 1 + docker-compose.yaml | 1 + helm/templates/configmap.yaml | 1 + helm/values.yaml | 1 + kubernetes/manifests/configmap.yaml | 1 + src/config.py | 4 +++- src/handler.py | 4 ++++ src/server.py | 1 + 8 files changed, 13 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0cf8b96..b84d955 100644 --- a/README.md +++ b/README.md @@ -185,6 +185,7 @@ To customize the deception server installation several **environment variables** | `CANARY_TOKEN_URL` | External canary token URL | None | | `DASHBOARD_SECRET_PATH` | Custom dashboard path | Auto-generated | | `PROBABILITY_ERROR_CODES` | Error response probability (0-100%) | `0` | +| `SERVER_HEADER` | HTTP Server header for deception | `Apache/2.2.22 (Ubuntu)` | ## robots.txt The actual (juicy) robots.txt configuration is the following diff --git a/docker-compose.yaml b/docker-compose.yaml index 57c648d..1612864 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -20,6 +20,7 @@ services: - MAX_COUNTER=10 - CANARY_TOKEN_TRIES=10 - PROBABILITY_ERROR_CODES=0 + - SERVER_HEADER=Apache/2.2.22 (Ubuntu) # Optional: Set your canary token URL # - CANARY_TOKEN_URL=http://canarytokens.com/api/users/YOUR_TOKEN/passwords.txt # Optional: Set custom dashboard path (auto-generated if not set) diff --git a/helm/templates/configmap.yaml b/helm/templates/configmap.yaml index f6fe92c..c50ab75 100644 --- a/helm/templates/configmap.yaml +++ b/helm/templates/configmap.yaml @@ -14,4 +14,5 @@ data: MAX_COUNTER: {{ .Values.config.maxCounter | quote }} CANARY_TOKEN_TRIES: {{ .Values.config.canaryTokenTries | quote }} PROBABILITY_ERROR_CODES: {{ .Values.config.probabilityErrorCodes | quote }} + SERVER_HEADER: {{ .Values.config.serverHeader | quote }} CANARY_TOKEN_URL: {{ .Values.config.canaryTokenUrl | quote }} diff --git a/helm/values.yaml b/helm/values.yaml index 9ee9ca5..a095632 100644 --- a/helm/values.yaml +++ b/helm/values.yaml @@ -73,6 +73,7 @@ config: maxCounter: 10 canaryTokenTries: 10 probabilityErrorCodes: 0 + serverHeader: "Apache/2.2.22 (Ubuntu)" # canaryTokenUrl: set-your-canary-token-url-here networkPolicy: diff --git a/kubernetes/manifests/configmap.yaml b/kubernetes/manifests/configmap.yaml index 42ba002..431b9a3 100644 --- a/kubernetes/manifests/configmap.yaml +++ b/kubernetes/manifests/configmap.yaml @@ -13,4 +13,5 @@ data: MAX_COUNTER: "10" CANARY_TOKEN_TRIES: "10" PROBABILITY_ERROR_CODES: "0" + SERVER_HEADER: "Apache/2.2.22 (Ubuntu)" # CANARY_TOKEN_URL: set-your-canary-token-url-here \ No newline at end of file diff --git a/src/config.py b/src/config.py index 51391a9..7c6714c 100644 --- a/src/config.py +++ b/src/config.py @@ -21,6 +21,7 @@ class Config: api_server_port: int = 8080 api_server_path: str = "/api/v2/users" probability_error_codes: int = 0 # Percentage (0-100) + server_header: str = "Apache/2.2.22 (Ubuntu)" @classmethod def from_env(cls) -> 'Config': @@ -44,5 +45,6 @@ class Config: api_server_url=os.getenv('API_SERVER_URL'), api_server_port=int(os.getenv('API_SERVER_PORT', 8080)), api_server_path=os.getenv('API_SERVER_PATH', '/api/v2/users'), - probability_error_codes=int(os.getenv('PROBABILITY_ERROR_CODES', 5)) + probability_error_codes=int(os.getenv('PROBABILITY_ERROR_CODES', 5)), + server_header=os.getenv('SERVER_HEADER', 'Apache/2.2.22 (Ubuntu)') ) diff --git a/src/handler.py b/src/handler.py index 81f48fa..bed3369 100644 --- a/src/handler.py +++ b/src/handler.py @@ -46,6 +46,10 @@ class Handler(BaseHTTPRequestHandler): """Extract user agent from request""" return self.headers.get('User-Agent', '') + def version_string(self) -> str: + """Return custom server version for deception.""" + return self.config.server_header + def _should_return_error(self) -> bool: """Check if we should return an error based on probability""" if self.config.probability_error_codes <= 0: diff --git a/src/server.py b/src/server.py index d10d33e..73f0ce9 100644 --- a/src/server.py +++ b/src/server.py @@ -31,6 +31,7 @@ def print_usage(): print(' DASHBOARD_SECRET_PATH - Secret path for dashboard (auto-generated if not set)') print(' PROBABILITY_ERROR_CODES - Probability (0-100) to return HTTP error codes (default: 0)') print(' CHAR_SPACE - Characters for random links') + print(' SERVER_HEADER - HTTP Server header for deception (default: Apache/2.2.22 (Ubuntu))') def main(): From d0101b34faf33bc85d3065051353da55bb0bf56f Mon Sep 17 00:00:00 2001 From: Phillip Tarrant Date: Fri, 26 Dec 2025 08:00:16 -0600 Subject: [PATCH 2/2] Added test script to show the server header --- tests/check_header.sh | 3 +++ 1 file changed, 3 insertions(+) create mode 100755 tests/check_header.sh diff --git a/tests/check_header.sh b/tests/check_header.sh new file mode 100755 index 0000000..78b8e5d --- /dev/null +++ b/tests/check_header.sh @@ -0,0 +1,3 @@ +#!/bin/env bash +# -s is for silent (no progress bar) | -I is to get the headers | grep is to find only the Server line +curl -s -I http://localhost:5000 | grep "Server:" \ No newline at end of file