Merge branch 'master' of github.com:kickstarter/rack-attack

This commit is contained in:
Vincent Boisard 2015-12-29 10:10:36 +01:00
commit 297ef4a2ae
18 changed files with 140 additions and 6 deletions

View file

@ -1,13 +1,21 @@
appraise 'activesupport3.2' do appraise 'activesupport3.2' do
gem 'activesupport', '~> 3.2.0' gem 'activesupport', '~> 3.2.0'
gem 'actionpack', '~> 3.2.0'
end end
appraise 'activesupport4.0' do appraise 'activesupport4.0' do
gem 'activesupport', '~> 4.0.0' gem 'activesupport', '~> 4.0.0'
gem 'actionpack', '~> 4.0.0'
end end
appraise 'activesupport4.1' do appraise 'activesupport4.1' do
gem 'activesupport', '~> 4.1.0' gem 'activesupport', '~> 4.1.0'
gem 'actionpack', '~> 4.1.0'
end
appraise 'activesupport4.2' do
gem 'activesupport', '~> 4.2.0'
gem 'actionpack', '~> 4.2.0'
end end
appraise 'dalli1.1' do appraise 'dalli1.1' do

View file

@ -1,7 +1,13 @@
# Changlog # Changlog
## master (unreleased) ## master (unreleased)
## v4.3.1 - 18 Dec 2015
- SECURITY FIX: Normalize request paths when using ActionDispatch. Thanks
Andres Riancho at @includesecurity for reporting it.
- Remove support for ruby 1.9.x - Remove support for ruby 1.9.x
- Add Code of Conduct
- Several documentation and testing improvements
## v4.3.0 - 22 May 2015 ## v4.3.0 - 22 May 2015

View file

@ -1,4 +1,9 @@
source "https://rubygems.org" source 'https://rubygems.org'
gemspec gemspec
#gem 'debugger', platform: 'ruby' group :development do
gem 'pry'
gem 'guard' # NB: this is necessary in newer versions
gem 'guard-minitest'
end

10
Guardfile Normal file
View file

@ -0,0 +1,10 @@
# A sample Guardfile
# More info at https://github.com/guard/guard#readme
guard :minitest do
# with Minitest::Spec
watch(%r{^spec/(.*)_spec\.rb$})
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
watch(%r{^spec/spec_helper\.rb$}) { 'spec' }
end

View file

@ -147,6 +147,8 @@ Rack::Attack.blacklist('fail2ban pentesters') do |req|
end end
``` ```
Note that `Fail2Ban` filters are not automatically scoped to the blacklist, so when using multiple filters in an application the scoping must be added to the discriminator e.g. `"pentest:#{req.ip}"`.
#### Allow2Ban #### Allow2Ban
`Allow2Ban.filter` works the same way as the `Fail2Ban.filter` except that it *allows* requests from misbehaving `Allow2Ban.filter` works the same way as the `Fail2Ban.filter` except that it *allows* requests from misbehaving
clients until such time as they reach maxretry at which they are cut off as per normal. clients until such time as they reach maxretry at which they are cut off as per normal.

View file

@ -4,5 +4,12 @@ source "https://rubygems.org"
gem "activesupport", "~> 3.2.0" gem "activesupport", "~> 3.2.0"
gem "memcache-client" gem "memcache-client"
gem "actionpack", "~> 3.2.0"
group :development do
gem "pry"
gem "guard"
gem "guard-minitest"
end
gemspec :path => "../" gemspec :path => "../"

View file

@ -3,5 +3,12 @@
source "https://rubygems.org" source "https://rubygems.org"
gem "activesupport", "~> 4.0.0" gem "activesupport", "~> 4.0.0"
gem "actionpack", "~> 4.0.0"
group :development do
gem "pry"
gem "guard"
gem "guard-minitest"
end
gemspec :path => "../" gemspec :path => "../"

View file

@ -3,5 +3,12 @@
source "https://rubygems.org" source "https://rubygems.org"
gem "activesupport", "~> 4.1.0" gem "activesupport", "~> 4.1.0"
gem "actionpack", "~> 4.1.0"
group :development do
gem "pry"
gem "guard"
gem "guard-minitest"
end
gemspec :path => "../" gemspec :path => "../"

View file

@ -2,6 +2,13 @@
source "https://rubygems.org" source "https://rubygems.org"
gem "activesupport", "~> 4.2.1" gem "activesupport", "~> 4.2.0"
gem "actionpack", "~> 4.2.0"
group :development do
gem "pry"
gem "guard"
gem "guard-minitest"
end
gemspec :path => "../" gemspec :path => "../"

View file

