2020-07-10 22:15:12 -05:00
2020-06-18 17:28:47 +02:00
module Msf::Exploit::SQLi
class Common
2020-06-26 15:06:30 -05:00
include Msf :: Module :: UI
2020-06-18 17:28:47 +02:00
#
2020-08-27 19:08:27 +02:00
# Creates an instance of an SQL Injection object, users should use the create_dbms method of Msf::Exploit::SQLi instead
2020-06-18 17:28:47 +02:00
#
2020-08-27 19:08:27 +02:00
# @param datastore [DataStore]
# @param framework [Framework]
# @param user_output [Rex::Ui::Text::Output::Stdio]
2023-09-24 17:42:00 -04:00
# @param opts [Hash] a dictionary containing the parameters needed
2020-06-18 17:28:47 +02:00
# @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
2020-08-27 19:08:27 +02:00
# @param query_proc [Proc] a block that will receive the payload, and should send the request to the target,
2020-06-18 17:28:47 +02:00
# - 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
2020-06-25 12:46:05 +02:00
# - 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.
2020-06-18 17:28:47 +02:00
#
2020-06-27 18:28:12 +02:00
def initialize ( datastore , framework , user_output , opts = { } , & query_proc )
2023-09-24 17:42:00 -04:00
raise ArgumentError , 'Missing the block that does the requests' unless block_given?
2020-06-30 16:16:35 +02:00
raise ArgumentError , 'Positional arguments can\'t be nil' if [ datastore , framework , user_output ] . any? ( & :nil? )
2020-06-18 17:28:47 +02:00
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 ]
2020-06-26 15:06:30 -05:00
@datastore = datastore
@framework = framework
@user_output = user_output
2020-06-18 17:28:47 +02:00
end
#
2023-09-24 17:42:00 -04:00
# Queries the block with the given SQL query, without necessarily returning a result (needed for
2020-08-09 19:21:57 +02:00
# example when uploading a file using a time-based SQL injection, as it's not necessary to
2023-09-24 17:42:00 -04:00
# run multiple queries for that purpose), not to be overridden, it is guaranteed that the query
2020-08-09 19:21:57 +02:00
# will run only once.
2020-06-18 17:28:47 +02:00
# @param query [String] The SQL query to execute
2020-08-27 19:08:27 +02:00
# @return [void]
2020-06-18 17:28:47 +02:00
#
2020-08-09 19:21:57 +02:00
def raw_run_sql ( query )
2020-06-27 18:28:12 +02:00
vprint_status " {SQLi} Executing ( #{ query } ) "
2020-06-18 17:28:47 +02:00
if @hex_encode_strings
query = hex_encode_strings ( query )
2020-06-27 18:28:12 +02:00
vprint_status " {SQLi} Encoded to ( #{ query } ) "
2020-06-18 17:28:47 +02:00
end
@query_proc . call ( query )
end
2020-06-22 17:41:20 +02:00
2020-08-09 19:21:57 +02:00
#
2023-09-24 17:42:00 -04:00
# Queries the block with the given SQL query, and returns the result, this method is overridden in
2020-08-09 19:21:57 +02:00
# blind SQL injection classes, implementing the logic of leaking one bit at a time, and working
# exactly the same as this method.
# @param query [String] The SQL query to execute
# @return [String] The query results
#
def run_sql ( query )
raw_run_sql ( query )
end
2020-06-27 18:28:12 +02:00
attr_reader :datastore , :framework
2020-07-01 23:00:23 +02:00
attr_accessor :concat_separator , :second_concat_separator , :null_replacement , :truncation_length , :safe
2020-06-18 17:28:47 +02:00
private
#
# This method checks that the required options are present, and have valid values
2020-08-27 19:08:27 +02:00
# @param opts [Hash] the options provided by the user
# @return [void]
2020-06-18 17:28:47 +02:00
#
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