passive-recon
WHOIS情報やDNS履歴、SSL証明書などを幅広く調査し、相手に気づかれずに公開情報から企業や組織のインフラ全体像を把握したり、初期段階のプロファイリングに役立てたりするSkill。
📜 元の英語説明(参考)
Comprehensive passive reconnaissance covering WHOIS, DNS history, reverse IP, SSL certificates, Google dorks, and Wayback Machine enumeration. Use when: initial target profiling without active scanning, stealth recon where no direct target contact is desired, or building a complete picture of a target's infrastructure from public data alone.
🇯🇵 日本人クリエイター向け解説
WHOIS情報やDNS履歴、SSL証明書などを幅広く調査し、相手に気づかれずに公開情報から企業や組織のインフラ全体像を把握したり、初期段階のプロファイリングに役立てたりするSkill。
※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。
下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o passive-recon.zip https://jpskill.com/download/15236.zip && unzip -o passive-recon.zip && rm passive-recon.zip
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/15236.zip -OutFile "$d\passive-recon.zip"; Expand-Archive "$d\passive-recon.zip" -DestinationPath $d -Force; ri "$d\passive-recon.zip"
完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。
💾 手動でダウンロードしたい(コマンドが難しい人向け)
- 1. 下の青いボタンを押して
passive-recon.zipをダウンロード - 2. ZIPファイルをダブルクリックで解凍 →
passive-reconフォルダができる - 3. そのフォルダを
C:\Users\あなたの名前\.claude\skills\(Win)または~/.claude/skills/(Mac)へ移動 - 4. Claude Code を再起動
⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。
🎯 このSkillでできること
下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。
📦 インストール方法 (3ステップ)
- 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
- 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
- 3. 展開してできたフォルダを、ホームフォルダの
.claude/skills/に置く- · macOS / Linux:
~/.claude/skills/ - · Windows:
%USERPROFILE%\.claude\skills\
- · macOS / Linux:
Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。
詳しい使い方ガイドを見る →- 最終更新
- 2026-05-18
- 取得日時
- 2026-05-18
- 同梱ファイル
- 1
📖 Skill本文(日本語訳)
※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。
[Skill 名] passive-recon
パッシブ偵察
概要
パッシブ偵察は、公開されている情報のみを使用してターゲットに関する情報を収集します。ターゲットのインフラストラクチャにパケットが送信されることはありません。これにより、公開されているデータに対して使用する場合は完全に検出不可能で、法的に安全になります。目標は、ターゲットとアクティブな接触を行う前に、WHOIS レコード、DNS の履歴、SSL 証明書ログ、検索エンジンのキャッシュ、および Web アーカイブから包括的な情報を作成することです。
手順
ステップ 1: WHOIS ルックアップ
import whois
import subprocess
import json
import re
def whois_lookup(domain):
"""python-whois ライブラリを使用して WHOIS ルックアップを実行します。"""
# pip install python-whois
try:
w = whois.whois(domain)
print(f"\n=== WHOIS: {domain} ===")
print(f"Registrar: {w.registrar}")
print(f"Created: {w.creation_date}")
print(f"Updated: {w.updated_date}")
print(f"Expires: {w.expiration_date}")
print(f"Name servers: {w.name_servers}")
print(f"Registrant org: {getattr(w, 'org', 'N/A')}")
print(f"Registrant email:{getattr(w, 'emails', 'N/A')}")
print(f"Registrant country: {getattr(w, 'country', 'N/A')}")
# プライバシー保護の確認
raw = str(w.text)
if any(word in raw.lower() for word in ["privacy", "redacted", "withheld", "domains by proxy"]):
print("\n ⚠ WHOIS プライバシー保護が有効になっています")
return dict(w)
except Exception as e:
print(f"WHOIS error for {domain}: {e}")
return None
def reverse_whois_email(email):
"""同じメールアドレスで登録されているドメインを検索します (ViewDNS または WHOIS API 経由)。"""
url = f"https://viewdns.info/reversewhois/?q={email}"
print(f"Reverse WHOIS for {email}: {url}")
# 注: ViewDNS.info には Web UI があります。自動化には API を使用してください
return url
whois_lookup("example.com")
ステップ 2: DNS 列挙と履歴
import dns.resolver
import requests
def dns_lookup(domain):
"""ドメインの DNS レコードを列挙します。"""
record_types = ["A", "AAAA", "MX", "NS", "TXT", "SOA", "CNAME"]
results = {}
print(f"\n=== DNS Records: {domain} ===")
for rtype in record_types:
try:
answers = dns.resolver.resolve(domain, rtype, lifetime=5)
records = [str(r) for r in answers]
results[rtype] = records
print(f" {rtype:<8}: {', '.join(records)}")
except (dns.resolver.NoAnswer, dns.resolver.NXDOMAIN, dns.exception.Timeout):
pass
return results
def dns_history_securitytrails(domain, api_key):
"""SecurityTrails API から過去の DNS レコードを取得します。"""
headers = {"apikey": api_key, "Accept": "application/json"}
base_url = "https://api.securitytrails.com/v1"
# 過去の A レコード
resp = requests.get(f"{base_url}/history/{domain}/dns/a", headers=headers, timeout=15)
data = resp.json()
print(f"\n=== DNS History (SecurityTrails): {domain} ===")
for record in data.get("records", []):
first_seen = record.get("first_seen")
last_seen = record.get("last_seen")
ips = [v.get("ip") for v in record.get("values", [])]
print(f" [{first_seen} → {last_seen}] {', '.join(ips)}")
return data
def passive_dns_free(domain):
"""無料のパッシブ DNS ソースをクエリします。"""
results = {}
# HackerTarget Passive DNS (無料)
try:
resp = requests.get(
f"https://api.hackertarget.com/hostsearch/?q={domain}",
timeout=15
)
if "error" not in resp.text.lower():
hosts = [line.split(",")[0] for line in resp.text.strip().split("\n") if "," in line]
results["hackertarget_hosts"] = hosts
print(f"HackerTarget は {domain} のサブドメインを {len(hosts)} 個検出しました")
except Exception as e:
print(f"HackerTarget error: {e}")
# CIRCL Passive DNS (無料、認証不要)
try:
resp = requests.get(
f"https://www.circl.lu/pdns/query/{domain}",
headers={"Accept": "application/json"},
timeout=15
)
records = [json.loads(line) for line in resp.text.strip().split("\n") if line]
ips = list({r.get("rdata") for r in records if r.get("rrtype") == "A"})
results["circl_ips"] = ips
print(f"CIRCL passive DNS: {len(records)} records, {len(ips)} unique IPs")
except Exception as e:
print(f"CIRCL error: {e}")
return results
dns_lookup("example.com")
ステップ 3: リバース IP ルックアップ
def reverse_ip_lookup(ip_address):
"""同じ IP アドレスでホストされているすべてのドメインを検索します。"""
# HackerTarget API (無料、最大 500 件の結果)
try:
resp = requests.get(
f"https://api.hackertarget.com/reverseiplookup/?q={ip_address}",
timeout=15
)
if "error" not in resp.text.lower() and resp.text.strip():
domains = [d.strip() for d in resp.text.strip().split("\n")]
print(f"\n=== Reverse IP: {ip_address} ===")
print(f"Hosted domains: {len(domains)}")
for d in domains[:20]:
print(f" {d}")
if len(domains) > 20:
print(f" ... and {len(domains) - 20} more")
return domains
except Exception as e:
print(f"Reverse IP error: {e}")
return []
def ip_info(ip_address):
"""IP のジオロケーション、ASN、および組織情報を取得します。"""
resp = requests.get(f"https://ipapi.co/{ip_address}/json/", timeout=10)
data = resp.json()
print(f"\n=== IP Info: {ip_address} ===")
print(f" Organization: {data.get('org', 'N/A')}")
print(f" ASN: {data.get('asn', 'N/A')}")
print(f" Country: {data.get('country_name', 'N/A')}")
print(f" City: {data.get('city', 'N/A')}")
print(f" Hostname: {data.get('hostname', 'N/A')}")
return data
reverse_ip_lookup("93.184.216.34")
ip_info("93.184.2 📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開
Passive Reconnaissance
Overview
Passive reconnaissance gathers intelligence about a target using only publicly available information — no packets are sent to the target's infrastructure. This makes it completely undetectable and legally safe when used against publicly accessible data. The goal is to build a comprehensive intelligence picture from WHOIS records, DNS history, SSL certificate logs, search engine caches, and web archives before making any active contact with the target.
Instructions
Step 1: WHOIS lookups
import whois
import subprocess
import json
import re
def whois_lookup(domain):
"""Perform WHOIS lookup using python-whois library."""
# pip install python-whois
try:
w = whois.whois(domain)
print(f"\n=== WHOIS: {domain} ===")
print(f"Registrar: {w.registrar}")
print(f"Created: {w.creation_date}")
print(f"Updated: {w.updated_date}")
print(f"Expires: {w.expiration_date}")
print(f"Name servers: {w.name_servers}")
print(f"Registrant org: {getattr(w, 'org', 'N/A')}")
print(f"Registrant email:{getattr(w, 'emails', 'N/A')}")
print(f"Registrant country: {getattr(w, 'country', 'N/A')}")
# Check for privacy protection
raw = str(w.text)
if any(word in raw.lower() for word in ["privacy", "redacted", "withheld", "domains by proxy"]):
print("\n ⚠ WHOIS privacy protection is enabled")
return dict(w)
except Exception as e:
print(f"WHOIS error for {domain}: {e}")
return None
def reverse_whois_email(email):
"""Find domains registered with the same email (via ViewDNS or WHOIS API)."""
url = f"https://viewdns.info/reversewhois/?q={email}"
print(f"Reverse WHOIS for {email}: {url}")
# Note: ViewDNS.info has a web UI — use their API for automation
return url
whois_lookup("example.com")
Step 2: DNS enumeration and history
import dns.resolver
import requests
def dns_lookup(domain):
"""Enumerate DNS records for a domain."""
record_types = ["A", "AAAA", "MX", "NS", "TXT", "SOA", "CNAME"]
results = {}
print(f"\n=== DNS Records: {domain} ===")
for rtype in record_types:
try:
answers = dns.resolver.resolve(domain, rtype, lifetime=5)
records = [str(r) for r in answers]
results[rtype] = records
print(f" {rtype:<8}: {', '.join(records)}")
except (dns.resolver.NoAnswer, dns.resolver.NXDOMAIN, dns.exception.Timeout):
pass
return results
def dns_history_securitytrails(domain, api_key):
"""Get historical DNS records from SecurityTrails API."""
headers = {"apikey": api_key, "Accept": "application/json"}
base_url = "https://api.securitytrails.com/v1"
# Historical A records
resp = requests.get(f"{base_url}/history/{domain}/dns/a", headers=headers, timeout=15)
data = resp.json()
print(f"\n=== DNS History (SecurityTrails): {domain} ===")
for record in data.get("records", []):
first_seen = record.get("first_seen")
last_seen = record.get("last_seen")
ips = [v.get("ip") for v in record.get("values", [])]
print(f" [{first_seen} → {last_seen}] {', '.join(ips)}")
return data
def passive_dns_free(domain):
"""Query free passive DNS sources."""
results = {}
# HackerTarget Passive DNS (free)
try:
resp = requests.get(
f"https://api.hackertarget.com/hostsearch/?q={domain}",
timeout=15
)
if "error" not in resp.text.lower():
hosts = [line.split(",")[0] for line in resp.text.strip().split("\n") if "," in line]
results["hackertarget_hosts"] = hosts
print(f"HackerTarget found {len(hosts)} subdomains for {domain}")
except Exception as e:
print(f"HackerTarget error: {e}")
# CIRCL Passive DNS (free, no auth)
try:
resp = requests.get(
f"https://www.circl.lu/pdns/query/{domain}",
headers={"Accept": "application/json"},
timeout=15
)
records = [json.loads(line) for line in resp.text.strip().split("\n") if line]
ips = list({r.get("rdata") for r in records if r.get("rrtype") == "A"})
results["circl_ips"] = ips
print(f"CIRCL passive DNS: {len(records)} records, {len(ips)} unique IPs")
except Exception as e:
print(f"CIRCL error: {e}")
return results
dns_lookup("example.com")
Step 3: Reverse IP lookup
def reverse_ip_lookup(ip_address):
"""Find all domains hosted on the same IP address."""
# HackerTarget API (free, up to 500 results)
try:
resp = requests.get(
f"https://api.hackertarget.com/reverseiplookup/?q={ip_address}",
timeout=15
)
if "error" not in resp.text.lower() and resp.text.strip():
domains = [d.strip() for d in resp.text.strip().split("\n")]
print(f"\n=== Reverse IP: {ip_address} ===")
print(f"Hosted domains: {len(domains)}")
for d in domains[:20]:
print(f" {d}")
if len(domains) > 20:
print(f" ... and {len(domains) - 20} more")
return domains
except Exception as e:
print(f"Reverse IP error: {e}")
return []
def ip_info(ip_address):
"""Get IP geolocation, ASN, and organization info."""
resp = requests.get(f"https://ipapi.co/{ip_address}/json/", timeout=10)
data = resp.json()
print(f"\n=== IP Info: {ip_address} ===")
print(f" Organization: {data.get('org', 'N/A')}")
print(f" ASN: {data.get('asn', 'N/A')}")
print(f" Country: {data.get('country_name', 'N/A')}")
print(f" City: {data.get('city', 'N/A')}")
print(f" Hostname: {data.get('hostname', 'N/A')}")
return data
reverse_ip_lookup("93.184.216.34")
ip_info("93.184.216.34")
Step 4: SSL certificate transparency (crt.sh)
def crt_sh_lookup(domain, include_expired=True, deduplicate=True):
"""
Query crt.sh for all SSL certificates issued for a domain.
Certificate transparency logs are public and reveal all subdomains
that have ever had a certificate issued.
"""
# Use wildcard to find all subdomains
query = f"%.{domain}"
url = f"https://crt.sh/?q={query}&output=json"
try:
resp = requests.get(url, timeout=30)
certs = resp.json()
except (requests.RequestException, json.JSONDecodeError) as e:
print(f"crt.sh error: {e}")
return []
# Extract all names from certificates
all_names = set()
for cert in certs:
name_value = cert.get("name_value", "")
# name_value can contain multiple names separated by newlines
for name in name_value.split("\n"):
name = name.strip().lstrip("*.")
if name and domain in name:
all_names.add(name.lower())
subdomains = sorted(all_names)
print(f"\n=== Certificate Transparency: {domain} ===")
print(f"Total certificates: {len(certs)}")
print(f"Unique subdomains: {len(subdomains)}")
for sub in subdomains[:30]:
print(f" {sub}")
if len(subdomains) > 30:
print(f" ... and {len(subdomains) - 30} more")
return subdomains
# Also retrieve detailed cert info
def crt_sh_certs_detail(domain):
"""Get certificate details including issuer, validity, and fingerprint."""
resp = requests.get(f"https://crt.sh/?q={domain}&output=json", timeout=30)
certs = resp.json()
print(f"\nRecent certificates for {domain}:")
for cert in sorted(certs, key=lambda x: x.get("entry_timestamp", ""), reverse=True)[:10]:
print(f" [{cert.get('entry_timestamp', '')[:10]}] "
f"CN={cert.get('common_name', '?'):<40} "
f"Issuer: {cert.get('issuer_name', '?')[:50]}")
crt_sh_lookup("example.com")
Step 5: Google Dorks
def generate_dorks(domain):
"""Generate a comprehensive set of Google dorks for a target domain."""
company = domain.split(".")[0] # Rough heuristic
dorks = [
# Infrastructure discovery
(f"site:{domain}", "All indexed pages"),
(f"site:{domain} inurl:admin", "Admin panels"),
(f"site:{domain} inurl:login", "Login pages"),
(f"site:{domain} inurl:api", "API endpoints"),
(f"site:{domain} inurl:dev OR inurl:staging OR inurl:test", "Dev/staging environments"),
# File exposure
(f"site:{domain} filetype:pdf", "PDF documents"),
(f"site:{domain} filetype:xlsx OR filetype:csv", "Spreadsheets"),
(f"site:{domain} filetype:sql", "SQL database files"),
(f"site:{domain} filetype:env OR filetype:config", "Config files"),
(f"site:{domain} filetype:log", "Log files"),
(f'site:{domain} ext:bak OR ext:old OR ext:backup', "Backup files"),
# Credential exposure
(f'site:github.com "{domain}" password OR secret OR api_key', "Credentials on GitHub"),
(f'site:pastebin.com "{domain}"', "Domain on Pastebin"),
(f'"{domain}" filetype:txt password', "Password files"),
# Technology fingerprinting
(f"site:{domain} intext:\"Powered by\"", "CMS/framework identification"),
(f"site:{domain} inurl:wp-admin", "WordPress admin"),
(f"site:{domain} inurl:jira", "Jira instances"),
(f"site:{domain} inurl:confluence", "Confluence instances"),
# Email harvesting
(f'"@{domain}" filetype:xlsx', "Email lists in spreadsheets"),
(f'"@{domain}" site:linkedin.com', "Employee emails on LinkedIn"),
# Error pages (reveal technology stack)
(f'site:{domain} intext:"Error" intext:"stack trace"', "Error pages with stack traces"),
(f'site:{domain} "Index of /"', "Directory listings"),
]
print(f"\n=== Google Dorks: {domain} ===")
for query, description in dorks:
encoded = query.replace(" ", "+").replace('"', '%22')
url = f"https://www.google.com/search?q={encoded}"
print(f"\n[{description}]")
print(f" Query: {query}")
print(f" URL: {url}")
return dorks
generate_dorks("example.com")
Step 6: Wayback Machine enumeration
def wayback_cdx_enumeration(domain, limit=1000):
"""
Use the Wayback Machine CDX API to enumerate all historically crawled
URLs for a domain. Reveals old endpoints, APIs, and forgotten pages.
"""
cdx_url = "https://web.archive.org/cdx/search/cdx"
params = {
"url": f"*.{domain}/*",
"output": "json",
"fl": "original,timestamp,statuscode",
"filter": "statuscode:200",
"collapse": "original",
"limit": limit,
}
resp = requests.get(cdx_url, params=params, timeout=60)
data = resp.json()
if len(data) <= 1:
print(f"No Wayback data found for {domain}")
return []
urls = [row[0] for row in data[1:]] # Skip header row
timestamps = [row[1] for row in data[1:]]
print(f"\n=== Wayback Machine: {domain} ===")
print(f"Total unique URLs: {len(urls)}")
# Find interesting endpoints
interesting_patterns = [
r'/api/', r'/admin/', r'/login', r'/dashboard',
r'\.php', r'\.asp', r'\.env', r'\.bak', r'\.sql',
r'/wp-', r'/cgi-bin/', r'\.xml', r'\.json',
]
for pattern in interesting_patterns:
matching = [u for u in urls if re.search(pattern, u, re.IGNORECASE)]
if matching:
print(f"\n [{pattern}] {len(matching)} URLs:")
for u in matching[:5]:
print(f" {u}")
# Find unique subdomains from Wayback
subdomains = set()
for url in urls:
match = re.match(r'https?://([^/]+)', url)
if match:
host = match.group(1)
if domain in host:
subdomains.add(host.lower())
print(f"\n Subdomains in Wayback: {len(subdomains)}")
for sub in sorted(subdomains):
print(f" {sub}")
return urls
wayback_cdx_enumeration("example.com", limit=500)
Step 7: Full passive recon pipeline
def full_passive_recon(domain, output_dir="."):
"""Run a complete passive recon pipeline for a target domain."""
import os
os.makedirs(output_dir, exist_ok=True)
results = {"domain": domain, "timestamp": __import__("datetime").datetime.utcnow().isoformat()}
print(f"\n{'='*60}")
print(f"PASSIVE RECON: {domain}")
print(f"{'='*60}")
# 1. WHOIS
results["whois"] = whois_lookup(domain)
# 2. DNS records
results["dns"] = dns_lookup(domain)
# 3. Passive DNS (free sources)
results["passive_dns"] = passive_dns_free(domain)
# 4. Certificate transparency
results["subdomains_crt"] = crt_sh_lookup(domain)
# 5. Reverse IP for primary domain IP
try:
primary_ip = str(dns.resolver.resolve(domain, "A")[0])
results["primary_ip"] = primary_ip
results["reverse_ip"] = reverse_ip_lookup(primary_ip)
results["ip_info"] = ip_info(primary_ip)
except Exception as e:
print(f"IP lookup failed: {e}")
# 6. Wayback Machine
results["wayback_urls"] = wayback_cdx_enumeration(domain, limit=200)
# 7. Dorks (just generate, not execute automatically)
results["dorks"] = [(q, d) for q, d in generate_dorks(domain)]
# Save
output_file = f"{output_dir}/passive_recon_{domain.replace('.', '_')}.json"
with open(output_file, "w") as f:
json.dump(results, f, indent=2, default=str)
print(f"\n✓ Full passive recon saved to {output_file}")
return results
full_passive_recon("example.com")
Passive Recon Checklist
| Technique | Tool | Data Obtained |
|---|---|---|
| WHOIS lookup | python-whois |
Registrar, creation date, name servers, registrant |
| DNS records | dnspython |
A, MX, NS, TXT, SOA records |
| DNS history | SecurityTrails, CIRCL | Historical IPs, old name servers |
| Reverse IP | HackerTarget API | Other domains on same server |
| SSL certs | crt.sh | All subdomains ever issued a cert |
| Wayback Machine | CDX API | Historical URLs, old endpoints |
| Google Dorks | Google Search | Exposed files, admin panels, credentials |
| Shodan | shodan library |
Open ports, services, banners |
| Passive DNS | CIRCL, HackerTarget | Current and historical DNS records |
Guidelines
- Zero contact: All techniques in this skill make zero requests to the target's infrastructure. Requests go to third-party services (crt.sh, HackerTarget, CIRCL, etc.) only.
- Rate limits: HackerTarget free tier allows 100 API calls per day. Spread queries or cache results.
- crt.sh is gold: Certificate transparency is the fastest way to find subdomains. Combined with Wayback Machine, it often reveals more than active brute-force DNS.
- Historical IPs: Old IPs from DNS history may point to WAF bypass opportunities or forgotten servers. Always check historical data.
- Google cache: Combine
cache:example.comwith regular dorks to access pages that have since been removed.