threat intelligence

Performing Dark Web Monitoring for Threats

Dark web monitoring involves systematically scanning Tor hidden services, underground forums, paste sites, and dark web marketplaces to identify threats targeting an organization, including leaked credentials, data breaches, threat actor discussions, vulnerability exploitation tools, and planned attacks. This skill covers setting up monitoring infrastructure, using Tor-based collection tools, implementing automated alerting for brand mentions and credential leaks, and analyzing dark web intelligence for actionable threat indicators.

ctidark-webiocmitre-attackstixthreat-intelligencethreat-monitoringtor
Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-Skills
Framework mappings

Overview

Dark web monitoring involves systematically scanning Tor hidden services, underground forums, paste sites, and dark web marketplaces to identify threats targeting an organization, including leaked credentials, data breaches, threat actor discussions, vulnerability exploitation tools, and planned attacks. This skill covers setting up monitoring infrastructure, using Tor-based collection tools, implementing automated alerting for brand mentions and credential leaks, and analyzing dark web intelligence for actionable threat indicators.

When to Use

  • When conducting security assessments that involve performing dark web monitoring for threats
  • 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

  • Tor Browser and Tor proxy (SOCKS5 on port 9050)
  • Python 3.9+ with requests, stem, beautifulsoup4, stix2 libraries
  • Understanding of Tor hidden service architecture (.onion domains)
  • API access to dark web monitoring services (Flare, SpyCloud, DarkOwl, Intel 471)
  • Awareness of legal and ethical boundaries for dark web research
  • Isolated VM for dark web browsing (no personal or corporate identity leakage)

Key Concepts

Dark Web Intelligence Sources

  • Underground Forums: Hacking forums where threat actors discuss TTPs, sell exploits, and share tools
  • Paste Sites: Platforms for sharing stolen data, credentials, and code snippets
  • Marketplaces: Dark web markets selling stolen data, RaaS, exploit kits, and access
  • Telegram/Discord: Alternative communication channels for cybercriminal groups
  • Ransomware Leak Sites: Blogs where ransomware groups post stolen data from victims

Collection Methods

  • Automated Crawling: Tor-based web crawlers scanning hidden services
  • API-Based Monitoring: Commercial dark web monitoring APIs (Flare, DarkOwl, Intel 471)
  • Manual HUMINT: Analyst-driven research on specific forums and marketplaces
  • Credential Monitoring: Breach databases and paste site monitoring for leaked credentials

OPSEC for Dark Web Research

  • Use dedicated VMs with no personal data
  • Route all traffic through Tor (Whonix or Tails recommended)
  • Never use personal accounts or identifiable information
  • Use separate email addresses and personas for forum registration
  • Disable JavaScript in Tor Browser for enhanced security
  • Never download or execute files from dark web sources on production systems

Workflow

Step 1: Set Up Tor-Based HTTP Client

import requests
from requests.adapters import HTTPAdapter
 
def create_tor_session():
    """Create a requests session routed through Tor SOCKS5 proxy."""
    session = requests.Session()
    session.proxies = {
        "http": "socks5h://127.0.0.1:9050",
        "https": "socks5h://127.0.0.1:9050",
    }
    session.headers.update({
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; rv:109.0) Gecko/20100101 Firefox/115.0",
    })
    return session
 
 
def verify_tor_connection(session):
    """Verify that traffic is routed through Tor."""
    try:
        resp = session.get("https://check.torproject.org/api/ip", timeout=30)
        data = resp.json()
        return {
            "is_tor": data.get("IsTor", False),
            "ip": data.get("IP", ""),
        }
    except Exception as e:
        return {"error": str(e)}

Step 2: Monitor Paste Sites for Credential Leaks

import re
from datetime import datetime
 
