Class: Aikido::Zen::Scanners::SQLInjectionScanner
- Inherits:
-
Object
- Object
- Aikido::Zen::Scanners::SQLInjectionScanner
- Defined in:
- lib/aikido/zen/scanners/sql_injection_scanner.rb
Instance Attribute Summary collapse
-
#failed_to_tokenize ⇒ Object
readonly
Returns the value of attribute failed_to_tokenize.
Class Method Summary collapse
-
.call(query:, dialect:, scan:, 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.
55 56 57 58 59 |
# File 'lib/aikido/zen/scanners/sql_injection_scanner.rb', line 55 def initialize(query, input, dialect) @query = query.downcase @input = input.downcase @dialect = dialect end |
Instance Attribute Details
#failed_to_tokenize ⇒ Object (readonly)
Returns the value of attribute failed_to_tokenize.
53 54 55 |
# File 'lib/aikido/zen/scanners/sql_injection_scanner.rb', line 53 def failed_to_tokenize @failed_to_tokenize end |
Class Method Details
.call(query:, dialect:, scan:, 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.
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/aikido/zen/scanners/sql_injection_scanner.rb', line 26 def self.call(query:, dialect:, scan:, sink:, context:, operation:) dialect = Aikido::Zen::SQL::Dialects.fetch(dialect) context.payloads.each do |payload| scanner = new(query, payload.value.to_s, dialect) next unless scanner.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, failed_to_tokenize: scanner.failed_to_tokenize ) rescue Aikido::Zen::InternalsError => error Aikido::Zen.config.logger.warn(error.) scan.track_error(error, self) rescue => error scan.track_error(error, self) 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
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/aikido/zen/scanners/sql_injection_scanner.rb', line 61 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 Aikido::Zen::Helpers.regexp_with_timeout(/\A[[:alnum:]_]+\z/i).match?(@input) # If the input is a comma-separated list of numbers, ignore it. return false if Aikido::Zen::Helpers.regexp_with_timeout(/\A[ ,]*\d[ ,\d]*\z/).match?(@input) result = Internals.detect_sql_injection(@query, @input, @dialect) case result when 0 false when 1 true when 3 @failed_to_tokenize = true Aikido::Zen.config.block_invalid_sql? end rescue => err return true if defined?(Regexp::TimeoutError) && err.is_a?(Regexp::TimeoutError) raise err end |