Skip to main content

Cloud TLS Certificates

The Cloud TLS Certificates API provides access to DNS-related cloud certificate information discovered through FullHunt's Internet scanning infrastructure.

Query the database for DNS-related cloud certificate information.

HTTP Request

GET https://fullhunt.io/api/v1/nexus/cloud-certs/dns-search

Query Parameters

ParameterRequiredTypeDescription
queryYesstringSearch query to discover cloud assets with specific DNS names

Example Request

curl "https://fullhunt.io/api/v1/nexus/cloud-certs/dns-search?query=kaspersky" \
-H "X-API-KEY: xxxx-xxxx-xxxx-xxxxxx"

Example Response

{
"count": 4,
"data": [
{
"dns": ["kaspersky-test.mygiftcard.it", "carrefour-test.mygiftcard.it"],
"host": "34.107.159.9",
"port": "443"
},
{
"dns": ["kaspersky.com", "www.kaspersky.com"],
"host": "15.220.184.189",
"port": "443"
},
{
"dns": ["kaspersky.com", "www.kaspersky.com"],
"host": "3.122.200.240",
"port": "443"
},
{
"dns": ["kasperskylabs.jp"],
"host": "35.76.8.33",
"port": "443"
}
],
"error": "",
"status": 200
}

Response Fields

FieldTypeDescription
countintegerNumber of results found
dataarrayArray of certificate data objects
errorstringError message (empty on success)
statusintegerHTTP status code

Certificate Data Object Fields​

FieldTypeDescription
dnsarrayList of DNS names associated with the certificate
hoststringIP address of the host serving the certificate
portstringPort number where the certificate is served

Integration Example​

import requests
import json
from collections import defaultdict
import ipaddress

class CloudCertificateAnalyzer:
def __init__(self, api_key):
self.api_key = api_key
self.headers = {"X-API-KEY": api_key}
self.base_url = "https://fullhunt.io/api/v1/nexus/cloud-certs"

def search_dns_certificates(self, query):
"""Search for cloud certificates by DNS name."""
url = f"{self.base_url}/dns-search"
params = {"query": query}

response = requests.get(url, headers=self.headers, params=params)

if response.status_code == 200:
return response.json()
else:
print(f"Error searching certificates for '{query}': {response.status_code}")
return None

def analyze_certificate_distribution(self, query):
"""Analyze the distribution of certificates for a query."""
data = self.search_dns_certificates(query)

if not data or not data.get('data'):
print(f"No certificate data found for query: {query}")
return None

certificates = data['data']

print(f"šŸ“Š Certificate Analysis for '{query}'")
print("=" * 50)
print(f"Total certificates found: {len(certificates)}")

# Analyze by cloud provider
cloud_providers = self._identify_cloud_providers(certificates)

print(f"\nā˜ļø Cloud Provider Distribution:")
for provider, count in sorted(cloud_providers.items(), key=lambda x: x[1], reverse=True):
print(f" {provider}: {count} certificates")

# Analyze by port
port_distribution = defaultdict(int)
for cert in certificates:
port_distribution[cert['port']] += 1

print(f"\nšŸ”Œ Port Distribution:")
for port, count in sorted(port_distribution.items(), key=lambda x: x[1], reverse=True):
print(f" Port {port}: {count} certificates")

# Analyze DNS names
all_dns_names = []
for cert in certificates:
all_dns_names.extend(cert.get('dns', []))

unique_dns_names = set(all_dns_names)

print(f"\n🌐 DNS Names:")
print(f" Total DNS entries: {len(all_dns_names)}")
print(f" Unique DNS names: {len(unique_dns_names)}")

# Show top DNS names
dns_count = defaultdict(int)
for dns_name in all_dns_names:
dns_count[dns_name] += 1

print(f"\nšŸ“ˆ Top DNS Names:")
for dns_name, count in sorted(dns_count.items(), key=lambda x: x[1], reverse=True)[:10]:
print(f" {dns_name}: {count} occurrences")

return {
'total_certificates': len(certificates),
'cloud_providers': dict(cloud_providers),
'port_distribution': dict(port_distribution),
'unique_dns_names': len(unique_dns_names),
'top_dns_names': dict(sorted(dns_count.items(), key=lambda x: x[1], reverse=True)[:10])
}

def find_certificate_relationships(self, query):
"""Find relationships between certificates and infrastructure."""
data = self.search_dns_certificates(query)

if not data or not data.get('data'):
return None

certificates = data['data']

# Group by IP address
ip_groups = defaultdict(list)
for cert in certificates:
ip_groups[cert['host']].append(cert)

print(f"šŸ”— Certificate Relationships for '{query}'")
print("=" * 50)

# Find IPs hosting multiple certificates
multi_cert_ips = {ip: certs for ip, certs in ip_groups.items() if len(certs) > 1}

if multi_cert_ips:
print(f"\nšŸ“ IPs hosting multiple certificates: {len(multi_cert_ips)}")

