Install Digital Certificate
Adversaries may install SSL/TLS certificates on infrastructure they control — whether acquired or compromised — to encrypt command-and-control traffic, lend credibility to credential harvesting sites, or enable adversary-in-the-middle operations. Certificate installation occurs entirely on adversary infrastructure and produces no telemetry within the victim environment. Sea Turtle (G1041) exemplifies this technique by capturing legitimate SSL certificates from victim organizations and installing them on attacker-controlled servers to conduct adversary-in-the-middle attacks against DNS infrastructure. Detection must rely on downstream signals: TLS certificate anomalies observed when victim systems connect to adversary infrastructure via proxy or NGFW TLS inspection, email security alerts for HTTPS phishing URLs, and certificate transparency (CT) log monitoring for adversary-registered domains.
// T1608.003 — Install Digital Certificate
// Detects suspicious TLS certificate properties via proxy/NGFW TLS inspection (CommonSecurityLog)
// Requires: TLS/SSL inspection enabled on NGFW or forward proxy
let LookbackPeriod = 24h;
let WeakCNValues = dynamic(["localhost", "example.com", "test", "temp", "staging-", "*.invalid", "default"]);
// Analyze TLS certificate properties in NGFW/proxy logs
CommonSecurityLog
| where TimeGenerated > ago(LookbackPeriod)
| where DeviceAction !in~ ("deny", "block", "drop", "reset", "reset-both", "Reset-Server", "Reset-Client")
| where DestinationPort in (443, 8443, 4443, 10443)
// Extract TLS fields — naming varies by vendor (Palo Alto, Check Point, Fortinet, Cisco)
| extend TLSSubject = coalesce(
extract(@"(?i)ssl-subject=([^;|\r\n]+)", 1, AdditionalExtensions),
extract(@"(?i)cn=([^,/;|\r\n]+)", 1, AdditionalExtensions),
DeviceCustomString3
)
| extend TLSIssuer = coalesce(
extract(@"(?i)ssl-issuer=([^;|\r\n]+)", 1, AdditionalExtensions),
extract(@"(?i)issuer-cn=([^,/;|\r\n]+)", 1, AdditionalExtensions),
DeviceCustomString4
)
| where isnotempty(TLSSubject) or isnotempty(TLSIssuer)
// Indicator 1: Self-signed certificate — issuer equals subject, highest adversary infra signal
| extend IsSelfSigned = isnotempty(TLSSubject) and isnotempty(TLSIssuer) and (TLSSubject =~ TLSIssuer)
// Indicator 2: Certificate CN does not match destination hostname — certificate reuse or misconfigured stolen cert
| extend IsHostnameMismatch = isnotempty(DestinationHostName) and isnotempty(TLSSubject)
and not(DestinationHostName endswith replace_regex(TLSSubject, @"(?i)^cn=\*?\.", ""))
and not(TLSSubject has DestinationHostName)
// Indicator 3: Generic or placeholder certificate CN — quickly generated adversary certs
| extend HasWeakCN = TLSSubject has_any (WeakCNValues)
// Score: self-signed highest risk (3), mismatch and weak CN moderate (2 each)
| extend CertRiskScore = toint(IsSelfSigned) * 3 + toint(IsHostnameMismatch) * 2 + toint(HasWeakCN) * 2
| where CertRiskScore > 1
| extend RiskLevel = case(
CertRiskScore >= 5, "High",
CertRiskScore >= 3, "Medium",
"Low"
)
| project TimeGenerated, SourceIP, DestinationIP, DestinationHostName, DestinationPort,
TLSSubject, TLSIssuer,
IsSelfSigned, IsHostnameMismatch, HasWeakCN,
CertRiskScore, RiskLevel, DeviceVendor, DeviceAction
| sort by CertRiskScore desc, TimeGenerated desc Data Sources
Required Tables
False Positives
- Internal development, test, or lab environments using self-signed certificates for services that should not be exposed externally but are reachable via proxy
- Legacy applications with hardcoded certificate subjects that no longer match the current hostname following a server rename or migration
- Internal Certificate Authorities (CAs) whose root certificates were not imported into the monitoring infrastructure, causing valid internal certificates to appear self-signed
- CDN providers (Cloudflare, Akamai, Fastly) presenting wildcard certificates where the wildcard CN does not exactly match the specific subdomain being accessed
- VPN concentrators, reverse proxies, or internal load balancers presenting a shared certificate that does not match every individual backend hostname
References (10)
- https://attack.mitre.org/techniques/T1608/003/
- https://www.digicert.com/kb/ssl-certificate-installation.htm
- https://www.splunk.com/en_us/blog/security/tall-tales-of-hunting-with-tls-ssl-certificates.html
- https://blog.talosintelligence.com/sea-turtle-keeps-on-swimming/
- https://crt.sh/
- https://censys.io/
- https://letsencrypt.org/docs/acme-protocol/
- https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1608.003/T1608.003.md
- https://learn.microsoft.com/en-us/azure/sentinel/connect-common-event-format
- https://docs.splunk.com/Documentation/StreamApp/latest/DeployStreamApp/AboutSplunkStream
Unlock Pro Content
Get the full detection package for T1608.003 including response playbook, investigation guide, and atomic red team tests.