Class: Contrast::Agent::Protect::Rule::Deserialization

Inherits:
Base
  • Object
show all
Includes:
Components::Logger::InstanceMethods
Defined in:
lib/contrast/agent/protect/rule/deserialization/deserialization.rb

Overview

This class handles our implementation of the Untrusted Deserialization Protect rule.

Constant Summary collapse

INPUT_NAME =

Used to name this input since input analysis isn’t done for this rule

'Serialized Gadget'
NAME =
'untrusted-deserialization'
BLOCK_MESSAGE =

The rule specific reason for raising a security exception.

'Untrusted Deserialization rule triggered. Deserialization blocked.'
ERB_GADGETS =

Gadgets that map to ERB modules

%W[object:ERB o:\bERB].cs__freeze
ACTION_DISPATCH_GADGETS =

Gadgets that map to ActionDispatch modules

%w[
  object:ActionDispatch::Routing::RouteSet::NamedRouteCollection
  o:\bActionDispatch::Routing::RouteSet::NamedRouteCollection
].cs__freeze
AREL_GADGETS =

Gadgets that map to Arel Modules

%w[string:Arel::Nodes::SqlLiteral object:Arel::Nodes o:\bArel::Nodes].cs__freeze
ERB =

Used to indicate to TeamServer the gadget is an ERB module

'ERB'
DISPATCH =

Used to indicate to TeamServer the gadget is an ActionDispatch module

'ActionDispatch'
AREL =

Used to indicate to TeamServer the gadget is an Arel module

'Arel'

Constants inherited from Base

Base::BLOCKING_MODES, Base::RULE_NAME, Base::STACK_COLLECTION_RESULTS, Base::SUSPICIOUS_REPORTING_RULES

Constants included from Filters

Filters::POSTFILTER_MODES

Instance Attribute Summary

Attributes inherited from Base

#mode

Instance Method Summary collapse

Methods included from Components::Logger::InstanceMethods

#cef_logger, #logger

Methods inherited from Base

#append_to_activity, #cef_logging, #classification, #classify, #enabled?, #excluded?, #initialize, #stream_safe?, #sub_rules, #update

Methods included from Filters

#postfilter, #postfilter?, #prefilter, #prefilter?

Methods included from Builders

#build_attack_result, #build_attack_with_match, #build_attack_without_match, #build_base_sample, #build_violation

Methods included from Components::Scope::InstanceMethods

#contrast_enter_method_scopes!, #contrast_exit_method_scopes!, #with_app_scope, #with_contrast_scope, #with_deserialization_scope, #with_split_scope

Constructor Details

This class inherits a constructor from Contrast::Agent::Protect::Rule::Base

Instance Method Details

#block_messageString

Return the specific blocking message for this rule.

Returns:

  • (String)

    the reason for the raised security exception.



55
56
57
# File 'lib/contrast/agent/protect/rule/deserialization/deserialization.rb', line 55

def block_message
  BLOCK_MESSAGE
end

#check_command_scope(gadget_command) ⇒ Object

Determine if the issued command was called while we’re deserializing. If we are, treat this as an attack.

Parameters:

  • gadget_command (String)

    the command being executed during the deserialization call.

Raises:



99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/contrast/agent/protect/rule/deserialization/deserialization.rb', line 99

def check_command_scope gadget_command
  # If we're within 'deserialization scope', then we've got a
  # deserialization method in our call stack.
  return unless in_deserialization_scope?

  context = Contrast::Agent::REQUEST_TRACKER.current
  kwargs = { COMMAND_SCOPE: true }
  ia_result = build_evaluation(gadget_command)
  result = build_attack_with_match(context, ia_result, nil, gadget_command, **kwargs)
  append_to_activity(context, result)
  raise(Contrast::SecurityException.new(self, BLOCK_MESSAGE)) if blocked?
end

#infilter(context, serialized_input) ⇒ Object

Determine if the input being deserialized is an attack and take appropriate actions.

Parameters:

Raises:



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/contrast/agent/protect/rule/deserialization/deserialization.rb', line 76

def infilter context, serialized_input
  return unless infilter?(context)

  gadget = find_gadget(serialized_input)
  # If there isn't a gadget, this isn't an attack, so we have nothing
  # to do here. Let the application carry on business as usual.
  return unless gadget

  ia_result = build_evaluation(serialized_input)
  kwargs = { GADGET_TYPE: gadget }
  result = build_attack_with_match(context, ia_result, nil, serialized_input, **kwargs)
  append_to_activity(context, result)
  record_triggered(context)

  raise(Contrast::SecurityException.new(self, block_message)) if blocked_violation?(result)
end

#infilter?(_context) ⇒ Boolean

Per the spec, this rule applies regardless of input. Only the mode of the rule and code exclusions apply at this point.

Returns:

  • (Boolean)

    should the rule apply to this call.



62
63
64
65
66
67
# File 'lib/contrast/agent/protect/rule/deserialization/deserialization.rb', line 62

def infilter?_context
  return false unless enabled?
  return false if protect_excluded_by_url?(rule_name)

  true
end

#rule_nameString

Return the TeamServer understood id / name of this rule.

Returns:

  • (String)

    the TeamServer understood id / name of this rule.



48
49
50
# File 'lib/contrast/agent/protect/rule/deserialization/deserialization.rb', line 48

def rule_name
  NAME
end