for ip, certs in multi_cert_ips.items():
cloud_info = self._get_cloud_info(ip)
print(f"\n {ip} ({cloud_info}):")

all_dns = set()
for cert in certs:
all_dns.update(cert.get('dns', []))

for dns_name in sorted(all_dns)[:5]: # Show first 5
print(f" • {dns_name}")

if len(all_dns) > 5:
print(f" ... and {len(all_dns) - 5} more")

# Find certificates with shared DNS names
dns_to_ips = defaultdict(set)
for cert in certificates:
for dns_name in cert.get('dns', []):
dns_to_ips[dns_name].add(cert['host'])

shared_dns = {dns: ips for dns, ips in dns_to_ips.items() if len(ips) > 1}

if shared_dns:
print(f"\nšŸ”„ DNS names served from multiple IPs: {len(shared_dns)}")

for dns_name, ips in list(shared_dns.items())[:5]: # Show first 5
print(f"\n {dns_name}:")
for ip in sorted(ips):
cloud_info = self._get_cloud_info(ip)
print(f" • {ip} ({cloud_info})")

return {
'multi_cert_ips': len(multi_cert_ips),
'shared_dns_names': len(shared_dns),
'ip_groups': {ip: len(certs) for ip, certs in ip_groups.items()}
}

def _identify_cloud_providers(self, certificates):
"""Identify cloud providers based on IP addresses."""
provider_count = defaultdict(int)

for cert in certificates:
ip = cert['host']
provider = self._get_cloud_provider(ip)
provider_count[provider] += 1

return provider_count

def _get_cloud_provider(self, ip_address):
"""Identify cloud provider from IP address (simplified)."""
try:
ip = ipaddress.ip_address(ip_address)

# AWS ranges (simplified examples)
aws_ranges = [
ipaddress.ip_network('3.0.0.0/8'),
ipaddress.ip_network('13.0.0.0/8'),
ipaddress.ip_network('15.0.0.0/8'),
ipaddress.ip_network('18.0.0.0/8'),
ipaddress.ip_network('34.0.0.0/8'),
ipaddress.ip_network('35.0.0.0/8'),
ipaddress.ip_network('52.0.0.0/8'),
ipaddress.ip_network('54.0.0.0/8'),
]

# Google Cloud ranges (simplified examples)
gcp_ranges = [
ipaddress.ip_network('34.64.0.0/10'),
ipaddress.ip_network('35.184.0.0/13'),
ipaddress.ip_network('35.192.0.0/14'),
ipaddress.ip_network('35.196.0.0/15'),
]

# Azure ranges (simplified examples)
azure_ranges = [
ipaddress.ip_network('13.64.0.0/11'),
ipaddress.ip_network('13.96.0.0/13'),
ipaddress.ip_network('20.0.0.0/6'),
ipaddress.ip_network('40.64.0.0/10'),
]

for range_net in aws_ranges:
if ip in range_net:
return "AWS"

for range_net in gcp_ranges:
if ip in range_net:
return "Google Cloud"

for range_net in azure_ranges:
if ip in range_net:
return "Microsoft Azure"

return "Other/Unknown"

except ValueError:
return "Invalid IP"

def _get_cloud_info(self, ip_address):
"""Get cloud provider info for display."""
provider = self._get_cloud_provider(ip_address)
return provider

def export_certificate_data(self, query, filename=None):
"""Export certificate data to JSON file."""
data = self.search_dns_certificates(query)

if not data:
print("No data to export")
return False

if filename is None:
filename = f"cloud_certs_{query}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"

try:
with open(filename, 'w') as f:
json.dump(data, f, indent=2)

print(f"šŸ“ Certificate data exported to: {filename}")
return True

except Exception as e:
print(f"āŒ Failed to export data: {e}")
return False

# Usage Examples
api_key = "your-api-key-here"
analyzer = CloudCertificateAnalyzer(api_key)

# Basic search
query = "kaspersky"
results = analyzer.search_dns_certificates(query)
print(f"Found {results.get('count', 0)} certificates for '{query}'")

# Detailed analysis
analysis = analyzer.analyze_certificate_distribution(query)

# Relationship analysis
relationships = analyzer.find_certificate_relationships(query)

# Export data
analyzer.export_certificate_data(query, f"{query}_certificates.json")

Advanced Analysis Examples​

import requests
import json
from datetime import datetime
import matplotlib.pyplot as plt
import pandas as pd

def certificate_discovery_analysis(api_key, company_keywords):
"""Perform comprehensive certificate discovery analysis."""
analyzer = CloudCertificateAnalyzer(api_key)

all_results = {}

print("šŸ” Certificate Discovery Analysis")
print("=" * 50)

for keyword in company_keywords:
print(f"\nSearching for: {keyword}")

data = analyzer.search_dns_certificates(keyword)

if data and data.get('data'):
all_results[keyword] = data['data']
print(f" Found {len(data['data'])} certificates")
else:
print(f" No certificates found")

# Combine all results
all_certificates = []
for keyword, certs in all_results.items():
for cert in certs:
cert['search_keyword'] = keyword
all_certificates.append(cert)

if not all_certificates:
print("No certificates found for any keywords")
return

print(f"\nšŸ“Š Combined Analysis:")
print(f" Total certificates: {len(all_certificates)}")

# Create comprehensive report
report = {
'timestamp': datetime.now().isoformat(),
'keywords_searched': company_keywords,
'total_certificates': len(all_certificates),
'certificates_by_keyword': {k: len(v) for k, v in all_results.items()},
'detailed_data': all_certificates
}

# Analyze infrastructure patterns
ip_frequency = {}
dns_patterns = {}

for cert in all_certificates:
ip = cert['host']
ip_frequency[ip] = ip_frequency.get(ip, 0) + 1

for dns_name in cert.get('dns', []):
# Extract domain from DNS name
domain_parts = dns_name.split('.')
if len(domain_parts) >= 2:
domain = '.'.join(domain_parts[-2:])
dns_patterns[domain] = dns_patterns.get(domain, 0) + 1

# Find most common infrastructure
print(f"\nšŸ—ļø Infrastructure Analysis:")

common_ips = sorted(ip_frequency.items(), key=lambda x: x[1], reverse=True)[:5]
print(f" Most common IPs:")
for ip, count in common_ips:
cloud_provider = analyzer._get_cloud_provider(ip)
print(f" {ip}: {count} certificates ({cloud_provider})")

common_domains = sorted(dns_patterns.items(), key=lambda x: x[1], reverse=True)[:10]
print(f"\n Most common domains:")
for domain, count in common_domains:
print(f" {domain}: {count} certificates")

# Save comprehensive report
report_filename = f"certificate_discovery_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
with open(report_filename, 'w') as f:
json.dump(report, f, indent=2)

print(f"\nšŸ“ Comprehensive report saved: {report_filename}")

return report

def monitor_certificate_changes(api_key, query, check_interval_hours=24):
"""Monitor for changes in certificate data over time."""
analyzer = CloudCertificateAnalyzer(api_key)

print(f"šŸ“” Starting certificate monitoring for: {query}")
print(f" Check interval: {check_interval_hours} hours")

# Get initial baseline
initial_data = analyzer.search_dns_certificates(query)

if not initial_data or not initial_data.get('data'):
print("No initial data found - cannot establish baseline")
return

baseline_certificates = set()
for cert in initial_data['data']:
cert_signature = f"{cert['host']}:{cert['port']}:{','.join(sorted(cert.get('dns', [])))}"
baseline_certificates.add(cert_signature)

print(f"šŸ“Š Baseline established: {len(baseline_certificates)} unique certificates")

# Save baseline
baseline_data = {
'timestamp': datetime.now().isoformat(),
'query': query,
'certificates': initial_data['data'],
'signature_count': len(baseline_certificates)
}

with open(f"certificate_baseline_{query}_{datetime.now().strftime('%Y%m%d')}.json", 'w') as f:
json.dump(baseline_data, f, indent=2)

return baseline_certificates

# Usage for advanced analysis
api_key = "your-api-key-here"

# Company-wide certificate discovery
company_keywords = ["acme", "acmecorp", "acme-corp"]
discovery_report = certificate_discovery_analysis(api_key, company_keywords)

# Start monitoring for changes
baseline = monitor_certificate_changes(api_key, "acme")

Use Cases​

Cloud Asset Discovery​

  • Discover cloud infrastructure associated with your organization
  • Identify shadow IT and unauthorized cloud deployments
  • Map certificate relationships across cloud providers

Security Assessment​

  • Analyze SSL/TLS certificate configurations
  • Identify potential certificate management issues
  • Monitor for certificate expiration and renewal patterns

Threat Intelligence​

  • Track infrastructure changes over time
  • Identify potential typosquatting or impersonation attempts
  • Correlate certificate data with threat actor infrastructure

Compliance Monitoring​

  • Ensure proper certificate management across cloud assets
  • Monitor for unauthorized certificate deployments
  • Validate certificate authority usage policies

Best Practices​

Search Optimization​

  1. Keyword Strategy: Use specific company names, products, and variations
  2. Iterative Searches: Start broad, then narrow down based on results
  3. Regular Monitoring: Set up periodic searches for infrastructure changes
  4. Data Validation: Cross-reference findings with known assets

Analysis Techniques​

  1. Pattern Recognition: Look for naming patterns and infrastructure relationships
  2. Cloud Provider Mapping: Identify which cloud providers host your certificates
  3. Change Detection: Monitor for new certificates and infrastructure changes
  4. Risk Assessment: Evaluate certificate configurations for security issues

Integration Tips​

  1. Asset Management: Feed discoveries into asset management systems
  2. Security Tools: Integrate with vulnerability scanners and monitoring platforms
  3. Alerting: Set up alerts for significant certificate infrastructure changes
  4. Documentation: Maintain records of discovered certificates and their purposes