File tree Expand file tree Collapse file tree 4 files changed +12
-19
lines changed
lib/action_dispatch/middleware Expand file tree Collapse file tree 4 files changed +12
-19
lines changed Original file line number Diff line number Diff line change @@ -102,21 +102,15 @@ def call(env)
102
102
end
103
103
104
104
private
105
+ HOSTNAME = /[a-z0-9.-]+|\[ [a-f0-9]*:[a-f0-9.:]+\] /i
106
+ VALID_ORIGIN_HOST = /\A (#{ HOSTNAME } )(?::\d +)?\z /
107
+ VALID_FORWARDED_HOST = /(?:\A |,[ ]?)(#{ HOSTNAME } )(?::\d +)?\z /
108
+
105
109
def authorized? ( request )
106
- valid_host = /
107
- \A
108
- (?<host>[a-z0-9.-]+|\[ [a-f0-9]*:[a-f0-9.:]+\] )
109
- (:\d +)?
110
- \z
111
- /x
112
-
113
- origin_host = valid_host . match (
114
- request . get_header ( "HTTP_HOST" ) . to_s . downcase )
115
- forwarded_host = valid_host . match (
116
- request . x_forwarded_host . to_s . split ( /,\s ?/ ) . last )
117
-
118
- origin_host && @permissions . allows? ( origin_host [ :host ] ) && (
119
- forwarded_host . nil? || @permissions . allows? ( forwarded_host [ :host ] ) )
110
+ origin_host = request . get_header ( "HTTP_HOST" ) &.slice ( VALID_ORIGIN_HOST , 1 ) || ""
111
+ forwarded_host = request . x_forwarded_host &.slice ( VALID_FORWARDED_HOST , 1 ) || ""
112
+
113
+ @permissions . allows? ( origin_host ) && ( forwarded_host . blank? || @permissions . allows? ( forwarded_host ) )
120
114
end
121
115
122
116
def excluded? ( request )
Original file line number Diff line number Diff line change @@ -221,15 +221,15 @@ class HostAuthorizationTest < ActionDispatch::IntegrationTest
221
221
assert_match "Blocked host: www.example.com" , response . body
222
222
end
223
223
224
- test "only compare to valid hostnames" do
224
+ test "blocks requests with invalid hostnames" do
225
225
@app = ActionDispatch ::HostAuthorization . new ( App , ".example.com" )
226
226
227
227
get "/" , env : {
228
- "HOST" => "example .com#sub .example.com" ,
228
+ "HOST" => "attacker .com#x .example.com" ,
229
229
}
230
230
231
231
assert_response :forbidden
232
- assert_match "Blocked host: example .com#sub .example.com" , response . body
232
+ assert_match "Blocked host: attacker .com#x .example.com" , response . body
233
233
end
234
234
235
235
test "blocks requests to similar host" do
Original file line number Diff line number Diff line change @@ -11,7 +11,6 @@ class RemoteIpTest < ActiveSupport::TestCase
11
11
def remote_ip ( env = { } )
12
12
remote_ip = nil
13
13
env = Rack ::MockRequest . env_for ( "/" ) . merge ( env ) . merge! (
14
- "HTTP_HOST" => "example.com" ,
15
14
"action_dispatch.show_exceptions" => false ,
16
15
"action_dispatch.key_generator" => ActiveSupport ::CachingKeyGenerator . new (
17
16
ActiveSupport ::KeyGenerator . new ( "b3c631c314c0bbca50c1b2843150fe33" , iterations : 1000 )
Original file line number Diff line number Diff line change @@ -82,7 +82,7 @@ def extract_body(response)
82
82
end
83
83
84
84
def get ( path )
85
- @app . call ( ::Rack ::MockRequest . env_for ( path , "HTTP_HOST" => "example.com" ) )
85
+ @app . call ( ::Rack ::MockRequest . env_for ( path ) )
86
86
end
87
87
88
88
def assert_welcome ( resp )
You can’t perform that action at this time.
0 commit comments