A Case Study in Attacking Keepass
A Case Study in Attacking
Keepass
@tifkin_
Red Teamer, Hunter, Capability Dev
UnmanagedPowerShell | RAT developer | PowerShell Junkie
@harmj0y
Offensive Engineer and Red Teamer
Co-founder of Empire/EmPyre | PowerTools | Veil-Framework
PowerSploit/BloodHound Developer
TL;DR
◈ KeePass Overview◈ “Attacking” KeePass
⬥ KeePass.config.xml, key files, and more⬥ Existing Work (KeeFarce)⬥ KeeThief⬥ The KeePass Trigger System
◈ Demos◈ Mitigations
Our Big Point
If a password vault is unlocked, the key material likely has to be somewhere in the process space,
so we can probably extract it.
But this doesn't mean you shouldn’t use a password manager!!!
X
KeePass Overview
Architectural Backgroundand Offensive Motivations
1
KeePass
◈ A “free, open source, light-weight and easy-to-use password manager”⬥ 1.X is unmanaged C++ code⬥ 2.X is C#/.NET
◈ Most commonly used password manager we’ve seen in corporate environments⬥ Self-contained/not hosted ‘in the cloud’
2.X Key Material Options
KeePass Security Protections
◈ Strong Crypto⬥ 6000 encryption rounds to prevent dictionary
attacks (though KeePass is now in HashCat ;)◈ Secure Desktop
⬥ Similar to UAC, allows for the entering of a master password on a different desktop to combat keyloggers, but not enabled by default
◈ Process Memory Protection⬥ RtlEncryptMemory/RtlDecryptMemory
KeePass and DPAPI
◈ The Data Protection API (DPAPI) is used to encrypt key material for the ‘Windows User Account’ setting⬥ Mixes the current Windows user account in with
the master password/or keyfile to create a composite master key
◈ The user’s DPAPI master key is used to encrypt/decrypt a KeePass-specific ‘blob’
Recovering DPAPI Key Material: Restore-UserDPAPI.ps1
Process Memory Protection
◈ Sensitive data chunks (such as the master password) are stored as encrypted blobs in memory by using RtlEncryptMemory() and RtlDecryptMemory()
◈ The “SameProcess” scope is set, so only the KeePass process can decrypt the in-memory strings!⬥ Encryption keys are in kernel land
“Attacking” KeePass
KeePass.config.xml, key files, and more
2
Identifying KeePass
◈ If running:⬥ Get-WmiObject win32_process | Where-Object
{$_.Name -like '*kee*'} | Select-Object -Expand ExecutablePath
◈ If not:⬥ Get-ChildItem -Path C:\Users\ -Include
@("*kee*.exe", "*.kdb*") -Recurse -ErrorAction SilentlyContinue | Select-Object -Expand FullName | fl
⬥ ls $env:APPDATA\Microsoft\Windows\Recent\ | ?{$_.FullName -match 'kdb|keepass'}
Identifying KeePass
Cracking a KeePass Database
◈ HashCat 3.0.0 (released 6/29/16) now includes support for KeePass 1.X and 2.X databases (-m 13400) thanks to @Fist0urs⬥ keepass2john lets you extract a crackable hash (use
latest version for key file support)
KeePass.config.xml
◈ Located at C:\Users\user\AppData\Roaming\KeePass\KeePass.config.xml or in the folder of a roaming installation
◈ The ‘KeySources’ section has some interesting information...
KeePass.config.xml
Finding/Parsing KeePass.config.xml’s
◈ KeePassConfig.ps1 in KeeThief includes Find-KeePassconfig:
Nabbing Key Files With WMI
◈ But what if key files are on a removable USB drive?
◈ We drew inspiration from Matt Graeber’s BlackHat 2015 “Abusing Windows Management Instrumentation (WMI) to Build a Persistent, Asynchronous, and Fileless Backdoor” presentation
Nabbing Key Files With WMI
◈ The extrinsic WMI event Win32_VolumeChangeEvent fires every time a USB drive is inserted and mounted
◈ Non-reboot persistent option:⬥ Register-WmiEvent -Query 'SELECT * FROM
Win32_VolumeChangeEvent WHERE EventType = 2' -SourceIdentifier 'DriveInserted' -Action {$DriveLetter = $EventArgs.NewEvent.DriveName;if (Test-Path "$DriveLetter\key.jpg") {Copy-Item "$DriveLetter\key.jpg" "C:\Temp\" -Force}}
New-WMIBackdoorAction Modification
Registering the Trigger
Register-WMIBackdoor -Trigger $(New-WMIBackdoorTrigger -DriveInsertion) -Action $(New-WMIBackdoorAction -FileClone)
Existing Work(KeeFarce)
3
KeeFarce Release
◈ Released October 2015 by Denis Andzakovic (denandz)⬥ https://github.com/denandz/KeeFarce
◈ Allows for the export of an unlocked KeePass database to a .CSV on disk!
“
“KeeFarce is not a threat...”
-Dominik Reichl (KeePass Author)
https://sourceforge.net/p/keepass/discussion/329220/thread/8e511d96/#e919
KeeFarce Process Part 1
1. Loads a malicious ‘bootstrap’ .DLL from disk into KeePass using VirtualAllocEx()/CreateRemoteThread() to force a call LoadLibraryA()
2. The .DLL loads the .NET CLR and then loads a custom .NET assembly from disk
3. The malicious assembly loads CLR MD and attaches to the current KeePass.exe process
KeeFarce Process Part 2
4. Assembly uses CLR MD to walk the KeePass heap, searching for KeePass.UI.DocumentManagerEx objects
5. Loads the KeePass assembly with reflection and instantiates a KeePass.DataExchange.PwExportInfo object
6. KeePass.DataExchange.Formats.KeePassCsv1x is instantiated, params set, and the export method is invoked to export db to csv
KeeFarce Disadvantages
◈ In KeeFarce’s current state, the following files have to be on disk:⬥ BootstrapDLL.dll (.DLL that’s loaded),
KeeFarce.exe (launcher), KeeFarceDLL.dll (malicious assembly), Microsoft.Diagnostic.Runtime.dll (CLR MD)
◈ No PowerShell weaponization◈ .NET 4+ (ClrMD)◈ Only exports DB contents
KeeThief
Our Approach
4
KeeThief
◈ PowerShell 2.0-compatible tool to extract the database key material from an opened KeePass database⬥ Uses a patched version of Microsoft’s CLR MD⬥ Most of the work is in a C# assembly⬥ Can be executed without a file touching disk!
◈ Also includes a patched KeePass version to reuse the extracted key material
m_pbData:Decryption key materialencrypted by RtlEncryptMemory
1. PowerShell script loads a custom.NET assembly
2. Custom assemblyloads .NET 2.0 backport of ClrMD
3. ClrMD locates CompositeKeyobject
4. ClrMD locates references to to key classes
5. ClrMD locates and extracts encrypted key material
6. Assembly injects shellcode to decrypt key material
7. Extracts plaintext key material
The KeePass Trigger System
Exfiltration Without Malware….yes, really
5
KeePass’ Trigger System
◈ Version 2.X of KeePass has an available event-condition-action trigger system⬥ Specified in the
<TriggerSystem>...</TriggerSystem> section of the active KeePass.config.xml, which is nearly always modifiable
◈ We can use this to exfiltrate a database on opening, or when specific entries are copied to the clipboard!
KeePass’ Trigger System
◈ Interesting triggers:⬥ Opened database file / Copied data to clipboard
◈ Interesting actions:⬥ Export active database
⬦ Available “KeePass CSV (1.x)” format!⬦ Accepts \\UNC paths as well as URLs!
⬥ Execute command line / URL⬦ Invoke arbitrary .VBS/.PS1/etc.
.VBS Trigger
Auto-backdooring Triggers
◈ KeeThief’s KeePassConfig.ps1 also includes Add-KeePassConfigTrigger to insert malicious triggers into a KeePass.config.xml
◈ Find-KeePassconfig | Add-KeePassConfigTrigger⬥ -Action <X> : either ‘ExportDatabase’ or
‘ExfilDataCopied’
7
Mitigations
All Is Not Lost
6
The Key Issue
◈ Ultimately, if a database is unlocked, the key material likely has to be somewhere in the process space, so we can probably extract it
◈ Current desktop OS architecture cannot prevent this attack
◈ Can’t protect against features (triggers)
Detection/Things to beware of
◈ Host based monitoring (Sysmon,Carbon Black, etc.)⬥ Cross-process interaction (OpenProcess,
ReadProcessMemory, WriteProcessMemory, CreateRemoteThread)
◈ PowerShell Module/Script Block Logging◈ WMI Events◈ Monitor changes to the KeePass config file
from non-KeePass processes
Thanks!
◈ Denis Andzakovic - Creator of KeeFarce◈ Matt Graeber’s PIC_BindShell
⬥ Generating shellcode from C-code in Visual Studio⬥ https://github.com/mattifestation/PIC_Bindshe
ll◈ Microsoft’s ClrMD - .NET memory analysis
⬥ https://github.com/Microsoft/clrmd
Thanks!
Any questions?
@tifkin_ and @harmj0y
Get KeeThief: https://github.com/HarmJ0y/KeeThief