Class: Contrast::Agent::Protect::Rule::Xxe::EntityWrapper

Inherits:
Object
  • Object
show all
Defined in:
lib/contrast/agent/protect/rule/xxe/entity_wrapper.rb

Overview

A holder for the external entity which was determined to be an attack.

Constant Summary collapse

SYSTEM_ID_REGEXP =

<!ENTITY name SYSTEM “URI”>

/<!ENTITY\s+(?<name>[a-zA-Z0-f]+)\s+SYSTEM\s+"(?<id>.*?)">/.cs__freeze
PUBLIC_ID_REGEXP =

<!ENTITY name PUBLIC “public_ID” “URI”>

/<!ENTITY\s+(?<name>[a-zA-Z0-f]+)\s+PUBLIC\s+".*?"\s+"(?<id>.*?)">/.cs__freeze
DTD_MARKER =
'.dtd'
FILE_START =
'file:'
FTP_START =
'ftp:'
GOPHER_START =
'gopher:'
JAR_START =
'jar:'
UP_DIR_LINUX =
'../'
UP_DIR_WIN =
'..\\'
FILE_PATTERN_WINDOWS =

we only use this against lowercase strings, removed A-Z for speed

/^[\\\\]*[a-z]{1,3}:.*/.cs__freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(entity) ⇒ EntityWrapper

Returns a new instance of EntityWrapper.



14
15
16
17
18
# File 'lib/contrast/agent/protect/rule/xxe/entity_wrapper.rb', line 14

def initialize entity
  @system_id = parse_system_id(entity)
  # an entity cannot be system and public
  @public_id = parse_public_id(entity) unless @system_id
end

Instance Attribute Details

#public_idObject (readonly)

Returns the value of attribute public_id.



12
13
14
# File 'lib/contrast/agent/protect/rule/xxe/entity_wrapper.rb', line 12

def public_id
  @public_id
end

#system_idObject (readonly)

Returns the value of attribute system_id.



12
13
14
# File 'lib/contrast/agent/protect/rule/xxe/entity_wrapper.rb', line 12

def system_id
  @system_id
end

Instance Method Details

#external_entity?Boolean

Returns:

  • (Boolean)


20
21
22
23
24
25
26
27
# File 'lib/contrast/agent/protect/rule/xxe/entity_wrapper.rb', line 20

def external_entity?
  @_external_entity ||= begin
    return external_id?(@system_id) if @system_id
    return external_id?(@public_id) if @public_id

    false
  end
end

#external_id?(entity_id) ⇒ Boolean

Returns:

  • (Boolean)


52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/contrast/agent/protect/rule/xxe/entity_wrapper.rb', line 52

def external_id? entity_id
  return false unless entity_id

  # downcase this since we don't have an ignore case compare
  tmp_id = entity_id.to_s.downcase

  # external if http(s) and not a dtd file
  http = tmp_id.start_with?(Contrast::Utils::ObjectShare::HTTP_START,
                            Contrast::Utils::ObjectShare::HTTPS_START)
  return true if http && !tmp_id.end_with?(DTD_MARKER)

  # external if using external protocol
  return true if tmp_id.start_with?(FTP_START, FILE_START,
                                    JAR_START, GOPHER_START)

  # external if start with path marker (/ or .)
  return true if tmp_id.start_with?(Contrast::Utils::ObjectShare::SLASH,
                                    Contrast::Utils::ObjectShare::PERIOD)

  # external if start with path up marker (../ or ..\)
  return true if tmp_id.start_with?(UP_DIR_LINUX, UP_DIR_WIN)

  # external if matches windows file pattern
  tmp_id.match?(FILE_PATTERN_WINDOWS)
end

#parse_public_id(entity) ⇒ Object



38
39
40
41
# File 'lib/contrast/agent/protect/rule/xxe/entity_wrapper.rb', line 38

def parse_public_id entity
  match = PUBLIC_ID_REGEXP.match(entity)
  match[:id] if match
end

#parse_system_id(entity) ⇒ Object



31
32
33
34
# File 'lib/contrast/agent/protect/rule/xxe/entity_wrapper.rb', line 31

def parse_system_id entity
  match = SYSTEM_ID_REGEXP.match(entity)
  match[:id] if match
end