railroader 4.3.5 → 4.3.7
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 +4 -4
- data/CHANGES.md +16 -0
- data/README.md +15 -0
- data/bin/railroader +1 -1
- data/lib/railroader/call_index.rb +11 -11
- data/lib/railroader/checks/base_check.rb +43 -43
- data/lib/railroader/checks/check_basic_auth.rb +3 -3
- data/lib/railroader/checks/check_content_tag.rb +9 -9
- data/lib/railroader/checks/check_create_with.rb +2 -2
- data/lib/railroader/checks/check_cross_site_scripting.rb +24 -24
- data/lib/railroader/checks/check_default_routes.rb +5 -5
- data/lib/railroader/checks/check_deserialize.rb +1 -1
- data/lib/railroader/checks/check_dynamic_finders.rb +1 -1
- data/lib/railroader/checks/check_escape_function.rb +3 -3
- data/lib/railroader/checks/check_evaluation.rb +4 -4
- data/lib/railroader/checks/check_execute.rb +8 -8
- data/lib/railroader/checks/check_file_access.rb +2 -2
- data/lib/railroader/checks/check_filter_skipping.rb +2 -2
- data/lib/railroader/checks/check_forgery_setting.rb +3 -3
- data/lib/railroader/checks/check_jruby_xml.rb +1 -1
- data/lib/railroader/checks/check_json_parsing.rb +2 -2
- data/lib/railroader/checks/check_link_to.rb +12 -12
- data/lib/railroader/checks/check_link_to_href.rb +9 -9
- data/lib/railroader/checks/check_mail_to.rb +4 -4
- data/lib/railroader/checks/check_mass_assignment.rb +5 -5
- data/lib/railroader/checks/check_model_attributes.rb +6 -6
- data/lib/railroader/checks/check_model_serialize.rb +2 -2
- data/lib/railroader/checks/check_nested_attributes.rb +2 -2
- data/lib/railroader/checks/check_nested_attributes_bypass.rb +1 -1
- data/lib/railroader/checks/check_quote_table_name.rb +3 -3
- data/lib/railroader/checks/check_redirect.rb +19 -19
- data/lib/railroader/checks/check_regex_dos.rb +3 -3
- data/lib/railroader/checks/check_render.rb +4 -4
- data/lib/railroader/checks/check_response_splitting.rb +2 -2
- data/lib/railroader/checks/check_safe_buffer_manipulation.rb +4 -4
- data/lib/railroader/checks/check_sanitize_methods.rb +2 -2
- data/lib/railroader/checks/check_select_tag.rb +4 -4
- data/lib/railroader/checks/check_select_vulnerability.rb +3 -3
- data/lib/railroader/checks/check_send.rb +1 -1
- data/lib/railroader/checks/check_send_file.rb +1 -1
- data/lib/railroader/checks/check_session_settings.rb +10 -10
- data/lib/railroader/checks/check_single_quotes.rb +8 -8
- data/lib/railroader/checks/check_skip_before_filter.rb +5 -5
- data/lib/railroader/checks/check_sql.rb +41 -41
- data/lib/railroader/checks/check_strip_tags.rb +6 -6
- data/lib/railroader/checks/check_symbol_dos_cve.rb +0 -1
- data/lib/railroader/checks/check_translate_bug.rb +4 -4
- data/lib/railroader/checks/check_unsafe_reflection.rb +1 -1
- data/lib/railroader/checks/check_validation_regex.rb +7 -7
- data/lib/railroader/checks/check_weak_hash.rb +1 -1
- data/lib/railroader/checks/check_without_protection.rb +9 -9
- data/lib/railroader/checks/check_yaml_parsing.rb +5 -5
- data/lib/railroader/checks.rb +18 -18
- data/lib/railroader/commandline.rb +1 -1
- data/lib/railroader/differ.rb +2 -2
- data/lib/railroader/options.rb +7 -7
- data/lib/railroader/parsers/rails2_erubis.rb +1 -1
- data/lib/railroader/parsers/rails2_xss_plugin_erubis.rb +4 -4
- data/lib/railroader/parsers/template_parser.rb +1 -1
- data/lib/railroader/processor.rb +17 -17
- data/lib/railroader/processors/alias_processor.rb +72 -72
- data/lib/railroader/processors/base_processor.rb +31 -31
- data/lib/railroader/processors/controller_alias_processor.rb +31 -31
- data/lib/railroader/processors/controller_processor.rb +29 -29
- data/lib/railroader/processors/erb_template_processor.rb +8 -8
- data/lib/railroader/processors/erubis_template_processor.rb +6 -6
- data/lib/railroader/processors/gem_processor.rb +1 -1
- data/lib/railroader/processors/haml_template_processor.rb +14 -14
- data/lib/railroader/processors/lib/call_conversion_helper.rb +1 -1
- data/lib/railroader/processors/lib/find_all_calls.rb +15 -15
- data/lib/railroader/processors/lib/find_call.rb +26 -26
- data/lib/railroader/processors/lib/find_return_value.rb +11 -11
- data/lib/railroader/processors/lib/module_helper.rb +1 -1
- data/lib/railroader/processors/lib/processor_helper.rb +4 -4
- data/lib/railroader/processors/lib/rails2_config_processor.rb +20 -20
- data/lib/railroader/processors/lib/rails2_route_processor.rb +38 -38
- data/lib/railroader/processors/lib/rails3_config_processor.rb +14 -14
- data/lib/railroader/processors/lib/rails3_route_processor.rb +16 -16
- data/lib/railroader/processors/lib/render_helper.rb +32 -32
- data/lib/railroader/processors/lib/route_helper.rb +12 -12
- data/lib/railroader/processors/library_processor.rb +1 -1
- data/lib/railroader/processors/model_processor.rb +9 -9
- data/lib/railroader/processors/output_processor.rb +3 -3
- data/lib/railroader/processors/slim_template_processor.rb +4 -4
- data/lib/railroader/processors/template_alias_processor.rb +10 -10
- data/lib/railroader/processors/template_processor.rb +7 -7
- data/lib/railroader/report/renderer.rb +1 -1
- data/lib/railroader/report/report_base.rb +12 -12
- data/lib/railroader/report/report_csv.rb +2 -2
- data/lib/railroader/report/report_html.rb +5 -5
- data/lib/railroader/report/report_markdown.rb +2 -2
- data/lib/railroader/report/report_table.rb +3 -3
- data/lib/railroader/report/report_tabs.rb +2 -2
- data/lib/railroader/report/report_text.rb +3 -4
- data/lib/railroader/report.rb +3 -3
- data/lib/railroader/rescanner.rb +36 -36
- data/lib/railroader/scanner.rb +23 -23
- data/lib/railroader/tracker/config.rb +3 -3
- data/lib/railroader/tracker/controller.rb +2 -2
- data/lib/railroader/tracker.rb +42 -42
- data/lib/railroader/util.rb +47 -47
- data/lib/railroader/version.rb +1 -1
- data/lib/railroader/warning.rb +9 -10
- data/lib/railroader.rb +32 -32
- data/lib/ruby_parser/bm_sexp.rb +63 -63
- data/lib/ruby_parser/bm_sexp_processor.rb +3 -3
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7f3e3d1142109902243a69df249c4914e374a904da6b861d89ce89e581a6a1e2
|
4
|
+
data.tar.gz: cea84ff58d67cae53ac7d3e754a8f61115ad6db779078d4e46ef0dffe0f6b5c8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 22d88d8de4ddb0aae8b402309dd73f495780ed4134f9ba098a1fe8e0c21751b2119103470dd3f4d4a3998438c4faa7858e41c4e2cb6f6cab19814b2472438d51
|
7
|
+
data.tar.gz: bd58f1f7d270a32ea5720b009418d7f49c3179b9c8a4837faa1ba56ae4449b4fe4bbfb0bf6f2c20c650d4b05312302c272489735e80c1e2b080e2796faf87957
|
data/CHANGES.md
CHANGED
@@ -1,3 +1,19 @@
|
|
1
|
+
# 4.3.7
|
2
|
+
|
3
|
+
* We earned a CII Best Practices badge! Show its badge on the README.
|
4
|
+
* Add use of the static analyzer Rubocop, and fix some issues it found.
|
5
|
+
* Add information on how to report vulnerabilities in the Railroader
|
6
|
+
application itself.
|
7
|
+
* Update `ruby_parser` to version 3.13.1. This improves and fixes handling of
|
8
|
+
some Ruby constructs, but it also means that we now longer support
|
9
|
+
running on Ruby 1.9. The last branch of Ruby 1.9 (1.9.3)
|
10
|
+
ended all support on 23 Feb 2015, after a one-year warning, per:
|
11
|
+
https://www.ruby-lang.org/en/news/2015/02/23/support-for-ruby-1-9-3-has-ended/
|
12
|
+
Since this is more than 5 years after the final warning, and more than
|
13
|
+
4 years after support ended, we think this is reasonable.
|
14
|
+
If you really need to run something on Ruby 1.9, forcibly select
|
15
|
+
an older version of Railroader such as 4.3.5.
|
16
|
+
|
1
17
|
# 4.3.5
|
2
18
|
|
3
19
|
* Mass rename to Railroader in docs/
|
data/README.md
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
[](https://travis-ci.org/david-a-wheeler/railroader)
|
4
4
|
[](https://codeclimate.com/github/david-a-wheeler/railroader/maintainability)
|
5
5
|
[](https://codeclimate.com/github/david-a-wheeler/railroader/test_coverage)
|
6
|
+
[](https://bestpractices.coreinfrastructure.org/projects/2514)
|
6
7
|
<!-- [](https://gitter.im/david-a-wheeler/railroader) -->
|
7
8
|
|
8
9
|
# Railroader
|
@@ -100,6 +101,9 @@ To compare results of a scan with a previous scan, use the JSON output option an
|
|
100
101
|
This will output JSON with two lists: one of fixed warnings and one of new warnings.
|
101
102
|
|
102
103
|
Railroader will ignore warnings if configured to do so. By default, it looks for a configuration file in `config/railroader.ignore`.
|
104
|
+
(To help people transition from Brakeman, if `config/railroader.ignore`
|
105
|
+
doesn't exist, but `config/brakeman.ignore` does, then we'' use the
|
106
|
+
latter file.)
|
103
107
|
To create and manage this file, use:
|
104
108
|
|
105
109
|
railroader -I
|
@@ -163,6 +167,17 @@ For even more continuous testing, try the [Guard plugin](https://github.com/guar
|
|
163
167
|
|
164
168
|
-->
|
165
169
|
|
170
|
+
# Contributing
|
171
|
+
|
172
|
+
We love contributions! Please help us!
|
173
|
+
|
174
|
+
For more about how to contribute, see [CONTRIBUTING.md](CONTRIBUTING.md).
|
175
|
+
|
176
|
+
# Reporting vulnerabilities in Railroader itself
|
177
|
+
|
178
|
+
If you find an exploitable vulnerability in Railroader itself,
|
179
|
+
see [CONTRIBUTING.md](CONTRIBUTING.md).
|
180
|
+
|
166
181
|
# Homepage/News
|
167
182
|
|
168
183
|
Website: http://railroader.org/
|
data/bin/railroader
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
require 'set'
|
2
2
|
|
3
|
-
#Stores call sites to look up later.
|
3
|
+
# Stores call sites to look up later.
|
4
4
|
class Railroader::CallIndex
|
5
5
|
|
6
|
-
#Initialize index with calls from FindAllCalls
|
6
|
+
# Initialize index with calls from FindAllCalls
|
7
7
|
def initialize calls
|
8
8
|
@calls_by_method = Hash.new { |h, k| h[k] = [] }
|
9
9
|
@calls_by_target = Hash.new { |h, k| h[k] = [] }
|
@@ -11,9 +11,9 @@ class Railroader::CallIndex
|
|
11
11
|
index_calls calls
|
12
12
|
end
|
13
13
|
|
14
|
-
#Find calls matching specified option hash.
|
14
|
+
# Find calls matching specified option hash.
|
15
15
|
#
|
16
|
-
#Options:
|
16
|
+
# Options:
|
17
17
|
#
|
18
18
|
# * :target - symbol, array of symbols, or regular expression to match target(s)
|
19
19
|
# * :method - symbol, array of symbols, or regular expression to match method(s)
|
@@ -26,7 +26,7 @@ class Railroader::CallIndex
|
|
26
26
|
|
27
27
|
if options[:chained]
|
28
28
|
return find_chain options
|
29
|
-
#Find by narrowest category
|
29
|
+
# Find by narrowest category
|
30
30
|
elsif target and method and target.is_a? Array and method.is_a? Array
|
31
31
|
if target.length > method.length
|
32
32
|
calls = filter_by_target calls_by_methods(method), target
|
@@ -35,7 +35,7 @@ class Railroader::CallIndex
|
|
35
35
|
calls = filter_by_method calls, method
|
36
36
|
end
|
37
37
|
|
38
|
-
#Find by target, then by methods, if provided
|
38
|
+
# Find by target, then by methods, if provided
|
39
39
|
elsif target
|
40
40
|
calls = calls_by_target target
|
41
41
|
|
@@ -43,13 +43,13 @@ class Railroader::CallIndex
|
|
43
43
|
calls = filter_by_method calls, method
|
44
44
|
end
|
45
45
|
|
46
|
-
#Find calls with no explicit target
|
47
|
-
#with either :target => nil or :target => false
|
46
|
+
# Find calls with no explicit target
|
47
|
+
# with either :target => nil or :target => false
|
48
48
|
elsif (options.key? :target or options.key? :targets) and not target and method
|
49
49
|
calls = calls_by_method method
|
50
50
|
calls = filter_by_target calls, nil
|
51
51
|
|
52
|
-
#Find calls by method
|
52
|
+
# Find calls by method
|
53
53
|
elsif method
|
54
54
|
calls = calls_by_method method
|
55
55
|
else
|
@@ -58,8 +58,8 @@ class Railroader::CallIndex
|
|
58
58
|
|
59
59
|
return [] if calls.nil?
|
60
60
|
|
61
|
-
#Remove calls that are actually targets of other calls
|
62
|
-
#Unless those are explicitly desired
|
61
|
+
# Remove calls that are actually targets of other calls
|
62
|
+
# Unless those are explicitly desired
|
63
63
|
calls = filter_nested calls unless nested
|
64
64
|
|
65
65
|
calls
|
@@ -3,7 +3,7 @@ require 'railroader/processors/lib/processor_helper'
|
|
3
3
|
require 'railroader/warning'
|
4
4
|
require 'railroader/util'
|
5
5
|
|
6
|
-
#Basis of vulnerability checks.
|
6
|
+
# Basis of vulnerability checks.
|
7
7
|
class Railroader::BaseCheck < Railroader::SexpProcessor
|
8
8
|
include Railroader::ProcessorHelper
|
9
9
|
include Railroader::SafeCallHelper
|
@@ -24,11 +24,11 @@ class Railroader::BaseCheck < Railroader::SexpProcessor
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
#Initialize Check with Checks.
|
27
|
+
# Initialize Check with Checks.
|
28
28
|
def initialize(app_tree, tracker)
|
29
29
|
super()
|
30
30
|
@app_tree = app_tree
|
31
|
-
@results = [] #only to check for duplicates
|
31
|
+
@results = [] # only to check for duplicates
|
32
32
|
@warnings = []
|
33
33
|
@tracker = tracker
|
34
34
|
@string_interp = false
|
@@ -38,10 +38,10 @@ class Railroader::BaseCheck < Railroader::SexpProcessor
|
|
38
38
|
@mass_assign_disabled = nil
|
39
39
|
@has_user_input = nil
|
40
40
|
@safe_input_attributes = Set[:to_i, :to_f, :arel_table, :id]
|
41
|
-
@comparison_ops
|
41
|
+
@comparison_ops = Set[:==, :!=, :>, :<, :>=, :<=]
|
42
42
|
end
|
43
43
|
|
44
|
-
#Add result to result list, which is used to check for duplicates
|
44
|
+
# Add result to result list, which is used to check for duplicates
|
45
45
|
def add_result result, location = nil
|
46
46
|
location ||= (@current_template && @current_template.name) || @current_class || @current_module || @current_set || result[:location][:class] || result[:location][:template]
|
47
47
|
location = location[:name] if location.is_a? Hash
|
@@ -59,8 +59,8 @@ class Railroader::BaseCheck < Railroader::SexpProcessor
|
|
59
59
|
@results << [line, location, result]
|
60
60
|
end
|
61
61
|
|
62
|
-
#Default Sexp processing. Iterates over each value in the Sexp
|
63
|
-
#and processes them if they are also Sexps.
|
62
|
+
# Default Sexp processing. Iterates over each value in the Sexp
|
63
|
+
# and processes them if they are also Sexps.
|
64
64
|
def process_default exp
|
65
65
|
exp.each do |e|
|
66
66
|
process e if sexp? e
|
@@ -69,7 +69,7 @@ class Railroader::BaseCheck < Railroader::SexpProcessor
|
|
69
69
|
exp
|
70
70
|
end
|
71
71
|
|
72
|
-
#Process calls and check if they include user input
|
72
|
+
# Process calls and check if they include user input
|
73
73
|
def process_call exp
|
74
74
|
unless @comparison_ops.include? exp.method
|
75
75
|
process exp.target if sexp? exp.target
|
@@ -85,7 +85,7 @@ class Railroader::BaseCheck < Railroader::SexpProcessor
|
|
85
85
|
@has_user_input = Match.new(:cookies, exp)
|
86
86
|
elsif request_env? target
|
87
87
|
@has_user_input = Match.new(:request, exp)
|
88
|
-
elsif sexp? target and model_name? target[1] #TODO: Can this be target.target?
|
88
|
+
elsif sexp? target and model_name? target[1] # TODO: Can this be target.target?
|
89
89
|
@has_user_input = Match.new(:model, exp)
|
90
90
|
end
|
91
91
|
end
|
@@ -94,7 +94,7 @@ class Railroader::BaseCheck < Railroader::SexpProcessor
|
|
94
94
|
end
|
95
95
|
|
96
96
|
def process_if exp
|
97
|
-
#This is to ignore user input in condition
|
97
|
+
# This is to ignore user input in condition
|
98
98
|
current_user_input = @has_user_input
|
99
99
|
process exp.condition
|
100
100
|
@has_user_input = current_user_input
|
@@ -105,19 +105,19 @@ class Railroader::BaseCheck < Railroader::SexpProcessor
|
|
105
105
|
exp
|
106
106
|
end
|
107
107
|
|
108
|
-
#Note that params are included in current expression
|
108
|
+
# Note that params are included in current expression
|
109
109
|
def process_params exp
|
110
110
|
@has_user_input = Match.new(:params, exp)
|
111
111
|
exp
|
112
112
|
end
|
113
113
|
|
114
|
-
#Note that cookies are included in current expression
|
114
|
+
# Note that cookies are included in current expression
|
115
115
|
def process_cookies exp
|
116
116
|
@has_user_input = Match.new(:cookies, exp)
|
117
117
|
exp
|
118
118
|
end
|
119
119
|
|
120
|
-
#Does not actually process string interpolation, but notes that it occurred.
|
120
|
+
# Does not actually process string interpolation, but notes that it occurred.
|
121
121
|
def process_dstr exp
|
122
122
|
unless @string_interp # don't overwrite existing value
|
123
123
|
@string_interp = Match.new(:interp, exp)
|
@@ -137,7 +137,7 @@ class Railroader::BaseCheck < Railroader::SexpProcessor
|
|
137
137
|
method[-1] == "?"
|
138
138
|
end
|
139
139
|
|
140
|
-
#Report a warning
|
140
|
+
# Report a warning
|
141
141
|
def warn options
|
142
142
|
extra_opts = { :check => self.class.to_s }
|
143
143
|
|
@@ -148,12 +148,12 @@ class Railroader::BaseCheck < Railroader::SexpProcessor
|
|
148
148
|
@warnings << warning
|
149
149
|
end
|
150
150
|
|
151
|
-
#Run _exp_ through OutputProcessor to get a nice String.
|
151
|
+
# Run _exp_ through OutputProcessor to get a nice String.
|
152
152
|
def format_output exp
|
153
153
|
Railroader::OutputProcessor.new.format(exp).gsub(/\r|\n/, "")
|
154
154
|
end
|
155
155
|
|
156
|
-
#Checks if mass assignment is disabled globally in an initializer.
|
156
|
+
# Checks if mass assignment is disabled globally in an initializer.
|
157
157
|
def mass_assign_disabled?
|
158
158
|
return @mass_assign_disabled unless @mass_assign_disabled.nil?
|
159
159
|
|
@@ -167,7 +167,7 @@ class Railroader::BaseCheck < Railroader::SexpProcessor
|
|
167
167
|
|
168
168
|
@mass_assign_disabled = true
|
169
169
|
else
|
170
|
-
#Check for ActiveRecord::Base.send(:attr_accessible, nil)
|
170
|
+
# Check for ActiveRecord::Base.send(:attr_accessible, nil)
|
171
171
|
tracker.check_initializers(:"ActiveRecord::Base", :attr_accessible).each do |result|
|
172
172
|
call = result.call
|
173
173
|
if call? call
|
@@ -191,7 +191,7 @@ class Railroader::BaseCheck < Railroader::SexpProcessor
|
|
191
191
|
end
|
192
192
|
|
193
193
|
unless @mass_assign_disabled
|
194
|
-
#Check for
|
194
|
+
# Check for
|
195
195
|
# class ActiveRecord::Base
|
196
196
|
# attr_accessible nil
|
197
197
|
# end
|
@@ -210,10 +210,10 @@ class Railroader::BaseCheck < Railroader::SexpProcessor
|
|
210
210
|
end
|
211
211
|
end
|
212
212
|
|
213
|
-
#There is a chance someone is using Rails 3.x and the `strong_parameters`
|
214
|
-
#gem and still using hack above, so this is a separate check for
|
215
|
-
#including ActiveModel::ForbiddenAttributesProtection in
|
216
|
-
#ActiveRecord::Base in an initializer.
|
213
|
+
# There is a chance someone is using Rails 3.x and the `strong_parameters`
|
214
|
+
# gem and still using hack above, so this is a separate check for
|
215
|
+
# including ActiveModel::ForbiddenAttributesProtection in
|
216
|
+
# ActiveRecord::Base in an initializer.
|
217
217
|
if not @mass_assign_disabled and version_between?("3.1.0", "3.9.9") and tracker.config.has_gem? :strong_parameters
|
218
218
|
matches = tracker.check_initializers([], :include)
|
219
219
|
forbidden_protection = Sexp.new(:colon2, Sexp.new(:const, :ActiveModel), :ForbiddenAttributesProtection)
|
@@ -245,8 +245,8 @@ class Railroader::BaseCheck < Railroader::SexpProcessor
|
|
245
245
|
true
|
246
246
|
end
|
247
247
|
|
248
|
-
#This is to avoid reporting duplicates. Checks if the result has been
|
249
|
-
#reported already from the same line number.
|
248
|
+
# This is to avoid reporting duplicates. Checks if the result has been
|
249
|
+
# reported already from the same line number.
|
250
250
|
def duplicate? result, location = nil
|
251
251
|
if result.is_a? Hash
|
252
252
|
line = result[:call].original_line || result[:call].line
|
@@ -275,34 +275,34 @@ class Railroader::BaseCheck < Railroader::SexpProcessor
|
|
275
275
|
false
|
276
276
|
end
|
277
277
|
|
278
|
-
#Checks if an expression contains string interpolation.
|
278
|
+
# Checks if an expression contains string interpolation.
|
279
279
|
#
|
280
|
-
#Returns Match with :interp type if found.
|
280
|
+
# Returns Match with :interp type if found.
|
281
281
|
def include_interp? exp
|
282
282
|
@string_interp = false
|
283
283
|
process exp
|
284
284
|
@string_interp
|
285
285
|
end
|
286
286
|
|
287
|
-
#Checks if _exp_ includes user input in the form of cookies, parameters,
|
288
|
-
#request environment, or model attributes.
|
287
|
+
# Checks if _exp_ includes user input in the form of cookies, parameters,
|
288
|
+
# request environment, or model attributes.
|
289
289
|
#
|
290
|
-
#If found, returns a struct containing a type (:cookies, :params, :request, :model) and
|
291
|
-
#the matching expression (Match#type and Match#match).
|
290
|
+
# If found, returns a struct containing a type (:cookies, :params, :request, :model) and
|
291
|
+
# the matching expression (Match#type and Match#match).
|
292
292
|
#
|
293
|
-
#Returns false otherwise.
|
293
|
+
# Returns false otherwise.
|
294
294
|
def include_user_input? exp
|
295
295
|
@has_user_input = false
|
296
296
|
process exp
|
297
297
|
@has_user_input
|
298
298
|
end
|
299
299
|
|
300
|
-
#This is used to check for user input being used directly.
|
300
|
+
# This is used to check for user input being used directly.
|
301
301
|
#
|
302
|
-
|
303
|
-
#the matching expression (Match#type and Match#match).
|
302
|
+
# #If found, returns a struct containing a type (:cookies, :params, :request) and
|
303
|
+
# the matching expression (Match#type and Match#match).
|
304
304
|
#
|
305
|
-
#Returns false otherwise.
|
305
|
+
# Returns false otherwise.
|
306
306
|
def has_immediate_user_input? exp
|
307
307
|
if exp.nil?
|
308
308
|
false
|
@@ -352,8 +352,8 @@ class Railroader::BaseCheck < Railroader::SexpProcessor
|
|
352
352
|
end
|
353
353
|
end
|
354
354
|
|
355
|
-
#Checks for a model attribute at the top level of the
|
356
|
-
#expression.
|
355
|
+
# Checks for a model attribute at the top level of the
|
356
|
+
# expression.
|
357
357
|
def has_immediate_model? exp, out = nil
|
358
358
|
out = exp if out.nil?
|
359
359
|
|
@@ -367,7 +367,7 @@ class Railroader::BaseCheck < Railroader::SexpProcessor
|
|
367
367
|
|
368
368
|
if always_safe_method? method
|
369
369
|
false
|
370
|
-
elsif call? target and not method.to_s[-1,1] == "?"
|
370
|
+
elsif call? target and not method.to_s[-1, 1] == "?"
|
371
371
|
if has_immediate_model?(target, out)
|
372
372
|
exp
|
373
373
|
else
|
@@ -414,11 +414,11 @@ class Railroader::BaseCheck < Railroader::SexpProcessor
|
|
414
414
|
end
|
415
415
|
end
|
416
416
|
|
417
|
-
#Checks if +exp+ is a model name.
|
417
|
+
# Checks if +exp+ is a model name.
|
418
418
|
#
|
419
|
-
#Prior to using this method, either @tracker must be set to
|
420
|
-
#the current tracker, or else @models should contain an array of the model
|
421
|
-
#names, which is available via tracker.models.keys
|
419
|
+
# Prior to using this method, either @tracker must be set to
|
420
|
+
# the current tracker, or else @models should contain an array of the model
|
421
|
+
# names, which is available via tracker.models.keys
|
422
422
|
def model_name? exp
|
423
423
|
@models ||= @tracker.models.keys
|
424
424
|
|
@@ -433,7 +433,7 @@ class Railroader::BaseCheck < Railroader::SexpProcessor
|
|
433
433
|
end
|
434
434
|
end
|
435
435
|
|
436
|
-
#Returns true if +target+ is in +exp+
|
436
|
+
# Returns true if +target+ is in +exp+
|
437
437
|
def include_target? exp, target
|
438
438
|
return false unless call? exp
|
439
439
|
|
@@ -1,9 +1,9 @@
|
|
1
1
|
require 'railroader/checks/base_check'
|
2
2
|
|
3
|
-
#Checks if password is stored in controller
|
4
|
-
#when using http_basic_authenticate_with
|
3
|
+
# Checks if password is stored in controller
|
4
|
+
# when using http_basic_authenticate_with
|
5
5
|
#
|
6
|
-
#Only for Rails >= 3.1
|
6
|
+
# Only for Rails >= 3.1
|
7
7
|
class Railroader::CheckBasicAuth < Railroader::BaseCheck
|
8
8
|
Railroader::Checks.add self
|
9
9
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'railroader/checks/check_cross_site_scripting'
|
2
2
|
|
3
|
-
#Checks for unescaped values in `content_tag`
|
3
|
+
# Checks for unescaped values in `content_tag`
|
4
4
|
#
|
5
5
|
# content_tag :tag, body
|
6
6
|
# ^-- Unescaped in Rails 2.x
|
@@ -56,15 +56,15 @@ class Railroader::CheckContentTag < Railroader::CheckCrossSiteScripting
|
|
56
56
|
|
57
57
|
@matched = false
|
58
58
|
|
59
|
-
#Silly, but still dangerous if someone uses user input in the tag type
|
59
|
+
# Silly, but still dangerous if someone uses user input in the tag type
|
60
60
|
check_argument result, tag_name
|
61
61
|
|
62
|
-
#Versions before 3.x do not escape body of tag, nor does the rails_xss gem
|
62
|
+
# Versions before 3.x do not escape body of tag, nor does the rails_xss gem
|
63
63
|
unless @matched or (tracker.options[:rails3] and not raw? content)
|
64
64
|
check_argument result, content
|
65
65
|
end
|
66
66
|
|
67
|
-
#Attribute keys are never escaped, so check them for user input
|
67
|
+
# Attribute keys are never escaped, so check them for user input
|
68
68
|
if not @matched and hash? attributes and not request_value? attributes
|
69
69
|
hash_iterate(attributes) do |k, _v|
|
70
70
|
check_argument result, k
|
@@ -72,13 +72,13 @@ class Railroader::CheckContentTag < Railroader::CheckCrossSiteScripting
|
|
72
72
|
end
|
73
73
|
end
|
74
74
|
|
75
|
-
#By default, content_tag escapes attribute values passed in as a hash.
|
76
|
-
#But this behavior can be disabled. So only check attributes hash
|
77
|
-
#if they are explicitly not escaped.
|
75
|
+
# By default, content_tag escapes attribute values passed in as a hash.
|
76
|
+
# But this behavior can be disabled. So only check attributes hash
|
77
|
+
# if they are explicitly not escaped.
|
78
78
|
if not @matched and attributes and (false? escape_attr or cve_2016_6316?)
|
79
79
|
if request_value? attributes or not hash? attributes
|
80
80
|
check_argument result, attributes
|
81
|
-
else #check hash values
|
81
|
+
else # check hash values
|
82
82
|
hash_iterate(attributes) do |_k, v|
|
83
83
|
check_argument result, v
|
84
84
|
return if @matched
|
@@ -88,7 +88,7 @@ class Railroader::CheckContentTag < Railroader::CheckCrossSiteScripting
|
|
88
88
|
end
|
89
89
|
|
90
90
|
def check_argument result, exp
|
91
|
-
#Check contents of raw() calls directly
|
91
|
+
# Check contents of raw() calls directly
|
92
92
|
if raw? exp
|
93
93
|
arg = process exp.first_arg
|
94
94
|
else
|
@@ -43,8 +43,8 @@ class Railroader::CheckCreateWith < Railroader::BaseCheck
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
-
#For a given create_with call, set confidence level.
|
47
|
-
#Ignore calls that use permit()
|
46
|
+
# For a given create_with call, set confidence level.
|
47
|
+
# Ignore calls that use permit()
|
48
48
|
def danger_level exp
|
49
49
|
return unless sexp? exp
|
50
50
|
|
@@ -4,10 +4,10 @@ require 'railroader/processors/lib/processor_helper'
|
|
4
4
|
require 'railroader/util'
|
5
5
|
require 'set'
|
6
6
|
|
7
|
-
#This check looks for unescaped output in templates which contains
|
8
|
-
#parameters or model attributes.
|
7
|
+
# This check looks for unescaped output in templates which contains
|
8
|
+
# parameters or model attributes.
|
9
9
|
#
|
10
|
-
#For example:
|
10
|
+
# For example:
|
11
11
|
#
|
12
12
|
# <%= User.find(:id).name %>
|
13
13
|
# <%= params[:id] %>
|
@@ -16,7 +16,7 @@ class Railroader::CheckCrossSiteScripting < Railroader::BaseCheck
|
|
16
16
|
|
17
17
|
@description = "Checks for unescaped output in views"
|
18
18
|
|
19
|
-
#Model methods which are known to be harmless
|
19
|
+
# Model methods which are known to be harmless
|
20
20
|
IGNORE_MODEL_METHODS = Set[:average, :count, :maximum, :minimum, :sum, :id]
|
21
21
|
|
22
22
|
MODEL_METHODS = Set[:all, :find, :first, :last, :new]
|
@@ -33,7 +33,7 @@ class Railroader::CheckCrossSiteScripting < Railroader::BaseCheck
|
|
33
33
|
|
34
34
|
FORM_BUILDER = Sexp.new(:call, Sexp.new(:const, :FormBuilder), :new)
|
35
35
|
|
36
|
-
#Run check
|
36
|
+
# Run check
|
37
37
|
def run_check
|
38
38
|
setup
|
39
39
|
|
@@ -119,7 +119,7 @@ class Railroader::CheckCrossSiteScripting < Railroader::BaseCheck
|
|
119
119
|
end
|
120
120
|
end
|
121
121
|
|
122
|
-
#Call already involves a model, but might not be acting on a record
|
122
|
+
# Call already involves a model, but might not be acting on a record
|
123
123
|
def likely_model_attribute? exp
|
124
124
|
return false unless call? exp
|
125
125
|
|
@@ -132,13 +132,13 @@ class Railroader::CheckCrossSiteScripting < Railroader::BaseCheck
|
|
132
132
|
end
|
133
133
|
end
|
134
134
|
|
135
|
-
#Process an output Sexp
|
135
|
+
# Process an output Sexp
|
136
136
|
def process_output exp
|
137
137
|
process exp.value.dup
|
138
138
|
end
|
139
139
|
|
140
|
-
#Look for calls to raw()
|
141
|
-
#Otherwise, ignore
|
140
|
+
# Look for calls to raw()
|
141
|
+
# Otherwise, ignore
|
142
142
|
def process_escaped_output exp
|
143
143
|
unless check_for_immediate_xss exp
|
144
144
|
if not duplicate? exp
|
@@ -152,12 +152,12 @@ class Railroader::CheckCrossSiteScripting < Railroader::BaseCheck
|
|
152
152
|
exp
|
153
153
|
end
|
154
154
|
|
155
|
-
#Check a call for user input
|
155
|
+
# Check a call for user input
|
156
156
|
#
|
157
157
|
#
|
158
|
-
#Since we want to report an entire call and not just part of one, use @mark
|
159
|
-
#to mark when a call is started. Any dangerous values inside will then
|
160
|
-
#report the entire call chain.
|
158
|
+
# Since we want to report an entire call and not just part of one, use @mark
|
159
|
+
# to mark when a call is started. Any dangerous values inside will then
|
160
|
+
# report the entire call chain.
|
161
161
|
def process_call exp
|
162
162
|
if @mark
|
163
163
|
actually_process_call exp
|
@@ -214,10 +214,10 @@ class Railroader::CheckCrossSiteScripting < Railroader::BaseCheck
|
|
214
214
|
|
215
215
|
method = exp.method
|
216
216
|
|
217
|
-
#Ignore safe items
|
217
|
+
# Ignore safe items
|
218
218
|
if ignore_call? target, method
|
219
219
|
@matched = false
|
220
|
-
elsif sexp? target and model_name? target[1] #TODO: use method call?
|
220
|
+
elsif sexp? target and model_name? target[1] # TODO: use method call?
|
221
221
|
@matched = Match.new(:model, exp)
|
222
222
|
elsif cookies? exp
|
223
223
|
@matched = Match.new(:cookies, exp)
|
@@ -228,39 +228,39 @@ class Railroader::CheckCrossSiteScripting < Railroader::BaseCheck
|
|
228
228
|
end
|
229
229
|
end
|
230
230
|
|
231
|
-
#Note that params have been found
|
231
|
+
# Note that params have been found
|
232
232
|
def process_params exp
|
233
233
|
@matched = Match.new(:params, exp)
|
234
234
|
exp
|
235
235
|
end
|
236
236
|
|
237
|
-
#Note that cookies have been found
|
237
|
+
# Note that cookies have been found
|
238
238
|
def process_cookies exp
|
239
239
|
@matched = Match.new(:cookies, exp)
|
240
240
|
exp
|
241
241
|
end
|
242
242
|
|
243
|
-
#Ignore calls to render
|
243
|
+
# Ignore calls to render
|
244
244
|
def process_render exp
|
245
245
|
exp
|
246
246
|
end
|
247
247
|
|
248
|
-
#Process as default
|
248
|
+
# Process as default
|
249
249
|
def process_dstr exp
|
250
250
|
process_default exp
|
251
251
|
end
|
252
252
|
|
253
|
-
#Process as default
|
253
|
+
# Process as default
|
254
254
|
def process_format exp
|
255
255
|
process_default exp
|
256
256
|
end
|
257
257
|
|
258
|
-
#Ignore output HTML escaped via HAML
|
258
|
+
# Ignore output HTML escaped via HAML
|
259
259
|
def process_format_escaped exp
|
260
260
|
exp
|
261
261
|
end
|
262
262
|
|
263
|
-
#Ignore condition in if Sexp
|
263
|
+
# Ignore condition in if Sexp
|
264
264
|
def process_if exp
|
265
265
|
process exp.then_clause if sexp? exp.then_clause
|
266
266
|
process exp.else_clause if sexp? exp.else_clause
|
@@ -268,8 +268,8 @@ class Railroader::CheckCrossSiteScripting < Railroader::BaseCheck
|
|
268
268
|
end
|
269
269
|
|
270
270
|
def process_case exp
|
271
|
-
#Ignore user input in case value
|
272
|
-
#TODO: also ignore when values
|
271
|
+
# Ignore user input in case value
|
272
|
+
# TODO: also ignore when values
|
273
273
|
|
274
274
|
current = 2
|
275
275
|
while current < exp.length
|
@@ -1,13 +1,13 @@
|
|
1
1
|
require 'railroader/checks/base_check'
|
2
2
|
|
3
|
-
#Checks if default routes are allowed in routes.rb
|
3
|
+
# Checks if default routes are allowed in routes.rb
|
4
4
|
class Railroader::CheckDefaultRoutes < Railroader::BaseCheck
|
5
5
|
Railroader::Checks.add self
|
6
6
|
|
7
7
|
@description = "Checks for default routes"
|
8
8
|
|
9
|
-
#Checks for :allow_all_actions globally and for individual routes
|
10
|
-
#if it is not enabled globally.
|
9
|
+
# Checks for :allow_all_actions globally and for individual routes
|
10
|
+
# if it is not enabled globally.
|
11
11
|
def run_check
|
12
12
|
check_for_default_routes
|
13
13
|
check_for_action_globs
|
@@ -16,7 +16,7 @@ class Railroader::CheckDefaultRoutes < Railroader::BaseCheck
|
|
16
16
|
|
17
17
|
def check_for_default_routes
|
18
18
|
if allow_all_actions?
|
19
|
-
#Default routes are enabled globally
|
19
|
+
# Default routes are enabled globally
|
20
20
|
warn :warning_type => "Default Routes",
|
21
21
|
:warning_code => :all_default_routes,
|
22
22
|
:message => "All public methods in controllers are available as actions in routes.rb",
|
@@ -52,7 +52,7 @@ class Railroader::CheckDefaultRoutes < Railroader::BaseCheck
|
|
52
52
|
def check_for_cve_2014_0130
|
53
53
|
case
|
54
54
|
when lts_version?("2.3.18.9")
|
55
|
-
#TODO: Should support LTS 3.0.20 too
|
55
|
+
# TODO: Should support LTS 3.0.20 too
|
56
56
|
return
|
57
57
|
when version_between?("2.0.0", "2.3.18")
|
58
58
|
upgrade = "3.2.18"
|
@@ -24,7 +24,7 @@ class Railroader::CheckDeserialize < Railroader::BaseCheck
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def check_methods target, *methods
|
27
|
-
tracker.find_call(:target => target, :methods => methods
|
27
|
+
tracker.find_call(:target => target, :methods => methods).each do |result|
|
28
28
|
check_deserialize result, target
|
29
29
|
end
|
30
30
|
end
|