What You Will Achieve
By the end of this playbook you will have:
- A typosquatting generator producing 200+ variants of your brand domain
- DNS resolution checks to identify which variants are actively registered
- isMalicious reputation scoring for all active variants
- Automated alerts when a new suspicious domain comes online
- Wazuh integration for SIEM visibility
Prerequisites
| Requirement | Details |
|---|---|
| isMalicious API key | Free tier works; Pro for higher rate limits |
| Python 3.9+ | Script runtime |
| dnstwist | pip install dnstwist |
| Your brand domains | List of domains to protect |
Step 1: Generate Typosquatting Variants
python
import dnstwist
import json
PROTECTED_DOMAINS = [
"yourdomain.com",
"your-product.com",
]
def generate_variants(domain):
dt = dnstwist.DnsTwist(domain)
dt.generate()
dt.resolve()
# Return only registered/live domains
return [
entry for entry in dt.domains
if entry.get("dns_a") or entry.get("dns_mx")
]
all_variants = []
for domain in PROTECTED_DOMAINS:
variants = generate_variants(domain)
all_variants.extend(variants)
print(f"{domain}: {len(variants)} live variants found")
print(f"\nTotal live suspicious domains: {len(all_variants)}")
Step 2: Check Reputation with isMalicious
python
import base64
import requests
import time
API_KEY = "YOUR_API_KEY"
API_SECRET = "YOUR_API_SECRET"
HEADERS = {
"X-API-KEY": base64.b64encode(f"{API_KEY}:{API_SECRET}".encode()).decode()
}
def check_reputation(domain):
try:
resp = requests.get(
"https://api.ismalicious.com/check",
params={"query": domain},
headers=HEADERS,
timeout=10
)
if resp.ok:
data = resp.json()
return {
"domain": domain,
"malicious": data.get("malicious", False),
"score": data.get("riskScore", {}).get("score", 0),
"categories": data.get("categories", []),
"confidence": data.get("confidenceScore", 0),
"sources": [s["name"] for s in data.get("sources", [])],
}
except Exception as e:
return {"domain": domain, "error": str(e)}
# Rate-limited batch check
results = []
for variant in all_variants:
domain = variant.get("domain", "")
if domain:
result = check_reputation(domain)
results.append({**variant, **result})
time.sleep(0.1) # Respect rate limits
# Sort by risk score descending
results.sort(key=lambda x: x.get("score", 0), reverse=True)
Step 3: Classify and Triage
python
HIGH_RISK_THRESHOLD = 60
SUSPICIOUS_THRESHOLD = 30
categories = {"high_risk": [], "suspicious": [], "monitor": []}
for r in results:
score = r.get("score", 0)
fuzzer = r.get("fuzzer", "unknown")
if score >= HIGH_RISK_THRESHOLD or r.get("malicious"):
categories["high_risk"].append(r)
elif score >= SUSPICIOUS_THRESHOLD:
categories["suspicious"].append(r)
else:
categories["monitor"].append(r)
print(f"High Risk: {len(categories['high_risk'])}")
print(f"Suspicious: {len(categories['suspicious'])}")
print(f"Monitor: {len(categories['monitor'])}")
Step 4: Automated Alerting
Email alert for new high-risk domains
python
import smtplib
from email.mime.text import MIMEText
from datetime import datetime
def send_alert(high_risk_domains):
if not high_risk_domains:
return
body = f"Phishing Domain Alert - {datetime.now().strftime('%Y-%m-%d')}\n\n"
body += f"Found {len(high_risk_domains)} high-risk typosquatting domains:\n\n"
for d in high_risk_domains:
body += f" {d['domain']} (score: {d.get('score', 0)}, "
body += f"cats: {', '.join(d.get('categories', []))})\n"
body += "\nCheck full report at: https://ismalicious.com/app\n"
msg = MIMEText(body)
msg["Subject"] = f"⚠️ {len(high_risk_domains)} Phishing Domains Detected"
msg["From"] = "alerts@yourdomain.com"
msg["To"] = "security-team@yourdomain.com"
with smtplib.SMTP("smtp.yourdomain.com") as server:
server.send_message(msg)
Step 5: Wazuh SIEM Integration
Add detected domains as custom Wazuh alerts.
Custom decoder (/var/ossec/etc/decoders/ismalicious.xml)
xml
<decoder name="ismalicious-phishing">
<prematch>ISMALICIOUS_PHISHING:</prematch>
<regex offset="after_prematch">(\S+) score=(\d+) categories=(\S+)</regex>
<order>domain, score, categories</order>
</decoder>
Log the detections
python
import logging
logger = logging.getLogger("ismalicious")
handler = logging.FileHandler("/var/ossec/logs/ismalicious.log")
logger.addHandler(handler)
for d in categories["high_risk"]:
logger.warning(
f"ISMALICIOUS_PHISHING: {d['domain']} "
f"score={d.get('score', 0)} "
f"categories={'|'.join(d.get('categories', []))}"
)
Wazuh rule (/var/ossec/etc/rules/ismalicious_rules.xml)
xml
<group name="ismalicious,phishing">
<rule id="100500" level="10">
<decoded_as>ismalicious-phishing</decoded_as>
<description>New phishing/typosquatting domain detected: $(domain)</description>
<mitre>
<id>T1566.002</id>
</mitre>
</rule>
</group>
Step 6: Full Pipeline Script
Save as phishing_scan.py and run via cron daily:
bash
# Daily at 6 AM
0 6 * * * /usr/bin/python3 /opt/ismalicious/phishing_scan.py >> /var/log/phishing_scan.log 2>&1
Expected Output
bash
yourdomain.com: 23 live variants found
Total live suspicious domains: 23
High Risk: 3
Suspicious: 7
Monitor: 13
High Risk Domains:
yourdomian.com (score: 87, cats: phishing)
your-d0main.com (score: 72, cats: phishing, malware)
yooudomain.com (score: 61, cats: phishing)
Next Steps
- Add the high-risk domains to your isMalicious Watchlist for continuous monitoring
- File takedown requests with registrars for confirmed phishing domains
- Submit URLs to Google Safe Browsing for faster blocklist propagation
- Integrate with your brand's legal team for rapid UDRP filings