151 lines
3.8 KiB
Ruby
151 lines
3.8 KiB
Ruby
##
|
|
# This module requires Metasploit: https://metasploit.com/download
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
##
|
|
|
|
class MetasploitModule < Msf::Post
|
|
include Msf::Post::Windows::Accounts
|
|
|
|
def initialize(info = {})
|
|
super(
|
|
update_info(
|
|
info,
|
|
'Name' => 'Windows Gather Directory Permissions Enumeration',
|
|
'Description' => %q{
|
|
This module enumerates directories and lists the permissions set
|
|
on found directories. Please note: if the PATH option isn't specified,
|
|
then the module will start enumerate whatever is in the target machine's
|
|
%PATH% variable.
|
|
},
|
|
'License' => MSF_LICENSE,
|
|
'Platform' => ['win'],
|
|
'SessionTypes' => ['meterpreter'],
|
|
'Author' => [
|
|
'Kx499',
|
|
'Ben Campbell',
|
|
'sinn3r'
|
|
],
|
|
'Compat' => {
|
|
'Meterpreter' => {
|
|
'Commands' => %w[
|
|
stdapi_fs_stat
|
|
]
|
|
}
|
|
}
|
|
)
|
|
)
|
|
|
|
register_options(
|
|
[
|
|
OptString.new('PATH', [ false, 'Directory to begin search from', '']),
|
|
OptEnum.new('FILTER', [ false, 'Filter to limit results by', 'NA', [ 'NA', 'R', 'W', 'RW' ]]),
|
|
OptInt.new('DEPTH', [ true, 'Depth to drill down into subdirs, O = no limit', 0]),
|
|
]
|
|
)
|
|
end
|
|
|
|
def enum_subdirs(perm_filter, dpath, maxdepth, token)
|
|
filter = datastore['FILTER']
|
|
filter = nil if datastore['FILTER'] == 'NA'
|
|
|
|
begin
|
|
dirs = session.fs.dir.foreach(dpath)
|
|
rescue Rex::Post::Meterpreter::RequestError
|
|
# Sometimes we cannot see the dir
|
|
dirs = []
|
|
end
|
|
|
|
if (maxdepth >= 1) || (maxdepth < 0)
|
|
dirs.each do |d|
|
|
next if d =~ /^(\.|\.\.)$/
|
|
|
|
realpath = dpath + '\\' + d
|
|
next unless session.fs.file.stat(realpath).directory?
|
|
|
|
perm = check_dir_perms(realpath, token)
|
|
if perm_filter && perm && perm.include?(perm_filter)
|
|
print_status(perm + "\t" + realpath)
|
|
end
|
|
enum_subdirs(perm_filter, realpath, maxdepth - 1, token)
|
|
end
|
|
end
|
|
end
|
|
|
|
def get_paths
|
|
p = datastore['PATH']
|
|
return [p] if !p.nil? && !p.empty?
|
|
|
|
begin
|
|
p = cmd_exec('cmd.exe', '/c echo %PATH%')
|
|
rescue Rex::Post::Meterpreter::RequestError => e
|
|
vprint_error(e.message)
|
|
return []
|
|
end
|
|
print_status("Option 'PATH' isn't specified. Using system %PATH%")
|
|
if p.include?(';')
|
|
return p.split(';')
|
|
else
|
|
return [p]
|
|
end
|
|
end
|
|
|
|
def get_token
|
|
print_status('Getting impersonation token...')
|
|
begin
|
|
t = get_imperstoken
|
|
rescue ::Exception => e
|
|
# Failure due to timeout, access denied, etc.
|
|
t = nil
|
|
vprint_error("Error #{e.message} while using get_imperstoken()")
|
|
vprint_error(e.backtrace)
|
|
end
|
|
return t
|
|
end
|
|
|
|
def enum_perms(perm_filter, token, depth, paths)
|
|
paths.each do |path|
|
|
next if path.empty?
|
|
|
|
path = path.strip
|
|
|
|
print_status("Checking directory permissions from: #{path}")
|
|
|
|
perm = check_dir_perms(path, token)
|
|
next if perm.nil?
|
|
|
|
# Show the permission of the parent directory
|
|
if perm_filter && perm.include?(perm_filter)
|
|
print_status(perm + "\t" + path)
|
|
end
|
|
|
|
# call recursive function to loop through and check all sub directories
|
|
enum_subdirs(perm_filter, path, depth, token)
|
|
end
|
|
end
|
|
|
|
def run
|
|
perm_filter = datastore['FILTER']
|
|
perm_filter = nil if datastore['FILTER'] == 'NA'
|
|
|
|
paths = get_paths
|
|
if paths.empty?
|
|
print_error('Unable to get the path')
|
|
return
|
|
end
|
|
|
|
depth = -1
|
|
if datastore['DEPTH'] > 0
|
|
depth = datastore['DEPTH']
|
|
end
|
|
|
|
t = get_token
|
|
|
|
if t
|
|
print_status("Got token: #{t}...")
|
|
enum_perms(perm_filter, t, depth, paths)
|
|
else
|
|
print_error('Getting impersonation token failed')
|
|
end
|
|
end
|
|
end
|