scanny 0.1.0

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.
Files changed (138) hide show
  1. data/.gitignore +5 -0
  2. data/Gemfile +11 -0
  3. data/LICENSE +23 -0
  4. data/README.md +185 -0
  5. data/Rakefile +5 -0
  6. data/bin/scanny +61 -0
  7. data/lib/scanny.rb +12 -0
  8. data/lib/scanny/checks/access_control_check.rb +52 -0
  9. data/lib/scanny/checks/backticks_check.rb +18 -0
  10. data/lib/scanny/checks/before_filters_check.rb +35 -0
  11. data/lib/scanny/checks/check.rb +33 -0
  12. data/lib/scanny/checks/csrf_check.rb +19 -0
  13. data/lib/scanny/checks/denial_of_service_check.rb +42 -0
  14. data/lib/scanny/checks/file_open_check.rb +46 -0
  15. data/lib/scanny/checks/frameworks_check.rb +24 -0
  16. data/lib/scanny/checks/helpers.rb +28 -0
  17. data/lib/scanny/checks/http_basic_auth_check.rb +39 -0
  18. data/lib/scanny/checks/http_header/header_injection_check.rb +38 -0
  19. data/lib/scanny/checks/http_redirect_check.rb +37 -0
  20. data/lib/scanny/checks/http_request_check.rb +74 -0
  21. data/lib/scanny/checks/http_usage_check.rb +31 -0
  22. data/lib/scanny/checks/information_leak_check.rb +55 -0
  23. data/lib/scanny/checks/input_filtering_check.rb +39 -0
  24. data/lib/scanny/checks/insecure_config/set_rails_env_check.rb +24 -0
  25. data/lib/scanny/checks/insecure_config/set_secret_check.rb +25 -0
  26. data/lib/scanny/checks/insecure_config/set_session_key_check.rb +23 -0
  27. data/lib/scanny/checks/insecure_method/eval_method_check.rb +26 -0
  28. data/lib/scanny/checks/insecure_method/marshal_check.rb +33 -0
  29. data/lib/scanny/checks/insecure_method/system_method_check.rb +46 -0
  30. data/lib/scanny/checks/mass_assignment_check.rb +48 -0
  31. data/lib/scanny/checks/random_numbers_check.rb +54 -0
  32. data/lib/scanny/checks/redirect_with_params_check.rb +48 -0
  33. data/lib/scanny/checks/regexp_check.rb +23 -0
  34. data/lib/scanny/checks/reset_session_check.rb +24 -0
  35. data/lib/scanny/checks/session/access_to_session_check.rb +49 -0
  36. data/lib/scanny/checks/session/session_secure_check.rb +47 -0
  37. data/lib/scanny/checks/shell_expanding_methods_check.rb +54 -0
  38. data/lib/scanny/checks/skip_before_filters_check.rb +41 -0
  39. data/lib/scanny/checks/sql_injection/find_method_check.rb +81 -0
  40. data/lib/scanny/checks/sql_injection/find_method_with_dynamic_string_check.rb +43 -0
  41. data/lib/scanny/checks/sql_injection/find_method_with_params_check.rb +80 -0
  42. data/lib/scanny/checks/sql_injection/sanitize_sql_check.rb +25 -0
  43. data/lib/scanny/checks/sql_injection/sql_check.rb +14 -0
  44. data/lib/scanny/checks/sql_injection/string_interpolation_with_params_check.rb +39 -0
  45. data/lib/scanny/checks/ssl/verify_check.rb +53 -0
  46. data/lib/scanny/checks/ssl/verify_peer_check.rb +37 -0
  47. data/lib/scanny/checks/system_tools/gpg_usage_check.rb +51 -0
  48. data/lib/scanny/checks/system_tools/sudo_check.rb +24 -0
  49. data/lib/scanny/checks/system_tools/tar_check.rb +24 -0
  50. data/lib/scanny/checks/system_tools/tar_commands_check.rb +27 -0
  51. data/lib/scanny/checks/system_tools/unzip_check.rb +30 -0
  52. data/lib/scanny/checks/temp_file_open_check.rb +57 -0
  53. data/lib/scanny/checks/user_find_check.rb +40 -0
  54. data/lib/scanny/checks/validates_check.rb +32 -0
  55. data/lib/scanny/checks/verify_check.rb +44 -0
  56. data/lib/scanny/checks/xss/xss_flash_check.rb +70 -0
  57. data/lib/scanny/checks/xss/xss_logger_check.rb +78 -0
  58. data/lib/scanny/checks/xss/xss_mark_check.rb +48 -0
  59. data/lib/scanny/checks/xss/xss_send_check.rb +70 -0
  60. data/lib/scanny/cli.rb +47 -0
  61. data/lib/scanny/issue.rb +28 -0
  62. data/lib/scanny/rake_task.rb +56 -0
  63. data/lib/scanny/reporters.rb +3 -0
  64. data/lib/scanny/reporters/reporter.rb +22 -0
  65. data/lib/scanny/reporters/simple_reporter.rb +19 -0
  66. data/lib/scanny/reporters/xml_reporter.rb +64 -0
  67. data/lib/scanny/ruby_version_check.rb +15 -0
  68. data/lib/scanny/runner.rb +90 -0
  69. data/scanny.gemspec +22 -0
  70. data/spec/scanny/check_spec.rb +22 -0
  71. data/spec/scanny/checks/access_control_check_spec.rb +43 -0
  72. data/spec/scanny/checks/backticks_check_spec.rb +22 -0
  73. data/spec/scanny/checks/before_filters_check_spec.rb +45 -0
  74. data/spec/scanny/checks/csrf_check_spec.rb +16 -0
  75. data/spec/scanny/checks/denial_of_service_check_spec.rb +28 -0
  76. data/spec/scanny/checks/file_open_check_spec.rb +22 -0
  77. data/spec/scanny/checks/frameworks_check_spec.rb +16 -0
  78. data/spec/scanny/checks/http_basic_auth_check_spec.rb +20 -0
  79. data/spec/scanny/checks/http_header/header_injection_check_spec.rb +21 -0
  80. data/spec/scanny/checks/http_redirect_check_spec.rb +15 -0
  81. data/spec/scanny/checks/http_request_check_spec.rb +37 -0
  82. data/spec/scanny/checks/http_usage_check_spec.rb +20 -0
  83. data/spec/scanny/checks/information_leak_check_spec.rb +32 -0
  84. data/spec/scanny/checks/input_filtering_check_spec.rb +19 -0
  85. data/spec/scanny/checks/insecure_config/set_rails_env_check_spec.rb +17 -0
  86. data/spec/scanny/checks/insecure_config/set_secret_check_spec.rb +22 -0
  87. data/spec/scanny/checks/insecure_config/set_session_key_check_spec.rb +21 -0
  88. data/spec/scanny/checks/insecure_method/eval_method_check_spec.rb +22 -0
  89. data/spec/scanny/checks/insecure_method/marshal_check_spec.rb +26 -0
  90. data/spec/scanny/checks/insecure_method/system_method_check_spec.rb +33 -0
  91. data/spec/scanny/checks/mass_assignment_check_spec.rb +30 -0
  92. data/spec/scanny/checks/random_numbers_check_spec.rb +41 -0
  93. data/spec/scanny/checks/redirect_with_params_check_spec.rb +24 -0
  94. data/spec/scanny/checks/regexp_check_spec.rb +22 -0
  95. data/spec/scanny/checks/reset_session_check_spec.rb +15 -0
  96. data/spec/scanny/checks/session/access_to_session_check_spec.rb +29 -0
  97. data/spec/scanny/checks/session/session_secure_check_spec.rb +22 -0
  98. data/spec/scanny/checks/shell_expanding_methods_check_spec.rb +67 -0
  99. data/spec/scanny/checks/skip_before_filters_check_spec.rb +81 -0
  100. data/spec/scanny/checks/sql_injection/find_method_check_spec.rb +62 -0
  101. data/spec/scanny/checks/sql_injection/find_method_with_dynamic_string_check_spec.rb +27 -0
  102. data/spec/scanny/checks/sql_injection/find_method_with_params_check_spec.rb +93 -0
  103. data/spec/scanny/checks/sql_injection/sanitize_sql_check_spec.rb +16 -0
  104. data/spec/scanny/checks/sql_injection/string_interpolation_with_params_check_spec.rb +18 -0
  105. data/spec/scanny/checks/ssl/verify_check_spec.rb +25 -0
  106. data/spec/scanny/checks/ssl/verify_peer_check_spec.rb +17 -0
  107. data/spec/scanny/checks/system_tools/gpg_usage_check_spec.rb +43 -0
  108. data/spec/scanny/checks/system_tools/sudo_check_spec.rb +24 -0
  109. data/spec/scanny/checks/system_tools/tar_check_spec.rb +20 -0
  110. data/spec/scanny/checks/system_tools/tar_commands_check_spec.rb +41 -0
  111. data/spec/scanny/checks/system_tools/unizp_check_spec.rb +29 -0
  112. data/spec/scanny/checks/temp_file_open_check_spec.rb +22 -0
  113. data/spec/scanny/checks/user_find_check_spec.rb +22 -0
  114. data/spec/scanny/checks/validates_check_spec.rb +19 -0
  115. data/spec/scanny/checks/verify_check_spec.rb +27 -0
  116. data/spec/scanny/checks/xss/xss_flash_check_spec.rb +22 -0
  117. data/spec/scanny/checks/xss/xss_logger_check_spec.rb +24 -0
  118. data/spec/scanny/checks/xss/xss_mark_check_spec.rb +31 -0
  119. data/spec/scanny/checks/xss/xss_send_check_spec.rb +34 -0
  120. data/spec/scanny/cli_spec.rb +167 -0
  121. data/spec/scanny/issue_spec.rb +82 -0
  122. data/spec/scanny/rake_taks_spec.rb +82 -0
  123. data/spec/scanny/reporters/reporter_spec.rb +24 -0
  124. data/spec/scanny/reporters/simple_reporter_spec.rb +48 -0
  125. data/spec/scanny/reporters/xml_reporter_spec.rb +52 -0
  126. data/spec/scanny/ruby_version_check_spec.rb +24 -0
  127. data/spec/scanny/runner_spec.rb +128 -0
  128. data/spec/spec_helper.rb +10 -0
  129. data/spec/support/aruba.rb +4 -0
  130. data/spec/support/check_spec_helpers.rb +5 -0
  131. data/spec/support/checks/extend_test_check.rb +11 -0
  132. data/spec/support/checks/test_check.rb +15 -0
  133. data/spec/support/checks/test_strict_check.rb +17 -0
  134. data/spec/support/const_spec_helpers.rb +36 -0
  135. data/spec/support/matchers/check_matcher.rb +43 -0
  136. data/spec/support/matchers/xpath_matcher.rb +30 -0
  137. data/spec/support/mock_task.rb +43 -0
  138. metadata +242 -0
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ .rbenv-version
2
+ Gemfile.lock
3
+ *.rbc
4
+ .rbx
5
+ reports
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source :gemcutter
2
+
3
+ # Specify your gem's dependencies in scanny.gemspec
4
+ gemspec
5
+
6
+ # Explicitly requiring test/unit here so that testing works on Ruby 1.9
7
+ group :test do
8
+ gem 'rspec'
9
+ gem 'rake'
10
+ gem 'aruba'
11
+ end
data/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ Copyright (c) 2011 SUSE
2
+ Copyright (c) 2008 Marty Andrews
3
+
4
+ Permission is hereby granted, free of charge, to any person
5
+ obtaining a copy of this software and associated documentation
6
+ files (the "Software"), to deal in the Software without
7
+ restriction, including without limitation the rights to use,
8
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the
10
+ Software is furnished to do so, subject to the following
11
+ conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
+ OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,185 @@
1
+ Scanny
2
+ ======
3
+
4
+ Scanny is a Ruby on Rails security scanner. It parses Ruby files, looks for various suspicious patterns in them (by traversing the AST) and produces a report. Scanny aims to be simple (it does one thing well) and extensible (it is easy to define new patterns).
5
+
6
+ **This is currently work in progress and it's probably not useful yet.**
7
+
8
+ Installation
9
+ ------------
10
+
11
+ You need to install the current development version of [Rubinius](http://rubini.us/) first. You can then install Scanny:
12
+
13
+ $ gem install scanny
14
+
15
+ Usage
16
+ -----
17
+
18
+ To scan one or more Ruby file, use the `scanny` command and pass the files to scan as arguments. Scanny will check the files and print a nice report:
19
+
20
+ $ cat bad.rb
21
+ `ls #{ARGV[1]}`
22
+ $ scanny bad.rb
23
+ bad.rb [2 checks done | 2 nodes inspected | 1 issues]
24
+ - [high] bad.rb:1: Backticks and %x{...} pass the executed command through shell expansion. (CWE-88, CWE-78)
25
+
26
+ Found 1 issues.
27
+
28
+ Rake task
29
+ ---------
30
+
31
+ To create scanny rake task you need to edit Rakefile.
32
+
33
+ ```ruby
34
+ require "scanny/rake_task"
35
+
36
+ Scanny::RakeTask.new do |t|
37
+ t.name = "scanny" # name of rake-task
38
+ t.include = "./custom/checks" # directory with custom checks
39
+ t.disable = "HTTPRedirectCheck" # checks to disable
40
+ t.format = :stdout # output format
41
+ t.strict = true # scanny strict mode
42
+ t.path = "./custom/app" # path to scan
43
+ t.fail_on_error = true # raise exception on error
44
+ t.ruby_mode = "18" # ruby parser mode (default 19)
45
+ end
46
+ ```
47
+
48
+ CI (Continuous Integration)
49
+ ---------------------------
50
+
51
+ ### Common for all CLI
52
+
53
+ * Add to ```Gemfile``` scanny gem
54
+
55
+ ```ruby
56
+ gem 'scanny'
57
+ ```
58
+
59
+ * Create [Rake task](https://github.com/openSUSE/scanny#rake-task).
60
+
61
+ ```ruby
62
+ Scanny::RakeTask.new do |t|
63
+ t.format = :stdout # you will see output on travis website
64
+ t.fail_on_error = false # security errors should not break build
65
+ end
66
+ ```
67
+
68
+ ### Travis
69
+
70
+ * Update your ```.travis.yml``` file. You need add ```before_script``` section.
71
+
72
+ ```yaml
73
+ before_script:
74
+ - test -s "$HOME/.rvm/scripts/rvm" && source "$HOME/.rvm/scripts/rvm"
75
+ - rvm rbx-19mode
76
+ - bundle install
77
+ - bundle exec rake scanny
78
+ - rvm $TRAVIS_RUBY_VERSION
79
+ ```
80
+
81
+ ### Jenkins
82
+
83
+ * Add build step
84
+
85
+ ```
86
+ bash -l -c '
87
+ rvm rbx-head &&
88
+ rvm gemset create scanny &&
89
+ rvm gemset use scanny &&
90
+ bundle install &&
91
+ bundle exec rake scanny'
92
+ ```
93
+
94
+ * Install [Log Parser Plugin](https://wiki.jenkins-ci.org/display/JENKINS/Log+Parser+Plugin) for Jenkins
95
+ * Create rules file
96
+
97
+ ```ruby
98
+ # /var/lib/jenkins/rules
99
+
100
+ info /- \[info\]/
101
+ warning /- \[low\]/
102
+ error /- \[(medium|high)\]/
103
+ ```
104
+
105
+ * Go to ```Manage Jenkins > Configure System > Console Output Parsing```.
106
+ Add path to rules with in **Parsing Rules File** field
107
+
108
+ * Go to and check ```[Project] > Configure > Console output (build log) parsing```
109
+ * Select proper **Select Parsing Rules**
110
+ * Warnings you can find in ```[Build] > Parsed Console Output```
111
+
112
+
113
+ Writing New Checks
114
+ ------------------
115
+ Internally, Scanny consists of multiple *checks*, each responsible for finding and reporting one suspicious pattern in the code. You can easily extend Scanny by writing new checks.
116
+
117
+ The checks are loaded automatically from files in the `lib/scanny/checks` directory. Let's look how a simple check may look like:
118
+
119
+ module Scanny
120
+ module Checks
121
+ # Finds all invocations of "boo" and "moo" methods.
122
+ class BooMooCheck < Check
123
+ def pattern
124
+ 'Send<name = :boo | :moo> | SendWithArguments<name = :boo | :moo>'
125
+ end
126
+
127
+ def check(node)
128
+ issue :high, "The \"#{node.name}\" method indicates wandering cows in the code.",
129
+ :cwe => 999
130
+ end
131
+ end
132
+ end
133
+ end
134
+
135
+ Checks are subclasses of the `Scanny::Checks::Check` class and they implement two methods: `pattern` and `check`.
136
+
137
+ ### The `pattern` method
138
+
139
+ The `pattern` method returns a [Machete](https://github.com/openSUSE/machete) pattern describing Rubinius AST nodes this check is interested in. See [Machete documentation](https://github.com/openSUSE/machete/blob/master/README.md) to learn about the pattern syntax.
140
+
141
+ **Tip:** When creating a check pattern it's often useful to inspect how Rubinius transforms some Ruby constructs into AST nodes. You can do this using the `to_ast` method:
142
+
143
+ '42'.to_ast # => #<Rubinius::AST::FixnumLiteral:0x36fc @value=42 @line=1>
144
+
145
+ ### The `check` method
146
+
147
+ The `check` method will be called on all AST nodes in the scanned files matched by the pattern returned by the `pattern` method. It will be passed the suspicious node. It can perform additional checks on it and report an issue if the node really is problematic.
148
+
149
+ Issues are reported using the `issue` method. As its arguments it accepts issue impact level (`:info`, `:low`, `:medium` or `:high`) and a message for the user, optionally followed by an options hash. The only currently implemented option is `:cwe`, which allows associating the issue with a [CWE number](http://www.cvedetails.com/cwe-definitions.php) (or multiple numbers if you pass an array).
150
+
151
+ ### Tests
152
+
153
+ Each check should be tested. The tests are written in RSpec and they are stored in the `spec/scanny/checks` directory. This is how a test for our sample check may look like:
154
+
155
+ require "spec_helper"
156
+
157
+ module Scanny::Checks
158
+ describe BooMooCheck do
159
+ it "reports \"boo\" correctly" do
160
+ @runner.should check('boo').with_issue(
161
+ issue(:high, "The \"boo\" method indicates wandering cows in the code.", 999)
162
+ )
163
+ end
164
+
165
+ it "reports \"moo\" correctly" do
166
+ @runner.should check('moo').with_issue(
167
+ issue(:high, "The \"moo\" method indicates wandering cows in the code.", 999)
168
+ )
169
+ end
170
+ end
171
+ end
172
+
173
+ Aim to create as simple test cases as possible. Also test different kinds of issues separately. See the existing tests to learn how more complex checks are tested.
174
+
175
+ Compatibility
176
+ -------------
177
+
178
+ Scanny requires Rubinius 1.9 mode to run.
179
+
180
+ Acknowledgement
181
+ ---------------
182
+
183
+ The tool was written as a replacement of Thomas Biege's [Ruby on Rails scanner](http://gitorious.org/code-scanner/ror-sec-scanner/) which was used internally at [SUSE](http://www.suse.com/). This tool needed replacement because it look for suspicious patterns using just regular expressions, which is very rough and has expressivity problems with more complex patterns.
184
+
185
+ The original AST parsing and checking code was copied and adapted from [Roodi](http://roodi.rubyforge.org/), a tool for detecting Ruby code design issues.
data/Rakefile ADDED
@@ -0,0 +1,5 @@
1
+ require "rspec/core/rake_task"
2
+
3
+ RSpec::Core::RakeTask.new
4
+
5
+ task :default => :spec
data/bin/scanny ADDED
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "docopt"
4
+ require_relative "../lib/scanny"
5
+ include Scanny::CLI
6
+
7
+ doc = "Scanny RoR secutiry scanner
8
+
9
+ Usage:
10
+ scanny [options] <files_or_dirs>...
11
+
12
+ Options:
13
+ -h, --help Show this screen.
14
+ -i <check>, --include <check> Include check to scanning process (file or directory).
15
+ -d <check>, --disable <check> Disable check class from scanning process.
16
+ -f <format>, --format <format> Output format (stdout, html, xml) [default: stdout].
17
+ -s, --strict Enable strict mode (for security guys) [default: false].
18
+ -m <mode>, --mode <mode> Ruby parser mode (18 or 19) [default: 19]"
19
+
20
+
21
+ options = Docopt(doc)
22
+
23
+ require_checks(options[:include])
24
+
25
+ runner = Scanny::Runner.new(:parser => use_parser(options[:mode]))
26
+
27
+ runner_with_custom_checks(runner, options[:disable], options[:strict])
28
+ issues = 0
29
+
30
+ files = build_paths.map { |arg| Dir[arg].to_a }.flatten
31
+
32
+ begin
33
+ runner.run(*files)
34
+ rescue SyntaxError => e
35
+ $stderr.puts "Can't parse #{runner.file} as Ruby file.",
36
+ "Parser currently is working in #{options[:mode]} mode.",
37
+ "It is possible that your project works with another version of ruby",
38
+ "You can change parser mode with '-m' flag"
39
+ exit 2
40
+ end
41
+
42
+ runner.checks_data.each do |check_data|
43
+ case options[:format]
44
+ when 'xml'
45
+ Scanny::Reporters::XMLReporter.new(check_data).report
46
+ when 'stdout'
47
+ Scanny::Reporters::SimpleReporter.new(check_data).report
48
+ else
49
+ raise "Format #{options[:format]} is not supported"
50
+ end
51
+ issues += check_data[:issues].size
52
+ end
53
+ puts
54
+
55
+ if issues == 0
56
+ puts "Found no issues."
57
+ exit 0
58
+ else
59
+ puts "Found #{issues} issues."
60
+ exit 1
61
+ end
data/lib/scanny.rb ADDED
@@ -0,0 +1,12 @@
1
+ require_relative "scanny/ruby_version_check"
2
+ require_relative "scanny/cli"
3
+ require_relative "scanny/issue"
4
+ require_relative "scanny/reporters"
5
+ require_relative "scanny/runner"
6
+ require_relative "scanny/checks/check"
7
+ require_relative "scanny/checks/helpers"
8
+ require_relative "scanny/rake_task"
9
+
10
+ Dir[File.dirname(__FILE__) + "/scanny/checks/**/*_check.rb"].each do |file|
11
+ require file
12
+ end
@@ -0,0 +1,52 @@
1
+ module Scanny
2
+ module Checks
3
+ # Checks for use of "params[:id]" in parameters of certain methods that
4
+ # requires authorizaton checks.
5
+ class AccessControlCheck < Check
6
+ # User.new(params[:id])
7
+ def pattern
8
+ <<-EOT
9
+ SendWithArguments<
10
+ name = :new | :create,
11
+ arguments = ActualArguments<
12
+ array = [
13
+ HashLiteral<
14
+ array = [
15
+ any{odd},
16
+ SendWithArguments<
17
+ receiver = Send<name = :params>,
18
+ name = :[],
19
+ arguments = ActualArguments<array = [SymbolLiteral<value = :id>]>
20
+ >,
21
+ any{even}
22
+ ]
23
+ >
24
+ ]
25
+ >
26
+ >
27
+ |
28
+ SendWithArguments<
29
+ name = :delete | :destroy,
30
+ arguments = ActualArguments<
31
+ array = [
32
+ any*,
33
+ SendWithArguments<
34
+ receiver = Send<name = :params>,
35
+ name = :[],
36
+ arguments = ActualArguments<array = [SymbolLiteral<value = :id>]>
37
+ >,
38
+ any*
39
+ ]
40
+ >
41
+ >
42
+ EOT
43
+ end
44
+
45
+ def check(node)
46
+ issue :medium,
47
+ "Using \"params[:id]\" requires proper authorization check.",
48
+ :cwe => 285
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,18 @@
1
+ module Scanny
2
+ module Checks
3
+ # Checks for backticks and %x{...} that pass the command through shell
4
+ # expansion. This can cause unwanted code execution if the command includes
5
+ # unescaped input.
6
+ class BackticksCheck < Check
7
+ # `command`
8
+ def pattern
9
+ 'ExecuteString | DynamicExecuteString'
10
+ end
11
+
12
+ def check(node)
13
+ issue :high, "Backticks and %x{...} pass the executed command through shell expansion.",
14
+ :cwe => [88, 78]
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,35 @@
1
+ module Scanny
2
+ module Checks
3
+ # Checks for use of the "before_filter" method with certain filters.
4
+ class BeforeFiltersCheck < Check
5
+ FILTERS = [:login_required, :admin_required]
6
+
7
+ # before_filter :login_required
8
+ def pattern
9
+ <<-EOT
10
+ SendWithArguments<
11
+ receiver = Self,
12
+ name = :before_filter,
13
+ arguments = ActualArguments<
14
+ array = [
15
+ any*,
16
+ SymbolLiteral<value = #{FILTERS.map(&:inspect).join(' | ')}>,
17
+ any*
18
+ ]
19
+ >
20
+ >
21
+ EOT
22
+ end
23
+
24
+ def check(node)
25
+ filter_node = node.arguments.array.find do |argument|
26
+ argument.is_a?(Rubinius::AST::SymbolLiteral) &&
27
+ FILTERS.include?(argument.value)
28
+ end
29
+
30
+ issue :info,
31
+ "The \"before_filter\" method with :#{filter_node.value} filter is used."
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,33 @@
1
+ module Scanny
2
+ module Checks
3
+ class Check
4
+ def visit(file, node)
5
+ @file = file
6
+ @line = node.line
7
+ @issues = []
8
+
9
+ check(node)
10
+
11
+ @issues
12
+ end
13
+
14
+ # @return [String] pattern used to find relevant nodes. It must respect Machete's syntax.
15
+ def pattern
16
+ raise "The Check class requires its childrens to provide an "\
17
+ "implementation of the 'pattern' method."
18
+ end
19
+
20
+ def issue(impact, message, options = {})
21
+ @issues << Issue.new(@file, @line, impact, message, options[:cwe])
22
+ end
23
+
24
+ def strict?
25
+ false
26
+ end
27
+
28
+ def compiled_pattern
29
+ @compiled_pattern ||= Machete::Parser.new.parse(pattern)
30
+ end
31
+ end
32
+ end
33
+ end