Communitygithub.com

使用DNSTwist分析域名抢注

使用dnstwist生成域名变体并检查DNS解析状态。

使用DNSTwist分析域名抢注 是什么?

此技能用于通过DNSTwist域名置换引擎检测域名抢注、同形异义字钓鱼攻击和品牌冒用。它利用字符替换、转置、插入、省略、同形字替换等多种技术生成数千个域名变体,并检查DNS记录(A、AAAA、NS、MX),通过模糊哈希(ssdeep)和感知哈希(pHash)计算网页相似度,识别已注册的潜在恶意域名。该技能适用于安全事件调查、威胁狩猎规则构建及SOC分析师执行结构化分析。支持Python 3.9+环境,并提供从基本扫描到风险评分、持续监控和生成拦截列表/下架报告的完整工作流程。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/mukul975/Anthropic-Cybersecurity-Skills/tree/main/skills/analyzing-typosquatting-domains-with-dnstwist

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

使用DNSTwist分析域名抢注 是做什么的?

概述

DNSTwist 是一个域名置换引擎,可生成相似外观的域名,用以检测域名抢注(typosquatting)、同形异义字钓鱼攻击和品牌冒用。它通过字符替换、转置、插入、省略以及同形字替换等技术生成数千个域名变体,然后检查 DNS 记录(A、AAAA、NS、MX),使用模糊哈希(ssdeep)和感知哈希(pHash)计算网页相似度,并识别已注册的可能恶意域名。

使用时机

  • 调查涉及使用 dnstwist 分析域名抢注的安全事件时
  • 为此类攻击构建检测规则或威胁狩猎查询时
  • SOC 分析师需要针对此类分析的结构化流程时
  • 验证安全监控覆盖相关攻击技术时

前置条件

  • Python 3.9+ 并安装 dnstwist(pip install dnstwist[full])
  • 可选:用于 IP 地理定位的 GeoIP 数据库
  • 可选:用于数据丰富化的 Shodan API 密钥
  • 具备执行 DNS 查询的网络访问权限
  • 理解 DNS 记录类型和域名注册

关键概念

域名置换技术

DNSTwist 通过以下方式生成变体:添加(追加字符)、位翻转(比特错误)、同形异义字(视觉相似的 Unicode 字符,如 rn 与 m)、连字符添加、插入、省略、重复、替换(相邻键盘键)、子域名(插入点号)、转置(交换相邻字符)、元音交换以及基于字典的追加(追加常见单词)。

模糊哈希与视觉相似度

DNSTwist 使用 ssdeep(局部敏感哈希)比较 HTML 内容,并使用 pHash(感知哈希)比较网页截图。这有助于识别视觉上模仿合法网站的克隆钓鱼站点。高相似度分数表明可能是钓鱼页面。

检测工作流程

典型工作流程为:生成域名变体 -> 解析 DNS 记录 -> 检查已注册域名 -> 比较网页相似度 -> 标记可疑域名 -> 通知安全团队 -> 请求下架。对于一个典型的公司域名,dnstwist 会生成 5,000 至 10,000 个变体。

工作流程

步骤 1:基本域名变体扫描

import subprocess
import json
import csv
from datetime import datetime

def run_dnstwist_scan(domain, output_file=None):
    """对目标域名运行 dnstwist 扫描。"""
    cmd = [
        "dnstwist",
        "--registered",     # 仅显示已注册域名
        "--format", "json", # 输出 JSON 格式
        "--nameservers", "8.8.8.8,1.1.1.1",
        "--threads", "50",
        "--mxcheck",        # 检查 MX 记录
        "--ssdeep",         # 模糊哈希比较
        "--geoip",          # GeoIP 查询
        domain,
    ]

    print(f"[*] 正在扫描 {domain} 的变体")
    result = subprocess.run(cmd, capture_output=True, text=True, timeout=600)

    if result.returncode == 0:
        results = json.loads(result.stdout)
        registered = [r for r in results if r.get("dns_a") or r.get("dns_aaaa")]
        print(f"[+] 发现 {len(registered)} 个已注册的相似域名")

        if output_file:
            with open(output_file, "w") as f:
                json.dump(registered, f, indent=2)
            print(f"[+] 结果已保存至 {output_file}")

        return registered
    else:
        print(f"[-] dnstwist 错误:{result.stderr}")
        return []

