By Davy Rogers. Use these techniques only in environments you own or have explicit permission to test.

Passive Reconnaissance: crt.sh (Certificate Transparency)

Certificate Transparency (CT) is a system that logs all SSL/TLS certificates issued by Certificate Authorities. The website crt.sh provides a searchable interface to these logs, making it an invaluable tool for passive reconnaissance. By searching CT logs, penetration testers can discover subdomains, infrastructure, and services without ever touching the target's systems.

What You'll Learn

  • What Certificate Transparency is and why it exists
  • How to use crt.sh for subdomain enumeration
  • Understanding SSL/TLS certificate information
  • Automating CT log searches
  • Finding hidden infrastructure and services
  • Combining CT logs with other reconnaissance
  • Using CT logs for asset discovery
  • Privacy implications of CT logs

What Is Certificate Transparency?

Certificate Transparency is an open framework for monitoring and auditing SSL/TLS certificates in real-time.

The Problem CT Solves:

Before CT:
1. CA issues certificate
2. Only CA and domain owner know
3. Malicious/fraudulent certs can exist undetected
4. No public record

After CT (2013+):
1. CA issues certificate
2. Certificate logged to public CT logs
3. Anyone can search and monitor
4. Detect fraudulent certificates
5. Accountability for CAs

Why This Matters for Recon:

Every subdomain that gets an SSL certificate:
→ Gets logged to CT
→ Becomes publicly searchable
→ Reveals infrastructure

Even if subdomain is:
- Not linked anywhere
- Not in DNS
- "Hidden"
→ CT logs expose it!

What Is crt.sh?

crt.sh is a web interface to search Certificate Transparency logs.

Access:

Website: https://crt.sh
Free, no registration required
Searches multiple CT logs

What You Can Find:

✓ Subdomains (most common use)
✓ Certificate details
✓ Certificate issuers
✓ Validity periods
✓ SANs (Subject Alternative Names)
✓ Wildcard certificates
✓ Historical certificates
✓ Related domains

Using crt.sh for Subdomain Enumeration

1. Go to https://crt.sh
2. Enter domain: example.com
3. Click "Search"
4. View all certificates for that domain

Search Operators:

Exact domain:

example.com

Include subdomains:

%.example.com

% = wildcard (like * in other tools)

Specific subdomain:

mail.example.com

Understanding the Results

Example Output:

Logged At              | crt.sh ID | Issuer         | Not Before | Not After  | Subject
──────────────────────────────────────────────────────────────────────────────────────
2024-01-15 14:23:45   | 12345678  | Let's Encrypt  | 2024-01-15 | 2024-04-15 | CN=example.com
2024-01-15 14:23:45   | 12345678  |                |            |            | DNS:example.com
                       |           |                |            |            | DNS:www.example.com
                       |           |                |            |            | DNS:mail.example.com
                       |           |                |            |            | DNS:api.example.com

Key Fields:

Logged At:

When certificate was added to CT log
Recent = currently in use
Old = historical (might be deprecated)

Issuer:

Certificate Authority that issued cert
Common: Let's Encrypt, DigiCert, Cloudflare

Subject & SANs:

Domain names covered by certificate
SANs (Subject Alternative Names):
- Multiple domains on one cert
- Reveals related subdomains

Validity Period:

Not Before: Certificate valid from
Not After: Certificate expires

Expired certs:
- Might indicate old infrastructure
- Services may be decommissioned

Command-Line CT Log Queries

Using curl:

# JSON output
curl -s "https://crt.sh/?q=%.example.com&output=json" | jq .

# Extract just domain names
curl -s "https://crt.sh/?q=%.example.com&output=json" | \
  jq -r '.[].name_value' | \
  sort -u

# Save to file
curl -s "https://crt.sh/?q=%.example.com&output=json" | \
  jq -r '.[].name_value' | \
  sort -u > subdomains.txt

Parsing and Cleaning:

# Remove wildcards and duplicates
curl -s "https://crt.sh/?q=%.example.com&output=json" | \
  jq -r '.[].name_value' | \
  sed 's/\*\.//g' | \
  sort -u | \
  grep -v "@"  # Remove email addresses if any

One-Liner for Quick Recon:

curl -s "https://crt.sh/?q=%.example.com&output=json" | \
  jq -r '.[].name_value' | \
  sort -u | \
  tee subdomains.txt

Automated CT Log Enumeration