def monitor_paste_sites(session, organization_domains):
    """Monitor paste sites for leaked credentials matching organization domains."""
    findings = []
 
    # Check Have I Been Pwned API (clearnet)
    for domain in organization_domains:
        try:
            resp = requests.get(
                f"https://haveibeenpwned.com/api/v3/breaches",
                headers={"hibp-api-key": "YOUR_HIBP_KEY"},
                timeout=30,
            )
            if resp.status_code == 200:
                breaches = resp.json()
                for breach in breaches:
                    if domain.lower() in breach.get("Domain", "").lower():
                        findings.append({
                            "source": "HIBP",
                            "breach_name": breach["Name"],
                            "breach_date": breach.get("BreachDate"),
                            "data_classes": breach.get("DataClasses", []),
                            "pwn_count": breach.get("PwnCount", 0),
                            "domain": domain,
                        })
        except Exception as e:
            print(f"[-] HIBP error for {domain}: {e}")
 
    return findings
 
 
def search_for_keywords(session, keywords, onion_paste_urls):
    """Search dark web paste sites for specific keywords."""
    results = []
 
    for paste_url in onion_paste_urls:
        try:
            resp = session.get(paste_url, timeout=60)
            if resp.status_code == 200:
                content = resp.text.lower()
                for keyword in keywords:
                    if keyword.lower() in content:
                        results.append({
                            "url": paste_url,
                            "keyword": keyword,
                            "timestamp": datetime.utcnow().isoformat(),
                            "snippet": extract_context(content, keyword.lower()),
                        })
        except Exception as e:
            print(f"[-] Error fetching {paste_url}: {e}")
 
    return results
 
 
def extract_context(text, keyword, context_chars=200):
    """Extract text context around a keyword match."""
    idx = text.find(keyword)
    if idx == -1:
        return ""
    start = max(0, idx - context_chars)
    end = min(len(text), idx + len(keyword) + context_chars)
    return text[start:end]

Step 3: Monitor Ransomware Leak Sites

def check_ransomware_leak_sites(session, organization_name):
    """Check known ransomware group leak sites for organization mentions."""
    # Use Ransomwatch API (clearnet aggregator of ransomware leak sites)
    try:
        resp = requests.get(
            "https://raw.githubusercontent.com/joshhighet/ransomwatch/main/posts.json",
            timeout=30,
        )
        if resp.status_code == 200:
            posts = resp.json()
            matches = []
            for post in posts:
                post_title = post.get("post_title", "").lower()
                if organization_name.lower() in post_title:
                    matches.append({
                        "group": post.get("group_name", ""),
                        "title": post.get("post_title", ""),
                        "discovered": post.get("discovered", ""),
                        "url": post.get("post_url", ""),
                    })
            return matches
    except Exception as e:
        print(f"[-] Ransomwatch error: {e}")
    return []

Step 4: Generate Dark Web Intelligence Report

def generate_dark_web_report(findings, organization):
    """Generate structured dark web intelligence report."""
    report = {
        "organization": organization,
        "report_date": datetime.utcnow().isoformat(),
        "executive_summary": "",
        "credential_leaks": [],
        "ransomware_mentions": [],
        "dark_web_mentions": [],
        "recommendations": [],
    }
 
    for finding in findings:
        if finding.get("source") == "HIBP":
            report["credential_leaks"].append(finding)
        elif finding.get("group"):
            report["ransomware_mentions"].append(finding)
        else:
            report["dark_web_mentions"].append(finding)
 
    # Generate executive summary
    cred_count = len(report["credential_leaks"])
    ransom_count = len(report["ransomware_mentions"])
    report["executive_summary"] = (
        f"Monitoring identified {cred_count} credential leak sources "
        f"and {ransom_count} ransomware group mentions for {organization}."
    )
 
    if ransom_count > 0:
        report["recommendations"].append(
            "CRITICAL: Organization mentioned on ransomware leak site. "
            "Initiate incident response immediately."
        )
    if cred_count > 0:
        report["recommendations"].append(
            "HIGH: Leaked credentials detected. Force password resets for "
            "affected accounts and enable MFA."
        )
 
    return report