results = run_dnstwist_scan("example.com", "typosquat_results.json")

步骤 2:分析结果并确定优先级

def analyze_results(results, legitimate_ips=None):
    """分析 dnstwist 结果并确定威胁优先级。"""
    legitimate_ips = legitimate_ips or set()
    high_risk = []
    medium_risk = []
    low_risk = []

    for entry in results:
        domain = entry.get("domain", "")
        fuzzer = entry.get("fuzzer", "")
        dns_a = entry.get("dns_a", [])
        dns_mx = entry.get("dns_mx", [])
        ssdeep_score = entry.get("ssdeep_score", 0)

        risk_score = 0
        risk_factors = []

        # 与合法网站高度相似
        if ssdeep_score and ssdeep_score > 50:
            risk_score += 40
            risk_factors.append(f"网页相似度高 ({ssdeep_score}%)")

        # 有 MX 记录(可接收邮件/用于钓鱼)
        if dns_mx:
            risk_score += 20
            risk_factors.append("存在 MX 记录(可收发邮件)")

        # 近期注册(如有 whois 数据)
        whois_created = entry.get("whois_created", "")
        if whois_created:
            try:
                created = datetime.fromisoformat(whois_created.replace("Z", "+00:00"))
                age_days = (datetime.now(created.tzinfo) - created).days
                if age_days < 30:
                    risk_score += 30
                    risk_factors.append(f"近期注册({age_days} 天前)")
                elif age_days < 90:
                    risk_score += 15
                    risk_factors.append(f"注册于 {age_days} 天前")
            except (ValueError, TypeError):
                pass

        # 同形异义字攻击风险最高
        if fuzzer == "homoglyph":
            risk_score += 25
            risk_factors.append("同形异义字(视觉相同)")
        elif fuzzer in ("addition", "replacement", "transposition"):
            risk_score += 10
            risk_factors.append(f"置换类型:{fuzzer}")

        # 未指向合法基础设施
        if dns_a and not set(dns_a).intersection(legitimate_ips):
            risk_score += 10
            risk_factors.append("IP 与合法站点不同")

        entry["risk_score"] = risk_score
        entry["risk_factors"] = risk_factors

        if risk_score >= 50:
            high_risk.append(entry)
        elif risk_score >= 25:
            medium_risk.append(entry)
        else:
            low_risk.append(entry)

    high_risk.sort(key=lambda x: x["risk_score"], reverse=True)
    medium_risk.sort(key=lambda x: x["risk_score"], reverse=True)

    print(f"\n=== 域名抢注分析 ===")
    print(f"高风险:{len(high_risk)}")
    print(f"中风险:{len(medium_risk)}")
    print(f"低风险:{len(low_risk)}")

    if high_risk:
        print(f"\n--- 高风险域名 ---")
        for entry in high_risk[:10]:
            print(f"  {entry['domain']}(分数:{entry['risk_score']})")
            for factor in entry['risk_factors']:
                print(f"    - {factor}")

    return {"high": high_risk, "medium": medium_risk, "low": low_risk}

analysis = analyze_results(results, legitimate_ips={"93.184.216.34"})

步骤 3:持续监控管道

import time
import hashlib

