Module: Contrast::Agent::Protect::Rule::SqlSampleBuilder::AttackBuilder

Included in:
NoSqli, Contrast::Agent::Protect::Rule::Sqli
Defined in:
lib/contrast/agent/protect/rule/sqli/sql_sample_builder.rb

Overview

This Module is how we apply the attack fo NoSQL and SQL Injection rule. It includes methods for building attack with match and database scanners

Instance Method Summary collapse

Instance Method Details

#append_match(context, input_analysis_result, result, query_string, **kwargs) ⇒ Object



144
145
146
147
148
# File 'lib/contrast/agent/protect/rule/sqli/sql_sample_builder.rb', line 144

def append_match context, input_analysis_result, result, query_string, **kwargs
  input_analysis_result.attack_count = input_analysis_result.attack_count + 1
  update_successful_attack_response(context, input_analysis_result, result, query_string)
  append_sample(context, input_analysis_result, result, query_string, **kwargs)
end

#build_attack_with_match(context, input_analysis_result, result, query_string, **kwargs) ⇒ Contrast::Agent::Reporting

Set up an attack result and assigns Database scanner for the No-SQL and SQLI injection detection rules



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/contrast/agent/protect/rule/sqli/sql_sample_builder.rb', line 73

def build_attack_with_match context, input_analysis_result, result, query_string, **kwargs
  return result if mode == :NO_ACTION || mode == :PERMIT

  attack_string = input_analysis_result.value
  regexp = Regexp.new(Regexp.escape(attack_string), Regexp::IGNORECASE)
  # extract struct result from kwargs
  agent_lib_struct_result = kwargs[:result_struct]
  return unless query_string.match?(regexp)

  database = kwargs[:database]
  scanner = select_scanner(database)
  ss = StringScanner.new(query_string)
  length = attack_string.length
  while ss.scan_until(regexp)
    # the pos of StringScanner is at the end of the regexp (input string), we need the beginning
    idx = ss.pos - attack_string.length
    last_boundary, boundary = scanner.crosses_boundary(query_string, idx, input_analysis_result.value)
    next unless last_boundary && boundary

    result ||= build_attack_result(context)

    # if the struct actually has the needed data in it - use it
    if agent_lib_struct_result.cs__is_a?(Hash)
      record_agent_lib_match(agent_lib_struct_result, length, kwargs)
    else
      record_match(idx, length, boundary, last_boundary, kwargs)
    end

    append_match(context, input_analysis_result, result, query_string, **kwargs)
  end

  result
end

#record_agent_lib_match(struct, length, kwargs) ⇒ Object



133
134
135
136
137
138
139
140
141
142
# File 'lib/contrast/agent/protect/rule/sqli/sql_sample_builder.rb', line 133

def record_agent_lib_match struct, length, kwargs
  kwargs[:start_idx] = struct[:start_index]
  kwargs[:end_idx] = if (struct[:end_index]).zero?
                       struct[:start_index] + length
                     else
                       struct[:end_index]
                     end
  kwargs[:boundary_overrun_idx] = struct[:boundary_overrun_index]
  kwargs[:input_boundary_idx] = struct[:input_boundary_index]
end

#record_match(idx, length, boundary, last_boundary, kwargs) ⇒ Object



123
124
125
126
127
128
# File 'lib/contrast/agent/protect/rule/sqli/sql_sample_builder.rb', line 123

def record_match idx, length, boundary, last_boundary, kwargs
  kwargs[:start_idx] = idx
  kwargs[:end_idx] = idx + length
  kwargs[:boundary_overrun_idx] = boundary
  kwargs[:input_boundary_idx] = last_boundary
end

#select_scanner(database) ⇒ Object



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/contrast/agent/protect/rule/sqli/sql_sample_builder.rb', line 107

def select_scanner database
  @scanners ||= {
      Contrast::Agent::Protect::Policy::AppliesSqliRule::DATABASE_MYSQL =>
      Contrast::Agent::Protect::Rule::Sqli::MysqlSqlScanner.new,
      Contrast::Agent::Protect::Policy::AppliesSqliRule::DATABASE_PG =>
      Contrast::Agent::Protect::Rule::Sqli::PostgresSqlScanner.new,
      Contrast::Agent::Protect::Policy::AppliesSqliRule::DATABASE_SQLITE =>
      Contrast::Agent::Protect::Rule::Sqli::SqliteSqlScanner.new,
      Contrast::Agent::Protect::Policy::AppliesNoSqliRule::DATABASE_NOSQL =>
      Contrast::Agent::Protect::Rule::NoSqli::MongoNoSqlScanner.new
  }.cs__freeze

  @default_scanner ||= Contrast::Agent::Protect::Rule::Sqli::DefaultSqlScanner.new
  @scanners[database.to_s] || @default_scanner
end