Class: Aikido::Zen::Scanners::SQLInjectionScanner
- Inherits:
-
Object
- Object
- Aikido::Zen::Scanners::SQLInjectionScanner
- Defined in:
- lib/aikido/zen/scanners/sql_injection_scanner.rb
Defined Under Namespace
Classes: Dialect
Constant Summary collapse
- DIALECTS =
Maps easy-to-use Symbols to a struct that keeps both the name and the internal identifier used by libzen.
{ common: Dialect.new(name: "SQL", internals_key: 0), mysql: Dialect.new(name: "MySQL", internals_key: 8), postgresql: Dialect.new(name: "PostgreSQL", internals_key: 9), sqlite: Dialect.new(name: "SQLite", internals_key: 12) }
Class Method Summary collapse
-
.call(query:, dialect:, sink:, context:, operation:) ⇒ Aikido::Zen::Attack?
Checks if the given SQL query may have dangerous user input injected, and returns an Attack if so, based on the current request.
- .skips_on_nil_context? ⇒ Boolean
Instance Method Summary collapse
- #attack? ⇒ Boolean
-
#initialize(query, input, dialect) ⇒ SQLInjectionScanner
constructor
A new instance of SQLInjectionScanner.
Constructor Details
#initialize(query, input, dialect) ⇒ SQLInjectionScanner
Returns a new instance of SQLInjectionScanner.
51 52 53 54 55 |
# File 'lib/aikido/zen/scanners/sql_injection_scanner.rb', line 51 def initialize(query, input, dialect) @query = query.downcase @input = input.downcase @dialect = dialect end |
Class Method Details
.call(query:, dialect:, sink:, context:, operation:) ⇒ Aikido::Zen::Attack?
Checks if the given SQL query may have dangerous user input injected, and returns an Attack if so, based on the current request.
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/aikido/zen/scanners/sql_injection_scanner.rb', line 28 def self.call(query:, dialect:, sink:, context:, operation:) dialect = DIALECTS.fetch(dialect) do Aikido::Zen.config.logger.warn "Unknown SQL dialect #{dialect.inspect}" DIALECTS[:common] end context.payloads.each do |payload| next unless new(query, payload.value.to_s, dialect).attack? return Attacks::SQLInjectionAttack.new( sink: sink, query: query, input: payload, dialect: dialect, context: context, operation: "#{sink.operation}.#{operation}", stack: Aikido::Zen.clean_stack_trace ) end nil end |
.skips_on_nil_context? ⇒ Boolean
9 10 11 |
# File 'lib/aikido/zen/scanners/sql_injection_scanner.rb', line 9 def self.skips_on_nil_context? true end |
Instance Method Details
#attack? ⇒ Boolean
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/aikido/zen/scanners/sql_injection_scanner.rb', line 57 def attack? # Ignore single char inputs since they shouldn't be able to do much harm return false if @input.length <= 1 # If the input is longer than the query, then it is not part of it return false if @input.length > @query.length # If the input is not included in the query at all, then we are safe return false unless @query.include?(@input) # If the input is solely alphanumeric, we can ignore it return false if /\A[[:alnum:]_]+\z/i.match?(@input) # If the input is a comma-separated list of numbers, ignore it. return false if /\A(?:\d+(?:,\s*)?)+\z/i.match?(@input) Internals.detect_sql_injection(@query, @input, @dialect) end |