User Guide
Everything you need to take Zedmos CTI from sign-up to a fully wired SOC pipeline. Copy/paste-able curl examples throughout.
1. Quickstart (5 minutes)
The fastest path: log in to the admin console, issue a firewall token, and pull one of the curated feeds into your existing security stack.
ti / security / waf kinds, and copy the value — it is shown once.TOKEN="tihub_..."
curl -H "Authorization: Bearer $TOKEN" \
https://cti.zedmos.net/v1/feeds/security/phishing/domains.txt | head
2. Getting an API token
Every /v1/feeds/* and /v1/lookup/* endpoint is bearer-token gated. Tokens are issued from the admin console and hashed with SHA-256 server-side, so plaintext is never stored — that's also why we only show it once.
Token kinds
| Kind | Use case |
|---|---|
ti | Generic threat-intel (domain/IP block lists) |
security | Security-policy categories (phishing, malware, ransomware…) |
waf | WAF-grade signatures + JA3/JA4 fingerprints |
One token can carry multiple kinds. Token rotation: just issue a new one and update your firewall config; revoking on the old token takes effect immediately (no grace window).
3. Pulling feeds
All feeds follow the URL convention:
/v1/feeds/<kind>/<category>/<format>
Some popular combinations:
| URL | Format |
|---|---|
/v1/feeds/security/phishing/domains.txt | plain domain list |
/v1/feeds/ti/botnet_cc/ips.txt | plain IP/CIDR list |
/v1/feeds/security/malware_virus/suricata.rules | Suricata DNS-block rules (priority + threat metadata) |
/v1/feeds/security/ransomware/sigma.yml | Sigma rule (MITRE-tagged) |
/v1/feeds/ti/file_sha256_malware/yara.yar | YARA hash rule |
/v1/feeds/security/phishing/stix.json | STIX 2.1 bundle |
/v1/feeds/security/phishing/unbound.rpz | RPZ DNS sinkhole zone |
Available categories
phishing · malware_virus · ransomware · botnet_cc · banking_trojan · info_stealer · spyware_adware · keyloggers · exploit_kit · cryptominer · scanner · ddos_amplifier · anonymizer · bulletproof_hosting · dynamic_dns · newly_registered · turkish_usom · iot_botnet · ja3 · ja4 · compromised · recent_outbreaks · ...
See the full live catalogue at /v1/public/sources.
4. IOC scoring (composite filter)
Every IOC carries four 0-100 scores. The most useful one for production is composite: a weighted aggregate that drives default sorting and our recommended block threshold.
Score meanings
| Score | What it measures |
|---|---|
| confidence | How sure are we this IOC is malicious? (source quality × consensus × enrichment × sighting feedback) |
| threat | How dangerous if hit? (severity 1-10 × category weight × tier multiplier) |
| popularity | How widely observed? (distinct sources × 30d sightings × age window) |
| composite | Weighted aggregate: confidence×0.45 + threat×0.35 + popularity×0.20 |
min_score gating — recommended workflow
Every feed export accepts ?min_score=N (0-100). Gate by composite to ship only high-signal IOCs to noisy environments:
# Full feed (default — includes community-tier indicators)
curl -H "Authorization: Bearer $TOKEN" \
https://cti.zedmos.net/v1/feeds/security/phishing/domains.txt
# Strict mode: composite >= 70 (verified + corroborated only)
curl -H "Authorization: Bearer $TOKEN" \
"https://cti.zedmos.net/v1/feeds/security/phishing/fortinet.txt?min_score=70"
# Response includes X-Tihub-Min-Score and X-Tihub-Row-Count headers
Per-IOC lookup
curl -H "Authorization: Bearer $TOKEN" \
https://cti.zedmos.net/v1/lookup/domain/example.bet
Returns tier, sources, categories, the four scores, the effective MITRE techniques, and a recommendation string ready for ticketing.
5. MITRE ATT&CK mapping
Zedmos maps each category to a curated list of ATT&CK tactics + techniques (Enterprise v15, 2026 Q1). The mapping shows up in three places:
- Sigma rules —
tags: attack.t1566.001, attack.initial-access - STIX bundles —
kill_chain_phases+external_referencesto attack.mitre.org - Lookup endpoint —
mitre: { tactics, techniques }in JSON
Coverage matrix
Live aggregate of which ATT&CK techniques we cover, with IOC counts per technique. Open /admin-mitre-coverage.html (public, no auth) or hit the JSON:
curl https://cti.zedmos.net/v1/public/mitre/coverage | jq '.techniques[0:5]'
6. Vendor-native exports
Same IOC set, packaged for direct paste into your firewall console. All endpoints accept ?min_score.
Fortinet FortiGate
config system external-resource
edit "zedmos-phishing"
set type domain
set resource "https://cti.zedmos.net/v1/feeds/security/phishing/fortinet.txt?min_score=70"
set user-agent "Bearer <TOKEN>"
next
end
Palo Alto Networks (External Dynamic List)
# Objects → External Dynamic Lists → Add
# Type: IP List
# Source: https://cti.zedmos.net/v1/feeds/security/phishing/paloalto.txt
# Repeat every: Hour
# Certificate Profile: leave blank (HTTPS trusted by default)
Check Point Quantum
ioc_feeds add \
--feed_name Zedmos_Phishing \
--transport_type web_url \
--resource https://cti.zedmos.net/v1/feeds/security/phishing/checkpoint.csv \
--feed_action prevent \
--feed_format CSV
Sophos / Cisco Umbrella / Meraki / Juniper SRX / MikroTik / Pi-hole / OPNsense / Unbound RPZ
Snippets and config hints for all 16 supported integrations: /integrations.
7. EASM scanner — declare & scan your surface
EASM = External Attack Surface Management. You declare the externally-facing assets you own (domains, IPs, CIDRs, URLs) and Zedmos scans them periodically for misconfigurations and exposures.
What we check (today)
- Missing security headers (HSTS, CSP, X-Frame-Options)
- Server / X-Powered-By banner leaks
- Exposed sensitive paths (
.git/HEAD,.env,.aws/credentials, phpinfo) — content-signature validated, no wildcard-200 FPs - Dangling CNAMEs (subdomain takeover candidates — S3, Azure, CloudFront, Heroku, GitHub Pages)
- DNS no-resolution / parking detection
Workflow
api.example.com), optional label, scan interval in minutes. Click Add.open if the condition returns) · FP (false positive, hide it).Severity ladder
| Severity | Examples | SLA suggestion |
|---|---|---|
| critical | Exposed .git, .env, AWS creds, dangling CNAME to taken-over provider | fix today |
| high | Apache server-status, phpinfo, missing clickjacking protection | this week |
| medium | Missing HSTS, weak TLS cipher | this sprint |
| low | Server banner version leak, missing CSP | backlog |
8. Brand protection — typosquat & homograph hunting
Declare a "brand watch" with your root domain(s); we'll enumerate up to 1,500 visually-similar variants across 8 algorithms, resolve them on public DNS in parallel, and alert on each one that's actively registered (i.e. a real attacker squat, not a hypothetical).
Algorithms used
- char-omission —
zedmos → zdmos, edmos - char-transposition —
zedmos → zdemos - char-substitution (visual) —
m → rn, o → 0, l → 1, s → 5 - duplicate-char —
zedmos → zeedmos - hyphen-insertion —
zed-mos - homograph — Cyrillic / Greek look-alikes (rendered via Punycode)
- bitsquatting — DNS-resolver bit flips on each character
- tld-swap — abuse-prone TLDs (.shop, .xyz, .live, .top, .bet…)
Workflow
example.com, example.net) and brand keywords.run_interval_min field.9. Takedown workflow
A TakedownRequest is a state-machine record that follows your abuse case end-to-end.
Lifecycle
| State | Meaning | Next action |
|---|---|---|
| draft | Auto-created, awaiting your edit | Edit subject/body, then mark submitted |
| submitted | You sent the email/form, awaiting reply | Wait 48-72h; re-send if no ack |
| acknowledged | Registrar/host confirmed receipt | Track for resolution |
| in_progress | They're investigating | Re-verify in 7 days |
| removed | Target offline (DNS NX / page 410) | Auto-marked; you can re-open if it comes back |
| denied | Registrar refused | Escalate to ICANN / hosting provider |
| stale | 30+ days, no response | Auto-resubmit candidate |
RDAP abuse-contact lookup
curl -H "Cookie: session=..." \
https://cti.zedmos.net/admin/v1/admin/brand/abuse-contact/example.bet
# → { registrar: "abuse@example-reg.com", abuse_email: "...", raw: {...} }
10. API reference (cheat sheet)
Public (no auth)
| Endpoint | Returns |
|---|---|
GET /v1/public/health | health probe |
GET /v1/public/sources | feed catalogue |
GET /v1/public/dashboard | overall stats |
GET /v1/public/mitre/coverage | MITRE coverage matrix (5-min cached) |
GET /v1/integrations/vendors | 16-entry vendor catalog |
Bearer-token endpoints
| Endpoint | Returns |
|---|---|
GET /v1/feeds/<kind>/<cat>/domains.txt | plain domain list |
GET /v1/feeds/<kind>/<cat>/ips.txt | plain IP/CIDR list |
GET /v1/feeds/<kind>/<cat>/suricata.rules | Suricata 7 rules (priority + threat metadata) |
GET /v1/feeds/<kind>/<cat>/sigma.yml | Sigma rule (MITRE tagged) |
GET /v1/feeds/<kind>/<cat>/yara.yar | YARA rule (hash-based) |
GET /v1/feeds/<kind>/<cat>/stix.json | STIX 2.1 bundle |
GET /v1/feeds/<kind>/<cat>/{fortinet,paloalto,checkpoint,sophos,...} | vendor-native exports |
GET /v1/lookup/<type>/<value> | per-IOC lookup with scores + MITRE |
Admin endpoints (session JWT cookie)
| Endpoint | Purpose |
|---|---|
POST /admin/v1/admin/easm/assets | Add EASM asset |
POST /admin/v1/admin/easm/assets/:id/scan | Trigger scan |
GET /admin/v1/admin/easm/summary | Asset rollup |
POST /admin/v1/admin/brand/watches | Create brand watch |
POST /admin/v1/admin/brand/watches/:id/scan | Run typosquat scan |
POST /admin/v1/admin/brand/alerts/:id/takedown | Spawn takedown request |
GET /admin/v1/admin/brand/abuse-contact/:domain | RDAP abuse lookup |
11. Troubleshooting
401 unauthorized
Your token is wrong, expired, or revoked. Check FW Tokens in the admin console — disabled tokens have enabled=false. Issue a fresh one.
The feed I want is empty
You're probably hitting a strict min_score on a small category. Drop the filter (?min_score=0) and inspect X-Tihub-Row-Count; if it's still 0 the category may not have IPs/domains of that type — try the alternate format.
Suricata rejects the .rules file
You probably have a Suricata version without dns.query support (pre-5.0). Our rules require Suricata ≥ 6. For older boxes, use opnsense.txt or fortinet.txt as a plain alias.
EASM scan returns 0 findings
Either your perimeter is well-tuned (good!) or the asset is unreachable from our scanner egress. Check the errors[] array in the scan result for network-level failures.
Typosquat scan found 100+ variants — too noisy
Filter the BrandAlert list by severity=high (homograph hits) first; those are the highest-signal. Mark obvious legitimate brand-adjacent domains (e.g. partner sites) as ignored — they won't re-fire.
Still stuck? Email support@zedmos.com with the asset/alert ID. We aim for < 4h response on Premium, < 1 business day on Plus.