- Timestamp:
- 03/28/08 21:50:12 (2 years ago)
- Files:
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/2-0-stable/actionpack/CHANGELOG
r8842 r9125 1 1 *SVN* 2 3 * Avoid remote_ip spoofing. [Brian Candler] 2 4 3 5 * Correct inconsistencies in RequestForgeryProtection docs. #11032 [mislav] branches/2-0-stable/actionpack/lib/action_controller/request.rb
r8814 r9125 123 123 alias xhr? :xml_http_request? 124 124 125 # Which IP addresses are "trusted proxies" that can be stripped from 126 # the right-hand-side of X-Forwarded-For 127 TRUSTED_PROXIES = /^127\.0\.0\.1$|^(10|172\.(1[6-9]|2[0-9]|30|31)|192\.168)\./i 128 125 129 # Determine originating IP address. REMOTE_ADDR is the standard 126 130 # but will fail if the user is behind a proxy. HTTP_CLIENT_IP and/or 127 # HTTP_X_FORWARDED_FOR are set by proxies so check for these before 128 # falling back to REMOTE_ADDR. HTTP_X_FORWARDED_FOR may be a comma- 129 # delimited list in the case of multiple chained proxies; the first is 130 # the originating IP. 131 # 132 # Security note: do not use if IP spoofing is a concern for your 133 # application. Since remote_ip checks HTTP headers for addresses forwarded 134 # by proxies, the client may send any IP. remote_addr can't be spoofed but 135 # also doesn't work behind a proxy, since it's always the proxy's IP. 131 # HTTP_X_FORWARDED_FOR are set by proxies so check for these if 132 # REMOTE_ADDR is a proxy. HTTP_X_FORWARDED_FOR may be a comma- 133 # delimited list in the case of multiple chained proxies; the last 134 # address which is not trusted is the originating IP. 135 136 136 def remote_ip 137 return @env['HTTP_CLIENT_IP'] if @env.include? 'HTTP_CLIENT_IP' 137 if TRUSTED_PROXIES !~ @env['REMOTE_ADDR'] 138 return @env['REMOTE_ADDR'] 139 end 140 141 if @env.include? 'HTTP_CLIENT_IP' 142 if @env.include? 'HTTP_X_FORWARDED_FOR' 143 # We don't know which came from the proxy, and which from the user 144 raise ActionControllerError.new(<<EOM) 145 IP spoofing attack?! 146 HTTP_CLIENT_IP=#{@env['HTTP_CLIENT_IP'].inspect} 147 HTTP_X_FORWARDED_FOR=#{@env['HTTP_X_FORWARDED_FOR'].inspect} 148 EOM 149 end 150 return @env['HTTP_CLIENT_IP'] 151 end 138 152 139 153 if @env.include? 'HTTP_X_FORWARDED_FOR' then 140 remote_ips = @env['HTTP_X_FORWARDED_FOR'].split(',').reject do |ip| 141 ip.strip =~ /^unknown$|^(10|172\.(1[6-9]|2[0-9]|30|31)|192\.168)\./i 142 end 143 144 return remote_ips.first.strip unless remote_ips.empty? 154 remote_ips = @env['HTTP_X_FORWARDED_FOR'].split(',') 155 while remote_ips.size > 1 && TRUSTED_PROXIES =~ remote_ips.last.strip 156 remote_ips.pop 157 end 158 159 return remote_ips.last.strip 145 160 end 146 161 branches/2-0-stable/actionpack/test/controller/request_test.rb
r8814 r9125 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