diff --git a/rack-protection/README.md b/rack-protection/README.md index 4ec10e54..90b4b332 100644 --- a/rack-protection/README.md +++ b/rack-protection/README.md @@ -70,6 +70,13 @@ Prevented by: * `Rack::Protection::SessionHijacking` +## IP Spoofing + + +Prevented by: + +* `Rack::Protection::IPSpoofing` + # Installation gem install rack-protection diff --git a/rack-protection/lib/rack/protection.rb b/rack-protection/lib/rack/protection.rb index 46c66a26..d51b75ee 100644 --- a/rack-protection/lib/rack/protection.rb +++ b/rack-protection/lib/rack/protection.rb @@ -8,6 +8,7 @@ module Rack autoload :EscapedParams, 'rack/protection/escaped_params' autoload :FormToken, 'rack/protection/form_token' autoload :FrameOptions, 'rack/protection/frame_options' + autoload :IPSpoofing, 'rack/protection/ip_spoofing' autoload :JsonCsrf, 'rack/protection/json_csrf' autoload :NoReferrer, 'rack/protection/no_referrer' autoload :PathTraversal, 'rack/protection/path_traversal' @@ -22,6 +23,7 @@ module Rack Rack::Builder.new do use EscapedParams, options unless except.include? :escaped_params use FrameOptions, options unless except.include? :frame_options + use IPSpoofing, options unless except.include? :ip_spoofing use JsonCsrf, options unless except.include? :json_csrf use PathTraversal, options unless except.include? :path_traversal use RemoteToken, options unless except.include? :remote_token diff --git a/rack-protection/lib/rack/protection/ip_spoofing.rb b/rack-protection/lib/rack/protection/ip_spoofing.rb new file mode 100644 index 00000000..d16bb57f --- /dev/null +++ b/rack-protection/lib/rack/protection/ip_spoofing.rb @@ -0,0 +1,23 @@ +require 'rack/protection' + +module Rack + module Protection + ## + # Prevented attack:: IP spoofing + # Supported browsers:: all + # More infos:: http://blog.c22.cc/2011/04/22/surveymonkey-ip-spoofing/ + # + # Detect (some) IP spoofing attacks. + class IPSpoofing < Base + default_reaction :deny + + def accepts?(env) + return true unless env.include? 'HTTP_X_FORWARDED_FOR' + ips = env['HTTP_X_FORWARDED_FOR'].split /\s*,\s*/ + return false if env.include? 'HTTP_CLIENT_IP' and not ips.include? env['HTTP_CLIENT_IP'] + return false if env.include? 'HTTP_X_REAL_IP' and not ips.include? env['HTTP_X_REAL_IP'] + true + end + end + end +end diff --git a/rack-protection/spec/ip_spoofing.rb b/rack-protection/spec/ip_spoofing.rb new file mode 100644 index 00000000..238a2fb8 --- /dev/null +++ b/rack-protection/spec/ip_spoofing.rb @@ -0,0 +1,11 @@ +require File.expand_path('../spec_helper.rb', __FILE__) + +describe Rack::Protection::IPSpoofing do + it_behaves_like "any rack application" + it 'accepts requests without X-Forward-For header' + it 'accepts requests with proper X-Forward-For header' + it 'denies requests where the client spoofs X-Forward-For but not the IP' + it 'denies requests where the client spoofs the IP but not X-Forward-For' + it 'denies requests where IP and X-Forward-For are spoofed but not X-Real-IP' + it 'denies requests where X-Real-IP is spoofed' +end