npx skills add mukul975/Anthropic-Cybersecurity-SkillsMITRE ATT&CK
Overview
SpiderFoot is an open-source OSINT automation tool with 200+ modules that integrates with data sources for threat intelligence and attack surface mapping. This skill uses the SpiderFoot REST API and CLI (sf.py/spiderfoot-cli) to create and manage scans, select modules by use case (footprint, investigate, passive), parse structured results for domains, IPs, email addresses, leaked credentials, and DNS records, and generate target intelligence profiles.
When to Use
- When conducting security assessments that involve performing osint with spiderfoot
- When following incident response procedures for related security events
- When performing scheduled security testing or auditing activities
- When validating security controls through hands-on testing
Prerequisites
- SpiderFoot 4.0+ installed or SpiderFoot HX cloud account
- Python 3.8+ with requests library
- SpiderFoot server running on default port 5001
- Optional: API keys for VirusTotal, Shodan, HaveIBeenPwned modules
Steps
- Connect to SpiderFoot REST API or use CLI interface
- Create a new scan with target specification (domain, IP, email, name)
- Select scan modules by use case (all, footprint, investigate, passive)
- Monitor scan progress via API polling
- Retrieve and parse scan results by data element type
- Extract key findings: subdomains, IPs, emails, leaked credentials
- Generate structured OSINT intelligence report
Expected Output
JSON report containing OSINT findings organized by data type (domains, IPs, emails, credentials, DNS records), module source attribution, and target profile summary with risk indicators.
References and resources
Everything below is rendered for inspection. Script files are read-only and never run.
References 1
api-reference.md1.9 KB
SpiderFoot OSINT API Reference
REST API Endpoints
List Modules
GET /api/modules
Response: [{"name": "sfp_dnsresolve", "descr": "...", "group": "Footprint", "provides": [...]}]Start Scan
POST /api/startscan
Content-Type: application/x-www-form-urlencoded
scanname=my-scan&scantarget=example.com&usecase=footprint
Response: {"scanid": "abc123"}Check Scan Status
GET /api/scanstatus/{scan_id}
Response: {"status": "RUNNING"} # RUNNING, FINISHED, ABORTED, ERROR-FAILEDGet Scan Results
GET /api/scanresults/{scan_id}
Response: [{"type": "INTERNET_NAME", "data": "sub.example.com", "module": "sfp_dnsresolve", "source": "example.com"}]Delete Scan
GET /api/scandelete/{scan_id}List Scans
GET /api/scanlistScan Use Cases
| Use Case | Description |
|---|---|
| all | All modules (slowest, most comprehensive) |
| footprint | Attack surface mapping: subdomains, IPs, ports |
| investigate | Deep analysis: WHOIS, DNS, reputation checks |
| passive | Passive only: no active probing of target |
Data Element Types
| Type | Description |
|---|---|
| INTERNET_NAME | Discovered domain/subdomain |
| IP_ADDRESS | IP addresses |
| EMAILADDR | Email addresses |
| LEAKSITE_CONTENT | Leaked credentials/data |
| DNS_TEXT | DNS TXT/MX/NS records |
| LINKED_URL_INTERNAL | URLs on target domain |
| CO_HOSTED_SITE | Sites sharing same IP |
| AFFILIATE_INTERNET_NAME | Related domains |
CLI Usage (sf.py)
# Start scan via CLI
python sf.py -s example.com -t INTERNET_NAME,IP_ADDRESS -m sfp_dnsresolve,sfp_portscan_tcp
# Passive footprint
python sf.py -s example.com -u passive
# List modules
python sf.py -MAgent CLI Usage
python agent.py --target example.com --use-case footprint --output report.json
python agent.py --target 203.0.113.5 --use-case investigate --timeout 1200
python agent.py --list-modules --server http://spiderfoot:5001Scripts 1
agent.py6.8 KB
#!/usr/bin/env python3
"""OSINT automation agent using SpiderFoot REST API for target profiling and reconnaissance."""
import os
import json
import time
import argparse
from datetime import datetime
import requests
def get_sf_session(base_url):
"""Create a requests session for SpiderFoot API."""
session = requests.Session()
session.headers.update({"Accept": "application/json"})
session.base_url = base_url.rstrip("/")
return session
def list_modules(session):
"""List available SpiderFoot modules."""
resp = session.get(f"{session.base_url}/api/modules", timeout=30)
resp.raise_for_status()
modules = resp.json()
return [{"name": m.get("name", ""), "descr": m.get("descr", ""),
"group": m.get("group", ""), "provides": m.get("provides", [])}
for m in modules]
def list_scan_types(session):
"""List available scan types (use cases)."""
resp = session.get(f"{session.base_url}/api/scantypes", timeout=30)
resp.raise_for_status()
return resp.json()
def start_scan(session, target, scan_name, use_case="all"):
"""Start a new SpiderFoot scan via REST API."""
data = {
"scanname": scan_name,
"scantarget": target,
"usecase": use_case,
}
resp = session.post(f"{session.base_url}/api/startscan", data=data, timeout=30)
resp.raise_for_status()
result = resp.json()
scan_id = result.get("scanid", result.get("id", ""))
print(f"[+] Scan started: {scan_id} (target: {target}, use_case: {use_case})")
return scan_id
def get_scan_status(session, scan_id):
"""Check scan status."""
resp = session.get(f"{session.base_url}/api/scanstatus/{scan_id}", timeout=30)
resp.raise_for_status()
return resp.json()
def wait_for_scan(session, scan_id, poll_interval=10, timeout=600):
"""Poll scan status until completion or timeout."""
elapsed = 0
while elapsed < timeout:
status = get_scan_status(session, scan_id)
state = status.get("status", "")
if state in ("FINISHED", "ABORTED", "ERROR-FAILED"):
print(f"[+] Scan {scan_id} completed with status: {state}")
return state
print(f"[*] Scan status: {state} (elapsed: {elapsed}s)")
time.sleep(poll_interval)
elapsed += poll_interval
print(f"[!] Scan timed out after {timeout}s")
return "TIMEOUT"
def get_scan_results(session, scan_id):
"""Retrieve all results from a completed scan."""
resp = session.get(f"{session.base_url}/api/scanresults/{scan_id}", timeout=30)
resp.raise_for_status()
return resp.json()
def categorize_results(results):
"""Categorize scan results by data element type."""
categories = {
"domains": [], "ips": [], "emails": [], "credentials": [],
"dns_records": [], "urls": [], "hostnames": [], "other": [],
}
type_map = {
"INTERNET_NAME": "domains", "IP_ADDRESS": "ips", "EMAILADDR": "emails",
"LEAKSITE_CONTENT": "credentials", "DNS_TEXT": "dns_records",
"LINKED_URL_INTERNAL": "urls", "LINKED_URL_EXTERNAL": "urls",
"AFFILIATE_INTERNET_NAME": "hostnames", "CO_HOSTED_SITE": "hostnames",
}
for result in results:
data_type = result.get("type", "")
category = type_map.get(data_type, "other")
entry = {
"data": result.get("data", ""),
"type": data_type,
"module": result.get("module", ""),
"source": result.get("source", ""),
}
categories[category].append(entry)
return categories
def generate_target_profile(target, categories):
"""Generate structured OSINT profile from categorized results."""
return {
"target": target,
"profile_time": datetime.utcnow().isoformat() + "Z",
"summary": {
"domains_found": len(categories["domains"]),
"ips_found": len(categories["ips"]),
"emails_found": len(categories["emails"]),
"credentials_found": len(categories["credentials"]),
"dns_records": len(categories["dns_records"]),
"urls_found": len(categories["urls"]),
"hostnames_found": len(categories["hostnames"]),
"other_findings": len(categories["other"]),
},
"domains": [d["data"] for d in categories["domains"][:50]],
"ips": [d["data"] for d in categories["ips"][:50]],
"emails": [d["data"] for d in categories["emails"][:50]],
"leaked_credentials": len(categories["credentials"]),
"dns_records": [d["data"] for d in categories["dns_records"][:20]],
"data_sources": list({r["module"] for cat in categories.values() for r in cat}),
}
def main():
parser = argparse.ArgumentParser(description="SpiderFoot OSINT Agent")
parser.add_argument("--target", required=True, help="Scan target (domain, IP, email, name)")
parser.add_argument("--server", default=os.environ.get("SPIDERFOOT_URL", "http://127.0.0.1:5001"),
help="SpiderFoot server URL")
parser.add_argument("--use-case", choices=["all", "footprint", "investigate", "passive"],
default="footprint", help="Scan use case")
parser.add_argument("--scan-name", default="", help="Scan name (default: auto-generated)")
parser.add_argument("--timeout", type=int, default=600, help="Scan timeout in seconds")
parser.add_argument("--poll-interval", type=int, default=10, help="Status poll interval in seconds")
parser.add_argument("--output", default="osint_report.json", help="Output report path")
parser.add_argument("--list-modules", action="store_true", help="List available modules and exit")
args = parser.parse_args()
session = get_sf_session(args.server)
if args.list_modules:
modules = list_modules(session)
for m in modules:
print(f" {m['name']}: {m['descr']}")
print(f"\n[+] Total modules: {len(modules)}")
return
scan_name = args.scan_name or f"osint-{args.target}-{datetime.utcnow().strftime('%Y%m%d%H%M%S')}"
scan_id = start_scan(session, args.target, scan_name, args.use_case)
final_status = wait_for_scan(session, scan_id, args.poll_interval, args.timeout)
results = get_scan_results(session, scan_id)
print(f"[+] Retrieved {len(results)} results from scan")
categories = categorize_results(results)
profile = generate_target_profile(args.target, categories)
profile["scan_id"] = scan_id
profile["scan_status"] = final_status
profile["use_case"] = args.use_case
with open(args.output, "w") as f:
json.dump(profile, f, indent=2)
print(f"[+] Domains: {profile['summary']['domains_found']}, IPs: {profile['summary']['ips_found']}, "
f"Emails: {profile['summary']['emails_found']}")
print(f"[+] Report saved to {args.output}")
if __name__ == "__main__":
main()