FEATURE: Protect against replay attacks when using TLS 1.3 0-RTT (#8020)

FEATURE: Protect against replay attacks when using TLS 1.3 0-RTT (#8020)

diff --git a/config/application.rb b/config/application.rb
index 2d946b3..cef1abf 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -214,6 +214,9 @@ module Discourse
     config.middleware.delete Rack::ETag
 
     unless Rails.env.development?
+      require 'middleware/early_data_check'
+      config.middleware.insert_after Rack::MethodOverride, Middleware::EarlyDataCheck
+
       require 'middleware/enforce_hostname'
       config.middleware.insert_after Rack::MethodOverride, Middleware::EnforceHostname
     end
diff --git a/lib/middleware/early_data_check.rb b/lib/middleware/early_data_check.rb
new file mode 100644
index 0000000..dd3ced6
--- /dev/null
+++ b/lib/middleware/early_data_check.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Middleware
+  class EarlyDataCheck
+    def initialize(app, settings = nil)
+      @app = app
+    end
+
+    # When a new connection happens, and it uses TLS 1.3 0-RTT
+    # the reverse proxy will set the header `Early-Data` to 1.
+    # Due to 0-RTT susceptibility to Replay Attacks only GET
+    # requests for anonymous users are allowed.
+    # Reference: https://tools.ietf.org/html/rfc8446#appendix-E.5
+    def call(env)
+      if env['HTTP_EARLY_DATA'].to_s == '1' &&
+         (env['REQUEST_METHOD'] != 'GET' || CurrentUser.has_auth_cookie?(env))
+        [
+          425,
+          { 'Content-Type' => 'text/html', 'Content-Length' => '9' },
+          ['Too Early']
+        ]
+      else
+        @app.call(env)
+      end
+    end
+  end
+end

GitHub sha: 39c31a3d

1 Like

Revert "FEATURE: Protect against replay attacks when using TLS 1.3 0-RTT (#8020)"