Validation Criteria

  • Tor connection established and verified via check.torproject.org
  • Credential leak monitoring returns results from HIBP and paste sites
  • Ransomware leak site monitoring identifies relevant mentions
  • Dark web intelligence report generated with actionable recommendations
  • All monitoring performed within legal and ethical boundaries
  • OPSEC maintained: no personal or corporate identity exposure

References

Source materials

References and resources

Everything below is rendered for inspection. Script files are read-only and never run.

References 3

api-reference.md5.7 KB

API Reference: Dark Web Threat Monitoring

Libraries Used

Library Purpose
requests HTTP client for Tor-proxied requests and clearnet APIs
json Parse breach data and monitoring results
re Pattern matching for credentials and brand mentions
hashlib Hash credentials for safe lookup (k-anonymity)
datetime Track monitoring timelines

Installation

pip install requests
 
# Tor service (required for .onion access)
# Ubuntu/Debian
sudo apt install tor
sudo systemctl start tor
 
# macOS
brew install tor && brew services start tor

Authentication and Proxy Configuration

Tor SOCKS5 Proxy Setup

import requests
import os
 
TOR_PROXY = os.environ.get("TOR_PROXY", "socks5h://127.0.0.1:9050")
proxies = {"http": TOR_PROXY, "https": TOR_PROXY}
 
def tor_request(url, timeout=30):
    """Make an HTTP request through the Tor network."""
    resp = requests.get(url, proxies=proxies, timeout=timeout)
    return resp

Verify Tor Connectivity

def check_tor_connection():
    try:
        resp = requests.get(
            "https://check.torproject.org/api/ip",
            proxies=proxies,
            timeout=15,
        )
        data = resp.json()
        return {"tor_active": data.get("IsTor", False), "exit_ip": data.get("IP")}
    except requests.RequestException as e:
        return {"tor_active": False, "error": str(e)}

Credential Breach Monitoring

Have I Been Pwned API (k-Anonymity)

import hashlib
 
HIBP_API = "https://api.pwnedpasswords.com/range/"
 
def check_password_breach(password):
    """Check if a password appears in known breaches using k-anonymity."""
    sha1 = hashlib.sha1(password.encode()).hexdigest().upper()
    prefix = sha1[:5]
    suffix = sha1[5:]
 
    resp = requests.get(f"{HIBP_API}{prefix}", timeout=10)
    resp.raise_for_status()
 
    for line in resp.text.splitlines():
        hash_suffix, count = line.split(":")
        if hash_suffix == suffix:
            return {"breached": True, "count": int(count)}
    return {"breached": False, "count": 0}

Check Email in Breaches

HIBP_ACCOUNT_API = "https://haveibeenpwned.com/api/v3/breachedaccount/"
 
def check_email_breaches(email, api_key):
    """Check if an email appears in known data breaches."""
    resp = requests.get(
        f"{HIBP_ACCOUNT_API}{email}",
        headers={
            "hibp-api-key": api_key,
            "user-agent": "SecurityAuditTool",
        },
        params={"truncateResponse": "false"},
        timeout=15,
    )
    if resp.status_code == 200:
        breaches = resp.json()
        return {
            "email": email,
            "breached": True,
            "breach_count": len(breaches),
            "breaches": [
                {
                    "name": b["Name"],
                    "date": b["BreachDate"],
                    "data_classes": b["DataClasses"],
                }
                for b in breaches
            ],
        }
    elif resp.status_code == 404:
        return {"email": email, "breached": False, "breach_count": 0}
    return {"email": email, "error": resp.status_code}

Brand Mention Monitoring

Search Paste Sites

def search_paste_sites(brand_keywords, api_key=None):
    """Search paste monitoring services for brand mentions."""
    findings = []
    for keyword in brand_keywords:
        # IntelligenceX API (example)
        resp = requests.get(
            "https://2.intelx.io/intelligent/search",
            headers={"x-key": api_key} if api_key else {},
            params={
                "term": keyword,
                "buckets": "pastes",
                "maxresults": 20,
                "datefrom": "",
                "dateto": "",
                "sort": 2,  # Date descending
            },
            timeout=30,
        )
        if resp.status_code == 200:
            results = resp.json().get("records", [])
            for r in results:
                findings.append({
                    "keyword": keyword,
                    "source": r.get("systemid"),
                    "date": r.get("date"),
                    "bucket": r.get("bucket"),
                })
    return findings

Domain Monitoring

Monitor for Credential Dumps Mentioning Domain

def monitor_domain_mentions(domain, sources):
    """Search for domain mentions across dark web sources."""
    findings = []
    email_pattern = re.compile(rf"[\w.+-]+@{re.escape(domain)}", re.IGNORECASE)
 
    for source in sources:
        try:
            resp = tor_request(source["url"], timeout=30)
            matches = email_pattern.findall(resp.text)
            if matches:
                findings.append({
                    "source": source["name"],
                    "emails_found": len(set(matches)),
                    "sample": list(set(matches))[:5],
                    "risk": "high",
                })
        except requests.RequestException:
            continue
    return findings

Alerting

def create_alert(finding, severity="high"):
    return {
        "alert_type": "dark_web_mention",
        "severity": severity,
        "source": finding.get("source"),
        "detail": finding,
        "timestamp": datetime.now().isoformat(),
        "action_required": "Investigate and rotate exposed credentials",
    }

Output Format

{
  "monitoring_date": "2025-01-15",
  "domain": "example.com",
  "tor_connected": true,
  "credential_breaches": {
    "emails_checked": 50,
    "breached_accounts": 8,
    "unique_breaches": 12
  },
  "paste_mentions": 3,
  "dark_web_findings": [
    {
      "source": "paste-site",
      "type": "credential_dump",
      "emails_found": 15,
      "risk": "high",
      "action": "Force password reset for affected accounts"
    }
  ]
}
standards.md1.6 KB

Standards and Frameworks Reference

Dark Web Intelligence Classification

  • TLP:RED: Dark web source details, forum credentials, HUMINT methods
  • TLP:AMBER: Specific threat actor mentions, leaked data analysis
  • TLP:GREEN: Aggregated trends, anonymized statistics
  • TLP:CLEAR: Public dark web monitoring advisories

MITRE ATT&CK Mapping

  • T1589 - Gather Victim Identity Information (credential theft)
  • T1590 - Gather Victim Network Information (reconnaissance)
  • T1597 - Search Closed Sources (dark web forums)
  • T1598 - Phishing for Information

Dark Web Source Categories

Category Description Examples
Forums Discussion boards for cybercriminals RaidForums successors, XSS.is, Exploit.in
Marketplaces Buying/selling stolen data and tools Various .onion markets
Paste Sites Anonymous text sharing Dark web paste services
Leak Sites Ransomware data publication LockBit, BlackCat, Royal blogs
Chat Channels Real-time communication Telegram groups, Discord

Legal and Ethical Framework

  • Passive observation of publicly accessible dark web content is legal in most jurisdictions
  • Active engagement (posting, purchasing) requires legal authorization
  • Credential harvesting for defensive purposes requires clear policy
  • Evidence collection must follow chain of custody procedures

References

workflows.md1.5 KB

Dark Web Monitoring Workflows

Workflow 1: Credential Leak Monitoring

[Organization Domains] --> [HIBP API Check] --> [Paste Site Monitoring] --> [Alert Generation]
                                                                                  |
                                                                                  v
                                                                        [Password Reset Enforcement]

Workflow 2: Brand Threat Monitoring

[Brand Keywords] --> [Dark Web Crawl] --> [Forum Monitoring] --> [Threat Assessment]
                                                                        |
                                                                        v
                                                                [Intel Report] --> [SOC Briefing]

Workflow 3: Ransomware Leak Monitoring

[Ransomwatch Feed] --> [Organization Match] --> [CRITICAL ALERT] --> [IR Activation]
                                                                          |
                                                                          v
                                                                  [Scope Assessment]

Workflow 4: Continuous Dark Web Intelligence

