diff --git a/bugs.md b/bugs.md index fe3a71d0..5cb61a46 100644 --- a/bugs.md +++ b/bugs.md @@ -30,18 +30,6 @@ --- -### H11. Hardcoded Session Salts (8 bytes) - -**File:** `lib/towerops_web/endpoint.ex:11-12` -**File:** `config/config.exs:135` - -**Severity:** HIGH — Weak entropy for cookie signing; identical across all environments - -**Description:** `signing_salt: "hrDZxLhd"` and `encryption_salt: "vK3p8mNx"` are hardcoded 8-byte salts. Phoenix recommends 16+ bytes. Also baked into source code — can't rotate without deploy. - -**Fix:** Load from env vars, increase to 16+ bytes. - ---- diff --git a/config/config.exs b/config/config.exs index a7dfc95d..76a44007 100644 --- a/config/config.exs +++ b/config/config.exs @@ -138,6 +138,7 @@ config :towerops, ToweropsWeb.Endpoint, # to "/data/coverage" (the shared NFS mount) in config/prod.exs so all # replicas can serve the rasters and pod restarts don't lose them. config :towerops, :coverage_storage_dir, {:towerops, "priv/static/coverage"} +config :towerops, :live_view_signing_salt, "Uh1ABfdI" # SNMP MIB directories for production (in Docker image) # MIB files are included in the release at /app/priv/mibs @@ -161,6 +162,9 @@ config :towerops, :scopes, test_setup_helper: :register_and_log_in_user ] +config :towerops, :session_encryption_salt, "vK3p8mNx" +config :towerops, :session_signing_salt, "hrDZxLhd" + # Agent Docker Image # Override this in runtime.exs or environment-specific config config :towerops, diff --git a/config/runtime.exs b/config/runtime.exs index f93e8e6d..5878bbf6 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -58,6 +58,27 @@ if config_env() == :prod do # want to use a different value for prod and you most likely don't want # to check this value into version control, so we use an environment # variable instead. + session_signing_salt = + System.get_env("SESSION_SIGNING_SALT") || + raise """ + environment variable SESSION_SIGNING_SALT is missing. + You can generate one by calling: openssl rand -base64 16 + """ + + session_encryption_salt = + System.get_env("SESSION_ENCRYPTION_SALT") || + raise """ + environment variable SESSION_ENCRYPTION_SALT is missing. + You can generate one by calling: openssl rand -base64 16 + """ + + live_view_signing_salt = + System.get_env("LIVE_VIEW_SIGNING_SALT") || + raise """ + environment variable LIVE_VIEW_SIGNING_SALT is missing. + You can generate one by calling: openssl rand -base64 16 + """ + secret_key_base = System.get_env("SECRET_KEY_BASE") || raise """ @@ -411,6 +432,7 @@ if config_env() == :prod do "//towerops.net", "//*.towerops.net" ], + live_view: [signing_salt: live_view_signing_salt], http: [ # Enable IPv6 and bind on all interfaces. # Set it to {0, 0, 0, 0, 0, 0, 0, 1} for local network only access. @@ -436,6 +458,8 @@ if config_env() == :prod do # Set default sender for all emails config :towerops, :mailer_from, {"Towerops", "hi@towerops.net"} config :towerops, :redis, redis_config + config :towerops, :session_encryption_salt, session_encryption_salt + config :towerops, :session_signing_salt, session_signing_salt # Cloudflare API credentials for brute force protection config :towerops, diff --git a/k8s/deployment.yaml b/k8s/deployment.yaml index 822d94fb..b8e9870c 100644 --- a/k8s/deployment.yaml +++ b/k8s/deployment.yaml @@ -67,6 +67,21 @@ spec: secretKeyRef: name: towerops-secrets key: CLOAK_KEY + - name: SESSION_SIGNING_SALT + valueFrom: + secretKeyRef: + name: towerops-secrets + key: SESSION_SIGNING_SALT + - name: SESSION_ENCRYPTION_SALT + valueFrom: + secretKeyRef: + name: towerops-secrets + key: SESSION_ENCRYPTION_SALT + - name: LIVE_VIEW_SIGNING_SALT + valueFrom: + secretKeyRef: + name: towerops-secrets + key: LIVE_VIEW_SIGNING_SALT - name: STRIPE_SECRET_KEY valueFrom: secretKeyRef: @@ -188,6 +203,21 @@ spec: secretKeyRef: name: towerops-secrets key: CLOAK_KEY + - name: SESSION_SIGNING_SALT + valueFrom: + secretKeyRef: + name: towerops-secrets + key: SESSION_SIGNING_SALT + - name: SESSION_ENCRYPTION_SALT + valueFrom: + secretKeyRef: + name: towerops-secrets + key: SESSION_ENCRYPTION_SALT + - name: LIVE_VIEW_SIGNING_SALT + valueFrom: + secretKeyRef: + name: towerops-secrets + key: LIVE_VIEW_SIGNING_SALT - name: STRIPE_SECRET_KEY valueFrom: secretKeyRef: diff --git a/lib/towerops_web/endpoint.ex b/lib/towerops_web/endpoint.ex index 7eac4da4..c05a893e 100644 --- a/lib/towerops_web/endpoint.ex +++ b/lib/towerops_web/endpoint.ex @@ -12,8 +12,8 @@ defmodule ToweropsWeb.Endpoint do @session_options [ store: :cookie, key: "_towerops_key", - signing_salt: "hrDZxLhd", - encryption_salt: "vK3p8mNx", + signing_salt: Application.compile_env(:towerops, :session_signing_salt, "default-signing-salt-missing-env"), + encryption_salt: Application.compile_env(:towerops, :session_encryption_salt, "default-encryption-salt-missing-env"), same_site: "Lax", http_only: true, secure: Application.compile_env(:towerops, :secure_cookies, false)