Cloud TLS Certificates
The Cloud TLS Certificates API provides access to DNS-related cloud certificate information discovered through FullHunt's Internet scanning infrastructure.
DNS Searchā
Query the database for DNS-related cloud certificate information.
HTTP Request
GET https://fullhunt.io/api/v1/nexus/cloud-certs/dns-search
Query Parameters
Parameter | Required | Type | Description |
---|---|---|---|
query | Yes | string | Search 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
Field | Type | Description |
---|---|---|
count | integer | Number of results found |
data | array | Array of certificate data objects |
error | string | Error message (empty on success) |
status | integer | HTTP status code |
Certificate Data Object Fieldsā
Field | Type | Description |
---|---|---|
dns | array | List of DNS names associated with the certificate |
host | string | IP address of the host serving the certificate |
port | string | Port 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ā
- Keyword Strategy: Use specific company names, products, and variations
- Iterative Searches: Start broad, then narrow down based on results
- Regular Monitoring: Set up periodic searches for infrastructure changes
- Data Validation: Cross-reference findings with known assets
Analysis Techniquesā
- Pattern Recognition: Look for naming patterns and infrastructure relationships
- Cloud Provider Mapping: Identify which cloud providers host your certificates
- Change Detection: Monitor for new certificates and infrastructure changes
- Risk Assessment: Evaluate certificate configurations for security issues
Integration Tipsā
- Asset Management: Feed discoveries into asset management systems
- Security Tools: Integrate with vulnerability scanners and monitoring platforms
- Alerting: Set up alerts for significant certificate infrastructure changes
- Documentation: Maintain records of discovered certificates and their purposes