bot-away 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,11 @@
1
+ === 1.0.1 2010-04-02
2
+ * 2 minor enhancements:
3
+ * ActionController::Request.accepts_unfiltered_params creates an array of params that will not be checked
4
+ * Took all honeypots out of the keyboard tab order using randomized negative indexes.
5
+
6
+ * Bugfixes:
7
+ * Empty select tags no longer raise errors
8
+
1
9
  === 0.0.1 2010-03-24
2
10
 
3
11
  * 1 major enhancement:
@@ -5,13 +5,15 @@
5
5
  == DESCRIPTION:
6
6
 
7
7
  Unobtrusively detects form submissions made by spambots, and silently drops those submissions. The key word here is
8
- "unobtrusive" -- this is NOT a CAPTCHA. This is transparent, modular implementation of the bot-catching techniques
9
- discussed by Ned Batchelder at http://nedbatchelder.com/text/stopbots.html
8
+ "unobtrusive" -- this is NOT a CAPTCHA. This is a transparent, modular implementation of the bot-catching techniques
9
+ discussed by Ned Batchelder at http://nedbatchelder.com/text/stopbots.html.
10
10
 
11
- If a submission is detected, the params hash is cleared, so the data can't be used. Since this includes the authenticity
12
- token, Rails should barf due to an invalid or missing authenticity token. Congrats, spam blocked.
11
+ == WHAT'S GOING ON:
13
12
 
14
- The specifics of the techniques employed for filtering spambots are discussed Ned's site at the above location; however,
13
+ If a bot submission is detected, the params hash is cleared, so the data can't be used. Since this includes the
14
+ authenticity token, Rails should complain about an invalid or missing authenticity token. Congrats, spam blocked.
15
+
16
+ The specifics of the techniques employed for filtering spambots are discussed Ned's site in the description; however,
15
17
  here's a brief run-down of what's going on:
16
18
 
17
19
  * Your code stays the same. After the bot-away gem has been activated, all Rails-generated forms on your site
@@ -46,6 +48,19 @@ here's a brief run-down of what's going on:
46
48
  in order to avoid confusing lots of humans (such as hiding the honeypots), it is always theoretically possible for
47
49
  a spambot to get around it. It's just very, very difficult.
48
50
 
51
+ * I feel this library has been fairly well-tested (99.5% test coverage as of this writing), but if you discover a bug
52
+ and can't be bothered to let me know about it (or you just don't have time to wait for a fix or fix it yourself),
53
+ then you can simply add the name of the offending form element to the ActionController::Request.unfiltered_params
54
+ array like so:
55
+ ActionController::Request.accepts_unfiltered_params 'role_ids'
56
+ ActionController::Request.accepts_unfiltered_params 'user' # this can be called multiple times
57
+ You should also take note that this is an array, not a hash. So if you have a user[role_ids] as well as a
58
+ group[role_ids], the +role_ids+ will not be matched on EITHER of these models.
59
+
60
+ * Currently, there's no direct support for per-request configuration of unfiltered params. This is mostly due to
61
+ Bot-Away's low-level approach to filtering bots: the params have already been filtered by the time your controller
62
+ is created. I'd like to revisit per-request filtering sometime in the future, once I figure out the best way to do it.
63
+
49
64
  == REQUIREMENTS:
50
65
 
51
66
  * Rails 2.3.5 or better.
@@ -85,4 +100,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
85
100
  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
86
101
  CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
87
102
  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
88
- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
103
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile CHANGED
@@ -21,7 +21,7 @@ Rake::RDocTask.new(:docs) do |rdoc|
21
21
  'lib/**/*.rb', 'doc/**/*.rdoc']#, 'spec/*.rb']
22
22
  rdoc.rdoc_files.add(files)
23
23
  rdoc.main = 'README.rdoc'
24
- rdoc.title = 'EVE Documentation'
24
+ rdoc.title = 'Bot-Away Documentation'
25
25
  #rdoc.template = '/path/to/gems/allison-2.0/lib/allison'
26
26
  rdoc.rdoc_dir = 'doc'
27
27
  rdoc.options << '--line-numbers' << '--inline-source'
@@ -12,7 +12,7 @@ require 'bot-away/action_view/helpers/instance_tag'
12
12
  require 'bot-away/spinner'
13
13
 
14
14
  module BotAway
15
- VERSION = '1.0.0'
15
+ VERSION = '1.0.1'
16
16
  end
17
17
 
18
18
  # WHY do I have to do this???
@@ -3,6 +3,17 @@ class ActionController::Request < Rack::Request
3
3
  @parameters ||= BotAway::ParamParser.new(ip, parameters_without_deobfuscation).params
4
4
  end
5
5
 
6
+ class << self
7
+ def unfiltered_params(*keys)
8
+ unfiltered_params = instance_variable_get("@unfiltered_params") || instance_variable_set("@unfiltered_params", [])
9
+ unfiltered_params.concat keys.flatten.collect { |k| k.to_s }
10
+ unfiltered_params
11
+ end
12
+
13
+ alias_method :accepts_unfiltered_params, :unfiltered_params
14
+ end
15
+
16
+ delegate :accepts_unfiltered_params, :unfiltered_params, :to => :"self.class"
6
17
  alias_method_chain :parameters, :deobfuscation
7
18
  alias_method :params, :parameters
8
19
  end
@@ -21,6 +21,7 @@ class ActionView::Helpers::InstanceTag
21
21
  assuming(spinner && options) do
22
22
  options['value'] &&= ''
23
23
  options['autocomplete'] = 'off'
24
+ options['tabindex'] = -rand(10)
24
25
  end
25
26
  end
26
27
 
@@ -64,7 +65,12 @@ class ActionView::Helpers::InstanceTag
64
65
  else