class TyposquatMonitor:
    def __init__(self, domains, known_domains_file="known_typosquats.json"):
        self.domains = domains
        self.known_file = known_domains_file
        self.known_domains = self._load_known()

    def _load_known(self):
        try:
            with open(self.known_file, "r") as f:
                return json.load(f)
        except FileNotFoundError:
            return {}

    def _save_known(self):
        with open(self.known_file, "w") as f:
            json.dump(self.known_domains, f, indent=2)

    def scan_all_domains(self):
        """扫描所有监控域名以发现新的抢注域名。"""
        new_findings = []
        for domain in self.domains:
            results = run_dnstwist_scan(domain)
            for entry in results:
                domain_key = entry.get("domain", "")
                if domain_key not in self.known_domains:
                    entry["first_seen"] = datetime.now().isoformat()
                    entry["monitored_domain"] = domain
                    self.known_domains[domain_key] = entry
                    new_findings.append(entry)
                    print(f"  [新增] {domain_key} ({entry.get('fuzzer', '')})")

        self._save_known()
        print(f"\n[+] 发现新的抢注域名数量:{len(new_findings)}")
        return new_findings

    def generate_alert(self, findings):
        """为新的高风险抢注域名生成告警。"""
        analysis = analyze_results(findings)
        alerts = []
        for entry in analysis["high"]:
            alerts.append({
                "severity": "HIGH",
                "domain": entry["domain"],
                "target": entry.get("monitored_domain", ""),
                "risk_score": entry["risk_score"],
                "risk_factors": entry["risk_factors"],
                "dns_a": entry.get("dns_a", []),
                "dns_mx": entry.get("dns_mx", []),
                "timestamp": datetime.now().isoformat(),
            })
        return alerts

monitor = TyposquatMonitor(["mycompany.com", "mycompany.org"])
new_findings = monitor.scan_all_domains()
alerts = monitor.generate_alert(new_findings)

步骤 4:导出拦截列表并执行下架

def export_blocklist(analysis, output_file="blocklist.txt"):
    """将高风险域名导出为防火墙/代理的拦截列表。"""
    domains = []
    for entry in analysis["high"] + analysis["medium"]:
        domain = entry.get("domain", "")
        if domain:
            domains.append(domain)

    with open(output_file, "w") as f:
        f.write(f"# 抢注域名拦截列表,生成时间 {datetime.now().isoformat()}\n")
        for d in sorted(set(domains)):
            f.write(f"{d}\n")

    print(f"[+] 拦截列表已保存:{len(domains)} 个域名 -> {output_file}")
    return domains

def generate_takedown_report(high_risk_domains):
    """生成下架请求报告。"""
    report = f"""# 域名下架请求
生成时间:{datetime.now().isoformat()}

## 摘要
已识别出 {len(high_risk_domains)} 个潜在抢注/钓鱼域名。

## 需要下架的域名
"""
    for entry in high_risk_domains:
        report += f"""
### {entry['domain']}
- **置换类型**:{entry.get('fuzzer', '未知')}
- **IP 地址**:{', '.join(entry.get('dns_a', ['N/A']))}
- **MX 记录**:{', '.join(entry.get('dns_mx', ['N/A']))}
- **风险分数**:{entry.get('risk_score', 0)}
- **风险因素**:{';'.join(entry.get('risk_factors', []))}
- **网页相似度**:{entry.get('ssdeep_score', 'N/A')}%
"""
    with open("takedown_report.md", "w") as f:
        f.write(report)
    print("[+] 下架报告已生成:takedown_report.md")

export_blocklist(analysis)
generate_takedown_report(analysis["high"])

验证标准

  • DNSTwist 为目标域名生成域名变体
  • DNS 解析识别出已注册的相似域名
  • 网页相似度评分检测到克隆的钓鱼页面
  • 风险评分按威胁级别对域名进行优先级排序
  • 持续监控可检测到新注册的抢注域名
  • 拦截列表和下架报告正确生成

参考资料

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

abusing-dpapi-for-credential-access

Extract and decrypt Windows DPAPI-protected secrets (Credential Manager, browser logins/cookies, Wi-Fi credentials, KeePass keys) online or offline using SharpDPAPI, SharpChrome, Mimikatz, or Impacket

abusing-shadow-credentials-for-privesc

Take over Active Directory accounts by writing attacker-controlled public keys to msDS-KeyCredentialLink (Shadow Credentials) with pyWhisker, Whisker, or Certipy, then authenticate via PKINIT to recover the target

achieving-cmmc-level-2-compliance

>-

acquiring-disk-image-with-dd-and-dcfldd

