railroader 4.3.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (165) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES.md +1091 -0
  3. data/FEATURES +16 -0
  4. data/README.md +174 -0
  5. data/bin/railroader +8 -0
  6. data/lib/railroader/app_tree.rb +191 -0
  7. data/lib/railroader/call_index.rb +219 -0
  8. data/lib/railroader/checks/base_check.rb +505 -0
  9. data/lib/railroader/checks/check_basic_auth.rb +88 -0
  10. data/lib/railroader/checks/check_basic_auth_timing_attack.rb +33 -0
  11. data/lib/railroader/checks/check_content_tag.rb +200 -0
  12. data/lib/railroader/checks/check_create_with.rb +74 -0
  13. data/lib/railroader/checks/check_cross_site_scripting.rb +381 -0
  14. data/lib/railroader/checks/check_default_routes.rb +86 -0
  15. data/lib/railroader/checks/check_deserialize.rb +56 -0
  16. data/lib/railroader/checks/check_detailed_exceptions.rb +55 -0
  17. data/lib/railroader/checks/check_digest_dos.rb +38 -0
  18. data/lib/railroader/checks/check_divide_by_zero.rb +42 -0
  19. data/lib/railroader/checks/check_dynamic_finders.rb +48 -0
  20. data/lib/railroader/checks/check_escape_function.rb +21 -0
  21. data/lib/railroader/checks/check_evaluation.rb +35 -0
  22. data/lib/railroader/checks/check_execute.rb +189 -0
  23. data/lib/railroader/checks/check_file_access.rb +71 -0
  24. data/lib/railroader/checks/check_file_disclosure.rb +35 -0
  25. data/lib/railroader/checks/check_filter_skipping.rb +31 -0
  26. data/lib/railroader/checks/check_forgery_setting.rb +81 -0
  27. data/lib/railroader/checks/check_header_dos.rb +31 -0
  28. data/lib/railroader/checks/check_i18n_xss.rb +48 -0
  29. data/lib/railroader/checks/check_jruby_xml.rb +36 -0
  30. data/lib/railroader/checks/check_json_encoding.rb +47 -0
  31. data/lib/railroader/checks/check_json_parsing.rb +107 -0
  32. data/lib/railroader/checks/check_link_to.rb +132 -0
  33. data/lib/railroader/checks/check_link_to_href.rb +146 -0
  34. data/lib/railroader/checks/check_mail_to.rb +49 -0
  35. data/lib/railroader/checks/check_mass_assignment.rb +196 -0
  36. data/lib/railroader/checks/check_mime_type_dos.rb +39 -0
  37. data/lib/railroader/checks/check_model_attr_accessible.rb +55 -0
  38. data/lib/railroader/checks/check_model_attributes.rb +119 -0
  39. data/lib/railroader/checks/check_model_serialize.rb +67 -0
  40. data/lib/railroader/checks/check_nested_attributes.rb +38 -0
  41. data/lib/railroader/checks/check_nested_attributes_bypass.rb +58 -0
  42. data/lib/railroader/checks/check_number_to_currency.rb +74 -0
  43. data/lib/railroader/checks/check_permit_attributes.rb +43 -0
  44. data/lib/railroader/checks/check_quote_table_name.rb +40 -0
  45. data/lib/railroader/checks/check_redirect.rb +256 -0
  46. data/lib/railroader/checks/check_regex_dos.rb +68 -0
  47. data/lib/railroader/checks/check_render.rb +97 -0
  48. data/lib/railroader/checks/check_render_dos.rb +37 -0
  49. data/lib/railroader/checks/check_render_inline.rb +53 -0
  50. data/lib/railroader/checks/check_response_splitting.rb +21 -0
  51. data/lib/railroader/checks/check_route_dos.rb +42 -0
  52. data/lib/railroader/checks/check_safe_buffer_manipulation.rb +31 -0
  53. data/lib/railroader/checks/check_sanitize_methods.rb +112 -0
  54. data/lib/railroader/checks/check_secrets.rb +40 -0
  55. data/lib/railroader/checks/check_select_tag.rb +59 -0
  56. data/lib/railroader/checks/check_select_vulnerability.rb +60 -0
  57. data/lib/railroader/checks/check_send.rb +47 -0
  58. data/lib/railroader/checks/check_send_file.rb +19 -0
  59. data/lib/railroader/checks/check_session_manipulation.rb +35 -0
  60. data/lib/railroader/checks/check_session_settings.rb +176 -0
  61. data/lib/railroader/checks/check_simple_format.rb +58 -0
  62. data/lib/railroader/checks/check_single_quotes.rb +101 -0
  63. data/lib/railroader/checks/check_skip_before_filter.rb +60 -0
  64. data/lib/railroader/checks/check_sql.rb +700 -0
  65. data/lib/railroader/checks/check_sql_cves.rb +106 -0
  66. data/lib/railroader/checks/check_ssl_verify.rb +48 -0
  67. data/lib/railroader/checks/check_strip_tags.rb +89 -0
  68. data/lib/railroader/checks/check_symbol_dos.rb +71 -0
  69. data/lib/railroader/checks/check_symbol_dos_cve.rb +30 -0
  70. data/lib/railroader/checks/check_translate_bug.rb +45 -0
  71. data/lib/railroader/checks/check_unsafe_reflection.rb +50 -0
  72. data/lib/railroader/checks/check_unscoped_find.rb +57 -0
  73. data/lib/railroader/checks/check_validation_regex.rb +116 -0
  74. data/lib/railroader/checks/check_weak_hash.rb +148 -0
  75. data/lib/railroader/checks/check_without_protection.rb +80 -0
  76. data/lib/railroader/checks/check_xml_dos.rb +45 -0
  77. data/lib/railroader/checks/check_yaml_parsing.rb +121 -0
  78. data/lib/railroader/checks.rb +209 -0
  79. data/lib/railroader/codeclimate/engine_configuration.rb +97 -0
  80. data/lib/railroader/commandline.rb +179 -0
  81. data/lib/railroader/differ.rb +66 -0
  82. data/lib/railroader/file_parser.rb +54 -0
  83. data/lib/railroader/format/style.css +133 -0
  84. data/lib/railroader/options.rb +339 -0
  85. data/lib/railroader/parsers/rails2_erubis.rb +6 -0
  86. data/lib/railroader/parsers/rails2_xss_plugin_erubis.rb +48 -0
  87. data/lib/railroader/parsers/rails3_erubis.rb +81 -0
  88. data/lib/railroader/parsers/template_parser.rb +108 -0
  89. data/lib/railroader/processor.rb +102 -0
  90. data/lib/railroader/processors/alias_processor.rb +1229 -0
  91. data/lib/railroader/processors/base_processor.rb +295 -0
  92. data/lib/railroader/processors/config_processor.rb +14 -0
  93. data/lib/railroader/processors/controller_alias_processor.rb +278 -0
  94. data/lib/railroader/processors/controller_processor.rb +249 -0
  95. data/lib/railroader/processors/erb_template_processor.rb +77 -0
  96. data/lib/railroader/processors/erubis_template_processor.rb +92 -0
  97. data/lib/railroader/processors/gem_processor.rb +64 -0
  98. data/lib/railroader/processors/haml_template_processor.rb +191 -0
  99. data/lib/railroader/processors/lib/basic_processor.rb +37 -0
  100. data/lib/railroader/processors/lib/call_conversion_helper.rb +90 -0
  101. data/lib/railroader/processors/lib/find_all_calls.rb +224 -0
  102. data/lib/railroader/processors/lib/find_call.rb +183 -0
  103. data/lib/railroader/processors/lib/find_return_value.rb +166 -0
  104. data/lib/railroader/processors/lib/module_helper.rb +111 -0
  105. data/lib/railroader/processors/lib/processor_helper.rb +88 -0
  106. data/lib/railroader/processors/lib/rails2_config_processor.rb +145 -0
  107. data/lib/railroader/processors/lib/rails2_route_processor.rb +313 -0
  108. data/lib/railroader/processors/lib/rails3_config_processor.rb +132 -0
  109. data/lib/railroader/processors/lib/rails3_route_processor.rb +308 -0
  110. data/lib/railroader/processors/lib/render_helper.rb +181 -0
  111. data/lib/railroader/processors/lib/render_path.rb +107 -0
  112. data/lib/railroader/processors/lib/route_helper.rb +68 -0
  113. data/lib/railroader/processors/lib/safe_call_helper.rb +16 -0
  114. data/lib/railroader/processors/library_processor.rb +74 -0
  115. data/lib/railroader/processors/model_processor.rb +91 -0
  116. data/lib/railroader/processors/output_processor.rb +144 -0
  117. data/lib/railroader/processors/route_processor.rb +17 -0
  118. data/lib/railroader/processors/slim_template_processor.rb +111 -0
  119. data/lib/railroader/processors/template_alias_processor.rb +118 -0
  120. data/lib/railroader/processors/template_processor.rb +85 -0
  121. data/lib/railroader/report/config/remediation.yml +71 -0
  122. data/lib/railroader/report/ignore/config.rb +153 -0
  123. data/lib/railroader/report/ignore/interactive.rb +362 -0
  124. data/lib/railroader/report/pager.rb +112 -0
  125. data/lib/railroader/report/renderer.rb +24 -0
  126. data/lib/railroader/report/report_base.rb +292 -0
  127. data/lib/railroader/report/report_codeclimate.rb +79 -0
  128. data/lib/railroader/report/report_csv.rb +55 -0
  129. data/lib/railroader/report/report_hash.rb +23 -0
  130. data/lib/railroader/report/report_html.rb +216 -0
  131. data/lib/railroader/report/report_json.rb +45 -0
  132. data/lib/railroader/report/report_markdown.rb +107 -0
  133. data/lib/railroader/report/report_table.rb +117 -0
  134. data/lib/railroader/report/report_tabs.rb +17 -0
  135. data/lib/railroader/report/report_text.rb +198 -0
  136. data/lib/railroader/report/templates/controller_overview.html.erb +22 -0
  137. data/lib/railroader/report/templates/controller_warnings.html.erb +21 -0
  138. data/lib/railroader/report/templates/error_overview.html.erb +29 -0
  139. data/lib/railroader/report/templates/header.html.erb +58 -0
  140. data/lib/railroader/report/templates/ignored_warnings.html.erb +25 -0
  141. data/lib/railroader/report/templates/model_warnings.html.erb +21 -0
  142. data/lib/railroader/report/templates/overview.html.erb +38 -0
  143. data/lib/railroader/report/templates/security_warnings.html.erb +23 -0
  144. data/lib/railroader/report/templates/template_overview.html.erb +21 -0
  145. data/lib/railroader/report/templates/view_warnings.html.erb +34 -0
  146. data/lib/railroader/report/templates/warning_overview.html.erb +17 -0
  147. data/lib/railroader/report.rb +88 -0
  148. data/lib/railroader/rescanner.rb +483 -0
  149. data/lib/railroader/scanner.rb +321 -0
  150. data/lib/railroader/tracker/collection.rb +93 -0
  151. data/lib/railroader/tracker/config.rb +154 -0
  152. data/lib/railroader/tracker/constants.rb +171 -0
  153. data/lib/railroader/tracker/controller.rb +161 -0
  154. data/lib/railroader/tracker/library.rb +17 -0
  155. data/lib/railroader/tracker/model.rb +90 -0
  156. data/lib/railroader/tracker/template.rb +33 -0
  157. data/lib/railroader/tracker.rb +362 -0
  158. data/lib/railroader/util.rb +503 -0
  159. data/lib/railroader/version.rb +3 -0
  160. data/lib/railroader/warning.rb +294 -0
  161. data/lib/railroader/warning_codes.rb +117 -0
  162. data/lib/railroader.rb +544 -0
  163. data/lib/ruby_parser/bm_sexp.rb +626 -0
  164. data/lib/ruby_parser/bm_sexp_processor.rb +116 -0
  165. metadata +386 -0
