DEV Community

Rxkov
Rxkov

Posted on Originally published at blog.mago.team

CT Logs for OSINT: Map Subdomains and Infrastructure Without Sending a Single Packet

CT Logs for OSINT: Map Subdomains and Infrastructure Without Sending a Single Packet

During a technical M&A due diligence, the analyst ran no active scanner. He ran curl 'https://crt.sh/?q=target-company.com&output=json' | jq '.[].name_value' and got back 63 names: analytics-staging.target-company.com, internal-jenkins.target-company.com, legacy-api-v1.target-company.com. Three of them responded with 200 OK and login forms with no basic authentication. The data room for that deal changed that afternoon.

Every TLS certificate issued by a public CA gets recorded in Certificate Transparency logs before it ever reaches a server. A practitioner querying those logs can enumerate every subdomain for which an organization has ever issued a certificate, without sending a single packet to the target. A CT log is not a side effect of public PKI. It is a permanent and involuntary inventory of any organization's TLS infrastructure, available to anyone with a terminal and an internet connection. This guide shows how to extract that inventory systematically, from the initial query to identifying concrete attack vectors.

CT Logs Are Cryptographic Structures, Not Erasable Databases

CT logs were defined by RFC 6962 (2013); RFC 9162 (CT v2.0, 2021, which introduced submission policies and more efficient log formats) updated the original protocol. There are now 8 active operators in the ecosystem: Google (Xenon and Argon series), Cloudflare, DigiCert, Sectigo, Let's Encrypt (Sycamore and Willow), TrustAsia, IPNG, and Geomys. For the technical foundation of the CT protocol, see: CT Logs: Your Infrastructure Inventory.

The implication for OSINT is direct. Once a certificate enters any log, it stays there indefinitely. The subdomain staging-legacy.company.com.br issued in 2017, forgotten by the ops team, with default credentials still active, shows up in any query against the logs today. The data is immutable and public from the moment of issuance, regardless of what happened to the server afterward.

A Wildcard Query on crt.sh Returns the Full Subdomain Inventory

crt.sh is maintained by Comodo CA and indexes certificates from all major logs in a Postgres database with direct SQL query support. A single wildcard query returns the full certificate history for a domain, including expired, revoked, and long-forgotten ones.

curl -s 'https://crt.sh/?q=%.target.com&output=json' | jq -r '.[].name_value' | sort -u
Enter fullscreen mode Exit fullscreen mode

This command extracts the name_value field from each entry returned by the JSON API. That field contains the certificate's SANs (Subject Alternative Names): a single multi-domain certificate can list over 100 subdomains in one SAN. Certificates issued by platform teams to cover multiple services in a single issuance are the most productive: each SAN is a potential entry point. The sort -u removes duplicates across different entries that share SANs.

InventiveHQ documented that roughly 1/3 of subdomains discovered via CT are invisible to standard DNS queries or conventional crawling. These are the most interesting assets: never indexed, never scanned, never surfaced by any other recon tool. Historical records go back to 2015. Staging environments, development servers, CI/CD instances, and legacy systems show up in results even when the corresponding DNS was removed years ago. The organization forgot the server. The log did not. Bug bounty hunters have documented cases of staging servers found exclusively via CT, with default credentials still active, with no other recon method having returned the host.

Certificate Metadata Reveals What Was Never in the Plan

The subdomain list is the most obvious data in a CT log. The metadata accompanying each certificate is often more revealing. The issuance date of a burst of certificates for *.internal.company.com in 2019 points to infrastructure expansion or system migration during that specific period, even with no corresponding public announcement.

Issuer changes tell stories of internal policy shifts. A company that moved from DigiCert to Let's Encrypt on a subset of domains signaled automation or cost cutting. To detect this shift systematically:

curl 'https://crt.sh/?q=company.com&output=json' | jq '[.[] | {date: .entry_timestamp, issuer: .issuer_name}] | unique_by(.issuer)'
Enter fullscreen mode Exit fullscreen mode