65
66
  # this should cover all Rails selects.
66
67
  if spinner && options && (options.keys.include?('id') || options.keys.include?('name'))
67
- disguise(content_tag_without_obfuscation(name, '', honeypot_options(options), *args)) +
68
+ if name == 'select' && !content_or_options_with_block.empty?
69
+ content = '<option selected value=""></option>'
70
+ else
71
+ content = ""
72
+ end
73
+ disguise(content_tag_without_obfuscation(name, content, honeypot_options(options), *args)) +
68
74
  content_tag_without_obfuscation(name, content_or_options_with_block, obfuscate_options(options), *args)
69
75
  else
70
76
  content_tag_without_obfuscation(name, content_or_options_with_block, options, *args)
@@ -1,7 +1,5 @@
1
1
  module BotAway
2
2
  class ParamParser
3
- class ObfuscationMissing < StandardError; end #:nodoc:
4
-
5
3
  attr_reader :params, :ip, :authenticity_token
6
4
 
7
5
  def initialize(ip, params, authenticity_token = params[:authenticity_token])
@@ -20,10 +18,12 @@ module BotAway
20
18
  end
21
19
 
22
20
  current.each do |key, value|
23
- if object_name
21
+ if object_name && !value.kind_of?(Hash) && !ActionController::Request.unfiltered_params.include?(key)
24
22
  if value.blank? && params.keys.include?(spun_key = spinner.encode("#{object_name}[#{key}]"))
25
23
  current[key] = params.delete(spun_key)
26
24
  else
25
+ #puts "throwing on #{object_name}[#{key}] because its not blank" if !value.blank?
26
+ #puts "throwing on #{object_name}[#{key}] because its not found" if defined?(spun_key) && !spun_key.nil?
27
27
  throw :bastard, :took_the_bait
28
28
  end
29
29
  end
@@ -78,6 +78,18 @@ describe TestController do
78
78
  @response.template.controller.params.should == { 'suspected_bot' => true }
79
79
  end
80
80
 
81
+ it "processes no params" do
82
+ post 'proc_form', { 'authenticity_token' => '1234' }
83
+ @response.template.controller.params.should_not == { 'suspected_bot' => true }
84
+ end
85
+
86
+ it "should not fail on unfiltered params" do
87
+ ActionController::Request.accepts_unfiltered_params :role_ids
88
+ @request.remote_addr = '127.0.0.1'
89
+ post 'proc_form', {'authenticity_token' => '1234', 'user' => { 'role_ids' => [1, 2] }}
90
+ @response.template.controller.params.should_not == { 'suspected_bot' => true }
91
+ end
92
+
81
93
  it "does not drop valid authentication request" do
82
94
  #@request.session[:_csrf_token] = 'yPgTAsngzpBO8k1v83RGH26sTrQYD50Ou2oiMT4r/iw='
83
95
  form = { 'authenticity_token' => 'yPgTAsngzpBO8k1v83RGH26sTrQYD50Ou2oiMT4r/iw=',
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 1
7
7
  - 0
8
- - 0
9
- version: 1.0.0
8
+ - 1
9
+ version: 1.0.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - Colin MacKenzie IV
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-04-01 00:00:00 -04:00
17
+ date: 2010-04-02 00:00:00 -04:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -89,31 +89,8 @@ dependencies:
89
89
  version_requirements: *id005
90
90
  description: |-
91
91
  Unobtrusively detects form submissions made by spambots, and silently drops those submissions. The key word here is
92
- "unobtrusive" -- this is NOT a CAPTCHA. This is transparent, modular implementation of the bot-catching techniques
93
- discussed by Ned Batchelder at http://nedbatchelder.com/text/stopbots.html
94
-
95
- If a submission is detected, the params hash is cleared, so the data can't be used. Since this includes the authenticity
96
- token, Rails should barf due to an invalid or missing authenticity token. Congrats, spam blocked.
97
-
98
- The specifics of the techniques employed for filtering spambots are discussed Ned's site at the above location; however,
99
- here's a brief run-down of what's going on:
100
-
101
- * Your code stays the same. After the bot-away gem has been activated, all Rails-generated forms on your site
102
- will automatically be transformed into bot-resistent forms.
103
- * All of the form elements that you create (for instance, a "comment" model with a "body" field) are turned into
104
- dummy elements, or honeypots, and are made invisible to the end user. This is done using div elements and inline CSS
105
- stylesheets. There are several ways an element can be hidden, and these approaches are chosen at random to help
106
- minimize predictability. In the rare event that a real user actually can see the element, it has a label next to it
107
- along the lines of "Leave this blank" -- though the exact message is randomized to help prevent detection.
108
- * All of the form elements are mirrored by hashes. The hashes are generated using the session's authenticity token,
109
- so they can't be predicted.
110
- * When data is submitted, bot-away steps in and 1.) validates that no honeypots have been filled in; and 2)
111
- converts the hashed elements back into the field names that you are expecting (replacing the honeypot fields).
112
- * If a honeypot has been filled in, or a hashed element is missing where it was expected, then the request is
113
- considered to be either spam, or tampered with; and the entire params hash is emptied. Since this happens at the
114
- lowest level, the most likely result is that Rails will complain that the user's authenticity token is invalid. If
115
- that does not happen, then your code will be passed a params hash containing only a "suspected_bot" key, and an error
116
- will result. Either way, the spambot has been foiled!
92
+ "unobtrusive" -- this is NOT a CAPTCHA. This is a transparent, modular implementation of the bot-catching techniques
93
+ discussed by Ned Batchelder at http://nedbatchelder.com/text/stopbots.html.
117
94
  email:
118
95
  - sinisterchipmunk@gmail.com
119
96
  executables: []