Home / Blog / Threat Intelligence

Intermediate Threat Intelligence

How to Enrich a Suspicious Domain Without Alerting the Attacker

A practical workflow for investigating an unknown domain with internal logs, RDAP, passive DNS and certificate data, then turning the results into a clear verdict.

An unknown domain in an alert raises a simple question with a messy answer: is it dangerous? This guide helps analysts enrich a domain in a sensible order, avoid exposing the investigation and record a verdict that others can trust.

GoalA verdict with evidence and a stated confidence
Start withYour own logs, then passive sources
ATT&CKT1583.001, T1584.001, T1568
>

Scenario: A DNS rule flags WS-207 resolving m365-login-portal.example. The name looks like a Microsoft sign-in page, but it has no vendor verdicts yet. A user is waiting to hear whether their laptop is safe, and your lead wants to know whether to block the domain.

Choose how much noise to make

Not every lookup is equal. Some methods query data that already exists. Others cause a system to contact the domain, which can appear in the operator's server logs, or publish your interest to anyone watching.

Level 1

Passive lookups

Your own logs, RDAP, passive DNS, certificate logs and existing reports. Nothing touches the domain's servers.

Start here
Level 2

Third party scans

A sandbox or scanner visits the site for you. It hides your IP address, but the visit happens and results may be shared.

New urlscan.io scan
Level 3

Direct contact

Browsing or using curl from your own network. It reveals your source address and may trigger a payload.

Isolated lab only
!

Watch out: Full URLs can carry email addresses or sign-in tokens. Before you submit a URL to any shared service, remove anything that identifies the user or your organisation. Searching for a domain is much safer than uploading a full link.

Check your own logs first

Your telemetry answers the question nobody else can: has this reached us? Find out how many hosts were involved, which process made contact and when it started. This also decides how urgent the rest of your work is.

Microsoft Defender XDR or Sentinel

RemoteUrl holds the URL or fully qualified domain name of the connection. This query uses contains so that it also catches subdomains and full URLs.

Microsoft Defender XDR or SentinelKQL
let Domain = "m365-login-portal.example";
DeviceNetworkEvents
| where Timestamp > ago(30d)
| where RemoteUrl contains Domain
| summarize FirstSeen = min(Timestamp), LastSeen = max(Timestamp), Connections = count(),
    Devices = dcount(DeviceName), Processes = make_set(InitiatingProcessFileName, 20),
    RemoteIPs = make_set(RemoteIP, 20)
    by RemoteUrl
| order by FirstSeen asc

Splunk with Sysmon

Sysmon Event ID 22 records DNS queries along with the process that made them. Change the index to match your environment.

Splunk, Sysmon Event ID 22SPL
index=sysmon EventCode=22 QueryName="*m365-login-portal.example"
| stats min(_time) as first_seen max(_time) as last_seen count dc(host) as hosts
    values(Image) as processes values(QueryResults) as answers by QueryName
| convert ctime(first_seen) ctime(last_seen)
i

Note: A resolved name does not prove a connection was made, and a connection does not prove a credential was entered. Browsers can also resolve names ahead of a click. Separate these facts in your notes, then follow up with proxy, sign-in and process data.

Read the registration data with RDAP

For generic top-level domains, RDAP became the definitive source of registration data on 28 January 2025, replacing WHOIS. It returns structured JSON, which makes it easy to script. The rdap.org service redirects your query to the authoritative server.

Registration events, status and name serversBash
curl -Ls https://rdap.org/domain/m365-login-portal.example | jq '{
  name: .ldhName,
  status: .status,
  events: [.events[]? | {(.eventAction): .eventDate}],
  nameservers: [.nameservers[]?.ldhName]
}'

The .example domain is only a placeholder, so run this against the real indicator. Look at the registration date, last changed date and name servers. The registrar appears in the entities section of the full response. Personal contact details are often redacted, so do not treat that as suspicious in itself. Coverage for country code domains varies, so you may need the registry's own service.

Map the infrastructure around it

One domain rarely stands alone. Two passive sources help you see what else it is connected to.

Passive DNS

Passive DNS shows what a name resolved to over time, and what other names shared an address. You can get it from services such as VirusTotal or commercial platforms. Treat shared IP addresses with care: one address on a large hosting or CDN provider may serve thousands of unrelated sites.

A rapidly changing set of addresses can point to T1568 Dynamic Resolution, such as fast flux. Random looking names can suggest a domain generation algorithm, T1568.002.

Certificate Transparency

