brakeman 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/FEATURES +16 -0
  2. data/README.md +112 -0
  3. data/WARNING_TYPES +69 -0
  4. data/bin/brakeman +266 -0
  5. data/lib/checks.rb +67 -0
  6. data/lib/checks/base_check.rb +338 -0
  7. data/lib/checks/check_cross_site_scripting.rb +216 -0
  8. data/lib/checks/check_default_routes.rb +29 -0
  9. data/lib/checks/check_evaluation.rb +29 -0
  10. data/lib/checks/check_execute.rb +110 -0
  11. data/lib/checks/check_file_access.rb +46 -0
  12. data/lib/checks/check_forgery_setting.rb +25 -0
  13. data/lib/checks/check_mass_assignment.rb +72 -0
  14. data/lib/checks/check_model_attributes.rb +36 -0
  15. data/lib/checks/check_redirect.rb +98 -0
  16. data/lib/checks/check_render.rb +65 -0
  17. data/lib/checks/check_send_file.rb +15 -0
  18. data/lib/checks/check_session_settings.rb +36 -0
  19. data/lib/checks/check_sql.rb +124 -0
  20. data/lib/checks/check_validation_regex.rb +60 -0
  21. data/lib/format/style.css +105 -0
  22. data/lib/processor.rb +83 -0
  23. data/lib/processors/alias_processor.rb +384 -0
  24. data/lib/processors/base_processor.rb +235 -0
  25. data/lib/processors/config_processor.rb +146 -0
  26. data/lib/processors/controller_alias_processor.rb +222 -0
  27. data/lib/processors/controller_processor.rb +175 -0
  28. data/lib/processors/erb_template_processor.rb +84 -0
  29. data/lib/processors/erubis_template_processor.rb +62 -0
  30. data/lib/processors/haml_template_processor.rb +115 -0
  31. data/lib/processors/lib/find_call.rb +176 -0
  32. data/lib/processors/lib/find_model_call.rb +39 -0
  33. data/lib/processors/lib/processor_helper.rb +36 -0
  34. data/lib/processors/lib/render_helper.rb +118 -0
  35. data/lib/processors/library_processor.rb +117 -0
  36. data/lib/processors/model_processor.rb +125 -0
  37. data/lib/processors/output_processor.rb +204 -0
  38. data/lib/processors/params_processor.rb +77 -0
  39. data/lib/processors/route_processor.rb +338 -0
  40. data/lib/processors/template_alias_processor.rb +86 -0
  41. data/lib/processors/template_processor.rb +55 -0
  42. data/lib/report.rb +628 -0
  43. data/lib/scanner.rb +232 -0
  44. data/lib/tracker.rb +144 -0
  45. data/lib/util.rb +141 -0
  46. data/lib/warning.rb +97 -0
  47. metadata +191 -0
