From f516e317ea639bf0d2cdf3d1f1e2e00b5b7c90ef Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sun, 11 Nov 2018 06:10:21 +0000 Subject: plugs: add CSPPlug --- lib/pleroma/plugs/csp_plug.ex | 38 ++++++++++++++++++++++++++++++++++++++ lib/pleroma/web/endpoint.ex | 1 + 2 files changed, 39 insertions(+) create mode 100644 lib/pleroma/plugs/csp_plug.ex (limited to 'lib') diff --git a/lib/pleroma/plugs/csp_plug.ex b/lib/pleroma/plugs/csp_plug.ex new file mode 100644 index 000000000..15d466c36 --- /dev/null +++ b/lib/pleroma/plugs/csp_plug.ex @@ -0,0 +1,38 @@ +defmodule Pleroma.Plugs.CSPPlug do + import Plug.Conn + + def init(opts), do: opts + + def call(conn, options) do + conn = merge_resp_headers(conn, headers()) + end + + defp headers do + [ + {"x-xss-protection", "1; mode=block"}, + {"x-permitted-cross-domain-policies", "none"}, + {"x-frame-options", "DENY"}, + {"x-content-type-options", "nosniff"}, + {"referrer-policy", "same-origin"}, + {"x-download-options", "noopen"}, + {"content-security-policy", csp_string() <> ";"} + ] + end + + defp csp_string do + [ + "default-src 'none'", + "base-uri 'self'", + "form-action *", + "frame-ancestors 'none'", + "img-src 'self' data: https:", + "media-src 'self' https:", + "style-src 'self' 'unsafe-inline'", + "font-src 'self'", + "script-src 'self'", + "connect-src 'self' " <> String.replace(Pleroma.Web.Endpoint.static_url(), "http", "ws"), + "upgrade-insecure-requests" + ] + |> Enum.join("; ") + end +end diff --git a/lib/pleroma/web/endpoint.ex b/lib/pleroma/web/endpoint.ex index cb5de087b..370d2d792 100644 --- a/lib/pleroma/web/endpoint.ex +++ b/lib/pleroma/web/endpoint.ex @@ -12,6 +12,7 @@ defmodule Pleroma.Web.Endpoint do # You should set gzip to true if you are running phoenix.digest # when deploying your static files in production. plug(CORSPlug) + plug(Pleroma.Plugs.CSPPlug) plug(Plug.Static, at: "/media", from: Pleroma.Uploaders.Local.upload_path(), gzip: false) -- cgit v1.2.3 From a2bf5426cb84940dbd58aec10a7b1b0a90f26a60 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sun, 11 Nov 2018 06:42:14 +0000 Subject: sample config: document how to make CSPPlug send STS headers (off by default to allow for SSL debugging) --- lib/mix/tasks/sample_config.eex | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib') diff --git a/lib/mix/tasks/sample_config.eex b/lib/mix/tasks/sample_config.eex index 3881ead26..824bc97a1 100644 --- a/lib/mix/tasks/sample_config.eex +++ b/lib/mix/tasks/sample_config.eex @@ -25,6 +25,10 @@ config :pleroma, Pleroma.Repo, hostname: "localhost", pool_size: 10 +# Enable Strict-Transport-Security once SSL is working: +# config :pleroma, :csp, +# sts: true + # Configure S3 support if desired. # The public S3 endpoint is different depending on region and provider, # consult your S3 provider's documentation for details on what to use. -- cgit v1.2.3 From 331cf6ada1e4df51b366c79126e094ee335dd684 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sun, 11 Nov 2018 06:50:28 +0000 Subject: csp plug: add sts support --- lib/pleroma/plugs/csp_plug.ex | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/plugs/csp_plug.ex b/lib/pleroma/plugs/csp_plug.ex index 15d466c36..56f2376ee 100644 --- a/lib/pleroma/plugs/csp_plug.ex +++ b/lib/pleroma/plugs/csp_plug.ex @@ -1,10 +1,17 @@ defmodule Pleroma.Plugs.CSPPlug do + alias Pleroma.Config import Plug.Conn def init(opts), do: opts def call(conn, options) do - conn = merge_resp_headers(conn, headers()) + if Config.get([:csp, :enabled]) do + conn = + merge_resp_headers(conn, headers()) + |> maybe_send_sts_header(Config.get([:csp, :sts])) + else + conn + end end defp headers do @@ -35,4 +42,14 @@ defmodule Pleroma.Plugs.CSPPlug do ] |> Enum.join("; ") end + + defp maybe_send_sts_header(conn, true) do + max_age = Config.get([:csp, :sts_max_age]) + + merge_resp_headers(conn, [ + {"strict-transport-security", "max-age=#{max_age}; includeSubDomains"} + ]) + end + + defp maybe_send_sts_header(conn, _), do: conn end -- cgit v1.2.3 From df72978dce3805157537e8fa1a2fec35fcf9a7cd Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sun, 11 Nov 2018 06:53:42 +0000 Subject: csp plug: add support for certificate transparency --- lib/pleroma/plugs/csp_plug.ex | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/pleroma/plugs/csp_plug.ex b/lib/pleroma/plugs/csp_plug.ex index 56f2376ee..8fc21b909 100644 --- a/lib/pleroma/plugs/csp_plug.ex +++ b/lib/pleroma/plugs/csp_plug.ex @@ -44,10 +44,12 @@ defmodule Pleroma.Plugs.CSPPlug do end defp maybe_send_sts_header(conn, true) do - max_age = Config.get([:csp, :sts_max_age]) + max_age_sts = Config.get([:csp, :sts_max_age]) + max_age_ct = Config.get([:csp, :ct_max_age]) merge_resp_headers(conn, [ - {"strict-transport-security", "max-age=#{max_age}; includeSubDomains"} + {"strict-transport-security", "max-age=#{max_age_sts}; includeSubDomains"}, + {"expect-ct", "enforce, max-age=#{max_age_ct}"} ]) end -- cgit v1.2.3 From fe67665e19cc98faff4a8ee53a3f4ca4190ca2ef Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Mon, 12 Nov 2018 15:08:02 +0000 Subject: rename CSPPlug to HTTPSecurityPlug. --- lib/pleroma/plugs/csp_plug.ex | 57 --------------------------------- lib/pleroma/plugs/http_security_plug.ex | 57 +++++++++++++++++++++++++++++++++ lib/pleroma/web/endpoint.ex | 2 +- 3 files changed, 58 insertions(+), 58 deletions(-) delete mode 100644 lib/pleroma/plugs/csp_plug.ex create mode 100644 lib/pleroma/plugs/http_security_plug.ex (limited to 'lib') diff --git a/lib/pleroma/plugs/csp_plug.ex b/lib/pleroma/plugs/csp_plug.ex deleted file mode 100644 index 8fc21b909..000000000 --- a/lib/pleroma/plugs/csp_plug.ex +++ /dev/null @@ -1,57 +0,0 @@ -defmodule Pleroma.Plugs.CSPPlug do - alias Pleroma.Config - import Plug.Conn - - def init(opts), do: opts - - def call(conn, options) do - if Config.get([:csp, :enabled]) do - conn = - merge_resp_headers(conn, headers()) - |> maybe_send_sts_header(Config.get([:csp, :sts])) - else - conn - end - end - - defp headers do - [ - {"x-xss-protection", "1; mode=block"}, - {"x-permitted-cross-domain-policies", "none"}, - {"x-frame-options", "DENY"}, - {"x-content-type-options", "nosniff"}, - {"referrer-policy", "same-origin"}, - {"x-download-options", "noopen"}, - {"content-security-policy", csp_string() <> ";"} - ] - end - - defp csp_string do - [ - "default-src 'none'", - "base-uri 'self'", - "form-action *", - "frame-ancestors 'none'", - "img-src 'self' data: https:", - "media-src 'self' https:", - "style-src 'self' 'unsafe-inline'", - "font-src 'self'", - "script-src 'self'", - "connect-src 'self' " <> String.replace(Pleroma.Web.Endpoint.static_url(), "http", "ws"), - "upgrade-insecure-requests" - ] - |> Enum.join("; ") - end - - defp maybe_send_sts_header(conn, true) do - max_age_sts = Config.get([:csp, :sts_max_age]) - max_age_ct = Config.get([:csp, :ct_max_age]) - - merge_resp_headers(conn, [ - {"strict-transport-security", "max-age=#{max_age_sts}; includeSubDomains"}, - {"expect-ct", "enforce, max-age=#{max_age_ct}"} - ]) - end - - defp maybe_send_sts_header(conn, _), do: conn -end diff --git a/lib/pleroma/plugs/http_security_plug.ex b/lib/pleroma/plugs/http_security_plug.ex new file mode 100644 index 000000000..8d652a2f3 --- /dev/null +++ b/lib/pleroma/plugs/http_security_plug.ex @@ -0,0 +1,57 @@ +defmodule Pleroma.Plugs.HTTPSecurityPlug do + alias Pleroma.Config + import Plug.Conn + + def init(opts), do: opts + + def call(conn, options) do + if Config.get([:http_security, :enabled]) do + conn = + merge_resp_headers(conn, headers()) + |> maybe_send_sts_header(Config.get([:http_security, :sts])) + else + conn + end + end + + defp headers do + [ + {"x-xss-protection", "1; mode=block"}, + {"x-permitted-cross-domain-policies", "none"}, + {"x-frame-options", "DENY"}, + {"x-content-type-options", "nosniff"}, + {"referrer-policy", "same-origin"}, + {"x-download-options", "noopen"}, + {"content-security-policy", csp_string() <> ";"} + ] + end + + defp csp_string do + [ + "default-src 'none'", + "base-uri 'self'", + "form-action *", + "frame-ancestors 'none'", + "img-src 'self' data: https:", + "media-src 'self' https:", + "style-src 'self' 'unsafe-inline'", + "font-src 'self'", + "script-src 'self'", + "connect-src 'self' " <> String.replace(Pleroma.Web.Endpoint.static_url(), "http", "ws"), + "upgrade-insecure-requests" + ] + |> Enum.join("; ") + end + + defp maybe_send_sts_header(conn, true) do + max_age_sts = Config.get([:http_security, :sts_max_age]) + max_age_ct = Config.get([:http_security, :ct_max_age]) + + merge_resp_headers(conn, [ + {"strict-transport-security", "max-age=#{max_age_sts}; includeSubDomains"}, + {"expect-ct", "enforce, max-age=#{max_age_ct}"} + ]) + end + + defp maybe_send_sts_header(conn, _), do: conn +end diff --git a/lib/pleroma/web/endpoint.ex b/lib/pleroma/web/endpoint.ex index 370d2d792..7783b8e5c 100644 --- a/lib/pleroma/web/endpoint.ex +++ b/lib/pleroma/web/endpoint.ex @@ -12,7 +12,7 @@ defmodule Pleroma.Web.Endpoint do # You should set gzip to true if you are running phoenix.digest # when deploying your static files in production. plug(CORSPlug) - plug(Pleroma.Plugs.CSPPlug) + plug(Pleroma.Plugs.HTTPSecurityPlug) plug(Plug.Static, at: "/media", from: Pleroma.Uploaders.Local.upload_path(), gzip: false) -- cgit v1.2.3 From ee5932a504d69e591aad7bdd52bd97d1f92d4e32 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Mon, 12 Nov 2018 15:14:46 +0000 Subject: http security: allow referrer-policy to be configured --- lib/pleroma/plugs/http_security_plug.ex | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/pleroma/plugs/http_security_plug.ex b/lib/pleroma/plugs/http_security_plug.ex index 8d652a2f3..960c7f6bf 100644 --- a/lib/pleroma/plugs/http_security_plug.ex +++ b/lib/pleroma/plugs/http_security_plug.ex @@ -15,12 +15,14 @@ defmodule Pleroma.Plugs.HTTPSecurityPlug do end defp headers do + referrer_policy = Config.get([:http_security, :referrer_policy]) + [ {"x-xss-protection", "1; mode=block"}, {"x-permitted-cross-domain-policies", "none"}, {"x-frame-options", "DENY"}, {"x-content-type-options", "nosniff"}, - {"referrer-policy", "same-origin"}, + {"referrer-policy", referrer_policy}, {"x-download-options", "noopen"}, {"content-security-policy", csp_string() <> ";"} ] -- cgit v1.2.3 From 2829fa41830ad8565fc186c3dc110f4d275f8827 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Mon, 12 Nov 2018 15:17:04 +0000 Subject: sample config: chase http_security change --- lib/mix/tasks/sample_config.eex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/mix/tasks/sample_config.eex b/lib/mix/tasks/sample_config.eex index 824bc97a1..462c34636 100644 --- a/lib/mix/tasks/sample_config.eex +++ b/lib/mix/tasks/sample_config.eex @@ -26,7 +26,7 @@ config :pleroma, Pleroma.Repo, pool_size: 10 # Enable Strict-Transport-Security once SSL is working: -# config :pleroma, :csp, +# config :pleroma, :http_security, # sts: true # Configure S3 support if desired. -- cgit v1.2.3