@ -4,4 +4,10 @@ source "https://rubygems.org"
gem "dalli", "1.1.5" gem "dalli", "1.1.5"
group :development do
gem "pry"
gem "guard"
gem "guard-minitest"
end
gemspec :path => "../" gemspec :path => "../"

View file

@ -4,4 +4,10 @@ source "https://rubygems.org"
gem "dalli", "~> 2.0" gem "dalli", "~> 2.0"
group :development do
gem "pry"
gem "guard"
gem "guard-minitest"
end
gemspec :path => "../" gemspec :path => "../"

View file

@ -3,6 +3,7 @@ require 'forwardable'
class Rack::Attack class Rack::Attack
autoload :Cache, 'rack/attack/cache' autoload :Cache, 'rack/attack/cache'
autoload :PathNormalizer, 'rack/attack/path_normalizer'
autoload :Check, 'rack/attack/check' autoload :Check, 'rack/attack/check'
autoload :Throttle, 'rack/attack/throttle' autoload :Throttle, 'rack/attack/throttle'
autoload :Whitelist, 'rack/attack/whitelist' autoload :Whitelist, 'rack/attack/whitelist'
@ -92,6 +93,7 @@ class Rack::Attack
end end
def call(env) def call(env)
env['PATH_INFO'] = PathNormalizer.normalize_path(env['PATH_INFO'])
req = Rack::Attack::Request.new(env) req = Rack::Attack::Request.new(env)
if whitelisted?(req) if whitelisted?(req)

View file

@ -0,0 +1,27 @@
class Rack::Attack
# When using Rack::Attack with a Rails app, developers expect the request path
# to be normalized. In particular, trailing slashes are stripped.
# (See http://git.io/v0rrR for implementation.)
#
# Look for an ActionDispatch utility class that Rails folks would expect
# to normalize request paths. If unavailable, use a fallback class that
# doesn't normalize the path (as a non-Rails rack app developer expects).
module FallbackPathNormalizer
def self.normalize_path(path)
path
end
end
PathNormalizer = if defined?(::ActionDispatch::Journey::Router::Utils)
# For Rails 4+ apps
::ActionDispatch::Journey::Router::Utils
elsif defined?(::Journey::Router::Utils)
# for Rails 3.2
::Journey::Router::Utils
else
FallbackPathNormalizer
end
end

View file

@ -1,5 +1,5 @@
module Rack module Rack
class Attack class Attack
VERSION = '4.3.0' VERSION = '4.3.1'
end end
end end

View file

@ -28,6 +28,7 @@ Gem::Specification.new do |s|
s.add_development_dependency 'rake' s.add_development_dependency 'rake'
s.add_development_dependency 'appraisal' s.add_development_dependency 'appraisal'
s.add_development_dependency 'activesupport', '>= 3.0.0' s.add_development_dependency 'activesupport', '>= 3.0.0'
s.add_development_dependency 'actionpack', '>= 3.0.0'
s.add_development_dependency 'redis-activesupport' s.add_development_dependency 'redis-activesupport'
s.add_development_dependency 'dalli' s.add_development_dependency 'dalli'
s.add_development_dependency 'connection_pool' s.add_development_dependency 'connection_pool'

View file

@ -0,0 +1,17 @@
require_relative 'spec_helper'
describe Rack::Attack::PathNormalizer do
subject { Rack::Attack::PathNormalizer }
it 'should have a normalize_path method' do
subject.normalize_path('/foo').must_equal '/foo'
end
describe 'FallbackNormalizer' do
subject { Rack::Attack::FallbackPathNormalizer }
it '#normalize_path does not change the path' do
subject.normalize_path('').must_equal ''
end
end
end

View file

@ -3,6 +3,17 @@ require_relative 'spec_helper'
describe 'Rack::Attack' do describe 'Rack::Attack' do
allow_ok_requests allow_ok_requests
describe 'normalizing paths' do
before do
Rack::Attack.blacklist("banned_path") {|req| req.path == '/foo' }
end
it 'blocks requests with trailing slash' do
get '/foo/'
last_response.status.must_equal 403
end
end
describe 'blacklist' do describe 'blacklist' do
before do before do
@bad_ip = '1.2.3.4' @bad_ip = '1.2.3.4'

View file

@ -5,12 +5,17 @@ require "minitest/autorun"
require "minitest/pride" require "minitest/pride"
require "rack/test" require "rack/test"
require 'active_support' require 'active_support'
require 'action_dispatch'
# Load Journey for Rails 3.2
require 'journey' if ActionPack::VERSION::MAJOR == 3
require "rack/attack" require "rack/attack"
begin begin
require 'debugger' require 'pry'
rescue LoadError rescue LoadError
#nothing to do here #nothing to do here
end end
class MiniTest::Spec class MiniTest::Spec