@@ -0,0 +1,16 @@
1
+ Can detect:
2
+ -Possibly unescaped model attributes or parameters in views (Cross Site Scripting)
3
+ -Bad string interpolation in calls to Model.find, Model.last, Model.first, etc., as well as chained calls (SQL Injection)
4
+ -String interpolation in find_by_sql (SQL Injection)
5
+ -String interpolation or params in calls to system, exec, and syscall and `` (Command Injection)
6
+ -Unrestricted mass assignments
7
+ -Global restriction of mass assignment
8
+ -Missing call to protect_from_forgery in ApplicationController (CSRF protection)
9
+ -Default routes, per-controller and globally
10
+ -Redirects based on params (probably too broad currently)
11
+ -Validation regexes not using \A and \z
12
+ -Calls to render with dynamic paths
13
+
14
+ General capabilities:
15
+ -Search for method calls based on target class and/or method name
16
+ -Determine 'output' of templates using ERB, Erubis, or HAML. Can handle automatic escaping
@@ -0,0 +1,112 @@
1
+ # Brakeman
2
+
3
+ Brakeman is a static analysis tool which checks Ruby on Rails applications for security vulnerabilities.
4
+
5
+ It targets Rails versions > 2.0 and < 3.0.
6
+
7
+ # Installation
8
+
9
+ gem build brakeman.gemspec
10
+ gem install brakeman*.gem
11
+
12
+ # Usage
13
+
14
+ brakeman path/to/rails/app/root
15
+
16
+ # Options
17
+
18
+ To specify an output file for the results:
19
+
20
+ brakeman -o output_file path/to/rails/app/root
21
+
22
+ The output format is determined by the file extension or by using the `-f` option. Current options are: `text`, `html`, and `csv`.
23
+
24
+ To suppress informational warnings and just output the report:
25
+
26
+ brakeman -q path/to/rails/app/root
27
+
28
+ To see all kinds of debugging information:
29
+
30
+ brakeman -d path/to/rails/app/root
31
+
32
+ Specific checks can be skipped, if desired. The name needs to be the correct case. For example, to skip looking for default routes (`DefaultRoutes`):
33
+
34
+ brakeman -x DefaultRoutes path/to/rails/app/root
35
+
36
+ Multiple checks should be separated by a comma:
37
+
38
+ brakeman -x DefaultRoutes,Redirect path/to/rails/app/root
39
+
40
+ To do the opposite and only run a certain set of tests:
41
+
42
+ brakeman -t SQL,ValidationRegex path/to/rails/app/root
43
+
44
+ To indicate certain methods are "safe":
45
+
46
+ brakeman -s benign_method,totally_safe path/to/rails/app/root
47
+
48
+ By default, brakeman will assume that unknown methods involving untrusted data are dangerous. For example, this would a warning:
49
+
50
+ <%= some_method(:option => params[:input]) %>
51
+
52
+ To only raise warnings only when untrusted data is being directly used:
53
+
54
+ brakeman -r path/to/rails/app/root
55
+
56
+ # Warning information
57
+
58
+ See WARNING_TYPES for more information on the warnings reported by this tool.
59
+
60
+ # Warning context
61
+
62
+ The HTML output format provides an excerpt from the original application source where a warning was triggered. Due to the processing done while looking for vulnerabilities, the source may not resemble the reported warning and reported line numbers may be slightly off. However, the context still provides a quick look into the code which raised the warning.
63
+
64
+ # Confidence levels
65
+
66
+ Brakeman assigns a confidence level to each warning. This provides a rough estimate of how certain the tool is that a given warning is actually a problem. Naturally, these ratings should not be taken as absolute truth.
67
+
68
+ There are three levels of confidence:
69
+
70
+ + High - Either this is a simple warning (boolean value) or user input is very likely being used in unsafe ways.
71
+ + Medium - This generally indicates an unsafe use of a variable, but the variable may or may not be user input.
72
+ + Weak - Typically means user input was indirectly used in a potentially unsafe manner.
73
+
74
+ To only get warnings above a given confidence level:
75
+
76
+ brakeman -w3 /path/to/rails/app/root
77
+
78
+ The `-w` switch takes a number from 1 to 3, with 1 being low (all warnings) and 3 being high (only high confidence warnings).
79
+
80
+ # Configuration files
81
+
82
+ Brakeman options can stored and read from YAML files. To simplify the process of writing a configuration file, the `-C` option will output the currently set options.
83
+
84
+ Options passed in on the commandline have priority over configuration files.
85
+
86
+ The default config locations are `./config.yaml`, `~/.brakeman/`, and `/etc/brakeman/config.yaml`
87
+
88
+ The `-c` option can be used to specify a configuration file to use.
89
+
90
+ # License
91
+
92
+ The MIT License
93
+
94
+ Copyright (c) 2010, YELLOWPAGES.COM, LLC
95
+
96
+ Permission is hereby granted, free of charge, to any person obtaining a copy
97
+ of this software and associated documentation files (the "Software"), to deal
98
+ in the Software without restriction, including without limitation the rights
99
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
100
+ copies of the Software, and to permit persons to whom the Software is
101
+ furnished to do so, subject to the following conditions:
102
+
103
+ The above copyright notice and this permission notice shall be included in
104
+ all copies or substantial portions of the Software.
105
+
106
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
107
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
108
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
109
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
110
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
111
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
112
+ THE SOFTWARE.
@@ -0,0 +1,69 @@
1
+ This file describes the various warning types reported by this tool.
2
+
3
+ # Cross Site Scripting
4
+
5
+ Cross site scripting warnings are raised when a parameter or model attribute is output through a view without being escaped.
6
+
7
+ See http://guides.rubyonrails.org/security.html#cross-site-scripting-xss for details.
8
+
9
+ # SQL Injection
10
+
11
+ String interpolation or concatenation has been detected in an SQL query. Use parameterized queries instead.
12
+
13
+ See http://guides.rubyonrails.org/security.html#sql-injection for details.
14
+
15
+ # Command Injection
16
+
17
+ Request parameters or string interpolation has been detected in a `system` call. This can lead to someone executing arbitrary commands. Use the safe form of `system` instead, which will pass in arguments safely.
18
+
19
+ See http://guides.rubyonrails.org/security.html#command-line-injection for details.
20
+
21
+ # Mass Assignment
22
+
23
+ Mass assignment is a method for initializing models. If the attributes which are set is not restricted, someone may set the attributes to any value they wish.
24
+
25
+ Mass assignment can be disabled globally.
26
+
27
+ Please see http://railspikes.com/2008/9/22/is-your-rails-application-safe-from-mass-assignment for more details.
28
+
29
+ # Attribute Restriction
30
+
31
+ This warning comes up if a model does not limit what attributes can be set through mass assignment.
32
+
33
+ In particular, this check looks for `attr_accessible` inside model definitions. If it is not found, this warning will be issued.
34
+
35
+ Note that disabling mass assignment globally will suppress these warnings.
36
+
37
+ # Cross-Site Request Forgery
38
+
39
+ No call to `protect_from_forgery` was found in `ApplicationController`. This method prevents CSRF.
40
+
41
+ See http://guides.rubyonrails.org/security.html#cross-site-request-forgery-csrf for details.
42
+
43
+ # Redirect
44
+
45
+ Redirects which rely on user-supplied values can be used to "spoof" websites or hide malicious links in otherwise harmless-looking URLs. They can also allow access to restricted areas of a site if the destination is not validated.
46
+
47
+ This warning is shown when request parameters are used inside a call to `redirect_to`.
48
+
49
+ See http://www.owasp.org/index.php/Top_10_2010-A10 for more information.
50
+
51
+ # Default Routes
52
+
53
+ The general default routes warning means there is a call to `map.connect ":controller/:action/:id"` in config/routes.rb. This allows any public method on any controller to be called as an action.
54
+
55
+ If this warning is reported for a particular controller, it means there is a route to that controller containing `:action`.
56
+
57
+ Default routes can be dangerous if methods are made public which are not intended to be used as URLs or actions.
58
+
59
+ # Format Validation
60
+
61
+ Calls to `validates_format_of ..., :with => //` which do not use `\A` and `\z` as anchors will cause this warning. Using `^` and `$` is not sufficient, as `$` will only match up to a new line. This allows an attacker to put whatever malicious input they would like after a new line character.
62
+
63
+ See http://guides.rubyonrails.org/security.html#regular-expressions for details.
64
+
65
+ # Dynamic Render Path
66
+
67
+ When a call to `render` uses a dynamically generated path, template name, file name, or action, there is the possibility that a user can access templates that should be restricted. The issue may be worse if those templates execute code or modify the database.
68
+
69
+ This warning is shown whenever the path to be rendered is not a static string or symbol.
@@ -0,0 +1,266 @@
1
+ #!/usr/bin/env ruby
2
+ require "optparse"
3
+ require 'set'
4
+ require 'yaml'
5
+
6
+ Version = "0.0.2"
7
+
8
+ trap("INT") do
9
+ $stderr.puts "\nInterrupted - exiting."
10
+ exit!
11
+ end
12
+
13
+ #Load scanner
14
+ begin
15
+ require 'scanner'
16
+ rescue LoadError
17
+ #Try to find lib directory locally
18
+ $: << "#{File.expand_path(File.dirname(__FILE__))}/../lib"
19
+
20
+ begin
21
+ require 'scanner'
22
+ rescue LoadError
23
+ abort "Cannot find lib/ directory."
24
+ end
25
+ end
26
+
27
+ #Parse command line options
28
+ options = {}
29
+
30
+ OptionParser.new do |opts|
31
+ opts.banner = "Usage: brakeman [options] rails/root/path"
32
+
33
+ opts.on "-p", "--path PATH", "Specify path to Rails application" do |path|
34
+ options[:app_path] = File.expand_path path
35
+ end
36
+
37
+ opts.on "-q", "--quiet", "Suppress informational messages" do
38
+ options[:quiet] = true
39
+ $VERBOSE = nil
40
+ end
41
+
42
+ opts.separator ""
43
+ opts.separator "Scanning options:"
44
+
45
+ opts.on "--ignore-model-output", "Consider model attributes XSS-safe" do
46
+ options[:ignore_model_output] = true
47
+ end
48
+
49
+ opts.on "-r", "--report-direct", "Only report direct use of untrusted data" do |option|
50
+ options[:check_arguments] = !option
51
+ end
52
+
53
+ opts.on "-s", "--safe-methods meth1,meth2,etc", Array, "Consider the specified methods safe" do |methods|
54
+ options[:safe_methods] ||= Set.new
55
+ options[:safe_methods].merge methods.map {|e| e.to_sym }
56
+ end
57
+
58
+ opts.on "-t", "--test Check1,Check2,etc", Array, "Only run the specified checks" do |checks|
59
+ checks.each_with_index do |s, index|
60
+ if s[0,5] != "Check"
61
+ checks[index] = "Check" << s
62
+ end
63
+ end
64
+
65
+ options[:run_checks] ||= Set.new
66
+ options[:run_checks].merge checks
67
+ end
68
+
69
+ opts.on "-x", "--except Check1,Check2,etc", Array, "Skip the specified checks" do |skip|
70
+ skip.each do |s|
71
+ if s[0,5] != "Check"
72
+ s = "Check" << s
73
+ end
74
+
75
+ options[:skip_checks] ||= Set.new
76
+ options[:skip_checks] << s
77
+ end
78
+ end
79
+
80
+ opts.separator ""
81
+ opts.separator "Output options:"
82
+
83
+ opts.on "-d", "--debug", "Lots of output" do
84
+ options[:debug] = true
85
+ end
86
+
87
+ opts.on "-f",
88
+ "--format TYPE",
89
+ [:pdf, :text, :html, :csv],
90
+ "Specify output format. Default is text" do |type|
91
+
92
+ type = "s" if type == :text
93
+ options[:output_format] = ("to_" << type.to_s).to_sym
94
+ end
95
+
96
+ opts.on "-l", "--[no]-combine-locations", "Combine warning locations (Default)" do |combine|
97
+ options[:combine_locations] = combine
98
+ end
99
+
100
+ opts.on "-m", "--routes", "Report controller information" do
101
+ options[:report_routes] = true
102
+ end
103
+
104
+ opts.on "--message-limit LENGTH", "Limit message length in HTML report" do |limit|
105
+ options[:message_limit] = limit.to_i
106
+ end
107
+
108
+ opts.on "-o", "--output FILE", "Specify file for output. Defaults to stdout" do |file|
109
+ options[:output_file] = file
110
+ end
111
+
112
+ opts.on "-w",
113
+ "--confidence-level LEVEL",
114
+ ["1", "2", "3"],
115
+ "Set minimal confidence level (1 - 3). Default: 1" do |level|
116
+
117
+ options[:min_confidence] = 3 - level.to_i
118
+ end
119
+
120
+ opts.separator ""
121
+ opts.separator "Configuration files:"
122
+
123
+ opts.on "-c", "--config-file FILE", "Use specified configuration file" do |file|
124
+ options[:config_file] = File.expand_path(file)
125
+ end
126
+
127
+ opts.on "-C", "--create-config [FILE]", "Output configuration file based on options" do |file|
128
+ if file
129
+ options[:create_config] = file
130
+ else
131
+ options[:create_config] = true
132
+ end
133
+ end
134
+
135
+ opts.separator ""
136
+
137
+ opts.on_tail "-h", "--help", "Display this message" do
138
+ puts opts
139
+ exit
140
+ end
141
+ end.parse!(ARGV)
142
+
143
+ #Load configuation file
144
+ [File.expand_path(options[:config_file].to_s),
145
+ File.expand_path("./config.yaml"),
146
+ File.expand_path("~/.brakeman/config.yaml"),
147
+ File.expand_path("/etc/brakeman/config.yaml"),
148
+ "#{File.expand_path(File.dirname(__FILE__))}/../lib/config.yaml"].each do |f|
149
+
150
+ if File.exist? f and not File.directory? f
151
+ warn "[Notice] Using configuration in #{f}" unless options[:quiet]
152
+ OPTIONS = YAML.load_file f
153
+ OPTIONS.merge! options
154
+ OPTIONS.each do |k,v|
155
+ if v.is_a? Array
156
+ OPTIONS[k] = Set.new v
157
+ end
158
+ end
159
+ break
160
+ end
161
+ end
162
+
163
+ OPTIONS = options unless defined? OPTIONS
164
+
165
+ #Set defaults just in case
166
+ { :skip_checks => Set.new,
167
+ :check_arguments => true,
168
+ :safe_methods => Set.new,
169
+ :min_confidence => 2,
170
+ :combine_locations => true,
171
+ :collapse_mass_assignment => true,
172
+ :ignore_redirect_to_model => true,
173
+ :ignore_model_output => false,
174
+ :message_limit => 100,
175
+ :html_style => "#{File.expand_path(File.dirname(__FILE__))}/../lib/format/style.css"
176
+ }.each do |k,v|
177
+ OPTIONS[k] = v if OPTIONS[k].nil?
178
+ end
179
+
180
+
181
+ #Set output format
182
+ if OPTIONS[:output_format]
183
+ case OPTIONS[:output_format]
184
+ when :html, :to_html
185
+ OPTIONS[:output_format] = :to_html
186
+ when :csv, :to_csv
187
+ OPTIONS[:output_format] = :to_csv
188
+ when :pdf, :to_pdf
189
+ OPTIONS[:output_format] = :to_pdf
190
+ else
191
+ OPTIONS[:output_format] = :to_s
192
+ end
193
+ else
194
+ case OPTIONS[:output_file]
195
+ when /\.html$/i
196
+ OPTIONS[:output_format] = :to_html
197
+ when /\.csv$/i
198
+ OPTIONS[:output_format] = :to_csv
199
+ when /\.pdf$/i
200
+ OPTIONS[:output_format] = :to_pdf
201
+ else
202
+ OPTIONS[:output_format] = :to_s
203
+ end
204
+ end
205
+
206
+ #Output configuration if requested
207
+ if OPTIONS[:create_config]
208
+
209
+ if OPTIONS[:create_config].is_a? String
210
+ file = OPTIONS[:create_config]
211
+ else
212
+ file = nil
213
+ end
214
+
215
+ OPTIONS.delete :create_config
216
+
217
+ OPTIONS.each do |k,v|
218
+ if v.is_a? Set
219
+ OPTIONS[k] = v.to_a
220
+ end
221
+ end
222
+
223
+ if file
224
+ File.open file, "w" do |f|
225
+ YAML.dump OPTIONS, f
226
+ end
227
+ puts "Output configuration to #{file}"
228
+ else
229
+ puts YAML.dump(OPTIONS)
230
+ end
231
+ exit
232
+ end
233
+
234
+
235
+ #Check application path
236
+ unless OPTIONS[:app_path]
237
+ if ARGV[-1].nil?
238
+ OPTIONS[:app_path] = File.expand_path "."
239
+ else
240
+ OPTIONS[:app_path] = File.expand_path ARGV[-1]
241
+ end
242
+ end
243
+
244
+ app_path = OPTIONS[:app_path]
245
+
246
+ abort("Please supply the path to a Rails application.") unless app_path and File.exist? app_path + "/app"
247
+
248
+ warn "[Notice] Using Ruby #{RUBY_VERSION}. Please make sure this matches the one used to run your Rails application."
249
+
250
+ #Start scanning
251
+ scanner = Scanner.new app_path
252
+
253
+ warn "Processing application in #{app_path}"
254
+ tracker = scanner.process
255
+
256
+ warn "Running checks..."
257
+ tracker.run_checks
258
+
259
+ warn "Generating report..."
260
+ if OPTIONS[:output_file]
261
+ File.open OPTIONS[:output_file], "w" do |f|
262
+ f.puts tracker.report.send(OPTIONS[:output_format])
263
+ end
264
+ else
265
+ puts tracker.report.send(OPTIONS[:output_format])
266
+ end