[Scheduled Scans] --> [Data Collection] --> [NLP Analysis] --> [Trend Analysis]
                                                                     |
                                                                     v
                                                            [Weekly Intelligence Brief]

Scripts 2

agent.py8.7 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""Dark web threat monitoring agent.

Monitors for organization-specific threats on the dark web by checking
breach databases (Have I Been Pwned API), paste sites, and public
threat intelligence feeds for leaked credentials, exposed data, and
mentions of organizational domains.
"""
import argparse
import hashlib
import json
import os
import sys
import time
from datetime import datetime, timezone

try:
    import requests
except ImportError:
    print("[!] 'requests' required: pip install requests", file=sys.stderr)
    sys.exit(1)


def check_hibp_breaches(domain, api_key=None):
    """Check Have I Been Pwned for breaches involving a domain."""
    findings = []
    print(f"[*] Checking HIBP breaches for domain: {domain}")
    headers = {"user-agent": "dark-web-monitor-agent"}
    if api_key:
        headers["hibp-api-key"] = api_key
    try:
        resp = requests.get(
            f"https://haveibeenpwned.com/api/v3/breaches",
            headers=headers, timeout=15,
        )
        resp.raise_for_status()
        breaches = resp.json()
        domain_breaches = [b for b in breaches if domain.lower() in b.get("Domain", "").lower()]
        for breach in domain_breaches:
            findings.append({
                "type": "breach",
                "source": "HIBP",
                "name": breach.get("Name", ""),
                "domain": breach.get("Domain", ""),
                "breach_date": breach.get("BreachDate", ""),
                "added_date": breach.get("AddedDate", ""),
                "pwn_count": breach.get("PwnCount", 0),
                "data_classes": breach.get("DataClasses", []),
                "is_verified": breach.get("IsVerified", False),
                "severity": "CRITICAL" if breach.get("PwnCount", 0) > 10000 else "HIGH",
            })
        print(f"[+] Found {len(domain_breaches)} breaches for {domain}")
    except requests.RequestException as e:
        print(f"[!] HIBP API error: {e}")
    return findings


def check_hibp_email(email, api_key):
    """Check if a specific email appears in known breaches."""
    if not api_key:
        return []
    findings = []
    headers = {"hibp-api-key": api_key, "user-agent": "dark-web-monitor-agent"}
    try:
        resp = requests.get(
            f"https://haveibeenpwned.com/api/v3/breachedaccount/{email}",
            headers=headers, params={"truncateResponse": "false"}, timeout=15,
        )
        if resp.status_code == 200:
            breaches = resp.json()
            for breach in breaches:
                findings.append({
                    "type": "email_breach",
                    "email": email,
                    "breach": breach.get("Name", ""),
                    "breach_date": breach.get("BreachDate", ""),
                    "data_classes": breach.get("DataClasses", []),
                    "severity": "HIGH",
                })
        elif resp.status_code == 404:
            pass  # Not found in any breaches
        time.sleep(1.5)  # HIBP rate limit
    except requests.RequestException:
        pass
    return findings


def check_hibp_password(password):
    """Check if a password appears in known breaches using k-anonymity."""
    sha1 = hashlib.sha1(password.encode("utf-8")).hexdigest().upper()
    prefix = sha1[:5]
    suffix = sha1[5:]
    try:
        resp = requests.get(
            f"https://api.pwnedpasswords.com/range/{prefix}",
            timeout=10,
        )
        resp.raise_for_status()
        for line in resp.text.splitlines():
            parts = line.split(":")
            if parts[0] == suffix:
                count = int(parts[1])
                return {"compromised": True, "count": count, "severity": "CRITICAL"}
        return {"compromised": False, "count": 0, "severity": "INFO"}
    except requests.RequestException:
        return {"compromised": None, "error": "API unavailable"}


def check_paste_dumps(domain, api_key=None):
    """Check for organization mentions in paste sites via HIBP."""
    findings = []
    if not api_key:
        return findings
    # HIBP paste API requires per-email queries
    return findings


def search_threat_intel_feeds(domain):
    """Search public threat intelligence for domain mentions."""
    findings = []
    print(f"[*] Checking public threat intelligence for: {domain}")

    # Check URLhaus for malicious URLs from domain
    try:
        resp = requests.post(
            "https://urlhaus-api.abuse.ch/v1/host/",
            data={"host": domain}, timeout=15,
        )
        if resp.status_code == 200:
            data = resp.json()
            if data.get("query_status") == "ok":
                urls = data.get("urls", [])
                if urls:
                    findings.append({
                        "type": "malicious_urls",
                        "source": "URLhaus",
                        "domain": domain,
                        "count": len(urls),
                        "severity": "HIGH",
                        "detail": f"{len(urls)} malicious URLs associated with domain",
                        "samples": [u.get("url", "")[:80] for u in urls[:5]],
                    })
    except requests.RequestException:
        pass

    # Check AbuseIPDB
    abuse_key = os.environ.get("ABUSEIPDB_KEY", "")
    if abuse_key:
        try:
            resp = requests.get(
                "https://api.abuseipdb.com/api/v2/check-block",
                headers={"Key": abuse_key, "Accept": "application/json"},
                params={"network": domain}, timeout=15,
            )
        except requests.RequestException:
            pass

    return findings


def format_summary(all_findings, domain):
    """Print monitoring summary."""
    print(f"\n{'='*60}")
    print(f"  Dark Web Threat Monitoring Report")
    print(f"{'='*60}")
    print(f"  Target Domain: {domain}")
    print(f"  Total Findings: {len(all_findings)}")

    by_type = {}
    for f in all_findings:
        t = f.get("type", "unknown")
        by_type[t] = by_type.get(t, 0) + 1

    if by_type:
        print(f"\n  By Type:")
        for t, count in by_type.items():
            print(f"    {t:20s}: {count}")

    breaches = [f for f in all_findings if f["type"] == "breach"]
    if breaches:
        print(f"\n  Known Breaches ({len(breaches)}):")
        for b in breaches:
            print(f"    [{b['severity']:8s}] {b['name']:25s} | "
                  f"Date: {b['breach_date']} | Records: {b.get('pwn_count', 'N/A')}")
            if b.get("data_classes"):
                print(f"             Data: {', '.join(b['data_classes'][:5])}")

    severity_counts = {}
    for f in all_findings:
        sev = f.get("severity", "INFO")
        severity_counts[sev] = severity_counts.get(sev, 0) + 1
    return severity_counts


def main():
    parser = argparse.ArgumentParser(description="Dark web threat monitoring agent")
    parser.add_argument("--domain", required=True, help="Organization domain to monitor")
    parser.add_argument("--emails", nargs="+", help="Specific emails to check")
    parser.add_argument("--hibp-key", help="HIBP API key (or HIBP_API_KEY env)")
    parser.add_argument("--check-passwords", nargs="+", help="Check passwords against breach DB")
    parser.add_argument("--output", "-o", help="Output JSON report")
    parser.add_argument("--verbose", "-v", action="store_true")
    args = parser.parse_args()

    hibp_key = args.hibp_key or os.environ.get("HIBP_API_KEY", "")
    all_findings = []

    all_findings.extend(check_hibp_breaches(args.domain, hibp_key))

    if args.emails and hibp_key:
        for email in args.emails:
            all_findings.extend(check_hibp_email(email, hibp_key))

    if args.check_passwords:
        for pwd in args.check_passwords:
            result = check_hibp_password(pwd)
            if result.get("compromised"):
                all_findings.append({
                    "type": "compromised_password",
                    "severity": "CRITICAL",
                    "detail": f"Password found in {result['count']} breaches",
                })

    all_findings.extend(search_threat_intel_feeds(args.domain))
    severity_counts = format_summary(all_findings, args.domain)

    report = {
        "timestamp": datetime.now(timezone.utc).isoformat(),
        "tool": "Dark Web Monitor",
        "domain": args.domain,
        "findings": all_findings,
        "severity_counts": severity_counts,
        "risk_level": (
            "CRITICAL" if severity_counts.get("CRITICAL", 0) > 0
            else "HIGH" if severity_counts.get("HIGH", 0) > 0
            else "MEDIUM" if all_findings else "LOW"
        ),
    }

    if args.output:
        with open(args.output, "w") as f:
            json.dump(report, f, indent=2)
        print(f"\n[+] Report saved to {args.output}")
    elif args.verbose:
        print(json.dumps(report, indent=2))


if __name__ == "__main__":
    main()
process.py8.8 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""
Dark Web Monitoring for Threats Script

Monitors dark web sources for organizational threats:
- Credential leak detection via HIBP and paste sites
- Ransomware leak site monitoring via Ransomwatch
- Brand mention monitoring across dark web sources
- Generates structured intelligence reports

Requirements:
    pip install requests[socks] beautifulsoup4 stix2

Usage:
    python process.py --org "Acme Corp" --domains acme.com,acme.io --check-credentials
    python process.py --org "Acme Corp" --check-ransomware
    python process.py --org "Acme Corp" --full-scan --output report.json
"""