Create forensically sound bit-for-bit disk images with dd or dcfldd on a Linux forensic workstation, preserving evidence integrity through hash verification (MD5/SHA) during acquisition. Use when imaging a suspect drive, USB device, or memory card for investigation, preserving volatile disk evidence during incident response, or producing a verified copy for legal or law-enforcement proceedings before any destructive analysis.

analyzing-active-directory-acl-abuse

Detect dangerous ACL misconfigurations in Active Directory using ldap3

analyzing-android-malware-with-apktool

Perform static analysis of Android APK malware using apktool for resource decompilation, jadx for Java source recovery, and androguard for manifest inspection, dangerous permission-combination detection, and identification of obfuscated code, dynamic code loading, and reflection-based API calls. Use to statically triage a suspicious APK without executing it or to build mobile malware detection rules.

analyzing-api-gateway-access-logs

Parses API Gateway access logs (AWS API Gateway, Kong, Nginx) to detect

analyzing-apt-group-with-mitre-navigator

Query ATT&CK data with attackcti, mitreattack-python, and stix2, then build MITRE ATT&CK Navigator layers and multi-layer heatmap overlays mapping one or more APT groups

analyzing-azure-activity-logs-for-threats

Queries Azure Monitor activity logs and sign-in logs via azure-monitor-query

analyzing-bootkit-and-rootkit-samples

Analyzes bootkit and advanced rootkit malware infecting the Master

analyzing-browser-forensics-with-hindsight

Parse Chromium-based browser databases with Hindsight to extract and correlate browsing history, downloads, cookies, cached content, autofill data, saved passwords, and extensions from Chrome, Edge, Brave, Opera, and Vivaldi into a unified timeline (XLSX, JSON, or SQLite output). Use during incident response, insider-threat investigations, or criminal cases when you need to reconstruct a user

analyzing-campaign-attribution-evidence

Systematically evaluate cyber-campaign evidence to attribute an operation to a threat actor, using the Diamond Model and Analysis of Competing Hypotheses (ACH) to weigh infrastructure overlaps, TTP consistency, malware code similarity, and timing/language artifacts into confidence-weighted attribution assessments. Use when an incident investigation needs a defensible attribution confidence level.

analyzing-certificate-transparency-for-phishing

Monitor Certificate Transparency logs using crt.sh and Certstream to

analyzing-cloud-storage-access-patterns

Detect abnormal access in AWS S3, GCS, and Azure Blob Storage by analyzing CloudTrail Data Events, GCS audit logs, and Azure Storage Analytics for after-hours bulk downloads, new-IP access, and API-call spikes (e.g. GetObject) via statistical baselines and time-series anomaly detection. Use when investigating suspected cloud data exfiltration or building related detection rules.

analyzing-cobalt-strike-beacon-configuration

Extract and analyze Cobalt Strike beacon configuration from PE files

analyzing-cobaltstrike-malleable-c2-profiles

Parse and analyze Cobalt Strike Malleable C2 profiles with dissect.cobaltstrike (profiles and beacon-payload configs) and pyMalleableC2 (AST parsing) to extract HTTP/DNS transforms, URIs, headers, sleep/jitter, and injection behavior, then generate network detection signatures. Use when reverse-engineering a captured malleable profile or building detections against Cobalt Strike Beacon traffic.

analyzing-command-and-control-communication

Analyzes malware C2 communication over HTTP, HTTPS, DNS, and custom

analyzing-cyber-kill-chain

Analyzes intrusion activity against the Lockheed Martin Cyber Kill Chain

analyzing-disk-image-with-autopsy

Perform comprehensive forensic analysis of raw (dd), E01, or AFF disk images with Autopsy and The Sleuth Kit, recovering deleted files, examining metadata and embedded artifacts, keyword searching, and building investigation timelines with visual reports. Use for structured analysis of a forensic disk image or when stakeholders need visual reports from evidence.

analyzing-dns-logs-for-exfiltration

Analyzes DNS query logs to detect data exfiltration via DNS tunneling,

相关技能