Publicly trusted TLS certificates are recorded in public logs. Searching them can reveal when a certificate was issued and which sibling hostnames were included. You query the log service, not the suspect's servers.

Certificates for a domain and its subdomainsBash
curl -s "https://crt.sh/?q=%25.m365-login-portal.example&output=json" \
  | jq -r '.[] | [.not_before, .issuer_name, .name_value] | @tsv' | sort -u

This community service can be slow or time out at busy periods, so try again later or use the web page if needed. Free certificates are normal and say nothing about intent. The useful detail is timing and naming: a certificate issued just before the first sighting, or sibling names that imitate other brands, adds weight to your assessment.

Check reputation sources carefully

Reputation data helps, but a clean result is weak evidence, particularly for a new domain that no vendor has seen yet.

VirusTotalVendor verdicts, DNS records, categories, plus relationships such as resolutions and communicating files.
urlscan.ioSearch existing scans first with page.domain: to see screenshots and page behaviour from earlier visits.
abuse.chURLhaus and ThreatFox track malware URLs and indicators. Their APIs require a free Auth-Key.
VirusTotal API v3 domain reportBash
curl -s -H "x-apikey: $VT_API_KEY" \
  https://www.virustotal.com/api/v3/domains/m365-login-portal.example \
  | jq '.data.attributes | {creation_date, registrar, reputation, last_analysis_stats, categories}'

The creation_date value is a Unix timestamp. Other useful attributes include last_dns_records and last_https_certificate.

!

Watch out: VirusTotal's public API has tight request limits and its terms bar use in commercial products or services, so check what your organisation is licensed for. On urlscan.io, scans have public, unlisted and private visibility. Read what each one exposes and follow your team's policy before you submit anything.

Weigh the signals properly

No single signal settles the question. Each one can mislead you, so use this table to avoid overconfident conclusions.

SignalSupportsLimitation
Recently registeredPurpose built infrastructureNew businesses and campaigns register domains too
Name imitates a brandPhishing, as described in T1583.001Could be a partner or reseller, so verify it
Long registration historyAn established ownerAttackers can repurpose expired domains that keep their old reputation
Odd subdomain on a known parentDomain shadowing or hijacking, as in T1584.001May just be an unusual internal naming choice
Clean vendor verdictsNothing known so farNew or targeted domains often have no detections
Shared IP with known bad sitesPossible common operatorWeak on shared hosting and CDNs
+

Tip: Domains are cheap to replace, so a blocklist entry may not last. Record the more durable patterns as well, such as name server choices, registrar, certificate naming habits and the lure's theme. These help you find the next domain.

Record a verdict people can act on

Finish with a decision, an explicit confidence level and the evidence behind it.

  1. L0
    BenignThe owner is verified, and the domain matches expected business activity. Close and note how you confirmed it.
    Close
  2. L1
    UnknownThere is little evidence either way and no harmful activity. Watch for new connections and review it later.
    Monitor
  3. L2
    SuspiciousSeveral independent signals agree, such as a brand lookalike that is newly registered. Block it and check who connected.
    Block
  4. L3
    Confirmed maliciousYou have seen credential capture, payload delivery or command and control traffic. Start your incident process.
    Escalate

A short, consistent note makes handover easier:

Ticket note templateText
Indicator:   m365-login-portal[.]example
Verdict:     Suspicious, medium confidence
Internal:    1 host (WS-207), 3 connections, msedge.exe, first seen 2026-11-06 09:41 UTC
Registered:  [date from RDAP], [registrar]
Evidence:    Brand lookalike, recent certificate, no vendor detections yet
Gaps:        Credential entry not yet confirmed, sign-in logs under review
Action:      Blocked at proxy and DNS, user contacted, review in 24 hours
Sharing:     TLP:AMBER

If you share the indicator outside the team, label it using TLP 2.0. For example, TLP:AMBER limits it to a need to know basis within the recipient's organisation and its clients, and TLP:AMBER+STRICT restricts it to the organisation only. Defang indicators in notes and messages to prevent accidental clicks.

Key takeaways

  1. Start with your own logs, because they show whether the domain actually reached your environment.
  2. Stay passive for as long as you can, and remove user data before you submit anything to a shared service.
  3. Use RDAP for registration details, and passive DNS and certificate logs to map related infrastructure.
  4. Treat a clean reputation or an old registration date as weak evidence, not as clearance.
  5. Finish with a verdict, a confidence level, your evidence and the gaps that remain.

Try this workflow on a domain from a recently closed ticket and time how long it takes. Once the order feels natural, turn your lookups into a saved script or a playbook so that everyone on shift enriches domains in the same way.