import argparse
import json
import sys
from datetime import datetime
from typing import Optional

import requests


class DarkWebMonitor:
    """Monitor dark web sources for organizational threats."""

    def __init__(self, organization: str, domains: list = None, hibp_key: str = ""):
        self.organization = organization
        self.domains = domains or []
        self.hibp_key = hibp_key
        self.findings = []

    def check_credential_leaks(self) -> list:
        """Check for credential leaks via HIBP API."""
        leaks = []
        headers = {}
        if self.hibp_key:
            headers["hibp-api-key"] = self.hibp_key

        try:
            resp = requests.get(
                "https://haveibeenpwned.com/api/v3/breaches",
                headers=headers,
                timeout=30,
            )
            if resp.status_code == 200:
                breaches = resp.json()
                for domain in self.domains:
                    for breach in breaches:
                        breach_domain = breach.get("Domain", "").lower()
                        if domain.lower() in breach_domain or breach_domain in domain.lower():
                            leak = {
                                "type": "credential_leak",
                                "source": "HIBP",
                                "breach_name": breach["Name"],
                                "breach_date": breach.get("BreachDate"),
                                "data_classes": breach.get("DataClasses", []),
                                "pwn_count": breach.get("PwnCount", 0),
                                "domain": domain,
                                "is_verified": breach.get("IsVerified", False),
                                "severity": "HIGH",
                            }
                            leaks.append(leak)
                            self.findings.append(leak)
                            print(
                                f"[!] Credential leak: {breach['Name']} "
                                f"({breach.get('PwnCount', 0)} accounts)"
                            )
        except Exception as e:
            print(f"[-] HIBP check failed: {e}")

        return leaks

    def check_ransomware_leaks(self) -> list:
        """Check ransomware leak site aggregator for organization mentions."""
        mentions = []
        try:
            resp = requests.get(
                "https://raw.githubusercontent.com/joshhighet/ransomwatch/main/posts.json",
                timeout=30,
            )
            if resp.status_code == 200:
                posts = resp.json()
                org_lower = self.organization.lower()
                domain_patterns = [d.lower().split(".")[0] for d in self.domains]

                for post in posts:
                    title = post.get("post_title", "").lower()
                    if org_lower in title or any(d in title for d in domain_patterns):
                        mention = {
                            "type": "ransomware_leak",
                            "source": "ransomwatch",
                            "group": post.get("group_name", ""),
                            "title": post.get("post_title", ""),
                            "discovered": post.get("discovered", ""),
                            "url": post.get("post_url", ""),
                            "severity": "CRITICAL",
                        }
                        mentions.append(mention)
                        self.findings.append(mention)
                        print(
                            f"[!!!] RANSOMWARE LEAK: {post.get('group_name')} - "
                            f"{post.get('post_title')}"
                        )
        except Exception as e:
            print(f"[-] Ransomwatch check failed: {e}")

        return mentions

    def check_breach_directory(self) -> list:
        """Check public breach directories for organization data."""
        breaches = []
        try:
            # Check BreachDirectory (public API)
            for domain in self.domains:
                resp = requests.get(
                    f"https://breachdirectory.org/api/entries?domain={domain}",
                    timeout=30,
                )
                if resp.status_code == 200:
                    data = resp.json()
                    if data.get("result"):
                        breaches.append({
                            "type": "breach_directory",
                            "domain": domain,
                            "entries_found": len(data.get("result", [])),
                            "severity": "HIGH",
                        })
        except Exception as e:
            print(f"[-] Breach directory check failed: {e}")
        return breaches

    def generate_report(self) -> dict:
        """Generate comprehensive dark web monitoring report."""
        critical = [f for f in self.findings if f.get("severity") == "CRITICAL"]
        high = [f for f in self.findings if f.get("severity") == "HIGH"]
        medium = [f for f in self.findings if f.get("severity") == "MEDIUM"]

        report = {
            "report_metadata": {
                "organization": self.organization,
                "domains_monitored": self.domains,
                "report_date": datetime.utcnow().isoformat(),
                "classification": "TLP:AMBER",
            },
            "executive_summary": (
                f"Dark web monitoring for {self.organization} identified "
                f"{len(critical)} critical, {len(high)} high, and "
                f"{len(medium)} medium severity findings."
            ),
            "findings_by_severity": {
                "critical": critical,
                "high": high,
                "medium": medium,
            },
            "all_findings": self.findings,
            "recommendations": [],
        }

        if critical:
            report["recommendations"].append(
                "IMMEDIATE: Activate incident response for ransomware leak detection. "
                "Assess data exposure scope and notify affected parties."
            )
        if high:
            report["recommendations"].append(
                "URGENT: Force password resets for all accounts in detected breaches. "
                "Enable MFA across all services."
            )
        report["recommendations"].append(
            "ONGOING: Continue dark web monitoring with weekly reporting cadence."
        )

        return report

    def full_scan(self) -> dict:
        """Run all dark web monitoring checks."""
        print(f"[*] Starting dark web monitoring for: {self.organization}")
        print(f"[*] Domains: {', '.join(self.domains)}")

        print("\n[*] Checking credential leaks...")
        self.check_credential_leaks()

        print("\n[*] Checking ransomware leak sites...")
        self.check_ransomware_leaks()

        print(f"\n[+] Total findings: {len(self.findings)}")
        return self.generate_report()


