contrast-agent 5.0.0 → 5.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/.simplecov +1 -2
  3. data/ext/cs__assess_kernel/cs__assess_kernel.c +7 -4
  4. data/ext/cs__assess_module/cs__assess_module.c +48 -38
  5. data/ext/cs__common/cs__common.c +4 -0
  6. data/ext/cs__common/cs__common.h +1 -0
  7. data/ext/cs__contrast_patch/cs__contrast_patch.c +52 -27
  8. data/ext/cs__contrast_patch/cs__contrast_patch.h +2 -0
  9. data/ext/cs__scope/cs__scope.c +747 -0
  10. data/ext/cs__scope/cs__scope.h +88 -0
  11. data/ext/cs__scope/extconf.rb +5 -0
  12. data/lib/contrast/agent/assess/contrast_event.rb +20 -13
  13. data/lib/contrast/agent/assess/contrast_object.rb +4 -1
  14. data/lib/contrast/agent/assess/policy/propagation_node.rb +2 -5
  15. data/lib/contrast/agent/assess/policy/propagator/match_data.rb +6 -0
  16. data/lib/contrast/agent/assess/policy/trigger_method.rb +4 -1
  17. data/lib/contrast/agent/assess/rule/response/auto_complete_rule.rb +69 -0
  18. data/lib/contrast/agent/assess/rule/response/base_rule.rb +25 -12
  19. data/lib/contrast/agent/assess/rule/response/body_rule.rb +109 -0
  20. data/lib/contrast/agent/assess/rule/response/cache_control_header_rule.rb +157 -0
  21. data/lib/contrast/agent/assess/rule/response/click_jacking_header_rule.rb +26 -0
  22. data/lib/contrast/agent/assess/rule/response/csp_header_insecure_rule.rb +100 -0
  23. data/lib/contrast/agent/assess/rule/response/csp_header_missing_rule.rb +26 -0
  24. data/lib/contrast/agent/assess/rule/response/framework/rails_support.rb +29 -0
  25. data/lib/contrast/agent/assess/rule/response/header_rule.rb +70 -0
  26. data/lib/contrast/agent/assess/rule/response/hsts_header_rule.rb +36 -0
  27. data/lib/contrast/agent/assess/rule/response/parameters_pollution_rule.rb +61 -0
  28. data/lib/contrast/agent/assess/rule/response/x_content_type_header_rule.rb +26 -0
  29. data/lib/contrast/agent/assess/rule/response/x_xss_protection_header_rule.rb +35 -0
  30. data/lib/contrast/agent/middleware.rb +1 -0
  31. data/lib/contrast/agent/patching/policy/after_load_patcher.rb +1 -3
  32. data/lib/contrast/agent/patching/policy/patch.rb +2 -6
  33. data/lib/contrast/agent/patching/policy/patcher.rb +1 -1
  34. data/lib/contrast/agent/protect/input_analyzer/input_analyzer.rb +94 -0
  35. data/lib/contrast/agent/protect/rule/base.rb +28 -1
  36. data/lib/contrast/agent/protect/rule/base_service.rb +10 -1
  37. data/lib/contrast/agent/protect/rule/cmd_injection.rb +2 -0
  38. data/lib/contrast/agent/protect/rule/deserialization.rb +6 -0
  39. data/lib/contrast/agent/protect/rule/http_method_tampering.rb +5 -1
  40. data/lib/contrast/agent/protect/rule/no_sqli.rb +1 -0
  41. data/lib/contrast/agent/protect/rule/path_traversal.rb +1 -0
  42. data/lib/contrast/agent/protect/rule/sqli/sqli_input_classification.rb +124 -0
  43. data/lib/contrast/agent/protect/rule/sqli/sqli_worth_watching.rb +121 -0
  44. data/lib/contrast/agent/protect/rule/sqli.rb +33 -0
  45. data/lib/contrast/agent/protect/rule/xxe.rb +4 -0
  46. data/lib/contrast/agent/reporting/input_analysis/input_analysis.rb +44 -0
  47. data/lib/contrast/agent/reporting/input_analysis/input_analysis_result.rb +115 -0
  48. data/lib/contrast/agent/reporting/input_analysis/input_type.rb +44 -0
  49. data/lib/contrast/agent/reporting/input_analysis/score_level.rb +21 -0
  50. data/lib/contrast/agent/reporting/report.rb +1 -0
  51. data/lib/contrast/agent/reporting/reporter.rb +8 -1
  52. data/lib/contrast/agent/reporting/reporting_events/finding.rb +77 -34
  53. data/lib/contrast/agent/reporting/reporting_events/finding_event.rb +88 -59
  54. data/lib/contrast/agent/reporting/reporting_events/{finding_object.rb → finding_event_object.rb} +24 -20
  55. data/lib/contrast/agent/reporting/reporting_events/finding_event_parent_object.rb +39 -0
  56. data/lib/contrast/agent/reporting/reporting_events/finding_event_property.rb +40 -0
  57. data/lib/contrast/agent/reporting/reporting_events/{finding_signature.rb → finding_event_signature.rb} +29 -24
  58. data/lib/contrast/agent/reporting/reporting_events/finding_event_source.rb +12 -8
  59. data/lib/contrast/agent/reporting/reporting_events/{finding_stack.rb → finding_event_stack.rb} +23 -19
  60. data/lib/contrast/agent/reporting/reporting_events/{finding_taint_range.rb → finding_event_taint_range.rb} +17 -15
  61. data/lib/contrast/agent/reporting/reporting_events/finding_request.rb +26 -53
  62. data/lib/contrast/agent/reporting/reporting_events/poll.rb +29 -0
  63. data/lib/contrast/agent/reporting/reporting_events/reporting_event.rb +5 -4
  64. data/lib/contrast/agent/reporting/reporting_events/route_discovery.rb +1 -0
  65. data/lib/contrast/agent/reporting/reporting_events/server_activity.rb +1 -1
  66. data/lib/contrast/agent/reporting/reporting_utilities/audit.rb +10 -3
  67. data/lib/contrast/agent/reporting/reporting_utilities/endpoints.rb +0 -1
  68. data/lib/contrast/agent/reporting/reporting_utilities/reporter_client.rb +1 -0
  69. data/lib/contrast/agent/reporting/reporting_utilities/reporter_client_utils.rb +28 -20
  70. data/lib/contrast/agent/reporting/reporting_utilities/response_handler.rb +1 -1
  71. data/lib/contrast/agent/reporting/reporting_utilities/response_handler_utils.rb +13 -1
  72. data/lib/contrast/agent/request_context.rb +6 -1
  73. data/lib/contrast/agent/request_context_extend.rb +87 -10
  74. data/lib/contrast/agent/scope.rb +102 -107
  75. data/lib/contrast/agent/service_heartbeat.rb +45 -2
  76. data/lib/contrast/agent/version.rb +1 -1
  77. data/lib/contrast/api/decorators/bot_blocker.rb +37 -0
  78. data/lib/contrast/api/decorators/ip_denylist.rb +37 -0
  79. data/lib/contrast/api/decorators/rasp_rule_sample.rb +29 -0
  80. data/lib/contrast/api/decorators/user_input.rb +11 -1
  81. data/lib/contrast/api/decorators/virtual_patch.rb +34 -0
  82. data/lib/contrast/components/logger.rb +5 -0
  83. data/lib/contrast/components/protect.rb +4 -2
  84. data/lib/contrast/components/scope.rb +98 -91
  85. data/lib/contrast/config/agent_configuration.rb +58 -12
  86. data/lib/contrast/config/api_configuration.rb +100 -12
  87. data/lib/contrast/config/api_proxy_configuration.rb +55 -3
  88. data/lib/contrast/config/application_configuration.rb +114 -15
  89. data/lib/contrast/config/assess_configuration.rb +106 -12
  90. data/lib/contrast/config/assess_rules_configuration.rb +44 -3
  91. data/lib/contrast/config/base_configuration.rb +1 -0
  92. data/lib/contrast/config/certification_configuration.rb +74 -3
  93. data/lib/contrast/config/exception_configuration.rb +61 -3
  94. data/lib/contrast/config/heap_dump_configuration.rb +101 -17
  95. data/lib/contrast/config/inventory_configuration.rb +64 -3
  96. data/lib/contrast/config/logger_configuration.rb +46 -3
  97. data/lib/contrast/config/protect_rule_configuration.rb +36 -9
  98. data/lib/contrast/config/protect_rules_configuration.rb +120 -17
  99. data/lib/contrast/config/request_audit_configuration.rb +68 -3
  100. data/lib/contrast/config/ruby_configuration.rb +96 -22
  101. data/lib/contrast/config/sampling_configuration.rb +76 -10
  102. data/lib/contrast/config/server_configuration.rb +56 -11
  103. data/lib/contrast/config/service_configuration.rb +66 -11
  104. data/lib/contrast/configuration.rb +6 -3
  105. data/lib/contrast/extension/assess/erb.rb +17 -0
  106. data/lib/contrast/logger/cef_log.rb +151 -0
  107. data/lib/contrast/utils/hash_digest.rb +14 -6
  108. data/lib/contrast/utils/log_utils.rb +114 -0
  109. data/lib/contrast/utils/middleware_utils.rb +6 -7
  110. data/lib/contrast/utils/net_http_base.rb +12 -9
  111. data/lib/contrast/utils/patching/policy/patch_utils.rb +0 -4
  112. data/lib/contrast.rb +4 -3
  113. data/resources/assess/policy.json +10 -0
  114. data/ruby-agent.gemspec +2 -2
  115. data/service_executables/VERSION +1 -1
  116. data/service_executables/linux/contrast-service +0 -0
  117. data/service_executables/mac/contrast-service +0 -0
  118. metadata +47 -19
  119. data/lib/contrast/agent/assess/rule/response/autocomplete_rule.rb +0 -130
  120. data/lib/contrast/extension/kernel.rb +0 -54
