rack-attack 4.3.0 → 4.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +21 -9
- data/lib/rack/attack.rb +2 -0
- data/lib/rack/attack/path_normalizer.rb +27 -0
- data/lib/rack/attack/version.rb +1 -1
- data/spec/rack_attack_path_normalizer_spec.rb +17 -0
- data/spec/rack_attack_spec.rb +11 -0
- data/spec/spec_helper.rb +7 -2
- metadata +21 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 62911565ba358aadd130a8edf862d1f3ca57786d
|
4
|
+
data.tar.gz: 55876d8afb3bed309bb09a5b1fae357c8d5cdf10
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
data/lib/rack/attack.rb
CHANGED
@@ -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
|
data/lib/rack/attack/version.rb
CHANGED
@@ -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
|
data/spec/rack_attack_spec.rb
CHANGED
@@ -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'
|
data/spec/spec_helper.rb
CHANGED
@@ -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 '
|
16
|
+
require 'pry'
|
12
17
|
rescue LoadError
|
13
|
-
|
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.
|
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-
|
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:
|
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
|