Python Script:

#!/usr/bin/env python3
import requests
import json

def get_subdomains(domain):
    """Fetch subdomains from crt.sh"""
    url = f"https://crt.sh/?q=%.{domain}&output=json"
    
    try:
        response = requests.get(url, timeout=30)
        data = json.loads(response.text)
        
        subdomains = set()
        for cert in data:
            # Extract common_name
            name = cert.get('name_value', '')
            # Split by newlines (SANs on separate lines)
            for subdomain in name.split('\n'):
                # Remove wildcards
                subdomain = subdomain.replace('*.', '')
                # Remove leading/trailing whitespace
                subdomain = subdomain.strip()
                if subdomain and '@' not in subdomain:
                    subdomains.add(subdomain)
        
        return sorted(subdomains)
    
    except Exception as e:
        print(f"Error: {e}")
        return []

if __name__ == "__main__":
    domain = "example.com"
    print(f"[*] Searching CT logs for: {domain}")
    
    subdomains = get_subdomains(domain)
    
    print(f"\n[+] Found {len(subdomains)} subdomains:\n")
    for subdomain in subdomains:
        print(subdomain)

Usage:

python3 crt_search.py
chmod +x crt_search.py
./crt_search.py

What Can You Discover?

1. Subdomains

Common findings:
- mail.example.com (email server)
- vpn.example.com (VPN portal)
- dev.example.com (development)
- staging.example.com (staging environment)
- api.example.com (API endpoints)
- admin.example.com (admin panel)
- internal.example.com (internal tools)

2. Infrastructure

Hosting providers:
- aws-ec2-1.example.com (AWS)
- azure-vm-prod.example.com (Azure)
- gcp-instance.example.com (Google Cloud)

Load balancers:
- lb1.example.com
- lb2.example.com

CDN:
- cdn.example.com
- static.example.com

3. Development/Staging

Non-production environments:
- dev.example.com
- test.example.com
- staging.example.com
- qa.example.com
- uat.example.com

Often less secure!
Good targets for testing

4. Regional/Geographic

- us.example.com
- eu.example.com
- uk.example.com
- asia.example.com

Reveals global infrastructure

5. Services

- webmail.example.com
- ftp.example.com
- ssh.example.com
- remote.example.com
- citrix.example.com

Advanced CT Log Techniques

1. Wildcard Certificate Analysis

If you find: *.example.com
This means:
- Organization uses wildcard cert
- Potentially many subdomains
- Other recon methods needed to find them

But:
- CT logs may show specific certs too
- Keep searching for non-wildcard certs

2. Historical Analysis

crt.sh shows ALL certificates:
- Current
- Expired
- Revoked

Old certificates reveal:
- Former subdomains
- Deprecated services
- Infrastructure changes
- Mergers/acquisitions

3. Certificate Issuer Patterns

Let's Encrypt:
- Free, automated
- Short validity (90 days)
- Frequent renewals
- Modern infrastructure

Paid CAs (DigiCert, etc.):
- Longer validity
- Organizational validation
- Higher assurance

Self-signed:
- Internal services
- Development/testing
- Security concern if in production

4. Subject Alternative Names (SANs)

One certificate can cover multiple domains:

Certificate for: example.com
SANs:
- www.example.com
- mail.example.com
- api.example.com
- shop.example.com

All revealed in one CT log entry!

Combining with Other Tools

Workflow:

1. crt.sh: Find subdomains
   ↓
2. Verify they resolve:
   ↓
   host subdomain.example.com
   ↓
3. Port scan live hosts:
   ↓
   nmap -sV subdomain.example.com
   ↓
4. Further enumeration:
   ↓
   nikto, gobuster, etc.

Example:

# Step 1: Get subdomains from crt.sh
curl -s "https://crt.sh/?q=%.example.com&output=json" | \
  jq -r '.[].name_value' | \
  sort -u > all_subdomains.txt

# Step 2: Check which resolve
while read subdomain; do
  if host "$subdomain" > /dev/null 2>&1; then
    echo "$subdomain" >> live_subdomains.txt
  fi
done < all_subdomains.txt

# Step 3: Scan live subdomains
nmap -iL live_subdomains.txt -oA scan_results

Other CT Log Tools

subfinder:

# Install
go install -v github.com/projectdiscovery/subfinder/v2/cmd/subfinder@latest

# Use (includes CT logs)
subfinder -d example.com