@@ -1,130 +0,0 @@
1
- # Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
- # frozen_string_literal: true
3
-
4
- require 'contrast/agent/assess/rule/response/base_rule'
5
- require 'contrast/utils/string_utils'
6
-
7
- module Contrast
8
- module Agent
9
- module Assess
10
- module Rule
11
- module Response
12
- # These rules check the content of the HTTP Response to determine if the body contains a form which
13
- # incorrectly sets the autocomplete attribute.
14
- class Autocomplete < BaseRule
15
- def rule_id
16
- 'autocomplete-missing'
17
- end
18
-
19
- protected
20
-
21
- HTML_PROP = 'html'.cs__freeze
22
- START_PROP = 'start'.cs__freeze
23
- END_PROP = 'end'.cs__freeze
24
-
25
- # Rules discern which responses they can/should analyze.
26
- #
27
- # @param response [Contrast::Agent::Response] the response of the application
28
- def analyze_response? response
29
- super && body?(response)
30
- end
31
-
32
- # Determine if the Response violates the Rule or not. If it does, return the evidence that proves it so.
33
- #
34
- # @param response [Contrast::Agent::Response] the response of the application
35
- # @return [Hash, nil] the evidence required to prove the violation of the rule
36
- def violated? response
37
- body = response.body
38
- forms = forms(body)
39
- forms.each do |form|
40
- # Because TeamServer will reject any subsequent form on the same page due to deduplication, we can
41
- # skip out on the first violation.
42
- return form if autocomplete?(form[HTML_PROP])
43
- end
44
- nil
45
- end
46
-
47
- # Find the forms in this body, if any, so as to determine if they violate this rule.
48
- #
49
- # @param body [String]
50
- # @return [Array<Hash>] the forms of this body, as well as their start and end indexes.
51
- def forms body
52
- forms = []
53
- body_start = 0
54
- # The instance of "<form" in the body may be a form. Turn them into chunks to check.
55
- potential_forms = body.split(form_start)
56
- potential_forms.each do |potential_form|
57
- # We can consider this a form if the next character is one of whitespace of form tag closing
58
- # characters.
59
- next unless potential_form
60
- next unless form_openings.any? { |opening| potential_form.start_with?(opening) }
61
-
62
- body_start = body.index(form_start, body_start)
63
- next unless body_start
64
-
65
- form_stop = potential_form.index('>').to_i
66
- next unless form_stop
67
-
68
- body_close = body_start + 6 + form_stop
69
- forms << capture(body, body_start, body_close, form_stop)
70
- body_start = body_close
71
- end
72
- forms
73
- end
74
-
75
- def form_start
76
- /<form/i
77
- end
78
-
79
- def form_openings
80
- [' ', "\n", "\r", "\t", '>']
81
- end
82
-
83
- def off_values
84
- [/"off"/, /'off'/, /off /, /off>/]
85
- end
86
-
87
- # Determine if the given form does not have a valid autocomplete tag. Because autocompletion is on by
88
- # default, the form must both have the value and set it to being disabled to not autocomplete.
89
- #
90
- # @param form [String] the form tag
91
- # @return [Boolean]
92
- def autocomplete? form
93
- idx = form =~ /autocomplete=/i
94
- return true unless idx
95
-
96
- # Adjust for the length of 'autocomplete='
97
- idx += 13
98
- off_values.each do |off_value|
99
- return false if (form =~ off_value) == idx
100
- end
101
- true
102
- end
103
-
104
- # Capture the information needed to build the properties of this finding by parsing out from the body
105
- #
106
- # @param body [String] the entire HTTP Response body
107
- # @param body_start [Integer] the start of the range to take from the body
108
- # @param body_close [Integer] the end of the range to take from the body
109
- # @param form_stop [Integer] the index of the end of the form from its start
110
- # @return [Hash]
111
- def capture body, body_start, body_close, form_stop
112
- form = {}
113
- # Capture the 50 characters in front of the form, or up to the start if the form starts before 50.
114
- capture_start = body_start < 50 ? 0 : body_start - 50
115
- # Start is where the '<form' is in the body
116
- # 6 accounts for the characters in the form and the opening char
117
- # potential_form.index('>') accounts for finding the rest of the form
118
- # 50 accounts for the context to capture beyond
119
- capture_close = body_close + 50
120
- form[HTML_PROP] = body[capture_start...capture_close]
121
- form[START_PROP] = body_start < 50 ? body_start : 50
122
- form[END_PROP] = form[START_PROP] + 6 + form_stop
123
- form
124
- end
125
- end
126
- end
127
- end
128
- end
129
- end
130
- end
@@ -1,54 +0,0 @@
1
- # Copyright (c) 2022 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details.
2
- # frozen_string_literal: true
3
-
4
- require 'contrast/components/scope'
5
-
6
- # This is a reasonable place for the Kernel#catch hook to live.
7
- # No current plans for component re-design, but if we had some kind of
8
- # "do this when a component is hooked in" thing, this would live there.
9
- # For now, it's over-engineering to live anywhere else. -ajm
10
- module Kernel # :nodoc:
11
- alias_method :cs__catch, :catch
12
-
13
- # In the event of a `throw`, we need to override `catch`
14
- # to save & restore scope state:
15
- #
16
- # scope_level == 0
17
- #
18
- # catch(:abc) do
19
- # with_contrast_scope do
20
- # throw :abc # will leak
21
- # end
22
- # end
23
- #
24
- # scope_level == 1
25
- #
26
- # Frankly, this isn't how scope should be used. This is in place of
27
- # proper `ensure` blocks within the instrumentation call stack.
28
- # This will actually /create/ scope leaks if you're doing something like:
29
- #
30
- # catch(:ohno) do
31
- # enter scope
32
- # end
33
- #
34
- # abc()
35
- #
36
- # exit scope
37
- #
38
- # i.e. if you intend to change net scope across a catch block boundary.
39
-
40
- private
41
-
42
- def catch *args, &block
43
- # Save current scope level
44
- scope_level = ::Contrast::SCOPE.scope_for_current_ec.instance_variable_get(:@contrast_scope)
45
-
46
- # Run original catch with block.
47
- retval = cs__catch(*args, &block)
48
-
49
- # Restore scope.
50
- ::Contrast::SCOPE.scope_for_current_ec.instance_variable_set(:@contrast_scope, scope_level)
51
-
52
- retval
53
- end
54
- end