Merge branch 'master' of https://github.com/rapid7/metasploit-framework into srsexec
commit
ff5de7b81d
10
Gemfile.lock
10
Gemfile.lock
|
@ -125,10 +125,10 @@ GEM
|
|||
docile (1.3.1)
|
||||
erubis (2.7.0)
|
||||
eventmachine (1.2.7)
|
||||
factory_bot (4.11.0)
|
||||
factory_bot (4.11.1)
|
||||
activesupport (>= 3.0.0)
|
||||
factory_bot_rails (4.11.0)
|
||||
factory_bot (~> 4.11.0)
|
||||
factory_bot_rails (4.11.1)
|
||||
factory_bot (~> 4.11.1)
|
||||
railties (>= 3.0.0)
|
||||
faker (1.9.1)
|
||||
i18n (>= 0.7)
|
||||
|
@ -188,7 +188,7 @@ GEM
|
|||
nexpose (7.2.1)
|
||||
nokogiri (1.8.4)
|
||||
mini_portile2 (~> 2.3.0)
|
||||
octokit (4.11.0)
|
||||
octokit (4.12.0)
|
||||
sawyer (~> 0.8.0, >= 0.5.3)
|
||||
openssl-ccm (1.2.1)
|
||||
openvas-omp (0.0.4)
|
||||
|
@ -307,7 +307,7 @@ GEM
|
|||
rspec-support (3.8.0)
|
||||
ruby-macho (2.0.0)
|
||||
ruby-rc4 (0.1.5)
|
||||
ruby_smb (1.0.3)
|
||||
ruby_smb (1.0.4)
|
||||
bindata
|
||||
rubyntlm
|
||||
windows_error
|
||||
|
|
|
@ -89842,7 +89842,7 @@
|
|||
"targets": [
|
||||
"Windows 7 and Server 2008 R2 (x64) All Service Packs"
|
||||
],
|
||||
"mod_time": "2018-07-10 11:05:00 +0000",
|
||||
"mod_time": "2018-08-29 23:53:58 +0000",
|
||||
"path": "/modules/exploits/windows/smb/ms17_010_eternalblue.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/smb/ms17_010_eternalblue",
|
||||
|
|
|
@ -620,10 +620,12 @@ class ReadableText
|
|||
'Indent' => indent,
|
||||
'SortIndex' => 1)
|
||||
|
||||
framework.db.sessions.each do |session|
|
||||
unless session.closed_at.nil?
|
||||
row = create_mdm_session_row(session, show_extended)
|
||||
tbl << row
|
||||
if framework.db.active
|
||||
framework.db.sessions.each do |session|
|
||||
unless session.closed_at.nil?
|
||||
row = create_mdm_session_row(session, show_extended)
|
||||
tbl << row
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -373,11 +373,11 @@ class Exploit < Msf::Module
|
|||
end
|
||||
|
||||
#
|
||||
# Performs last-minute sanity checking of auxiliary parameters. This method
|
||||
# Performs last-minute sanity checking of exploit parameters. This method
|
||||
# is called during automated exploitation attempts and allows an
|
||||
# auxiliary module to filter bad attempts, obtain more information, and choose
|
||||
# better parameters based on the available data. Returning anything that
|
||||
# evaluates to "false" will cause this specific auxiliary attempt to
|
||||
# exploit to filter bad targets, obtain more information, and choose
|
||||
# better targets based on the available data. Returning anything that
|
||||
# evaluates to "false" will cause this specific exploit attempt to
|
||||
# be skipped. This method can and will change datastore values and
|
||||
# may interact with the backend database.
|
||||
#
|
||||
|
|
|
@ -135,6 +135,19 @@ module Msf::Post::File
|
|||
end
|
||||
end
|
||||
|
||||
#
|
||||
# See if +path+ on the remote system exists and is writable
|
||||
#
|
||||
# @param path [String] Remote path to check
|
||||
#
|
||||
# @return [Boolean] true if +path+ exists and is writable
|
||||
#
|
||||
def writable?(path)
|
||||
raise "writable?' method does not support Windows systems" if session.platform == 'windows'
|
||||
|
||||
cmd_exec("test -w '#{path}' && echo true").to_s.include? 'true'
|
||||
end
|
||||
|
||||
#
|
||||
# Check for existence of +path+ on the remote file system
|
||||
#
|
||||
|
|
|
@ -11,19 +11,12 @@ module Priv
|
|||
# Returns true if running as root, false if not.
|
||||
#
|
||||
def is_root?
|
||||
root_priv = false
|
||||
user_id = cmd_exec("id -u")
|
||||
clean_user_id = user_id.to_s.gsub(/[^\d]/,"")
|
||||
unless clean_user_id.empty?
|
||||
if clean_user_id =~ /^0$/
|
||||
root_priv = true
|
||||
elsif clean_user_id =~ /^\d*$/
|
||||
root_priv = false
|
||||
end
|
||||
else
|
||||
user_id = cmd_exec('id -u')
|
||||
clean_user_id = user_id.to_s.gsub(/[^\d]/, '')
|
||||
if clean_user_id.empty?
|
||||
raise "Could not determine UID: #{user_id.inspect}"
|
||||
end
|
||||
return root_priv
|
||||
(clean_user_id == '0')
|
||||
end
|
||||
|
||||
end # Priv
|
||||
|
|
|
@ -11,12 +11,12 @@ module Priv
|
|||
# Returns true if running as root, false if not.
|
||||
#
|
||||
def is_root?
|
||||
root_priv = false
|
||||
user_id = cmd_exec("/usr/xpg4/bin/id -u")
|
||||
if user_id.to_i == 0
|
||||
root_priv = true
|
||||
clean_user_id = user_id.to_s.gsub(/[^\d]/, '')
|
||||
if clean_user_id.empty?
|
||||
raise "Could not determine UID: #{user_id.inspect}"
|
||||
end
|
||||
return root_priv
|
||||
(clean_user_id == '0')
|
||||
end
|
||||
|
||||
end # Priv
|
||||
|
|
|
@ -115,9 +115,9 @@ module System
|
|||
#
|
||||
def pidof(program)
|
||||
pids = []
|
||||
full = cmd_exec('ps aux').to_s
|
||||
full = cmd_exec('ps -elf').to_s
|
||||
full.split("\n").each do |pid|
|
||||
pids << pid.split(' ')[1].to_i if pid.include? program
|
||||
pids << pid.split(' ')[3].to_i if pid.include? program
|
||||
end
|
||||
pids
|
||||
end
|
||||
|
|
|
@ -1200,6 +1200,10 @@ class Core
|
|||
end
|
||||
end
|
||||
|
||||
if show_inactive && !framework.db.active
|
||||
print_warning("Database not connected; list of inactive sessions unavailable")
|
||||
end
|
||||
|
||||
last_known_timeout = nil
|
||||
|
||||
# Now, perform the actual method
|
||||
|
|
|
@ -22,7 +22,7 @@ class Console::CommandDispatcher::Stdapi::Sys
|
|||
#
|
||||
@@execute_opts = Rex::Parser::Arguments.new(
|
||||
"-a" => [ true, "The arguments to pass to the command." ],
|
||||
"-c" => [ false, "Channelized I/O (required for interaction)." ],
|
||||
"-c" => [ false, "Channelized I/O (required for interaction)." ], # -i sets -c
|
||||
"-f" => [ true, "The executable command to run." ],
|
||||
"-h" => [ false, "Help menu." ],
|
||||
"-H" => [ false, "Create the process hidden from view." ],
|
||||
|
@ -33,6 +33,14 @@ class Console::CommandDispatcher::Stdapi::Sys
|
|||
"-k" => [ false, "Execute process on the meterpreters current desktop" ],
|
||||
"-s" => [ true, "Execute process in a given session as the session user" ])
|
||||
|
||||
#
|
||||
# Options used by the 'shell' command.
|
||||
#
|
||||
@@shell_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help menu." ],
|
||||
"-l" => [ false, "List available shells (/etc/shells)." ],
|
||||
"-t" => [ true, "Spawn a PTY shell (/bin/bash if no argument given)." ]) # ssh(1) -t
|
||||
|
||||
#
|
||||
# Options used by the 'reboot' command.
|
||||
#
|
||||
|
@ -249,37 +257,149 @@ class Console::CommandDispatcher::Stdapi::Sys
|
|||
[]
|
||||
end
|
||||
|
||||
def cmd_shell_help
|
||||
print_line 'Usage: shell [options]'
|
||||
print_line
|
||||
print_line 'Opens an interactive native shell.'
|
||||
print_line @@shell_opts.usage
|
||||
end
|
||||
|
||||
def cmd_shell_tabs(str, words)
|
||||
return @@shell_opts.fmt.keys if words.length == 1
|
||||
[]
|
||||
end
|
||||
|
||||
#
|
||||
# Drop into a system shell as specified by %COMSPEC% or
|
||||
# as appropriate for the host.
|
||||
#
|
||||
def cmd_shell(*args)
|
||||
use_pty = false
|
||||
sh_path = '/bin/bash'
|
||||
|
||||
@@shell_opts.parse(args) do |opt, idx, val|
|
||||
case opt
|
||||
when '-h'
|
||||
cmd_shell_help
|
||||
return true
|
||||
when '-l'
|
||||
return false unless client.fs.file.exist?('/etc/shells')
|
||||
|
||||
begin
|
||||
client.fs.file.open('/etc/shells') do |f|
|
||||
print(f.read) until f.eof
|
||||
end
|
||||
rescue
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
when '-t'
|
||||
use_pty = true
|
||||
# XXX: No other options must follow
|
||||
sh_path = val if val
|
||||
end
|
||||
end
|
||||
|
||||
case client.platform
|
||||
when 'windows'
|
||||
path = client.fs.file.expand_path("%COMSPEC%")
|
||||
path = (path and not path.empty?) ? path : "cmd.exe"
|
||||
path = client.fs.file.expand_path('%COMSPEC%')
|
||||
path = (path && !path.empty?) ? path : 'cmd.exe'
|
||||
|
||||
# attempt the shell with thread impersonation
|
||||
begin
|
||||
cmd_execute("-f", path, "-c", "-H", "-i", "-t")
|
||||
cmd_execute('-f', path, '-c', '-i', '-H', '-t')
|
||||
rescue
|
||||
# if this fails, then we attempt without impersonation
|
||||
print_error( "Failed to spawn shell with thread impersonation. Retrying without it." )
|
||||
cmd_execute("-f", path, "-c", "-H", "-i")
|
||||
print_error('Failed to spawn shell with thread impersonation. Retrying without it.')
|
||||
cmd_execute('-f', path, '-c', '-i', '-H')
|
||||
end
|
||||
when 'linux', 'osx'
|
||||
if use_pty && pty_shell(sh_path)
|
||||
return true
|
||||
end
|
||||
|
||||
# Don't expand_path() this because it's literal anyway
|
||||
path = "/bin/sh"
|
||||
cmd_execute("-f", path, "-c", "-i")
|
||||
cmd_execute('-f', '/bin/sh', '-c', '-i')
|
||||
else
|
||||
# Then this is a multi-platform meterpreter (php or java), which
|
||||
# Then this is a multi-platform meterpreter (e.g., php or java), which
|
||||
# must special-case COMSPEC to return the system-specific shell.
|
||||
path = client.fs.file.expand_path("%COMSPEC%")
|
||||
path = client.fs.file.expand_path('%COMSPEC%')
|
||||
|
||||
# If that failed for whatever reason, guess it's unix
|
||||
path = (path and not path.empty?) ? path : "/bin/sh"
|
||||
cmd_execute("-f", path, "-c", "-i")
|
||||
path = (path && !path.empty?) ? path : '/bin/sh'
|
||||
|
||||
if use_pty && path == '/bin/sh' && pty_shell(sh_path)
|
||||
return true
|
||||
end
|
||||
|
||||
cmd_execute('-f', comspec, '-c', '-i')
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Spawn a PTY shell
|
||||
#
|
||||
def pty_shell(sh_path)
|
||||
sh_path = client.fs.file.exist?(sh_path) ? sh_path : '/bin/sh'
|
||||
|
||||
# Python Meterpreter calls pty.openpty() - No need for other methods
|
||||
if client.arch == 'python'
|
||||
cmd_execute('-f', sh_path, '-c', '-i')
|
||||
return true
|
||||
end
|
||||
|
||||
# Check for the following in /usr{,/local}/bin:
|
||||
# script
|
||||
# python{,2,3}
|
||||
# socat
|
||||
# expect
|
||||
paths = %w[
|
||||
/usr/bin/script
|
||||
/usr/bin/python
|
||||
/usr/local/bin/python
|
||||
/usr/bin/python2
|
||||
/usr/local/bin/python2
|
||||
/usr/bin/python3
|
||||
/usr/local/bin/python3
|
||||
/usr/bin/socat
|
||||
/usr/local/bin/socat
|
||||
/usr/bin/expect
|
||||
/usr/local/bin/expect
|
||||
]
|
||||
|
||||
# Select method for spawning PTY Shell based on availability on the target.
|
||||
path = paths.find { |p| client.fs.file.exist?(p) }
|
||||
|
||||
return false unless path
|
||||
|
||||
# Commands for methods
|
||||
cmd =
|
||||
case path
|
||||
when /script/
|
||||
if client.platform == 'linux'
|
||||
"#{path} -qc #{sh_path} /dev/null"
|
||||
else
|
||||
# script(1) invocation for BSD, OS X, etc.
|
||||
"#{path} -q /dev/null #{sh_path}"
|
||||
end
|
||||
when /python/
|
||||
"#{path} -c 'import pty; pty.spawn(\"#{sh_path}\")'"
|
||||
when /socat/
|
||||
# sigint isn't passed through yet
|
||||
"#{path} - exec:#{sh_path},pty,sane,setsid,sigint,stderr"
|
||||
when /expect/
|
||||
"#{path} -c 'spawn #{sh_path}; interact'"
|
||||
end
|
||||
|
||||
# "env TERM=xterm" provides colors, "clear" command, etc. as available on the target.
|
||||
cmd.prepend('env TERM=xterm HISTFILE= ')
|
||||
|
||||
print_status(cmd)
|
||||
cmd_execute('-f', cmd, '-c', '-i')
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
#
|
||||
# Gets the process identifier that meterpreter is running in on the remote
|
||||
|
|
|
@ -47,6 +47,7 @@ module Shell
|
|||
# Initialize the prompt
|
||||
self.cont_prompt = ' > '
|
||||
self.cont_flag = false
|
||||
self.prompt = prompt
|
||||
self.prompt_char = prompt_char
|
||||
|
||||
self.histfile = histfile
|
||||
|
|
|
@ -322,7 +322,7 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||
def smb1_anonymous_connect_ipc
|
||||
sock = connect(false)
|
||||
dispatcher = RubySMB::Dispatcher::Socket.new(sock)
|
||||
client = RubySMB::Client.new(dispatcher, smb1: true, smb2: false, username: smb_user, password: smb_pass)
|
||||
client = RubySMB::Client.new(dispatcher, smb1: true, smb2: false, username: smb_user, domain: smb_domain, password: smb_pass)
|
||||
response_code = client.login
|
||||
|
||||
unless response_code == ::WindowsError::NTStatus::STATUS_SUCCESS
|
||||
|
@ -365,7 +365,7 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||
def smb1_free_hole(start)
|
||||
sock = connect(false)
|
||||
dispatcher = RubySMB::Dispatcher::Socket.new(sock)
|
||||
client = RubySMB::Client.new(dispatcher, smb1: true, smb2: false, username: smb_user, password: smb_pass)
|
||||
client = RubySMB::Client.new(dispatcher, smb1: true, smb2: false, username: smb_user, domain: smb_domain, password: smb_pass)
|
||||
client.negotiate
|
||||
|
||||
pkt = ""
|
||||
|
@ -696,4 +696,18 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||
''
|
||||
end
|
||||
end
|
||||
|
||||
# Returns the value to be passed to SMB clients for
|
||||
# the domain. If the user has not supplied a domain
|
||||
# it returns an empty string to trigger an anonymous
|
||||
# logon.
|
||||
#
|
||||
# @return [String] the domain value
|
||||
def smb_domain
|
||||
if datastore['SMBDomain'].present?
|
||||
datastore['SMBDomain']
|
||||
else
|
||||
''
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue