rack-attack 4.3.0 → 4.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: da0016c3e3d7fee696a96f8f1e3a493b0b197518
4
- data.tar.gz: 6b337c7d2ed9c48dbfd4cfc031ab6157fbceda3d
3
+ metadata.gz: 62911565ba358aadd130a8edf862d1f3ca57786d
4
+ data.tar.gz: 55876d8afb3bed309bb09a5b1fae357c8d5cdf10
5
5
  SHA512:
6
- metadata.gz: 1f84ef0262ee5f64ed98d745bedf49f7e8ef38693a3bc8e0eddb643dc7165e881ee11642944cf75d52769e13f6da934be69bf3156c6945e938caa139bf886252
7
- data.tar.gz: b952d3bd6061eaf8c7b5172c0b6620d4e3797d383c7a00d9d6d80eef78d470ba3ce8dbb1c57f801f3685164f7076a587236fc5bc3550b433c3771bddbfe589ef
6
+ metadata.gz: b54245dad4b5101ce8364da45654d650bfe86c2f4e3c85d48e3923b7ca8a31ad5ec61e3938745dedefba3fd117447e522a4207145b086eccf86bf14ba1696643
7
+ data.tar.gz: 57063639a9c9d6e3884b1a89cbfce044fefebe7dcb4a95f1e025e260db75490a05447d4e7294060aa55531b55d567b9763101debb2119a690c8760b0b94787ec
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  Rack::Attack is a rack middleware to protect your web app from bad clients.
5
5
  It allows *whitelisting*, *blacklisting*, *throttling*, and *tracking* based on arbitrary properties of the request.
6
6
 
