scanny 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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