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.clean_wildcard_domain(domain)

Remove leading *. from domain names.

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.main_dns_twist()

Launch dnstwist algorithm.

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).