7
- Throttle state is stored in a configurable cache (e.g. `Rails.cache`), presumably backed by memcached or redis ([at least gem v3.0.0](https://rubygems.org/gems/redis)).
7
+ Throttle and fail2ban state is stored in a configurable cache (e.g. `Rails.cache`), presumably backed by memcached or redis ([at least gem v3.0.0](https://rubygems.org/gems/redis)).
8
8
 
9
9
  See the [Backing & Hacking blog post](http://www.kickstarter.com/backing-and-hacking/rack-attack-protection-from-abusive-clients) introducing Rack::Attack.
10
10
 
@@ -47,13 +47,13 @@ end
47
47
  *Tip:* The example in the wiki is a great way to get started:
48
48
  [Example Configuration](https://github.com/kickstarter/rack-attack/wiki/Example-Configuration)
49
49
 
50
- Optionally configure the cache store for throttling:
50
+ Optionally configure the cache store for throttling or fail2ban filtering:
51
51
 
52
52
  ```ruby
53
53
  Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new # defaults to Rails.cache
54
54
  ```
55
55
 
56
- Note that `Rack::Attack.cache` is only used for throttling; not blacklisting & whitelisting. Your cache store must implement `increment` and `write` like [ActiveSupport::Cache::Store](http://api.rubyonrails.org/classes/ActiveSupport/Cache/Store.html).
56
+ Note that `Rack::Attack.cache` is only used for throttling and fail2ban filtering; not blacklisting & whitelisting. Your cache store must implement `increment` and `write` like [ActiveSupport::Cache::Store](http://api.rubyonrails.org/classes/ActiveSupport/Cache/Store.html).
57
57
 
58
58
  ## How it works
59
59
 
@@ -104,7 +104,7 @@ A [Rack::Request](http://www.rubydoc.info/gems/rack/Rack/Request) object is pass
104
104
  # (blacklist & throttles are skipped)
105
105
  Rack::Attack.whitelist('allow from localhost') do |req|
106
106
  # Requests are allowed if the return value is truthy
107
- '127.0.0.1' == req.ip
107
+ '127.0.0.1' == req.ip || '::1' == req.ip
108
108
  end
109
109
  ```
110
110
 
@@ -128,21 +128,27 @@ end
128
128
  `Fail2Ban.filter` can be used within a blacklist to block all requests from misbehaving clients.
129
129
  This pattern is inspired by [fail2ban](http://www.fail2ban.org/wiki/index.php/Main_Page).
130
130
  See the [fail2ban documentation](http://www.fail2ban.org/wiki/index.php/MANUAL_0_8#Jail_Options) for more details on
131
- how the parameters work.
131
+ how the parameters work. For multiple filters, be sure to put each filter in a separate blacklist and use a unique discriminator for each fail2ban filter.
132
132
 
133
133
  ```ruby
134
- # Block requests containing '/etc/password' in the params.
134
+ # Block suspicious requests for '/etc/password' or wordpress specific paths.
135
135
  # After 3 blocked requests in 10 minutes, block all requests from that IP for 5 minutes.
136
136
  Rack::Attack.blacklist('fail2ban pentesters') do |req|
137
137
  # `filter` returns truthy value if request fails, or if it's from a previously banned IP
138
138
  # so the request is blocked
139
- Rack::Attack::Fail2Ban.filter(req.ip, :maxretry => 3, :findtime => 10.minutes, :bantime => 5.minutes) do
140
- # The count for the IP is incremented if the return value is truthy.
141
- CGI.unescape(req.query_string) =~ %r{/etc/passwd}
139
+ Rack::Attack::Fail2Ban.filter("pentesters-#{req.ip}", :maxretry => 3, :findtime => 10.minutes, :bantime => 5.minutes) do
140
+ # The count for the IP is incremented if the return value is truthy
141
+ CGI.unescape(req.query_string) =~ %r{/etc/passwd} ||
142
+ req.path.include?('/etc/passwd') ||
143
+ req.path.include?('wp-admin') ||
144
+ req.path.include?('wp-login')
145
+
142
146
  end
143
147
  end
144
148
  ```
145
149
 
150
+ 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}"`.
151
+
146
152
  #### Allow2Ban
147
153
  `Allow2Ban.filter` works the same way as the `Fail2Ban.filter` except that it *allows* requests from misbehaving
148
154
  clients until such time as they reach maxretry at which they are cut off as per normal.
@@ -283,6 +289,12 @@ It is impractical if not impossible to block abusive clients completely.
283
289
  Rack::Attack aims to let developers quickly mitigate abusive requests and rely
284
290
  less on short-term, one-off hacks to block a particular attack.
285
291
 
292
+ ## Contributing
293
+
294
+ Pull requests and issues are greatly appreciated. This project is intended to be
295
+ a safe, welcoming space for collaboration, and contributors are expected to
296
+ adhere to the [Code of Conduct](CODE_OF_CONDUCT.md).
297
+
286
298
  ## Mailing list
287
299
 
288
300
  New releases of Rack::Attack are announced on
@@ -3,6 +3,7 @@ require 'forwardable'
3
3
 
4
4
  class Rack::Attack
5
5
  autoload :Cache, 'rack/attack/cache'
6
+ autoload :PathNormalizer, 'rack/attack/path_normalizer'
6
7
  autoload :Check, 'rack/attack/check'
7
8
  autoload :Throttle, 'rack/attack/throttle'
8
9
  autoload :Whitelist, 'rack/attack/whitelist'
@@ -91,6 +92,7 @@ class Rack::Attack
91
92
  end
92
93
 
93
94
  def call(env)
95
+ env['PATH_INFO'] = PathNormalizer.normalize_path(env['PATH_INFO'])
94
96
  req = Rack::Attack::Request.new(env)
95
97
 
96
98
  if whitelisted?(req)
@@ -0,0 +1,27 @@
1
+ class Rack::Attack
2
+
3
+ # When using Rack::Attack with a Rails app, developers expect the request path
4
+ # to be normalized. In particular, trailing slashes are stripped.
5
+ # (See http://git.io/v0rrR for implementation.)
6
+ #
7
+ # Look for an ActionDispatch utility class that Rails folks would expect
8
+ # to normalize request paths. If unavailable, use a fallback class that
9
+ # doesn't normalize the path (as a non-Rails rack app developer expects).
10
+
11
+ module FallbackPathNormalizer
12
+ def self.normalize_path(path)
13
+ path
14
+ end
15
+ end
16
+
17
+ PathNormalizer = if defined?(::ActionDispatch::Journey::Router::Utils)
18
+ # For Rails 4+ apps
19
+ ::ActionDispatch::Journey::Router::Utils
20
+ elsif defined?(::Journey::Router::Utils)
21
+ # for Rails 3.2
22
+ ::Journey::Router::Utils
23
+ else
24
+ FallbackPathNormalizer
25
+ end
26
+
27
+ end
@@ -1,5 +1,5 @@
1
1
  module Rack
2
2
  class Attack
3
- VERSION = '4.3.0'
3
+ VERSION = '4.3.1'
4
4
  end
5
5
  end
@@ -0,0 +1,17 @@
1
+ require_relative 'spec_helper'
2
+
3
+ describe Rack::Attack::PathNormalizer do
4
+ subject { Rack::Attack::PathNormalizer }
5
+
6
+ it 'should have a normalize_path method' do
7
+ subject.normalize_path('/foo').must_equal '/foo'
8
+ end
9
+
10
+ describe 'FallbackNormalizer' do
11
+ subject { Rack::Attack::FallbackPathNormalizer }
12
+
13
+ it '#normalize_path does not change the path' do
14
+ subject.normalize_path('').must_equal ''
15
+ end
16
+ end
17
+ end
@@ -3,6 +3,17 @@ require_relative 'spec_helper'
3
3
  describe 'Rack::Attack' do
4
4
  allow_ok_requests
5
5
 
6
+ describe 'normalizing paths' do
7
+ before do
8
+ Rack::Attack.blacklist("banned_path") {|req| req.path == '/foo' }
9
+ end
10
+
11
+ it 'blocks requests with trailing slash' do
12
+ get '/foo/'
13
+ last_response.status.must_equal 403
14
+ end
15
+ end
16
+
6
17
  describe 'blacklist' do
7
18
  before do
8
19
  @bad_ip = '1.2.3.4'
@@ -5,12 +5,17 @@ require "minitest/autorun"
5
5
  require "minitest/pride"
6
6
  require "rack/test"
7
7
  require 'active_support'
8
+ require 'action_dispatch'
9
+
10
+ # Load Journey for Rails 3.2
11
+ require 'journey' if ActionPack::VERSION::MAJOR == 3
12
+
8
13
  require "rack/attack"
9
14
 
10
15
  begin
11
- require 'debugger'
16
+ require 'pry'
12
17
  rescue LoadError
13
- #nothing to do here
18
+ #nothing to do here
14
19
  end
15
20
 
16
21
  class MiniTest::Spec
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-attack
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.3.0
4
+ version: 4.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aaron Suggs
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-05-22 00:00:00.000000000 Z
11
+ date: 2015-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -94,6 +94,20 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: 3.0.0
97
+ - !ruby/object:Gem::Dependency
98
+ name: actionpack
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: 3.0.0
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: 3.0.0
97
111
  - !ruby/object:Gem::Dependency
98
112
  name: redis-activesupport
99
113
  requirement: !ruby/object:Gem::Requirement
@@ -150,6 +164,7 @@ files:
150
164
  - lib/rack/attack/cache.rb
151
165
  - lib/rack/attack/check.rb
152
166
  - lib/rack/attack/fail2ban.rb
167
+ - lib/rack/attack/path_normalizer.rb
153
168
  - lib/rack/attack/request.rb
154
169
  - lib/rack/attack/store_proxy.rb
155
170
  - lib/rack/attack/store_proxy/dalli_proxy.rb
@@ -163,6 +178,7 @@ files:
163
178
  - spec/integration/offline_spec.rb
164
179
  - spec/integration/rack_attack_cache_spec.rb
165
180
  - spec/rack_attack_dalli_proxy_spec.rb
181
+ - spec/rack_attack_path_normalizer_spec.rb
166
182
  - spec/rack_attack_request_spec.rb
167
183
  - spec/rack_attack_spec.rb
168
184
  - spec/rack_attack_throttle_spec.rb
@@ -181,7 +197,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
181
197
  requirements:
182
198
  - - ">="
183
199
  - !ruby/object:Gem::Version
184
- version: 1.9.2
200
+ version: 2.0.0
185
201
  required_rubygems_version: !ruby/object:Gem::Requirement
186
202
  requirements:
187
203
  - - ">="
@@ -189,7 +205,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
189
205
  version: '0'
190
206
  requirements: []
191
207
  rubyforge_project:
192
- rubygems_version: 2.4.5
208
+ rubygems_version: 2.4.5.1
193
209
  signing_key:
194
210
  specification_version: 4
195
211
  summary: Block & throttle abusive requests
@@ -199,6 +215,7 @@ test_files:
199
215
  - spec/integration/offline_spec.rb
200
216
  - spec/integration/rack_attack_cache_spec.rb
201
217
  - spec/rack_attack_dalli_proxy_spec.rb
218
+ - spec/rack_attack_path_normalizer_spec.rb
202
219
  - spec/rack_attack_request_spec.rb
203
220
  - spec/rack_attack_spec.rb
204
221
  - spec/rack_attack_throttle_spec.rb