Changeset 9124
- Timestamp:
- 03/28/08 21:38:01 (2 months ago)
- Files:
-
- trunk/actionpack/CHANGELOG (modified) (1 diff)
- trunk/actionpack/lib/action_controller/request.rb (modified) (1 diff)
- trunk/actionpack/test/controller/request_test.rb (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/actionpack/CHANGELOG
r9115 r9124 1 1 *SVN* 2 3 * Avoid remote_ip spoofing. [Brian Candler] 2 4 3 5 * Added support for regexp flags like ignoring case in the :requirements part of routes declarations #11421 [NeilW] trunk/actionpack/lib/action_controller/request.rb
r9113 r9124 125 125 alias xhr? :xml_http_request? 126 126 127 # Which IP addresses are "trusted proxies" that can be stripped from 128 # the right-hand-side of X-Forwarded-For 129 TRUSTED_PROXIES = /^127\.0\.0\.1$|^(10|172\.(1[6-9]|2[0-9]|30|31)|192\.168)\./i 130 127 131 # Determine originating IP address. REMOTE_ADDR is the standard 128 132 # but will fail if the user is behind a proxy. HTTP_CLIENT_IP and/or 129 # HTTP_X_FORWARDED_FOR are set by proxies so check for these before 130 # falling back to REMOTE_ADDR. HTTP_X_FORWARDED_FOR may be a comma- 131 # delimited list in the case of multiple chained proxies; the first is 132 # the originating IP. 133 # 134 # Security note: do not use if IP spoofing is a concern for your 135 # application. Since remote_ip checks HTTP headers for addresses forwarded 136 # by proxies, the client may send any IP. remote_addr can't be spoofed but 137 # also doesn't work behind a proxy, since it's always the proxy's IP. 133 # HTTP_X_FORWARDED_FOR are set by proxies so check for these if 134 # REMOTE_ADDR is a proxy. HTTP_X_FORWARDED_FOR may be a comma- 135 # delimited list in the case of multiple chained proxies; the last 136 # address which is not trusted is the originating IP. 137 138 138 def remote_ip 139 return @env['HTTP_CLIENT_IP'] if @env.include? 'HTTP_CLIENT_IP' 139 if TRUSTED_PROXIES !~ @env['REMOTE_ADDR'] 140 return @env['REMOTE_ADDR'] 141 end 142 143 if @env.include? 'HTTP_CLIENT_IP' 144 if @env.include? 'HTTP_X_FORWARDED_FOR' 145 # We don't know which came from the proxy, and which from the user 146 raise ActionControllerError.new(<<EOM) 147 IP spoofing attack?! 148 HTTP_CLIENT_IP=#{@env['HTTP_CLIENT_IP'].inspect} 149 HTTP_X_FORWARDED_FOR=#{@env['HTTP_X_FORWARDED_FOR'].inspect} 150 EOM 151 end 152 return @env['HTTP_CLIENT_IP'] 153 end 140 154 141 155 if @env.include? 'HTTP_X_FORWARDED_FOR' then 142 remote_ips = @env['HTTP_X_FORWARDED_FOR'].split(',').reject do |ip| 143 ip.strip =~ /^unknown$|^(10|172\.(1[6-9]|2[0-9]|30|31)|192\.168)\./i 144 end 145 146 return remote_ips.first.strip unless remote_ips.empty? 156 remote_ips = @env['HTTP_X_FORWARDED_FOR'].split(',') 157 while remote_ips.size > 1 && TRUSTED_PROXIES =~ remote_ips.last.strip 158 remote_ips.pop 159 end 160 161 return remote_ips.last.strip 147 162 end 148 163 trunk/actionpack/test/controller/request_test.rb
r9113 r9124 14 14 15 15 @request.env['HTTP_CLIENT_IP'] = '2.3.4.5' 16 assert_equal '1.2.3.4', @request.remote_ip 17 18 @request.remote_addr = '192.168.0.1' 16 19 assert_equal '2.3.4.5', @request.remote_ip 17 20 @request.env.delete 'HTTP_CLIENT_IP' 18 21 22 @request.remote_addr = '1.2.3.4' 23 @request.env['HTTP_X_FORWARDED_FOR'] = '3.4.5.6' 24 assert_equal '1.2.3.4', @request.remote_ip 25 26 @request.remote_addr = '127.0.0.1' 19 27 @request.env['HTTP_X_FORWARDED_FOR'] = '3.4.5.6' 20 28 assert_equal '3.4.5.6', @request.remote_ip … … 36 44 37 45 @request.env['HTTP_X_FORWARDED_FOR'] = '127.0.0.1,3.4.5.6' 38 assert_equal ' 127.0.0.1', @request.remote_ip46 assert_equal '3.4.5.6', @request.remote_ip 39 47 40 48 @request.env['HTTP_X_FORWARDED_FOR'] = 'unknown,192.168.0.1' 41 assert_equal '1.2.3.4', @request.remote_ip 49 assert_equal 'unknown', @request.remote_ip 50 51 @request.env['HTTP_X_FORWARDED_FOR'] = '9.9.9.9, 3.4.5.6, 10.0.0.1, 172.31.4.4' 52 assert_equal '3.4.5.6', @request.remote_ip 53 54 @request.env['HTTP_CLIENT_IP'] = '8.8.8.8' 55 e = assert_raises(ActionController::ActionControllerError) { 56 @request.remote_ip 57 } 58 assert_match /IP spoofing attack/, e.message 59 assert_match /HTTP_X_FORWARDED_FOR="9.9.9.9, 3.4.5.6, 10.0.0.1, 172.31.4.4"/, e.message 60 assert_match /HTTP_CLIENT_IP="8.8.8.8"/, e.message 61 62 @request.env.delete 'HTTP_CLIENT_IP' 42 63 @request.env.delete 'HTTP_X_FORWARDED_FOR' 43 64 end