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 Background
and 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:APPDATAMicrosoftWindowsRecent |
?{$_.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:UsersuserAppDataRoamingKeePas
sKeePass.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
"$DriveLetterkey.jpg") {Copy-Item "$DriveLetterkey.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 material
encrypted by
RtlEncryptMemory
1. PowerShell script
loads a custom
.NET assembly
2. Custom assembly
loads .NET 2.0
backport of ClrMD
3. ClrMD locates
CompositeKey
object
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

A Case Study in Attacking KeePass

  • 1.
    A Case Study inAttacking Keepass
  • 2.
    @tifkin_ Red Teamer, Hunter,Capability Dev UnmanagedPowerShell | RAT developer | PowerShell Junkie
  • 3.
    @harmj0y Offensive Engineer andRed Teamer Co-founder of Empire/EmPyre | PowerTools | Veil-Framework PowerSploit/BloodHound Developer
  • 4.
    TL;DR ◈ KeePass Overview ◈“Attacking” KeePass ⬥ KeePass.config.xml, key files, and more ⬥ Existing Work (KeeFarce) ⬥ KeeThief ⬥ The KeePass Trigger System ◈ Demos ◈ Mitigations
  • 5.
    Our Big Point Ifa 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
  • 6.
  • 7.
    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’
  • 8.
  • 9.
    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
  • 10.
    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’
  • 11.
    Recovering DPAPI KeyMaterial: Restore-UserDPAPI.ps1
  • 12.
    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
  • 13.
  • 14.
    Identifying KeePass ◈ Ifrunning: ⬥ 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:APPDATAMicrosoftWindowsRecent | ?{$_.FullName -match 'kdb|keepass'}
  • 15.
  • 16.
    Cracking a KeePassDatabase ◈ 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)
  • 17.
    KeePass.config.xml ◈ Located at C:UsersuserAppDataRoamingKeePas sKeePass.config.xmlor in the folder of a roaming installation ◈ The ‘KeySources’ section has some interesting information...
  • 18.
  • 19.
    Finding/Parsing KeePass.config.xml’s ◈ KeePassConfig.ps1in KeeThief includes Find-KeePassconfig:
  • 20.
    Nabbing Key FilesWith 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
  • 21.
    Nabbing Key FilesWith 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 "$DriveLetterkey.jpg") {Copy-Item "$DriveLetterkey.jpg" "C:Temp" -Force}}
  • 22.
  • 23.
    Registering the Trigger Register-WMIBackdoor-Trigger $(New-WMIBackdoorTrigger -DriveInsertion) -Action $(New-WMIBackdoorAction -FileClone)
  • 24.
  • 25.
    KeeFarce Release ◈ ReleasedOctober 2015 by Denis Andzakovic (denandz) ⬥ https://github.com/denandz/KeeFarce ◈ Allows for the export of an unlocked KeePass database to a .CSV on disk!
  • 26.
    “ “KeeFarce is not athreat...” -Dominik Reichl (KeePass Author) https://sourceforge.net/p/keepass/discussion/329220/thread/8e511d96/#e919
  • 27.
    KeeFarce Process Part1 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
  • 28.
    KeeFarce Process Part2 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
  • 29.
    KeeFarce Disadvantages ◈ InKeeFarce’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
  • 30.
  • 31.
    KeeThief ◈ PowerShell 2.0-compatibletool 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
  • 32.
  • 33.
    1. PowerShell script loadsa custom .NET assembly 2. Custom assembly loads .NET 2.0 backport of ClrMD 3. ClrMD locates CompositeKey object 4. ClrMD locates references to to key classes
  • 34.
    5. ClrMD locatesand extracts encrypted key material 6. Assembly injects shellcode to decrypt key material 7. Extracts plaintext key material
  • 36.
    The KeePass Trigger System ExfiltrationWithout Malware ….yes, really 5
  • 37.
    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!
  • 38.
    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.
  • 42.
  • 44.
    Auto-backdooring Triggers ◈ KeeThief’sKeePassConfig.ps1 also includes Add-KeePassConfigTrigger to insert malicious triggers into a KeePass.config.xml ◈ Find-KeePassconfig | Add-KeePassConfigTrigger ⬥ -Action <X> : either ‘ExportDatabase’ or ‘ExfilDataCopied’
  • 45.
  • 46.
  • 47.
    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)
  • 48.
    Detection/Things to bewareof ◈ 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
  • 49.
    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
  • 50.
    Thanks! Any questions? @tifkin_ and@harmj0y Get KeeThief: https://github.com/HarmJ0y/KeeThief