@@ -0,0 +1,321 @@
1
+ begin
2
+ Railroader.load_railroader_dependency 'ruby_parser'
3
+ require 'ruby_parser/bm_sexp.rb'
4
+ require 'ruby_parser/bm_sexp_processor.rb'
5
+ require 'railroader/processor'
6
+ require 'railroader/app_tree'
7
+ require 'railroader/file_parser'
8
+ require 'railroader/parsers/template_parser'
9
+ rescue LoadError => e
10
+ $stderr.puts e.message
11
+ $stderr.puts "Please install the appropriate dependency."
12
+ exit(-1)
13
+ end
14
+
15
+ #Scans the Rails application.
16
+ class Railroader::Scanner
17
+ attr_reader :options
18
+ RUBY_1_9 = RUBY_VERSION >= "1.9.0"
19
+
20
+ #Pass in path to the root of the Rails application
21
+ def initialize options, processor = nil
22
+ @options = options
23
+ @app_tree = Railroader::AppTree.from_options(options)
24
+
25
+ if (!@app_tree.root || !@app_tree.exists?("app")) && !options[:force_scan]
26
+ raise Railroader::NoApplication, "Please supply the path to a Rails application (looking in #{@app_tree.root})."
27
+ end
28
+
29
+ @processor = processor || Railroader::Processor.new(@app_tree, options)
30
+ end
31
+
32
+ #Returns the Tracker generated from the scan
33
+ def tracker
34
+ @processor.tracked_events
35
+ end
36
+
37
+ #Process everything in the Rails application
38
+ def process
39
+ Railroader.notify "Processing gems..."
40
+ process_gems
41
+ guess_rails_version
42
+ Railroader.notify "Processing configuration..."
43
+ process_config
44
+ Railroader.notify "Parsing files..."
45
+ parse_files
46
+ Railroader.notify "Processing initializers..."
47
+ process_initializers
48
+ Railroader.notify "Processing libs..."
49
+ process_libs
50
+ Railroader.notify "Processing routes... "
51
+ process_routes
52
+ Railroader.notify "Processing templates... "
53
+ process_templates
54
+ Railroader.notify "Processing data flow in templates..."
55
+ process_template_data_flows
56
+ Railroader.notify "Processing models... "
57
+ process_models
58
+ Railroader.notify "Processing controllers... "
59
+ process_controllers
60
+ Railroader.notify "Processing data flow in controllers..."
61
+ process_controller_data_flows
62
+ Railroader.notify "Indexing call sites... "
63
+ index_call_sites
64
+ tracker
65
+ end
66
+
67
+ def parse_files
68
+ fp = Railroader::FileParser.new tracker, @app_tree
69
+
70
+ files = {
71
+ :initializers => @app_tree.initializer_paths,
72
+ :controllers => @app_tree.controller_paths,
73
+ :models => @app_tree.model_paths
74
+ }
75
+
76
+ unless options[:skip_libs]
77
+ files[:libs] = @app_tree.lib_paths
78
+ end
79
+
80
+ files.each do |name, paths|
81
+ fp.parse_files paths, name
82
+ end
83
+
84
+ template_parser = Railroader::TemplateParser.new(tracker, fp)
85
+
86
+ fp.read_files(@app_tree.template_paths, :templates) do |path, contents|
87
+ template_parser.parse_template path, contents
88
+ end
89
+
90
+ @file_list = fp.file_list
91
+ end
92
+
93
+ #Process config/environment.rb and config/gems.rb
94
+ #
95
+ #Stores parsed information in tracker.config
96
+ def process_config
97
+ if options[:rails3] or options[:rails4] or options[:rails5]
98
+ process_config_file "application.rb"
99
+ process_config_file "environments/production.rb"
100
+ else
101
+ process_config_file "environment.rb"
102
+ process_config_file "gems.rb"
103
+ end
104
+
105
+ if @app_tree.exists?("vendor/plugins/rails_xss") or
106
+ options[:rails3] or options[:escape_html]
107
+
108
+ tracker.config.escape_html = true
109
+ Railroader.notify "[Notice] Escaping HTML by default"
110
+ end
111
+
112
+ if @app_tree.exists? ".ruby-version"
113
+ tracker.config.set_ruby_version @app_tree.read ".ruby-version"
114
+ end
115
+ end
116
+
117
+ def process_config_file file
118
+ path = "config/#{file}"
119
+
120
+ if @app_tree.exists?(path)
121
+ @processor.process_config(parse_ruby(@app_tree.read(path)), path)
122
+ end
123
+
124
+ rescue => e
125
+ Railroader.notify "[Notice] Error while processing #{path}"
126
+ tracker.error e.exception(e.message + "\nwhile processing #{path}"), e.backtrace
127
+ end
128
+
129
+ private :process_config_file
130
+
131
+ #Process Gemfile
132
+ def process_gems
133
+ gem_files = {}
134
+ if @app_tree.exists? "Gemfile"
135
+ gem_files[:gemfile] = { :src => parse_ruby(@app_tree.read("Gemfile")), :file => "Gemfile" }
136
+ elsif @app_tree.exists? "gems.rb"
137
+ gem_files[:gemfile] = { :src => parse_ruby(@app_tree.read("gems.rb")), :file => "gems.rb" }
138
+ end
139
+
140
+ if @app_tree.exists? "Gemfile.lock"
141
+ gem_files[:gemlock] = { :src => @app_tree.read("Gemfile.lock"), :file => "Gemfile.lock" }
142
+ elsif @app_tree.exists? "gems.locked"
143
+ gem_files[:gemlock] = { :src => @app_tree.read("gems.locked"), :file => "gems.locked" }
144
+ end
145
+
146
+ if gem_files[:gemfile] or gem_files[:gemlock]
147
+ @processor.process_gems gem_files
148
+ end
149
+ rescue => e
150
+ Railroader.notify "[Notice] Error while processing Gemfile."
151
+ tracker.error e.exception(e.message + "\nWhile processing Gemfile"), e.backtrace
152
+ end
153
+
154
+ #Set :rails3/:rails4 option if version was not determined from Gemfile
155
+ def guess_rails_version
156
+ unless tracker.options[:rails3] or tracker.options[:rails4]
157
+ if @app_tree.exists?("script/rails")
158
+ tracker.options[:rails3] = true
159
+ Railroader.notify "[Notice] Detected Rails 3 application"
160
+ elsif @app_tree.exists?("app/channels")
161
+ tracker.options[:rails3] = true
162
+ tracker.options[:rails4] = true
163
+ tracker.options[:rails5] = true
164
+ Railroader.notify "[Notice] Detected Rails 5 application"
165
+ elsif not @app_tree.exists?("script")
166
+ tracker.options[:rails3] = true
167
+ tracker.options[:rails4] = true
168
+ Railroader.notify "[Notice] Detected Rails 4 application"
169
+ end
170
+ end
171
+ end
172
+
173
+ #Process all the .rb files in config/initializers/
174
+ #
175
+ #Adds parsed information to tracker.initializers
176
+ def process_initializers
177
+ track_progress @file_list[:initializers] do |init|
178
+ Railroader.debug "Processing #{init[:path]}"
179
+ process_initializer init
180
+ end
181
+ end
182
+
183
+ #Process an initializer
184
+ def process_initializer init
185
+ @processor.process_initializer(init.path, init.ast)
186
+ end
187
+
188
+ #Process all .rb in lib/
189
+ #
190
+ #Adds parsed information to tracker.libs.
191
+ def process_libs
192
+ if options[:skip_libs]
193
+ Railroader.notify '[Skipping]'
194
+ return
195
+ end
196
+
197
+ track_progress @file_list[:libs] do |lib|
198
+ Railroader.debug "Processing #{lib.path}"
199
+ process_lib lib
200
+ end
201
+ end
202
+
203
+ #Process a library
204
+ def process_lib lib
205
+ @processor.process_lib lib.ast, lib.path
206
+ end
207
+
208
+ #Process config/routes.rb
209
+ #
210
+ #Adds parsed information to tracker.routes
211
+ def process_routes
212
+ if @app_tree.exists?("config/routes.rb")
213
+ begin
214
+ @processor.process_routes parse_ruby(@app_tree.read("config/routes.rb"))
215
+ rescue => e
216
+ tracker.error e.exception(e.message + "\nWhile processing routes.rb"), e.backtrace
217
+ Railroader.notify "[Notice] Error while processing routes - assuming all public controller methods are actions."
218
+ options[:assume_all_routes] = true
219
+ end
220
+ else
221
+ Railroader.notify "[Notice] No route information found"
222
+ end
223
+ end
224
+
225
+ #Process all .rb files in controllers/
226
+ #
227
+ #Adds processed controllers to tracker.controllers
228
+ def process_controllers
229
+ track_progress @file_list[:controllers] do |controller|
230
+ Railroader.debug "Processing #{controller.path}"
231
+ process_controller controller
232
+ end
233
+ end
234
+
235
+ def process_controller_data_flows
236
+ controllers = tracker.controllers.sort_by { |name, _| name.to_s }
237
+
238
+ track_progress controllers, "controllers" do |name, controller|
239
+ Railroader.debug "Processing #{name}"
240
+ controller.src.each do |file, src|
241
+ @processor.process_controller_alias name, src, nil, file
242
+ end
243
+ end
244
+
245
+ #No longer need these processed filter methods
246
+ tracker.filter_cache.clear
247
+ end
248
+
249
+ def process_controller astfile
250
+ begin
251
+ @processor.process_controller(astfile.ast, astfile.path)
252
+ rescue => e
253
+ tracker.error e.exception(e.message + "\nWhile processing #{astfile.path}"), e.backtrace
254
+ end
255
+ end
256
+
257
+ #Process all views and partials in views/
258
+ #
259
+ #Adds processed views to tracker.views
260
+ def process_templates
261
+ templates = @file_list[:templates].sort_by { |t| t[:path] }
262
+
263
+ track_progress templates, "templates" do |template|
264
+ Railroader.debug "Processing #{template[:path]}"
265
+ process_template template
266
+ end
267
+ end
268
+
269
+ def process_template template
270
+ @processor.process_template(template.name, template.ast, template.type, nil, template.path)
271
+ end
272
+
273
+ def process_template_data_flows
274
+ templates = tracker.templates.sort_by { |name, _| name.to_s }
275
+
276
+ track_progress templates, "templates" do |name, template|
277
+ Railroader.debug "Processing #{name}"
278
+ @processor.process_template_alias template
279
+ end
280
+ end
281
+
282
+ #Process all the .rb files in models/
283
+ #
284
+ #Adds the processed models to tracker.models
285
+ def process_models
286
+ track_progress @file_list[:models] do |model|
287
+ Railroader.debug "Processing #{model[:path]}"
288
+ process_model model[:path], model[:ast]
289
+ end
290
+ end
291
+
292
+ def process_model path, ast
293
+ @processor.process_model(ast, path)
294
+ end
295
+
296
+ def track_progress list, type = "files"
297
+ total = list.length
298
+ current = 0
299
+ list.each do |item|
300
+ report_progress current, total, type
301
+ current += 1
302
+ yield item
303
+ end
304
+ end
305
+
306
+ def report_progress(current, total, type = "files")
307
+ return unless @options[:report_progress]
308
+ $stderr.print " #{current}/#{total} #{type} processed\r"
309
+ end
310
+
311
+ def index_call_sites
312
+ tracker.index_call_sites
313
+ end
314
+
315
+ def parse_ruby input
316
+ RubyParser.new.parse input
317
+ end
318
+ end
319
+
320
+ # This is to allow operation without loading the Haml library
321
+ module Haml; class Error < StandardError; end; end
@@ -0,0 +1,93 @@
1
+ require 'railroader/util'
2
+
3
+ module Railroader
4
+ class Collection
5
+ include Railroader::Util
6
+
7
+ attr_reader :collection, :files, :includes, :name, :options, :parent, :src, :tracker
8
+
9
+ def initialize name, parent, file_name, src, tracker
10
+ @name = name
11
+ @parent = parent
12
+ @file_name = file_name
13
+ @files = [ file_name ]
14
+ @src = { file_name => src }
15
+ @includes = []
16
+ @methods = { :public => {}, :private => {}, :protected => {} }
17
+ @options = {}
18
+ @tracker = tracker
19
+ end
20
+
21
+ def ancestor? parent, seen={}
22
+ seen[self.name] = true
23
+
24
+ if self.parent == parent or seen[self.parent]
25
+ true
26
+ elsif parent_model = collection[self.parent]
27
+ parent_model.ancestor? parent, seen
28
+ else
29
+ false
30
+ end
31
+ end
32
+
33
+ def add_file file_name, src
34
+ @files << file_name unless @files.include? file_name
35
+ @src[file_name] = src
36
+ end
37
+
38
+ def add_include class_name
39
+ @includes << class_name
40
+ end
41
+
42
+ def add_option name, exp
43
+ @options[name] ||= []
44
+ @options[name] << exp
45
+ end
46
+
47
+ def add_method visibility, name, src, file_name
48
+ if src.node_type == :defs
49
+ name = :"#{src[1]}.#{name}"
50
+ end
51
+
52
+ @methods[visibility][name] = { :src => src, :file => file_name }
53
+ end
54
+
55
+ def each_method
56
+ @methods.each do |_vis, meths|
57
+ meths.each do |name, info|
58
+ yield name, info
59
+ end
60
+ end
61
+ end
62
+
63
+ def get_method name
64
+ each_method do |n, info|
65
+ if n == name
66
+ return info
67
+ end
68
+ end
69
+
70
+ nil
71
+ end
72
+
73
+ def file
74
+ @files.first
75
+ end
76
+
77
+ def top_line
78
+ if sexp? @src[file]
79
+ @src[file].line
80
+ else
81
+ @src.each_value do |source|
82
+ if sexp? source
83
+ return source.line
84
+ end
85
+ end
86
+ end
87
+ end
88
+
89
+ def methods_public
90
+ @methods[:public]
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,154 @@
1
+ require 'railroader/util'
2
+
3
+ module Railroader
4
+ class Config
5
+ include Util
6
+
7
+ attr_reader :rails, :tracker
8
+ attr_accessor :rails_version, :ruby_version
9
+ attr_writer :erubis, :escape_html
10
+ attr_reader :gems
11
+
12
+ def initialize tracker
13
+ @tracker = tracker
14
+ @rails = {}
15
+ @gems = {}
16
+ @settings = {}
17
+ @escape_html = nil
18
+ @erubis = nil
19
+ @ruby_version = ""
20
+ end
21
+
22
+ def allow_forgery_protection?
23
+ @rails[:action_controller] and
24
+ @rails[:action_controller][:allow_forgery_protection] == Sexp.new(:false)
25
+ end
26
+
27
+ def default_protect_from_forgery?
28
+ if version_between? "5.2.0", "9.9.9"
29
+ if @rails[:action_controller] and
30
+ @rails[:action_controller][:default_protect_from_forgery] == Sexp.new(:false)
31
+
32
+ return false
33
+ else
34
+ return true
35
+ end
36
+ end
37
+
38
+ false
39
+ end
40
+
41
+ def erubis?
42
+ @erubis
43
+ end
44
+
45
+ def escape_html?
46
+ @escape_html
47
+ end
48
+
49
+ def escape_html_entities_in_json?
50
+ #TODO add version-specific information here
51
+ @rails[:active_support] and
52
+ true? @rails[:active_support][:escape_html_entities_in_json]
53
+ end
54
+
55
+ def whitelist_attributes?
56
+ @rails[:active_record] and
57
+ @rails[:active_record][:whitelist_attributes] == Sexp.new(:true)
58
+ end
59
+
60
+ def gem_version name
61
+ @gems[name] and @gems[name][:version]
62
+ end
63
+
64
+ def add_gem name, version, file, line
65
+ name = name.to_sym
66
+ @gems[name] = {
67
+ :version => version,
68
+ :file => file,
69
+ :line => line
70
+ }
71
+ end
72
+
73
+ def has_gem? name
74
+ !!@gems[name]
75
+ end
76
+
77
+ def get_gem name
78
+ @gems[name]
79
+ end
80
+
81
+ def set_rails_version
82
+ # Ignore ~>, etc. when using values from Gemfile
83
+ version = gem_version(:rails) || gem_version(:railties)
84
+ if version and version.match(/(\d+\.\d+\.\d+.*)/)
85
+ @rails_version = $1
86
+
87
+ if tracker.options[:rails3].nil? and tracker.options[:rails4].nil?
88
+ if @rails_version.start_with? "3"
89
+ tracker.options[:rails3] = true
90
+ Railroader.notify "[Notice] Detected Rails 3 application"
91
+ elsif @rails_version.start_with? "4"
92
+ tracker.options[:rails3] = true
93
+ tracker.options[:rails4] = true
94
+ Railroader.notify "[Notice] Detected Rails 4 application"
95
+ elsif @rails_version.start_with? "5"
96
+ tracker.options[:rails3] = true
97
+ tracker.options[:rails4] = true
98
+ tracker.options[:rails5] = true
99
+ Railroader.notify "[Notice] Detected Rails 5 application"
100
+ end
101
+ end
102
+ end
103
+
104
+ if get_gem :rails_xss
105
+ @escape_html = true
106
+ Railroader.notify "[Notice] Escaping HTML by default"
107
+ end
108
+ end
109
+
110
+ def set_ruby_version version
111
+ return unless version.is_a? String
112
+
113
+ if version =~ /(\d+\.\d+\.\d+)/
114
+ self.ruby_version = $1
115
+ end
116
+ end
117
+
118
+ #Returns true if low_version <= RAILS_VERSION <= high_version
119
+ #
120
+ #If the Rails version is unknown, returns false.
121
+ def version_between? low_version, high_version, current_version = nil
122
+ current_version ||= rails_version
123
+ return false unless current_version
124
+
125
+ version = current_version.split(".").map!(&:to_i)
126
+ low_version = low_version.split(".").map!(&:to_i)
127
+ high_version = high_version.split(".").map!(&:to_i)
128
+
129
+ version.each_with_index do |v, i|
130
+ if v < low_version.fetch(i, 0)
131
+ return false
132
+ elsif v > low_version.fetch(i, 0)
133
+ break
134
+ end
135
+ end
136
+
137
+ version.each_with_index do |v, i|
138
+ if v > high_version.fetch(i, 0)
139
+ return false
140
+ elsif v < high_version.fetch(i, 0)
141
+ break
142
+ end
143
+ end
144
+
145
+ true
146
+ end
147
+
148
+ def session_settings
149
+ @rails[:action_controller] &&
150
+ @rails[:action_controller][:session]
151
+ end
152
+
153
+ end
154
+ end