# Output to file
subfinder -d example.com -o subdomains.txt

Amass:

# Install
go install -v github.com/owasp-amass/amass/v4/...@master

# Use (includes CT logs and much more)
amass enum -d example.com

# Passive only (including CT)
amass enum -passive -d example.com

ct-exposer:

# Python tool specifically for CT logs
git clone https://github.com/chris408/ct-exposer.git
cd ct-exposer
pip3 install -r requirements.txt

python3 ct-exposer.py -d example.com

Try It Yourself

1. Go to https://crt.sh
2. Search: %.tesla.com
3. Browse results
4. Identify:
   - How many subdomains?
   - Any interesting ones? (dev, staging, internal?)
   - Certificate issuers?
   - Wildcard certs?
# Search a domain (use a company you're authorized to test)
curl -s "https://crt.sh/?q=%.example.com&output=json" | \
  jq -r '.[].name_value' | \
  sort -u

# How many unique subdomains?
curl -s "https://crt.sh/?q=%.example.com&output=json" | \
  jq -r '.[].name_value' | \
  sort -u | \
  wc -l

Exercise 3: Verify Resolution

# Get subdomains
curl -s "https://crt.sh/?q=%.example.com&output=json" | \
  jq -r '.[].name_value' | \
  sort -u > subs.txt

# Check which resolve
while read sub; do
  ip=$(host "$sub" 2>/dev/null | grep "has address" | awk '{print $4}')
  if [ -n "$ip" ]; then
    echo "$sub -> $ip"
  fi
done < subs.txt

Exercise 4: Compare with Other Methods

# CT logs
curl -s "https://crt.sh/?q=%.example.com&output=json" | \
  jq -r '.[].name_value' | \
  sort -u > ct_subs.txt

# DNS brute force (smaller wordlist for testing)
dnsrecon -d example.com -t brt -D small_wordlist.txt -o dns_subs.txt

# Compare unique findings
comm -3 <(sort ct_subs.txt) <(sort dns_subs.txt)

Limitations of CT Logs

What CT Logs Don't Show:

✗ Subdomains without SSL certificates
✗ Internal-only domains (no public cert)
✗ Subdomains using wildcard certs (only)
✗ Services on non-443 ports (without HTTPS)
✗ Recently created subdomains (lag time)

Solutions:

Combine with:
1. DNS brute forcing
2. Google dorking (site:example.com)
3. Shodan/Censys searches
4. Zone transfers (if allowed)
5. Web scraping/spidering
6. API enumeration

Privacy and Security Implications

For Organizations:

CT logs expose:
✓ All public SSL certificates
✓ Subdomain structure
✓ Infrastructure details
✓ Development environments
✓ Third-party services

Mitigation:
- Assume all cert info is public
- Don't use descriptive subdomain names
- Secure all hosts (even "hidden" ones)
- Monitor CT logs for your own domain

For Pentesters:

✓ Completely passive
✓ Legal (public data)
✓ No interaction with target
✓ Fast reconnaissance
✓ Historical data available

Perfect for initial recon phase!

Quick Reference

# Web interface
https://crt.sh/?q=%.example.com

# JSON API
curl -s "https://crt.sh/?q=%.example.com&output=json"

# Extract subdomains
curl -s "https://crt.sh/?q=%.example.com&output=json" | \
  jq -r '.[].name_value' | \
  sort -u

# Remove wildcards
sed 's/\*\.//g'

# Filter valid domains
grep -E '^[a-zA-Z0-9.-]+$'

Resources

Tools:

  • crt.sh: Web interface to CT logs
  • subfinder: Automated subdomain discovery (includes CT)
  • Amass: Comprehensive recon (includes CT)
  • ct-exposer: CT log specific tool

Other CT Log Interfaces:

Reading:

Practice:

  • Search major companies on crt.sh
  • Automate CT log queries
  • Combine with other recon methods
  • Build a subdomain monitoring tool

Next Steps

  1. Master crt.sh queries for subdomain enumeration
  2. Automate CT log searches with scripts
  3. Verify discovered subdomains are live
  4. Combine with DNS enumeration for comprehensive results
  5. Monitor CT logs for defensive purposes

Certificate Transparency logs are a goldmine for passive reconnaissance. Use them to map attack surfaces without touching target systems!


"crt.sh: Where every SSL certificate tells a story about your infrastructure."