From 3f7f4715d1f026878d588951bd8a38a3b8a14765 Mon Sep 17 00:00:00 2001 From: moogle19 Date: Tue, 11 Apr 2023 11:28:37 +0200 Subject: [PATCH 1/5] Update SSL defaults according to Mozilla recommendation --- lib/plug/ssl.ex | 66 +++++++++++++++--------------------------- test/plug/ssl_test.exs | 36 +++++++++-------------- 2 files changed, 37 insertions(+), 65 deletions(-) diff --git a/lib/plug/ssl.ex b/lib/plug/ssl.ex index d030e836..1a4aeabc 100644 --- a/lib/plug/ssl.ex +++ b/lib/plug/ssl.ex @@ -74,31 +74,20 @@ defmodule Plug.SSL do import Plug.Conn @strong_tls_ciphers [ - ~c"ECDHE-RSA-AES256-GCM-SHA384", - ~c"ECDHE-ECDSA-AES256-GCM-SHA384", - ~c"ECDHE-RSA-AES128-GCM-SHA256", - ~c"ECDHE-ECDSA-AES128-GCM-SHA256", - ~c"DHE-RSA-AES256-GCM-SHA384", - ~c"DHE-RSA-AES128-GCM-SHA256" + ~c"TLS_AES_128_GCM_SHA256", + ~c"TLS_AES_256_GCM_SHA384", + ~c"TLS_CHACHA20_POLY1305_SHA256" ] @compatible_tls_ciphers [ - ~c"ECDHE-RSA-AES256-GCM-SHA384", - ~c"ECDHE-ECDSA-AES256-GCM-SHA384", - ~c"ECDHE-RSA-AES128-GCM-SHA256", ~c"ECDHE-ECDSA-AES128-GCM-SHA256", - ~c"DHE-RSA-AES256-GCM-SHA384", + ~c"ECDHE-RSA-AES128-GCM-SHA256", + ~c"ECDHE-ECDSA-AES256-GCM-SHA384", + ~c"ECDHE-RSA-AES256-GCM-SHA384", + ~c"ECDHE-ECDSA-CHACHA20-POLY1305", + ~c"ECDHE-RSA-CHACHA20-POLY1305", ~c"DHE-RSA-AES128-GCM-SHA256", - ~c"ECDHE-RSA-AES256-SHA384", - ~c"ECDHE-ECDSA-AES256-SHA384", - ~c"ECDHE-RSA-AES128-SHA256", - ~c"ECDHE-ECDSA-AES128-SHA256", - ~c"DHE-RSA-AES256-SHA256", - ~c"DHE-RSA-AES128-SHA256", - ~c"ECDHE-RSA-AES256-SHA", - ~c"ECDHE-ECDSA-AES256-SHA", - ~c"ECDHE-RSA-AES128-SHA", - ~c"ECDHE-ECDSA-AES128-SHA" + ~c"DHE-RSA-AES256-GCM-SHA384" ] @eccs [ @@ -136,30 +125,21 @@ defmodule Plug.SSL do To simplify configuration of TLS defaults, this function provides two preconfigured options: `cipher_suite: :strong` and `cipher_suite: :compatible`. The Ciphers - chosen and related configuration come from the [OWASP Cipher String Cheat - Sheet](https://www.owasp.org/index.php/TLS_Cipher_String_Cheat_Sheet) - - We've made two modifications to the suggested config from the OWASP recommendations. - First we include ECDSA certificates which are excluded from their configuration. - Second we have changed the order of the ciphers to deprioritize DHE because of - performance implications noted within the OWASP post itself. As the article notes - "...the TLS handshake with DHE hinders the CPU about 2.4 times more than ECDHE". + chosen and related configuration come from the + [Mozilla Security/Server Side TLS](https://wiki.mozilla.org/Security/Server_Side_TLS) - The **Strong** cipher suite only supports tlsv1.2. Ciphers were based on the OWASP - Group A+ and includes support for RSA or ECDSA certificates. The intention of this - configuration is to provide as secure as possible defaults knowing that it will not - be fully compatible with older browsers and operating systems. + The **Strong** cipher suite only supports tlsv1.3. Ciphers were based on the "Modern" + configuration recommandation and support forward secrecy and are authenticated. + The intention of this configuration is to provide as secure as possible defaults + knowing that it will not be fully compatible with older browsers and operating systems. - The **Compatible** cipher suite supports tlsv1, tlsv1.1 and tlsv1.2. Ciphers were - based on the OWASP Group B and includes support for RSA or ECDSA certificates. The - intention of this configuration is to provide as secure as possible defaults that - still maintain support for older browsers and Android versions 4.3 and earlier + The **Compatible** cipher suite supports tlsv1.2 and tlsv1.3. Ciphers were + based on the "Intermediate" configuration recommendation. The intention of this configuration + is to provide as secure as possible defaults that still maintain support for older browsers + and Android versions 10 and earlier For both suites we've specified certificate curves secp256r1, ecp384r1 and secp521r1. - Since OWASP doesn't prescribe curves we've based the selection on [Mozilla's - recommendations](https://wiki.mozilla.org/Security/Server_Side_TLS#Cipher_names_correspondence_table) - - **The cipher suites were last updated on 2018-JUN-14.** + **The cipher suites were last updated on 2023-APR-11.** """ @spec configure(Keyword.t()) :: {:ok, Keyword.t()} | {:error, String.t()} def configure(options) do @@ -276,14 +256,14 @@ defmodule Plug.SSL do options |> set_managed_tls_defaults |> Keyword.put_new(:ciphers, @strong_tls_ciphers) - |> Keyword.put_new(:versions, [:"tlsv1.2"]) + |> Keyword.put_new(:versions, [:"tlsv1.3"]) end defp set_compatible_tls_defaults(options) do options |> set_managed_tls_defaults - |> Keyword.put_new(:ciphers, @compatible_tls_ciphers) - |> Keyword.put_new(:versions, [:"tlsv1.2", :"tlsv1.1", :tlsv1]) + |> Keyword.put_new(:ciphers, @strong_tls_ciphers ++ @compatible_tls_ciphers) + |> Keyword.put_new(:versions, [:"tlsv1.3", :"tlsv1.2"]) end defp validate_ciphers(options) do diff --git a/test/plug/ssl_test.exs b/test/plug/ssl_test.exs index 5512ccb0..ec0747cc 100644 --- a/test/plug/ssl_test.exs +++ b/test/plug/ssl_test.exs @@ -29,15 +29,12 @@ defmodule Plug.SSLTest do assert opts[:cipher_suite] == nil assert opts[:honor_cipher_order] == true assert opts[:eccs] == [:secp256r1, :secp384r1, :secp521r1] - assert opts[:versions] == [:"tlsv1.2"] + assert opts[:versions] == [:"tlsv1.3"] assert opts[:ciphers] == [ - ~c"ECDHE-RSA-AES256-GCM-SHA384", - ~c"ECDHE-ECDSA-AES256-GCM-SHA384", - ~c"ECDHE-RSA-AES128-GCM-SHA256", - ~c"ECDHE-ECDSA-AES128-GCM-SHA256", - ~c"DHE-RSA-AES256-GCM-SHA384", - ~c"DHE-RSA-AES128-GCM-SHA256" + ~c"TLS_AES_128_GCM_SHA256", + ~c"TLS_AES_256_GCM_SHA384", + ~c"TLS_CHACHA20_POLY1305_SHA256" ] end @@ -46,25 +43,20 @@ defmodule Plug.SSLTest do assert opts[:cipher_suite] == nil assert opts[:honor_cipher_order] == true assert opts[:eccs] == [:secp256r1, :secp384r1, :secp521r1] - assert opts[:versions] == [:"tlsv1.2", :"tlsv1.1", :tlsv1] + assert opts[:versions] == [:"tlsv1.3", :"tlsv1.2"] assert opts[:ciphers] == [ - ~c"ECDHE-RSA-AES256-GCM-SHA384", - ~c"ECDHE-ECDSA-AES256-GCM-SHA384", - ~c"ECDHE-RSA-AES128-GCM-SHA256", + ~c"TLS_AES_128_GCM_SHA256", + ~c"TLS_AES_256_GCM_SHA384", + ~c"TLS_CHACHA20_POLY1305_SHA256", ~c"ECDHE-ECDSA-AES128-GCM-SHA256", - ~c"DHE-RSA-AES256-GCM-SHA384", + ~c"ECDHE-RSA-AES128-GCM-SHA256", + ~c"ECDHE-ECDSA-AES256-GCM-SHA384", + ~c"ECDHE-RSA-AES256-GCM-SHA384", + ~c"ECDHE-ECDSA-CHACHA20-POLY1305", + ~c"ECDHE-RSA-CHACHA20-POLY1305", ~c"DHE-RSA-AES128-GCM-SHA256", - ~c"ECDHE-RSA-AES256-SHA384", - ~c"ECDHE-ECDSA-AES256-SHA384", - ~c"ECDHE-RSA-AES128-SHA256", - ~c"ECDHE-ECDSA-AES128-SHA256", - ~c"DHE-RSA-AES256-SHA256", - ~c"DHE-RSA-AES128-SHA256", - ~c"ECDHE-RSA-AES256-SHA", - ~c"ECDHE-ECDSA-AES256-SHA", - ~c"ECDHE-RSA-AES128-SHA", - ~c"ECDHE-ECDSA-AES128-SHA" + ~c"DHE-RSA-AES256-GCM-SHA384" ] end From 5788c5cc7051100be9958e49c42effb488403ca1 Mon Sep 17 00:00:00 2001 From: moogle19 Date: Tue, 11 Apr 2023 11:33:15 +0200 Subject: [PATCH 2/5] Bump elixir version since OTP22 needed for tls1.3 --- mix.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix.exs b/mix.exs index c5a38498..f4a0bc67 100644 --- a/mix.exs +++ b/mix.exs @@ -9,7 +9,7 @@ defmodule Plug.MixProject do [ app: :plug, version: @version, - elixir: "~> 1.10", + elixir: "~> 1.12", deps: deps(), package: package(), description: @description, From b271c35972c732de7f63817ab6e33a113df5fd52 Mon Sep 17 00:00:00 2001 From: moogle19 Date: Tue, 11 Apr 2023 11:47:58 +0200 Subject: [PATCH 3/5] Bump Elixir and OTP versions in CI --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 89caf391..d3ee0c4d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,11 +16,11 @@ jobs: matrix: include: - pair: - elixir: 1.10.4 - otp: 21.3 + elixir: 1.12.3 + otp: 22.3 - pair: - elixir: 1.13.3 - otp: 24.2.1 + elixir: 1.14.4 + otp: 25.3 lint: lint steps: - uses: actions/checkout@v2 From 7bf4aa249a77fb7b3306a0ee0f8d5a8be7b1b408 Mon Sep 17 00:00:00 2001 From: moogle19 Date: Tue, 11 Apr 2023 12:08:02 +0200 Subject: [PATCH 4/5] Move set_secure_defaults/1 after configure_managed_tls/1 TLS1.3 doesn't support secure_renegotitate or reuse_sessions which is set to true by default. By moving the set_secure_defaults after the configuration, the correct options are set --- lib/plug/ssl.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/plug/ssl.ex b/lib/plug/ssl.ex index 1a4aeabc..8ec97989 100644 --- a/lib/plug/ssl.ex +++ b/lib/plug/ssl.ex @@ -148,8 +148,8 @@ defmodule Plug.SSL do |> validate_ciphers() |> normalize_ssl_files() |> convert_to_charlist() - |> set_secure_defaults() |> configure_managed_tls() + |> set_secure_defaults() catch {:configure, message} -> {:error, message} else From f48e6d3dea230aa8e8860aba7498a707c319051e Mon Sep 17 00:00:00 2001 From: Kevin Date: Tue, 11 Apr 2023 16:42:39 +0200 Subject: [PATCH 5/5] Update lib/plug/ssl.ex Co-authored-by: Bram Verburg --- lib/plug/ssl.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/plug/ssl.ex b/lib/plug/ssl.ex index 8ec97989..cdf8017c 100644 --- a/lib/plug/ssl.ex +++ b/lib/plug/ssl.ex @@ -129,7 +129,7 @@ defmodule Plug.SSL do [Mozilla Security/Server Side TLS](https://wiki.mozilla.org/Security/Server_Side_TLS) The **Strong** cipher suite only supports tlsv1.3. Ciphers were based on the "Modern" - configuration recommandation and support forward secrecy and are authenticated. + configuration recommendation and support forward secrecy and are authenticated. The intention of this configuration is to provide as secure as possible defaults knowing that it will not be fully compatible with older browsers and operating systems.