Merge branch 'staging/electro-release' into feature/MSP-9641/cred-rpc-calls
commit
1e32574768
|
@ -3,6 +3,8 @@
|
|||
--exclude \.ut\.rb/
|
||||
--exclude \.ts\.rb/
|
||||
--files CONTRIBUTING.md,COPYING,HACKING,LICENSE
|
||||
app/**/*.rb
|
||||
lib/msf/**/*.rb
|
||||
lib/metasploit/**/*.rb
|
||||
lib/rex/**/*.rb
|
||||
plugins/**/*.rb
|
||||
|
|
4
Gemfile
4
Gemfile
|
@ -7,9 +7,9 @@ group :db do
|
|||
# Needed for Msf::DbManager
|
||||
gem 'activerecord', '>= 3.0.0', '< 4.0.0'
|
||||
# Metasploit::Credential database models
|
||||
gem 'metasploit-credential', git: 'github-metasploit-credential:rapid7/metasploit-credential.git', tag: 'v0.7.1.pre.electro.pre.release'
|
||||
gem 'metasploit-credential', '>= 0.7.10.pre.core.pre.search', '< 0.8'
|
||||
# Database models shared between framework and Pro.
|
||||
gem 'metasploit_data_models', '>= 0.18.0', '< 0.19'
|
||||
gem 'metasploit_data_models', '~> 0.19'
|
||||
# Needed for module caching in Mdm::ModuleDetails
|
||||
gem 'pg', '>= 0.11'
|
||||
end
|
||||
|
|
28
Gemfile.lock
28
Gemfile.lock
|
@ -1,15 +1,3 @@
|
|||
GIT
|
||||
remote: github-metasploit-credential:rapid7/metasploit-credential.git
|
||||
revision: d5784729bf65a6419a05e2aaac1be217c4f93ff1
|
||||
tag: v0.7.1.pre.electro.pre.release
|
||||
specs:
|
||||
metasploit-credential (0.7.1.pre.electro.pre.release)
|
||||
metasploit-concern (~> 0.1.0)
|
||||
metasploit-model (>= 0.25.6)
|
||||
metasploit_data_models (>= 0.18.0.pre.compatibility, < 0.19)
|
||||
rubyntlm
|
||||
rubyzip (~> 1.1)
|
||||
|
||||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
|
@ -53,6 +41,8 @@ GEM
|
|||
i18n (~> 0.6, >= 0.6.4)
|
||||
multi_json (~> 1.0)
|
||||
arel (3.0.3)
|
||||
arel-helpers (2.0.0)
|
||||
activerecord (>= 3.1.0, < 5)
|
||||
bcrypt (3.1.7)
|
||||
builder (3.0.4)
|
||||
coderay (1.1.0)
|
||||
|
@ -70,11 +60,19 @@ GEM
|
|||
json (1.8.1)
|
||||
metasploit-concern (0.1.1)
|
||||
activesupport (~> 3.0, >= 3.0.0)
|
||||
metasploit-credential (0.7.10.pre.core.pre.search)
|
||||
metasploit-concern (~> 0.1.0)
|
||||
metasploit-model (>= 0.25.6)
|
||||
metasploit_data_models (~> 0.19)
|
||||
pg
|
||||
rubyntlm
|
||||
rubyzip (~> 1.1)
|
||||
metasploit-model (0.25.6)
|
||||
activesupport
|
||||
metasploit_data_models (0.18.0)
|
||||
metasploit_data_models (0.19.0)
|
||||
activerecord (>= 3.2.13, < 4.0.0)
|
||||
activesupport
|
||||
arel-helpers
|
||||
metasploit-concern (~> 0.1.0)
|
||||
metasploit-model (>= 0.25.1, < 0.26)
|
||||
pg
|
||||
|
@ -161,9 +159,9 @@ DEPENDENCIES
|
|||
factory_girl (>= 4.1.0)
|
||||
factory_girl_rails
|
||||
fivemat (= 1.2.1)
|
||||
metasploit-credential!
|
||||
metasploit-credential (>= 0.7.10.pre.core.pre.search, < 0.8)
|
||||
metasploit-framework!
|
||||
metasploit_data_models (>= 0.18.0, < 0.19)
|
||||
metasploit_data_models (~> 0.19)
|
||||
network_interface (~> 0.0.1)
|
||||
pcaprub
|
||||
pg (>= 0.11)
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
require 'metasploit/framework/credential'
|
||||
|
||||
module Metasploit
|
||||
module Framework
|
||||
|
||||
# This class is responsible for taking datastore options from the snmp_login module
|
||||
# and yielding appropriate {Metasploit::Framework::Credential}s to the {Metasploit::Framework::LoginScanner::SNMP}.
|
||||
# This one has to be different from {credentialCollection} as it will only have a {Metasploit::Framework::Credential#public}
|
||||
# It may be slightly confusing that the attribues are called password and pass_file, because this is what the legacy
|
||||
# module used. However, community Strings are now considered more to be public credentials than private ones.
|
||||
class CommunityStringCollection
|
||||
# @!attribute pass_file
|
||||
# Path to a file containing passwords, one per line
|
||||
# @return [String]
|
||||
attr_accessor :pass_file
|
||||
|
||||
# @!attribute password
|
||||
# @return [String]
|
||||
attr_accessor :password
|
||||
|
||||
# @!attribute prepended_creds
|
||||
# List of credentials to be tried before any others
|
||||
#
|
||||
# @see #prepend_cred
|
||||
# @return [Array<Credential>]
|
||||
attr_accessor :prepended_creds
|
||||
|
||||
# @option opts [String] :pass_file See {#pass_file}
|
||||
# @option opts [String] :password See {#password}
|
||||
# @option opts [Array<Credential>] :prepended_creds ([]) See {#prepended_creds}
|
||||
def initialize(opts = {})
|
||||
opts.each do |attribute, value|
|
||||
public_send("#{attribute}=", value)
|
||||
end
|
||||
self.prepended_creds ||= []
|
||||
end
|
||||
|
||||
# Combines all the provided credential sources into a stream of {Credential}
|
||||
# objects, yielding them one at a time
|
||||
#
|
||||
# @yieldparam credential [Metasploit::Framework::Credential]
|
||||
# @return [void]
|
||||
def each
|
||||
begin
|
||||
if pass_file.present?
|
||||
pass_fd = File.open(pass_file, 'r:binary')
|
||||
pass_fd.each_line do |line|
|
||||
line.chomp!
|
||||
yield Metasploit::Framework::Credential.new(public: line, paired: false)
|
||||
end
|
||||
end
|
||||
|
||||
if password.present?
|
||||
yield Metasploit::Framework::Credential.new(public: password, paired: false)
|
||||
end
|
||||
|
||||
ensure
|
||||
pass_fd.close if pass_fd && !pass_fd.closed?
|
||||
end
|
||||
end
|
||||
|
||||
# Add {Credential credentials} that will be yielded by {#each}
|
||||
#
|
||||
# @see prepended_creds
|
||||
# @param cred [Credential]
|
||||
# @return [self]
|
||||
def prepend_cred(cred)
|
||||
prepended_creds.unshift cred
|
||||
self
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -78,7 +78,9 @@ module Metasploit
|
|||
end
|
||||
|
||||
def ==(other)
|
||||
other.public == self.public && other.private == self.private && other.realm == self.realm
|
||||
other.respond_to?(:public) && other.public == self.public &&
|
||||
other.respond_to?(:private) && other.private == self.private &&
|
||||
other.respond_to?(:realm) && other.realm == self.realm
|
||||
end
|
||||
|
||||
def to_credential
|
||||
|
|
|
@ -119,6 +119,8 @@ module Metasploit
|
|||
|
||||
if config.present?
|
||||
cmd << ( "--config=" + config )
|
||||
else
|
||||
cmd << ( "--config=" + john_config_file )
|
||||
end
|
||||
|
||||
if pot.present?
|
||||
|
@ -162,6 +164,13 @@ module Metasploit
|
|||
end
|
||||
end
|
||||
|
||||
# This method returns the path to a default john.conf file.
|
||||
#
|
||||
# @return [String] the path to the default john.conf file
|
||||
def john_config_file
|
||||
::File.join( ::Msf::Config.data_directory, "john", "confs", "john.conf" )
|
||||
end
|
||||
|
||||
# This method returns the path to a default john.pot file.
|
||||
#
|
||||
# @return [String] the path to the default john.pot file
|
||||
|
@ -189,6 +198,8 @@ module Metasploit
|
|||
|
||||
if config
|
||||
cmd << "--config=#{config}"
|
||||
else
|
||||
cmd << ( "--config=" + john_config_file )
|
||||
end
|
||||
|
||||
cmd << hash_path
|
||||
|
@ -199,11 +210,11 @@ module Metasploit
|
|||
# This method tries to identify the correct version of the pre-shipped
|
||||
# JtR binaries to use based on the platform.
|
||||
#
|
||||
# @return [NilClass] if the correct bianry could not be determined
|
||||
# @return [NilClass] if the correct binary could not be determined
|
||||
# @return [String] the path to the selected binary
|
||||
def select_shipped_binary
|
||||
cpuinfo_base = ::File.join(Msf::Config.data_directory, "cpuinfo")
|
||||
runpath = nil
|
||||
run_path = nil
|
||||
if File.directory?(cpuinfo_base)
|
||||
data = nil
|
||||
|
||||
|
@ -215,11 +226,11 @@ module Metasploit
|
|||
end
|
||||
case data
|
||||
when /sse2/
|
||||
run_path ||= "run.win32.sse2/john.exe"
|
||||
run_path ||= ::File.join(Msf::Config.data_directory, "john", "run.win32.sse2", "john.exe")
|
||||
when /mmx/
|
||||
run_path ||= "run.win32.mmx/john.exe"
|
||||
run_path ||= ::File.join(Msf::Config.data_directory, "john", "run.win32.mmx", "john.exe")
|
||||
else
|
||||
run_path ||= "run.win32.any/john.exe"
|
||||
run_path ||= ::File.join(Msf::Config.data_directory, "john", "run.win32.any", "john.exe")
|
||||
end
|
||||
when /x86_64-linux/
|
||||
fname = "#{cpuinfo_base}/cpuinfo.ia64.bin"
|
||||
|
@ -229,9 +240,9 @@ module Metasploit
|
|||
end
|
||||
case data
|
||||
when /mmx/
|
||||
run_path ||= "run.linux.x64.mmx/john"
|
||||
run_path ||= ::File.join(Msf::Config.data_directory, "john", "run.linux.x64.mmx", "john")
|
||||
else
|
||||
run_path ||= "run.linux.x86.any/john"
|
||||
run_path ||= ::File.join(Msf::Config.data_directory, "john", "run.linux.x86.any", "john")
|
||||
end
|
||||
when /i[\d]86-linux/
|
||||
fname = "#{cpuinfo_base}/cpuinfo.ia32.bin"
|
||||
|
@ -241,15 +252,15 @@ module Metasploit
|
|||
end
|
||||
case data
|
||||
when /sse2/
|
||||
run_path ||= "run.linux.x86.sse2/john"
|
||||
run_path ||= ::File.join(Msf::Config.data_directory, "john", "run.linux.x86.sse2", "john")
|
||||
when /mmx/
|
||||
run_path ||= "run.linux.x86.mmx/john"
|
||||
run_path ||= ::File.join(Msf::Config.data_directory, "john", "run.linux.x86.mmx", "john")
|
||||
else
|
||||
run_path ||= "run.linux.x86.any/john"
|
||||
run_path ||= ::File.join(Msf::Config.data_directory, "john", "run.linux.x86.any", "john")
|
||||
end
|
||||
end
|
||||
end
|
||||
runpath
|
||||
run_path
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ module Metasploit
|
|||
# This method sets the sane defaults for things
|
||||
# like timeouts and TCP evasion options
|
||||
def set_sane_defaults
|
||||
self.connection_timeout || 30
|
||||
self.connection_timeout ||= 30
|
||||
self.port ||= DEFAULT_PORT
|
||||
self.max_send_size ||= 0
|
||||
self.send_delay ||= 0
|
||||
|
|
|
@ -41,6 +41,12 @@ module Auxiliary::JohnTheRipper
|
|||
|
||||
end
|
||||
|
||||
# @param pwd [String] Password recovered from cracking an LM hash
|
||||
# @param hash [String] NTLM hash for this password
|
||||
# @return [String] `pwd` converted to the correct case to match the
|
||||
# given NTLM hash
|
||||
# @return [nil] if no case matches the NT hash. This can happen when
|
||||
# `pwd` came from a john run that only cracked half of the LM hash
|
||||
def john_lm_upper_to_ntlm(pwd, hash)
|
||||
pwd = pwd.upcase
|
||||
hash = hash.upcase
|
||||
|
|
|
@ -30,7 +30,7 @@ class Metasploit3 < Msf::Auxiliary
|
|||
def run
|
||||
cracker = new_john_cracker
|
||||
|
||||
#generate our wordlist and close the file handle
|
||||
# generate our wordlist and close the file handle
|
||||
wordlist = wordlist_file
|
||||
wordlist.close
|
||||
print_status "Wordlist file written out to #{wordlist.path}"
|
||||
|
@ -53,10 +53,10 @@ class Metasploit3 < Msf::Auxiliary
|
|||
end
|
||||
|
||||
if format == 'lm'
|
||||
print_status "Cracking #{format} hashes in incremental mode (LanMan)..."
|
||||
print_status "Cracking #{format} hashes in incremental mode (All4)..."
|
||||
cracker_instance.rules = nil
|
||||
cracker_instance.wordlist = nil
|
||||
cracker_instance.incremental = 'LanMan'
|
||||
cracker_instance.incremental = 'All4'
|
||||
cracker_instance.crack do |line|
|
||||
print_status line.chomp
|
||||
end
|
||||
|
@ -98,6 +98,12 @@ class Metasploit3 < Msf::Auxiliary
|
|||
end
|
||||
end
|
||||
password = john_lm_upper_to_ntlm(password, nt_hash)
|
||||
# password can be nil if the hash is broken (i.e., the NT and
|
||||
# LM sides don't actually match) or if john was only able to
|
||||
# crack one half of the LM hash. In the latter case, we'll
|
||||
# have a line like:
|
||||
# username:???????WORD:...:...:::
|
||||
next if password.nil?
|
||||
end
|
||||
|
||||
print_good "#{username}:#{password}:#{core_id}"
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
|
||||
|
||||
require 'msf/core'
|
||||
require 'openssl'
|
||||
require 'snmp'
|
||||
require 'metasploit/framework/community_string_collection'
|
||||
require 'metasploit/framework/login_scanner/snmp'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
|
@ -49,260 +49,68 @@ class Metasploit3 < Msf::Auxiliary
|
|||
# Operate on an entire batch of hosts at once
|
||||
def run_batch(batch)
|
||||
|
||||
@found = {}
|
||||
@tried = []
|
||||
|
||||
begin
|
||||
udp_sock = nil
|
||||
idx = 0
|
||||
|
||||
# Create an unbound UDP socket if no CHOST is specified, otherwise
|
||||
# create a UDP socket bound to CHOST (in order to avail of pivoting)
|
||||
udp_sock = Rex::Socket::Udp.create( { 'LocalHost' => datastore['CHOST'] || nil, 'Context' => {'Msf' => framework, 'MsfExploit' => self} })
|
||||
add_socket(udp_sock)
|
||||
|
||||
each_user_pass do |user, pass|
|
||||
comm = pass
|
||||
|
||||
data1 = create_probe_snmp1(comm)
|
||||
data2 = create_probe_snmp2(comm)
|
||||
|
||||
batch.each do |ip|
|
||||
fq_pass = [ip,pass]
|
||||
next if @tried.include? fq_pass
|
||||
@tried << fq_pass
|
||||
vprint_status "#{ip}:#{datastore['RPORT']} - SNMP - Trying #{(pass.nil? || pass.empty?) ? "<BLANK>" : pass}..."
|
||||
|
||||
begin
|
||||
udp_sock.sendto(data1, ip, datastore['RPORT'].to_i, 0)
|
||||
udp_sock.sendto(data2, ip, datastore['RPORT'].to_i, 0)
|
||||
rescue ::Interrupt
|
||||
raise $!
|
||||
rescue ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionRefused
|
||||
nil
|
||||
end
|
||||
|
||||
if (idx % 10 == 0)
|
||||
while (r = udp_sock.recvfrom(65535, 0.25) and r[1])
|
||||
parse_reply(r)
|
||||
end
|
||||
end
|
||||
|
||||
idx += 1
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
idx = 0
|
||||
while (r = udp_sock.recvfrom(65535, 3) and r[1] and idx < 500)
|
||||
parse_reply(r)
|
||||
idx += 1
|
||||
end
|
||||
|
||||
if @found.keys.length > 0
|
||||
print_status("Validating scan results from #{@found.keys.length} hosts...")
|
||||
end
|
||||
|
||||
# Review all successful communities and determine write access
|
||||
@found.keys.sort.each do |host|
|
||||
fake_comm = Rex::Text.rand_text_alphanumeric(8)
|
||||
anycomm_ro = false
|
||||
anycomm_rw = false
|
||||
comms_ro = []
|
||||
comms_rw = []
|
||||
finished = false
|
||||
versions = ["1", "2"]
|
||||
|
||||
versions.each do |version|
|
||||
comms_todo = @found[host].keys.sort
|
||||
comms_todo.unshift(fake_comm)
|
||||
|
||||
comms_todo.each do |comm|
|
||||
begin
|
||||
sval = nil
|
||||
snmp = snmp_client(host, datastore['RPORT'].to_i, version, udp_sock, comm)
|
||||
resp = snmp.get("sysName.0")
|
||||
resp.each_varbind { |var| sval = var.value }
|
||||
next if not sval
|
||||
|
||||
svar = ::SNMP::VarBind.new("1.3.6.1.2.1.1.5.0", ::SNMP::OctetString.new(sval))
|
||||
resp = snmp.set(svar)
|
||||
|
||||
if resp.error_status == :noError
|
||||
comms_rw << comm
|
||||
print_status("Host #{host} provides READ-WRITE access with community '#{comm}'")
|
||||
if comm == fake_comm
|
||||
anycomm_rw = true
|
||||
finished = true
|
||||
break
|
||||
end
|
||||
else
|
||||
comms_ro << comm
|
||||
print_status("Host #{host} provides READ-ONLY access with community '#{comm}'")
|
||||
if comm == fake_comm
|
||||
anycomm_ro = true
|
||||
finished = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
# Used to flag whether this version was compatible
|
||||
finished = true
|
||||
|
||||
rescue ::SNMP::UnsupportedPduTag, ::SNMP::InvalidPduTag, ::SNMP::ParseError,
|
||||
::SNMP::InvalidErrorStatus, ::SNMP::InvalidTrapVarbind, ::SNMP::InvalidGenericTrap,
|
||||
::SNMP::BER::OutOfData, ::SNMP::BER::InvalidLength, ::SNMP::BER::InvalidTag,
|
||||
::SNMP::BER::InvalidObjectId, ::SNMP::MIB::ModuleNotLoadedError,
|
||||
::SNMP::UnsupportedValueTag
|
||||
next
|
||||
|
||||
rescue ::SNMP::UnsupportedVersion
|
||||
break
|
||||
rescue ::SNMP::RequestTimeout
|
||||
next
|
||||
end
|
||||
end
|
||||
|
||||
break if finished
|
||||
end
|
||||
|
||||
# Report on the results
|
||||
comms_ro = ["anything"] if anycomm_ro
|
||||
comms_rw = ["anything"] if anycomm_rw
|
||||
|
||||
comms_rw.each do |comm|
|
||||
report_auth_info(
|
||||
:host => host,
|
||||
:port => datastore['RPORT'].to_i,
|
||||
:proto => 'udp',
|
||||
:sname => 'snmp',
|
||||
:user => '',
|
||||
:pass => comm,
|
||||
:duplicate_ok => true,
|
||||
:active => true,
|
||||
:source_type => "user_supplied",
|
||||
:type => "password"
|
||||
)
|
||||
end
|
||||
|
||||
comms_ro.each do |comm|
|
||||
report_auth_info(
|
||||
:host => host,
|
||||
:port => datastore['RPORT'].to_i,
|
||||
:proto => 'udp',
|
||||
:sname => 'snmp',
|
||||
:user => '',
|
||||
:pass => comm,
|
||||
:duplicate_ok => true,
|
||||
:active => true,
|
||||
:source_type => "user_supplied",
|
||||
:type => "password_ro"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
rescue ::Interrupt
|
||||
raise $!
|
||||
rescue ::Exception => e
|
||||
print_error("Unknown error: #{e.class} #{e}")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
#
|
||||
# Allocate a SNMP client using the existing socket
|
||||
#
|
||||
def snmp_client(host, port, version, socket, community)
|
||||
version = :SNMPv1 if version == "1"
|
||||
version = :SNMPv2c if version == "2c"
|
||||
|
||||
snmp = ::SNMP::Manager.new(
|
||||
:Host => host,
|
||||
:Port => port,
|
||||
:Community => community,
|
||||
:Version => version,
|
||||
:Timeout => 1,
|
||||
:Retries => 2,
|
||||
:Transport => SNMP::RexUDPTransport,
|
||||
:Socket => socket
|
||||
)
|
||||
end
|
||||
|
||||
#
|
||||
# The response parsers
|
||||
#
|
||||
def parse_reply(pkt)
|
||||
|
||||
return if not pkt[1]
|
||||
|
||||
if(pkt[1] =~ /^::ffff:/)
|
||||
pkt[1] = pkt[1].sub(/^::ffff:/, '')
|
||||
end
|
||||
|
||||
asn = OpenSSL::ASN1.decode(pkt[0]) rescue nil
|
||||
return if not asn
|
||||
|
||||
snmp_error = asn.value[0].value rescue nil
|
||||
snmp_comm = asn.value[1].value rescue nil
|
||||
snmp_data = asn.value[2].value[3].value[0] rescue nil
|
||||
snmp_oid = snmp_data.value[0].value rescue nil
|
||||
snmp_info = snmp_data.value[1].value rescue nil
|
||||
|
||||
return if not (snmp_error and snmp_comm and snmp_data and snmp_oid and snmp_info)
|
||||
snmp_info = snmp_info.to_s.gsub(/\s+/, ' ')
|
||||
|
||||
inf = snmp_info
|
||||
com = snmp_comm
|
||||
|
||||
if(com)
|
||||
@found[pkt[1]]||={}
|
||||
if(not @found[pkt[1]][com])
|
||||
print_good("SNMP: #{pkt[1]} community string: '#{com}' info: '#{inf}'")
|
||||
@found[pkt[1]][com] = inf
|
||||
end
|
||||
|
||||
report_service(
|
||||
:host => pkt[1],
|
||||
:port => pkt[2],
|
||||
:proto => 'udp',
|
||||
:name => 'snmp',
|
||||
:info => inf,
|
||||
:state => "open"
|
||||
batch.each do |ip|
|
||||
collection = Metasploit::Framework::CommunityStringCollection.new(
|
||||
pass_file: datastore['PASS_FILE'],
|
||||
password: datastore['PASSWORD']
|
||||
)
|
||||
|
||||
scanner = Metasploit::Framework::LoginScanner::SNMP.new(
|
||||
host: ip,
|
||||
port: rport,
|
||||
cred_details: collection,
|
||||
stop_on_success: datastore['STOP_ON_SUCCESS'],
|
||||
connection_timeout: 2
|
||||
)
|
||||
|
||||
service_data = {
|
||||
address: ip,
|
||||
port: rport,
|
||||
service_name: 'snmp',
|
||||
protocol: 'udp',
|
||||
workspace_id: myworkspace_id
|
||||
}
|
||||
|
||||
scanner.scan! do |result|
|
||||
if result.success?
|
||||
credential_data = {
|
||||
module_fullname: self.fullname,
|
||||
origin_type: :service,
|
||||
username: result.credential.public
|
||||
}
|
||||
credential_data.merge!(service_data)
|
||||
|
||||
credential_core = create_credential(credential_data)
|
||||
|
||||
login_data = {
|
||||
core: credential_core,
|
||||
last_attempted_at: DateTime.now,
|
||||
status: Metasploit::Model::Login::Status::SUCCESSFUL
|
||||
}
|
||||
login_data.merge!(service_data)
|
||||
|
||||
create_credential_login(login_data)
|
||||
print_good "#{ip}:#{rport} - LOGIN SUCCESSFUL: #{result.credential}"
|
||||
else
|
||||
invalidate_data = {
|
||||
public: result.credential.public,
|
||||
private: result.credential.private,
|
||||
realm_key: result.credential.realm_key,
|
||||
realm_value: result.credential.realm,
|
||||
status: result.status
|
||||
} .merge(service_data)
|
||||
invalidate_login(invalidate_data)
|
||||
print_status "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def create_probe_snmp1(name)
|
||||
xid = rand(0x100000000)
|
||||
pdu =
|
||||
"\x02\x01\x00" +
|
||||
"\x04" + [name.length].pack('c') + name +
|
||||
"\xa0\x1c" +
|
||||
"\x02\x04" + [xid].pack('N') +
|
||||
"\x02\x01\x00" +
|
||||
"\x02\x01\x00" +
|
||||
"\x30\x0e\x30\x0c\x06\x08\x2b\x06\x01\x02\x01" +
|
||||
"\x01\x01\x00\x05\x00"
|
||||
head = "\x30" + [pdu.length].pack('C')
|
||||
data = head + pdu
|
||||
data
|
||||
def rport
|
||||
datastore['RPORT']
|
||||
end
|
||||
|
||||
def create_probe_snmp2(name)
|
||||
xid = rand(0x100000000)
|
||||
pdu =
|
||||
"\x02\x01\x01" +
|
||||
"\x04" + [name.length].pack('c') + name +
|
||||
"\xa1\x19" +
|
||||
"\x02\x04" + [xid].pack('N') +
|
||||
"\x02\x01\x00" +
|
||||
"\x02\x01\x00" +
|
||||
"\x30\x0b\x30\x09\x06\x05\x2b\x06\x01\x02\x01" +
|
||||
"\x05\x00"
|
||||
head = "\x30" + [pdu.length].pack('C')
|
||||
data = head + pdu
|
||||
data
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
|
|
@ -132,6 +132,11 @@ describe Metasploit::Framework::Credential do
|
|||
expect(other).not_to eq(cred_detail)
|
||||
end
|
||||
end
|
||||
|
||||
context "when comparing to a different object" do
|
||||
let(:other) {'a string'}
|
||||
specify do
|
||||
expect(other).not_to eq(cred_detail)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -73,9 +73,9 @@ describe Msf::Ui::Console::CommandDispatcher::Db do
|
|||
describe "-p" do
|
||||
before(:each) do
|
||||
host = FactoryGirl.create(:mdm_host, :workspace => framework.db.workspace, :address => "192.168.0.1")
|
||||
FactoryGirl.create(:mdm_service, :host => host, :port => 1024, name: 'Service1')
|
||||
FactoryGirl.create(:mdm_service, :host => host, :port => 1025, name: 'Service2')
|
||||
FactoryGirl.create(:mdm_service, :host => host, :port => 1026, name: 'Service3')
|
||||
FactoryGirl.create(:mdm_service, :host => host, :port => 1024, name: 'Service1', proto: 'udp')
|
||||
FactoryGirl.create(:mdm_service, :host => host, :port => 1025, name: 'Service2', proto: 'tcp')
|
||||
FactoryGirl.create(:mdm_service, :host => host, :port => 1026, name: 'Service3', proto: 'udp')
|
||||
end
|
||||
it "should list services that are on a given port" do
|
||||
db.cmd_services "-p", "1024,1025"
|
||||
|
@ -85,8 +85,8 @@ describe Msf::Ui::Console::CommandDispatcher::Db do
|
|||
"",
|
||||
"host port proto name state info",
|
||||
"---- ---- ----- ---- ----- ----",
|
||||
"192.168.0.1 1024 snmp Service1 open ",
|
||||
"192.168.0.1 1025 snmp Service2 open "
|
||||
"192.168.0.1 1024 udp Service1 open ",
|
||||
"192.168.0.1 1025 tcp Service2 open "
|
||||
]
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue