DNS Finder - Core Algorithm
- Watcher.dns_finder.core.certificate_domains(message)
Domains a CertStream certificate_update is about: the subject CN or, for the certificates that have none (CAs may omit it), their SAN list. Lowercased, without the leading
*..A certificate with a CN is judged on its CN only: multi-tenant certificates list hundreds of unrelated SAN names.
- Parameters:
message – CertStream event (Dict).
- Return type:
list[str]
- Watcher.dns_finder.core.check_dangling_status(dns_twisted)
Resolve a DnsTwisted row’s CNAME chain, match it against known takeover-able provider fingerprints, and confirm via DNS/HTTP. Updates the DnsTwisted row’s technical probe fields in place.
- Parameters:
dns_twisted – DnsTwisted Object.
- Returns:
The raw probe verdict: ‘ok’, ‘dangling_suspected’, or ‘dangling_confirmed’ (Str).
- Watcher.dns_finder.core.check_dnstwist(dns_monitored)
Runs dnstwist.
- Parameters:
dns_monitored – DnsMonitored Object.
- Returns:
- Watcher.dns_finder.core.evaluate_dangling_subdomain(dns_twisted, source)
Runs check_dangling_status and creates/updates the single subdomain_takeover Alert for this domain, notifying when the status transitions INTO ‘confirmed’ from some other status, or on the first verdict (‘pending’ -> ‘suspected’).
‘suspected’ (provider fingerprint matched but the HTTP probe failed) must reach the channels too: teams triaging only from TheHive never open the Watcher UI. It notifies once, from ‘pending’ only, so a flapping subdomain or a confirmed one hitting a transient probe error does not re-page. Escalating from ‘suspected’ to ‘confirmed’ notifies again.
- Parameters:
dns_twisted – DnsTwisted Object.
source – ‘certstream’ or ‘periodic_recheck’ (Str).
- Watcher.dns_finder.core.extract_certificate_metadata(message)
Extract issuer/SAN from a CertStream certificate_update message’s leaf certificate and issuing chain. Every field is read defensively - a leaner or differently-shaped certstream-server-go payload must never raise here, only omit data.
- Parameters:
message – CertStream event (Dict).
- Return type:
dict
- Watcher.dns_finder.core.get_monitored()
Monitored corporate domains and keywords, cached for MONITORED_CACHE_TTL seconds.
- Returns:
((id, domain_name), …) and ((id, name), …) (Tuple of tuples).
- Watcher.dns_finder.core.in_dns_monitored(domain)
Check if domain is a subdomain of one domain of the DnsMonitored list.
- Parameters:
domain – Domain to search (Str).
- Return type:
bool
- Watcher.dns_finder.core.invalidate_monitored_cache(**kwargs)
Forget the cached monitored domains and keywords (also used as a signal receiver).
- Watcher.dns_finder.core.is_legitimate_domain(domain)
Check if domain or its parent domain is in the Legitimate Domains list.
- Parameters:
domain – Domain to check (Str).
- Return type:
bool
- Watcher.dns_finder.core.load_dangling_fingerprints()
Load (and cache) the dangling-DNS provider fingerprint list.
- Return type:
list[dict]
- Watcher.dns_finder.core.main_certificate_transparency()
Launch CertStream scan using internal certstream-server-go.
- Watcher.dns_finder.core.match_fingerprint(cname_target)
Find the fingerprint entry whose cname_pattern is contained in cname_target.
- Parameters:
cname_target – Terminal CNAME hostname (Str) or None.
- Return type:
dict or None
- Watcher.dns_finder.core.print_callback(message, context)
Runs CertStream scan.
- Parameters:
message – event from CertStream.
context – parameter from CertStream.
- Watcher.dns_finder.core.recheck_dangling_subdomains()
Re-check every subdomain_takeover Alert that hasn’t been triaged as resolved/false_positive, to catch takeovers that appear long after the subdomain was first discovered.
- Watcher.dns_finder.core.resolve_cname_chain(subdomain, max_hops=5)
Follow the CNAME chain for a subdomain up to max_hops, returning the terminal target hostname, or None if there is no CNAME record.
- Parameters:
subdomain – Subdomain to resolve (Str).
max_hops – Maximum CNAME hops to follow (Int).
- Return type:
str or None
- Watcher.dns_finder.core.scan_certificate_domain(message, domain, keywords)
Check one domain of a certificate against the monitored keywords and alert on a match.
- Parameters:
message – event from CertStream (Dict).
domain – Domain to check (Str).
keywords – Monitored keywords, as (id, name) tuples (see get_monitored).
- Watcher.dns_finder.core.send_dns_finder_notifications(alert)
Sends notifications to Slack, Citadel, TheHive or Email for a DNS Threats Monitored alert, across all three sources. subdomain_takeover routes through the dedicated ‘dns_finder_dangling’ templates; dnstwist/certstream_keyword share ‘dns_finder’ and pick their template internally from source.
- Parameters:
alert – Alert Object.
- Watcher.dns_finder.core.send_dns_finder_notifications_group(dns_monitored, alerts_number, alerts)
Sends grouped notifications to Slack, Citadel, TheHive or Email based on dns_finder_group. If the application is TheHive, individual notifications are sent for each alert.
- Parameters:
keyword – The keyword or term associated with the DNS Threats Monitored.
alerts_number – The total number of alerts in the group.
alerts – The list of individual alerts to be processed and sent to TheHive.
- Watcher.dns_finder.core.start_scheduler()
- Launch multiple planning tasks in background:
Fire main_dns_twist from Monday to Sunday: every 2 hours.
Fire main_certificate_transparency from Monday to Sunday: every hour.
Fire recheck_dangling_subdomains from Monday to Sunday: every 6 hours.
- Watcher.dns_finder.core.track_dangling_subdomain(domain)
If domain is a genuine subdomain (not the root itself) of a monitored corporate root domain, catalog it for dangling-DNS tracking (a DnsTwisted row plus its subdomain_takeover Alert).
Discovery is catalog-only in real time: nothing is probed here. Verification (DNS resolution + HTTP probe, up to ~35s of blocking I/O) is left to the periodic recheck_dangling_subdomains job, which already picks up ‘pending’ rows. This runs on CertStream’s single-threaded message-reader callback, which has no queue: blocking it would make the feed drop (not buffer) certificate-transparency events, degrading the pre-existing typosquat detection that shares this callback.
Uses a strict suffix check (rather than in_dns_monitored’s substring check, which would also match unrelated domains sharing a substring) since correctness matters here: this path writes new DB rows.
- Parameters:
domain – Domain from a CertStream event (Str).