Short-lived ephemeral code signing certificates


Description

Identifies files signed by certificates with a lifespan <= 14 days on non-developer endpoints. While legitimate software certs last 1+ years, ephemeral certs indicate Malware-Signing-as-a-Service (MSaaS) abuse to evade reputation-based controls.

Query · kql

// --- ADAPTATION GUIDE ---
// 1. EphemeralThreshold: 14 days is the 'anomalous zone'. Values over 30d may lead to higher false positives.
// 2. DevSoftwareKeywords: Add internal dev tools (e.g., 'Jenkins', 'TeamCity') to reduce noise.
// 3. devDeviceTags: Add internal dev device group name to reduce noise.
// 4. ExcludedIssuers: Add your organization's internal CA name here to prevent false positives.

let ephemeralThreshold = 14d;
let lookback = 7d;
let devSoftwareKeywords = dynamic(["Visual Studio", "IntelliJ", "Jenkins", "GitHub", "Git", "Kubernetes", "Docker", "Sublime"]);
let devDeviceTags = dynamic(["Engineering", "Dev-Workstation", "Build-Server"]);
let excludedIssuers = dynamic(["Internal-CA-Example", "Local-Admin-Signer"]);

// Step 1: Create a lookup table of developer assets likely to use legitimate short-lived certificates via Software and Device Tags
let devAssets = (
  DeviceTvmSoftwareInventory
  | where SoftwareName has_any (devSoftwareKeywords)
  | summarize by DeviceId
  | union (
    DeviceInfo
    | where Timestamp >= ago(lookback)
    | where RegistryDeviceTag has_any (devDeviceTags) 
      // Optional table if used: or DeviceDynamicTags has_any (devDeviceTags) 
      // Optional table if used: or DeviceManualTags has_any (devDeviceTags)
    | summarize by DeviceId
  )
  | summarize by DeviceId
);

// Step 2: Identify certificates within the 14-day anomalous window
DeviceFileCertificateInfo
| extend TotalLifespan = CertificateExpirationTime - CertificateCreationTime
| where TotalLifespan <= ephemeralThreshold and TotalLifespan > 0d
| where isnotempty(Issuer) and not(Issuer has_any (excludedIssuers))

// Step 3: Remove known dev machines to surface anomalies on standard user endpoints
| join kind=leftanti (devAssets) on DeviceId

// Step 4: Enrich with the latest machine details
| join kind=inner (
    DeviceInfo 
    | where Timestamp >= ago(lookback)
    | summarize arg_max(Timestamp, *) by DeviceId
  ) on DeviceId
| project 
    Timestamp, 
    DeviceName,
    DeviceId,
    PublicIP, 
    LoggedOnUsers,
    SHA1,
    Signer,
    Issuer, 
    IsTrusted,
    TotalLifespan, 
    CertificateCreationTime, 
    CertificateExpirationTime
Raw source Short-lived ephemeral code signing certificates · KQL
Esc
Published by Azure/Azure-Sentinel ↗, licensed under MIT ↗. Reproduced here unmodified.
id: e920899f-edf0-446c-bb13-effbaf61b27b
name: Short-lived ephemeral code signing certificates
description: |
  Identifies files signed by certificates with a lifespan <= 14 days on non-developer endpoints. While legitimate software certs last 1+ years, ephemeral certs indicate Malware-Signing-as-a-Service (MSaaS) abuse to evade reputation-based controls.

description-detailed: |
  Commercial software is typically signed with certificates valid for 1 to 3 years. Ephemeral (short-lived) certificates are legitimately used in automated DevOps pipelines (e.g., Azure Artifact Signing). However, threat actors like Fox Tempest operate Malware-Signing-as-a-Service (MSaaS) to generate 72-hour to 14-day certificates for malicious payloads. Finding these short-lived certificates in a non-developer environment is a high-fidelity indicator of evasion, as it allows malware to bypass SmartScreen and EDR reputation filters before the certificate can be revoked.
  References:
  - https://www.microsoft.com/en-us/security/blog/2026/05/19/exposing-fox-tempest-a-malware-signing-service-operation/
  - https://learn.microsoft.com/en-us/azure/artifact-signing/overview