def main():
    parser = argparse.ArgumentParser(description="Dark Web Monitoring Tool")
    parser.add_argument("--org", required=True, help="Organization name")
    parser.add_argument("--domains", help="Comma-separated domains to monitor")
    parser.add_argument("--hibp-key", default="", help="HIBP API key")
    parser.add_argument("--check-credentials", action="store_true")
    parser.add_argument("--check-ransomware", action="store_true")
    parser.add_argument("--full-scan", action="store_true")
    parser.add_argument("--output", default="darkweb_report.json", help="Output file")

    args = parser.parse_args()
    domains = args.domains.split(",") if args.domains else []
    monitor = DarkWebMonitor(args.org, domains, args.hibp_key)

    if args.full_scan:
        report = monitor.full_scan()
    elif args.check_credentials:
        monitor.check_credential_leaks()
        report = monitor.generate_report()
    elif args.check_ransomware:
        monitor.check_ransomware_leaks()
        report = monitor.generate_report()
    else:
        report = monitor.full_scan()

    with open(args.output, "w") as f:
        json.dump(report, f, indent=2, default=str)
    print(f"\n[+] Report saved to {args.output}")
    print(json.dumps(report["executive_summary"], indent=2))


if __name__ == "__main__":
    main()

Assets 1

template.mdtext/markdown · 0.8 KB
Keep exploring