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
@@ -0,0 +1,47 @@
1
+ module Scanny
2
+ module Checks
3
+ module Session
4
+ class SessionSecureCheck < Check
5
+ def pattern
6
+ pattern_session_settings
7
+ end
8
+
9
+ def check(node)
10
+ issue :info, warning_message, :cwe => 614
11
+ end
12
+
13
+ def strict?
14
+ true
15
+ end
16
+
17
+ private
18
+
19
+ def warning_message
20
+ "Bad session security setting can cause problems"
21
+ end
22
+
23
+ # ActionController::Base.session_options[:session_secure]
24
+ def pattern_session_settings
25
+ <<-EOT
26
+ ElementAssignment<
27
+ arguments = ActualArguments<
28
+ array = [
29
+ SymbolLiteral<value = :session_secure | :secure>,
30
+ any
31
+ ]
32
+ >,
33
+ name = :[]=,
34
+ receiver = Send<
35
+ name = :session_options,
36
+ receiver = ScopedConstant<
37
+ name = :Base,
38
+ parent = ConstantAccess<name = :ActionController>
39
+ >
40
+ >
41
+ >
42
+ EOT
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,54 @@
1
+ module Scanny
2
+ module Checks
3
+ # Checks for methods executing external commands that pass the command
4
+ # through shell expansion. This can cause unwanted code execution if the
5
+ # command includes unescaped input.
6
+ class ShellExpandingMethodsCheck < Check
7
+ def pattern
8
+ [
9
+ pattern_shell_expanding,
10
+ pattern_popen,
11
+ pattern_execute_string
12
+ ].join("|")
13
+ end
14
+
15
+ def check(node)
16
+ # The command goes through shell expansion only if it is passed as one
17
+ # argument.
18
+ issue :high, warning_message(node), :cwe => [88, 78]
19
+ end
20
+
21
+ def warning_message(node = nil)
22
+ name = node.respond_to?(:name) ? node.name : "`"
23
+ "The \"#{name}\" method passes the executed command through shell expansion."
24
+ end
25
+
26
+ # system("rm -rf /")
27
+ def pattern_shell_expanding
28
+ <<-EOT
29
+ SendWithArguments<
30
+ receiver = Self | ConstantAccess<name = :Kernel>,
31
+ name = :` | :exec | :system | :spawn,
32
+ arguments = ActualArguments<array = [any]>
33
+ >
34
+ EOT
35
+ end
36
+
37
+ # IO.popen
38
+ # IO.popen3
39
+ def pattern_popen
40
+ <<-EOT
41
+ SendWithArguments<
42
+ name ^= :popen,
43
+ arguments = ActualArguments<array = [any]>
44
+ >
45
+ EOT
46
+ end
47
+
48
+ # `system_command`
49
+ def pattern_execute_string
50
+ "ExecuteString"
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,41 @@
1
+ module Scanny
2
+ module Checks
3
+ # Checks for use of the "before_filter" method with certain filters.
4
+ class SkipBeforeFiltersCheck < Check
5
+ FILTERS = [
6
+ :login_required,
7
+ :admin_required,
8
+ :verify_authenticity_token,
9
+ :authenticate
10
+ ]
11
+
12
+ # skip_before_filer :login_required
13
+ def pattern
14
+ <<-EOT
15
+ SendWithArguments<
16
+ receiver = Self,
17
+ name = :skip_before_filter,
18
+ arguments = ActualArguments<
19
+ array = [
20
+ any*,
21
+ SymbolLiteral<value = #{FILTERS.map(&:inspect).join(' | ')}>,
22
+ any*
23
+ ]
24
+ >
25
+ >
26
+ EOT
27
+ end
28
+
29
+ def check(node)
30
+ filter_node = node.arguments.array.find do |argument|
31
+ argument.is_a?(Rubinius::AST::SymbolLiteral) &&
32
+ FILTERS.include?(argument.value)
33
+ end
34
+
35
+ issue :info,
36
+ "The \"skip_before_filter\" method with :#{filter_node.value} filter is used.",
37
+ :cwe => [285, 288, 425]
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,81 @@
1
+ require_relative "sql_check"
2
+
3
+ module Scanny
4
+ module Checks
5
+ module Sql
6
+ # Check for methods executing external params on
7
+ # database engine
8
+ class FindMethodCheck < SqlCheck
9
+ def pattern
10
+ [
11
+ pattern_find_by_sql_and_execute_on_models,
12
+ pattern_find_by_with_params,
13
+ pattern_find_by_with_conditions
14
+ ].join("|")
15
+ end
16
+
17
+ def check(node)
18
+ issue :low, warning_message, :cwe => 89
19
+ end
20
+
21
+ private
22
+
23
+ # User.find_by_sql
24
+ # @collection.paginate(options)
25
+ def pattern_find_by_sql_and_execute_on_models
26
+ <<-EOT
27
+ Send<name = :paginate>
28
+ |
29
+ SendWithArguments<
30
+ name = :execute | :find_by_sql | :paginate
31
+ >
32
+ EOT
33
+ end
34
+
35
+ # find_by_id(params[:search])
36
+ def pattern_find_by_with_params
37
+ <<-EOT
38
+ SendWithArguments<
39
+ arguments = ActualArguments<
40
+ array = [
41
+ any*,
42
+ SendWithArguments<
43
+ name = :[],
44
+ receiver = Send<
45
+ name = :params
46
+ >
47
+ >,
48
+ any*
49
+ ]
50
+ >,
51
+ name ^= :find_by
52
+ >
53
+ EOT
54
+ end
55
+
56
+ # find(:first, :conditions => "string")
57
+ def pattern_find_by_with_conditions
58
+ <<-EOT
59
+ SendWithArguments<
60
+ arguments = ActualArguments<
61
+ array = [
62
+ any+,
63
+ HashLiteral<
64
+ array = [
65
+ any{even},
66
+ SymbolLiteral<
67
+ value = :conditions
68
+ >,
69
+ any{odd}
70
+ ]
71
+ >
72
+ ]
73
+ >,
74
+ name = :find
75
+ >
76
+ EOT
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,43 @@
1
+ require_relative "sql_check"
2
+
3
+ module Scanny
4
+ module Checks
5
+ module Sql
6
+ # Check for methods executing external params on
7
+ # database engine with dynamic string
8
+ class FindMethodWithDynamicStringCheck < SqlCheck
9
+ def pattern
10
+ pattern_find_by_with_conditions_dynamic_string
11
+ end
12
+
13
+ def check(node)
14
+ issue :medium, warning_message, :cwe => 89
15
+ end
16
+
17
+ private
18
+
19
+ # find(:first, :conditions => "#{string}")
20
+ def pattern_find_by_with_conditions_dynamic_string
21
+ <<-EOT
22
+ SendWithArguments<
23
+ arguments = ActualArguments<
24
+ array = [
25
+ any+,
26
+ HashLiteral<
27
+ array = [
28
+ any{even},
29
+ SymbolLiteral<value = :conditions>,
30
+ DynamicString,
31
+ any{even}
32
+ ]
33
+ >
34
+ ]
35
+ >,
36
+ name = :find
37
+ >
38
+ EOT
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,80 @@
1
+ require_relative "sql_check"
2
+
3
+ module Scanny
4
+ module Checks
5
+ module Sql
6
+ # Check for methods executing external parameters on
7
+ # database engine with params attribute
8
+ class FindMethodWithParamsCheck < SqlCheck
9
+ def pattern
10
+ [
11
+ pattern_find_by_sql_and_execute_on_models_with_params,
12
+ pattern_find_with_conditions_and_params_or_limit
13
+ ].join("|")
14
+ end
15
+
16
+ def check(node)
17
+ issue :high, warning_message, :cwe => 89
18
+ end
19
+
20
+ private
21
+
22
+ # User.execute(params[:input])
23
+ def pattern_find_by_sql_and_execute_on_models_with_params
24
+ <<-EOT
25
+ SendWithArguments<
26
+ arguments = ActualArguments<
27
+ array = [
28
+ any*,
29
+ SendWithArguments<
30
+ name = :[],
31
+ receiver = Send<name = :params>
32
+ >
33
+ |
34
+ DynamicString<
35
+ array = [
36
+ any*,
37
+ ToString<
38
+ value = SendWithArguments<
39
+ name = :[],
40
+ receiver = Send<name = :params>
41
+ >
42
+ >,
43
+ any*
44
+ ]
45
+ >,
46
+ any*
47
+ ]
48
+ >,
49
+ name = :execute | :find_by_sql | :paginate
50
+ >
51
+ EOT
52
+ end
53
+
54
+ # find(:first, :conditions => params[:password])
55
+ def pattern_find_with_conditions_and_params_or_limit
56
+ <<-EOT
57
+ SendWithArguments<
58
+ arguments = ActualArguments<
59
+ array = [
60
+ any+,
61
+ HashLiteral<
62
+ array = [
63
+ any{even},
64
+ SymbolLiteral<value = :limit | :conditions>,
65
+ SendWithArguments<
66
+ name = :[],
67
+ receiver = Send<name = :params | :session>
68
+ >,
69
+ any{even}
70
+ ]
71
+ >
72
+ ]
73
+ >,
74
+ name = :find>
75
+ EOT
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,25 @@
1
+ require_relative "sql_check"
2
+
3
+ module Scanny
4
+ module Checks
5
+ module Sql
6
+ # Check for use of the "sanitize_sql" method
7
+ class SanitizeCheck < SqlCheck
8
+ def pattern
9
+ pattern_sanitize_sql
10
+ end
11
+
12
+ def check(node)
13
+ issue :info, warning_message, :cwe => 89
14
+ end
15
+
16
+ private
17
+
18
+ # sanitize_sql()
19
+ def pattern_sanitize_sql
20
+ "SendWithArguments<name = :sanitize_sql>"
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,14 @@
1
+ module Scanny
2
+ module Checks
3
+ module Sql
4
+ class SqlCheck < Check
5
+ private
6
+
7
+ def warning_message
8
+ "Use of external parameters in queries to the database " +
9
+ "can lead to SQL injection issue"
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,39 @@
1
+ require_relative "sql_check"
2
+
3
+ module Scanny
4
+ module Checks
5
+ module Sql
6
+ # Checks for use of dynamic strings in when creating an SQL query
7
+ class StringInterpolationWithParamsCheck < SqlCheck
8
+ def pattern
9
+ pattern_params_in_select
10
+ end
11
+
12
+ def check(node)
13
+ issue :high, warning_message, :cwe => 89
14
+ end
15
+
16
+ private
17
+
18
+ # "SELECT params[:input] FROM users"
19
+ def pattern_params_in_select
20
+ <<-EOT
21
+ DynamicString<
22
+ array = [
23
+ any*,
24
+ ToString<
25
+ value = SendWithArguments<
26
+ name = :[],
27
+ receiver = Send<name = :params>
28
+ >
29
+ >,
30
+ any*
31
+ ],
32
+ string ^= "SELECT"
33
+ >
34
+ EOT
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,53 @@
1
+ module Scanny
2
+ module Checks
3
+ module SSL
4
+ class VerifyCheck < Check
5
+ def pattern
6
+ [
7
+ pattern_ssl_verify_none,
8
+ pattern_ca_file
9
+ ].join("|")
10
+ end
11
+
12
+ def check(node)
13
+ issue :high, warning_message, :cwe => [296, 297, 298, 299, 300, 599]
14
+ end
15
+
16
+ private
17
+
18
+ def warning_message
19
+ "Disable certificate verification can " +
20
+ "lead to connect to an unauthorized server"
21
+ end
22
+
23
+ # OpenSSL::SSL::VERIFY_NONE
24
+ def pattern_ssl_verify_none
25
+ <<-EOT
26
+ ScopedConstant<
27
+ name = :VERIFY_NONE,
28
+ parent = ScopedConstant<
29
+ name = :SSL,
30
+ parent = ConstantAccess<name = :OpenSSL>
31
+ >
32
+ >
33
+ EOT
34
+ end
35
+
36
+
37
+ # ssl_context.ca_file = nil
38
+ def pattern_ca_file
39
+ <<-EOT
40
+ AttributeAssignment<
41
+ arguments = ActualArguments<
42
+ array = [
43
+ NilLiteral
44
+ ]
45
+ >,
46
+ name = :ca_path= | :ca_file=
47
+ >
48
+ EOT
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end