requiredDataConnectors:
  - connectorId: MicrosoftThreatProtection
    dataTypes:
      - DeviceFileCertificateInfo
      - DeviceInfo
      - DeviceTvmSoftwareInventory
tactics:
  - DefenseEvasion
  - ResourceDevelopment
relevantTechniques:
  - T1553.002
  - T1588.003
tags:
  - FoxTempest
query: |
  // --- ADAPTATION GUIDE ---
  // 1. EphemeralThreshold: 14 days is the 'anomalous zone'. Values over 30d may lead to higher false positives.
  // 2. DevSoftwareKeywords: Add internal dev tools (e.g., 'Jenkins', 'TeamCity') to reduce noise.
  // 3. devDeviceTags: Add internal dev device group name to reduce noise.
  // 4. ExcludedIssuers: Add your organization's internal CA name here to prevent false positives.

  let ephemeralThreshold = 14d;
  let lookback = 7d;
  let devSoftwareKeywords = dynamic(["Visual Studio", "IntelliJ", "Jenkins", "GitHub", "Git", "Kubernetes", "Docker", "Sublime"]);
  let devDeviceTags = dynamic(["Engineering", "Dev-Workstation", "Build-Server"]);
  let excludedIssuers = dynamic(["Internal-CA-Example", "Local-Admin-Signer"]);

  // Step 1: Create a lookup table of developer assets likely to use legitimate short-lived certificates via Software and Device Tags
  let devAssets = (
    DeviceTvmSoftwareInventory
    | where SoftwareName has_any (devSoftwareKeywords)
    | summarize by DeviceId
    | union (
      DeviceInfo
      | where Timestamp >= ago(lookback)
      | where RegistryDeviceTag has_any (devDeviceTags) 
        // Optional table if used: or DeviceDynamicTags has_any (devDeviceTags) 
        // Optional table if used: or DeviceManualTags has_any (devDeviceTags)
      | summarize by DeviceId
    )
    | summarize by DeviceId
  );

  // Step 2: Identify certificates within the 14-day anomalous window
  DeviceFileCertificateInfo
  | extend TotalLifespan = CertificateExpirationTime - CertificateCreationTime
  | where TotalLifespan <= ephemeralThreshold and TotalLifespan > 0d
  | where isnotempty(Issuer) and not(Issuer has_any (excludedIssuers))

  // Step 3: Remove known dev machines to surface anomalies on standard user endpoints
  | join kind=leftanti (devAssets) on DeviceId

  // Step 4: Enrich with the latest machine details
  | join kind=inner (
      DeviceInfo 
      | where Timestamp >= ago(lookback)
      | summarize arg_max(Timestamp, *) by DeviceId
    ) on DeviceId
  | project 
      Timestamp, 
      DeviceName,
      DeviceId,
      PublicIP, 
      LoggedOnUsers,
      SHA1,
      Signer,
      Issuer, 
      IsTrusted,
      TotalLifespan, 
      CertificateCreationTime, 
      CertificateExpirationTime

entityMappings:
  - entityType: Host
    fieldMappings:
      - identifier: FullName
        columnName: DeviceName
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: PublicIP
  - entityType: FileHash
    fieldMappings:
      - identifier: Value
        columnName: SHA1
customDetails:
  DefenderDeviceId: DeviceId
  CertLifespanDays: TotalLifespan

version: 1.0.0
metadata:
  source:
    kind: Community
  author:
    name: Younes Al Taleb
  support:
    tier: Community
  categories:
    domains: [ "Security - Threat Protection" ]

Detection rules belong to the projects that publish them and remain under their own licenses. This site indexes and links to them; it claims no rights in them.