From c2c43ac98500d20fb19cf8cf9dedc04f6a08d123 Mon Sep 17 00:00:00 2001 From: Leonardo Bambini Date: Mon, 29 Dec 2025 18:51:37 +0100 Subject: [PATCH 1/4] Added randomized server header and changed behavior of SERVER_HEADER env var --- src/config.py | 2 +- src/generators.py | 13 ++++++++++++- src/handler.py | 4 ++-- src/wordlists.py | 7 ++++++- 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/config.py b/src/config.py index 7c6714c..ef78935 100644 --- a/src/config.py +++ b/src/config.py @@ -46,5 +46,5 @@ class Config: 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)), - server_header=os.getenv('SERVER_HEADER', 'Apache/2.2.22 (Ubuntu)') + server_header=os.getenv('SERVER_HEADER') ) diff --git a/src/generators.py b/src/generators.py index 16c0c32..6e24ba8 100644 --- a/src/generators.py +++ b/src/generators.py @@ -9,7 +9,8 @@ import string import json from templates import html_templates from wordlists import get_wordlists - +from config import Config +from logger import get_app_logger def random_username() -> str: """Generate random username""" @@ -36,6 +37,16 @@ def random_email(username: str = None) -> str: username = random_username() return f"{username}@{random.choice(wl.email_domains)}" +def random_server_header() -> str: + """Generate random server header""" + + if Config.from_env().server_header: + server_header = Config.from_env().server_header + else: + wl = get_wordlists() + server_header = random.choice(wl.server_headers) + + return server_header def random_api_key() -> str: """Generate random API key""" diff --git a/src/handler.py b/src/handler.py index ac7ca22..7c44726 100644 --- a/src/handler.py +++ b/src/handler.py @@ -13,7 +13,7 @@ from templates import html_templates from templates.dashboard_template import generate_dashboard from generators import ( credentials_txt, passwords_txt, users_json, api_keys_json, - api_response, directory_listing + api_response, directory_listing, random_server_header ) from wordlists import get_wordlists @@ -52,7 +52,7 @@ class Handler(BaseHTTPRequestHandler): def version_string(self) -> str: """Return custom server version for deception.""" - return self.config.server_header + return random_server_header() def _should_return_error(self) -> bool: """Check if we should return an error based on probability""" diff --git a/src/wordlists.py b/src/wordlists.py index 62e4045..342930a 100644 --- a/src/wordlists.py +++ b/src/wordlists.py @@ -57,7 +57,8 @@ class Wordlists: }, "users": { "roles": ["Administrator", "User"] - } + }, + "server_headers": ["Apache/2.4.41 (Ubuntu)", "nginx/1.18.0"] } @property @@ -111,6 +112,10 @@ class Wordlists: @property def error_codes(self): return self._data.get("error_codes", []) + + @property + def server_headers(self): + return self._data.get("server_headers", []) _wordlists_instance = None From a9808599dc3870f66241111fcfdd6defbd4da42f Mon Sep 17 00:00:00 2001 From: Leonardo Bambini Date: Mon, 29 Dec 2025 18:55:44 +0100 Subject: [PATCH 2/4] Added random server header and changed behavior of SERVER_HEADER env var --- README.md | 2 +- wordlists.json | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b84d955..0d3efe7 100644 --- a/README.md +++ b/README.md @@ -185,7 +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)` | +| `SERVER_HEADER` | HTTP Server header for deception, if not set use random server header | | ## robots.txt The actual (juicy) robots.txt configuration is the following diff --git a/wordlists.json b/wordlists.json index f1aae81..fddf3d3 100644 --- a/wordlists.json +++ b/wordlists.json @@ -193,5 +193,13 @@ 500, 502, 503 + ], + "server_headers": [ + "Apache/2.4.41 (Ubuntu)", + "nginx/1.18.0", + "Microsoft-IIS/10.0", + "cloudflare", + "AmazonS3", + "gunicorn/20.1.0" ] } From 06ffa2c480f9991ea391913be918bc59a65e636f Mon Sep 17 00:00:00 2001 From: Patrick Di Fazio Date: Mon, 29 Dec 2025 23:57:37 +0100 Subject: [PATCH 3/4] Added wordlists and server header logic to helm --- docker-compose.yaml | 2 +- helm/templates/configmap.yaml | 7 ++++++- helm/values.yaml | 14 +++++++++++++- src/config.py | 2 +- 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index 1612864..7026f11 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -20,7 +20,7 @@ services: - MAX_COUNTER=10 - CANARY_TOKEN_TRIES=10 - PROBABILITY_ERROR_CODES=0 - - SERVER_HEADER=Apache/2.2.22 (Ubuntu) + # - 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 c50ab75..fb590b0 100644 --- a/helm/templates/configmap.yaml +++ b/helm/templates/configmap.yaml @@ -14,5 +14,10 @@ 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 }} + {{- if .Values.config.dashboardSecretPath }} + DASHBOARD_SECRET_PATH: {{ .Values.config.dashboardSecretPath | quote }} + {{- end }} + {{- if .Values.config.serverHeader }} + SERVER_HEADER: {{ .Values.config.serverHeader | quote }} + {{- end }} \ No newline at end of file diff --git a/helm/values.yaml b/helm/values.yaml index a095632..217e9a6 100644 --- a/helm/values.yaml +++ b/helm/values.yaml @@ -73,7 +73,8 @@ config: maxCounter: 10 canaryTokenTries: 10 probabilityErrorCodes: 0 - serverHeader: "Apache/2.2.22 (Ubuntu)" +# serverHeader: "Apache/2.2.22 (Ubuntu)" +# dashboardSecretPath: "/my-secret-dashboard" # canaryTokenUrl: set-your-canary-token-url-here networkPolicy: @@ -268,6 +269,17 @@ wordlists: - .git/ - keys/ - credentials/ + server_headers: + - Apache/2.2.22 (Ubuntu) + - nginx/1.18.0 + - Microsoft-IIS/10.0 + - LiteSpeed + - Caddy + - Gunicorn/20.0.4 + - uvicorn/0.13.4 + - Express + - Flask/1.1.2 + - Django/3.1 error_codes: - 400 - 401 diff --git a/src/config.py b/src/config.py index ef78935..3fc5dd8 100644 --- a/src/config.py +++ b/src/config.py @@ -21,7 +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)" + server_header: Optional[str] = None @classmethod def from_env(cls) -> 'Config': From cddad984c3b556cbc990bd989f7f2295eb404394 Mon Sep 17 00:00:00 2001 From: Patrick Di Fazio Date: Tue, 30 Dec 2025 00:03:44 +0100 Subject: [PATCH 4/4] Added timezone to helm values --- helm/values.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/helm/values.yaml b/helm/values.yaml index dc18d4a..8a6bc1d 100644 --- a/helm/values.yaml +++ b/helm/values.yaml @@ -73,6 +73,7 @@ config: maxCounter: 10 canaryTokenTries: 10 probabilityErrorCodes: 0 +# timezone: "UTC" # serverHeader: "Apache/2.2.22 (Ubuntu)" # dashboardSecretPath: "/my-secret-dashboard" # canaryTokenUrl: set-your-canary-token-url-here