That infrastructure moved out of centralized procurement control and into individual teams, possibly outside any security review scope. SAN prefixes like api-dev-, stage-, uat- expose the organization's complete environment taxonomy: how many parallel environments exist, how they are named, what pattern the engineering team follows.

Shadow IT shows up as certificates issued for domains on unmanaged infrastructure: personal developer accounts, forgotten CNAMEs, servers provisioned by teams without formal security approval. Corporate acquisitions also leave a trail: certificates for legacy brands under the new parent domain appear in the logs before any public announcement. Heidbrink et al., "Certificate Transparency: An Empirical Analysis", IEEE EuroS&P 2023 (DOI: 10.1109/EuroSP57164.2023.00014) confirmed that CT log queries surfaced vulnerabilities in targets that were not found by any other active or passive reconnaissance method tested in the study.

Certstream Turns the CT Firehose into Real-Time Alerts

Certstream is a WebSocket server written in Elixir by CaliDog that aggregates all CT logs trusted by Chrome and Apple into a single continuous stream. It processes around 250TB of data per month and exposes each newly issued certificate in real time via WebSocket and SSE, with /stats and /metrics endpoints for Prometheus integration.

import certstream

def print_callback(message, context):
    if message['message_type'] == 'certificate_update':
        domains = message['data']['leaf_cert']['all_domains']
        for domain in domains:
            if 'target.com' in domain:
                print(domain)

certstream.listen_for_updates(print_callback)
Enter fullscreen mode Exit fullscreen mode

For offensive use, any new certificate for *.target.com triggers an alert before DNS propagates. You detect new target infrastructure the moment the CA registers it, not when it goes into production. For defensive use, a phishing domain like paypal-secure-login[.]com issues a Let's Encrypt certificate and appears in the stream within minutes, before the first malicious email is sent. There is also certstream.dev, a Rust implementation with a REST API for certificate lookup and log health checking, useful for production environments that need continuous monitoring.

Tools like subfinder and amass integrate CT directly. subfinder -d example.com queries crt.sh natively, without any additional configuration. The intelligence advantage is structural: certificate issuance happens before DNS propagation, making CT the earliest available signal for attack surface monitoring.

The Passive Pipeline: CT Query, Dedup, DNS Resolve, HTTP Probe

The first 3 steps of the pipeline send no packet directly to the target. Step 4 is the first active contact and can be isolated or deferred depending on the operation's scope.

Step 1: query crt.sh extracting name_value via curl and jq.

Step 2: deduplicate against an accumulated list of known subdomains with anew:

curl -s 'https://crt.sh/?q=%.target.com&output=json' | \
  jq -r '.[].name_value' | \
  sort -u | \
  anew subs.txt
Enter fullscreen mode Exit fullscreen mode

Step 3: DNS resolution to filter responding hosts, with dnsx:

dnsx -l subs.txt -o resolved.txt
Enter fullscreen mode Exit fullscreen mode

Step 4: HTTP probe for response fingerprinting with httpx:

httpx -l resolved.txt -status-code -title -tech-detect
Enter fullscreen mode Exit fullscreen mode

intel.mago.team (the MAGO team's tool) cross-references subdomains discovered via CT with API security scan results, identifying endpoints that appear in the logs but not in the declared surface. An endpoint at api-internal.company.com that was never declared in the API gateway but appears in a SAN issued in 2021 is a direct candidate for shadow API investigation. Detection happens passively, with no active scan against the target's infrastructure.

Crossing with RPKI

Each subdomain discovered via CT can be crossed with RPKI coverage to identify legacy infrastructure without routing protection. New IP blocks associated with newly discovered subdomains can be checked at stat.ripe.net for ROA coverage. Blocks with no route declaration often correspond to legacy infrastructure outside any formal review process. These are higher-value targets precisely because no one reviewed them.

The log is public and immutable. The attacker who queries first gets the full list. The organization that never queried does not know what it exposed. Every certificate issued was an involuntary publication. The impact depends on who reads the data first.

Top comments (0)