71 lines
3.7 KiB
Ruby
71 lines
3.7 KiB
Ruby
require 'msf/core/module/ui'
|
|
|
|
module Msf::Exploit::SQLi
|
|
class Common
|
|
include Msf::Module::UI
|
|
|
|
#
|
|
# Creates an instance of an SQL Injection object, instantiate directly only if you don't know the DBMS in use
|
|
#
|
|
# @param opts [Hash] a dictionnary containing the parameters needed
|
|
# @option opts [Integer] truncation_length : [Optional] The number of characters returned, if the query result is truncated
|
|
# @option opts [String] concat_separator : [Optional] The separator to use when concatenating rows (default ',')
|
|
# @option opts [String] second_concat_separator : [Optional] The separator to use when concatenating columns (default ';')
|
|
# @option opts [Boolean] safe : don't use group_concat, safer for large tables if group_concat truncates the result, but more queries will be performed
|
|
# @option opts [String] null_replacement : a string that will replace NULL values
|
|
# @option opts [Boolean] hex_encode_strings : encode strings as hex numbers, no quotes in the payload
|
|
# @option opts [Object] an encoder name, or a hash specifying a custom encoder, see Encoders in DBMS-specific classes
|
|
# @param query_proc is a block that will receive the payload, and should send the request to the target,
|
|
# - if it's a regular SQL injection, it should return the part of the response that is the query result (one row)
|
|
# - if it's a boolean-based blind SQL injection, it should return `true`, `false`, or a value that evaluates to one of them
|
|
# `true` if the query returned a result, false otherwise
|
|
# - if it's a time-based blind SQL injection, the return value does not matter, the time the block takes to run is used to leak information.
|
|
#
|
|
def initialize(datastore, framework, user_output, opts = {}, &query_proc)
|
|
raise ArgumentError, 'Missing the bloc that does the requests' unless block_given?
|
|
raise ArgumentError, 'Positional arguments can\'t be nil' if [datastore, framework, user_output].any?(&:nil?)
|
|
|
|
check_opts(opts)
|
|
@query_proc = query_proc
|
|
@safe = opts[:safe]
|
|
@concat_separator = opts[:concat_separator]
|
|
@second_concat_separator = opts[:second_concat_separator] || ';'
|
|
@null_replacement = opts[:null_replacement] || ''
|
|
@truncation_length = opts[:truncation_length] if opts[:truncation_length] && opts[:truncation_length].is_a?(Integer) && opts[:truncation_length] > 0
|
|
@hex_encode_strings = opts[:hex_encode_strings]
|
|
@encoder = opts[:encoder]
|
|
@datastore = datastore
|
|
@framework = framework
|
|
@user_output = user_output
|
|
end
|
|
|
|
#
|
|
# Queries the bloc with the given SQL query, and returns the result (this method is used in regular
|
|
# SQL injection exploits, where the query results are returned in the response to the user)
|
|
# @param query [String] The SQL query to execute
|
|
# @return [String] The query results
|
|
#
|
|
def run_sql(query)
|
|
vprint_status "{SQLi} Executing (#{query})"
|
|
if @hex_encode_strings
|
|
query = hex_encode_strings(query)
|
|
vprint_status "{SQLi} Encoded to (#{query})"
|
|
end
|
|
@query_proc.call(query)
|
|
end
|
|
|
|
attr_reader :datastore, :framework
|
|
attr_accessor :concat_separator, :second_concat_separator, :null_replacement, :truncation_length, :safe
|
|
|
|
private
|
|
|
|
#
|
|
# This method checks that the required options are present, and have valid values
|
|
#
|
|
def check_opts(opts)
|
|
raise ArgumentError, 'null_replacement option cannot contain single quotes' if opts[:null_replacement] && opts[:null_replacement].include?("'")
|
|
raise ArgumentError, 'truncation_length must be an integer' if opts[:truncation_length] && !opts[:truncation_length].is_a?(Integer)
|
|
end
|
|
end
|
|
end
|