SOC Analysts & Incident Responders
Triage alerts, trace IPs to networks, investigate hostnames, pivot through DNS, and run a full IOC investigation in one query.
SOC Analysts & Incident Responders Documentation
You've received an alert and need to triage fast. These recipes take you from a raw indicator to a full infrastructure picture without leaving your terminal.
Quick Triage
Trace an IP to Its Network Owner
Your SIEM flagged an outbound connection to an unfamiliar IP. Before escalating, you need to know who owns it and what network it belongs to.
-- Full BGP chain: IP -> announced prefix -> ASN -> network name
MATCH (ip:IPV4 {name: "104.16.132.229"})
-[:ANNOUNCED_BY]->(ap:ANNOUNCED_PREFIX)
-[:ROUTES]->(a:ASN)
-[:HAS_NAME]->(n:ASN_NAME)
RETURN ip.name AS ip, ap.name AS prefix, a.name AS asn, n.name AS network
Sample output:
[{"ip": "104.16.132.229", "prefix": "104.16.128.0/20", "asn": "AS13335", "network": "CLOUDFLARENET - Cloudflare, Inc."}]
Tip:
ANNOUNCED_BYresolves BGP routing data at query time, so you always get current routing information. For IPs where BGP data is unavailable,BELONGS_TOgives the registered allocation block instead.
Check If an IP Is Threat-Listed
You have a suspicious IP and need to know whether any threat intelligence feeds track it.
-- Check which threat feeds list this IP
MATCH (ip:IPV4 {name: "185.220.101.1"})-[:LISTED_IN]->(f:FEED_SOURCE)
RETURN ip.name, f.name
Sample output:
[
{"ip.name": "185.220.101.1", "f.name": "Dan Tor Exit"},
{"ip.name": "185.220.101.1", "f.name": "FireHOL Level 2"},
{"ip.name": "185.220.101.1", "f.name": "IPsum"},
{"ip.name": "185.220.101.1", "f.name": "Tor Exit Nodes"},
{"ip.name": "185.220.101.1", "f.name": "Spamhaus DROP"},
{"ip.name": "185.220.101.1", "f.name": "FireHOL Anonymous"}
]
Tip: The graph indexes 40 threat feeds. If the result is empty, the IP is not currently listed — but also run
CALL explain()(see below) for a composite score that accounts for network-level reputation.
Get a Full Threat Assessment
You want a scored, human-readable verdict on an IP, domain, ASN, or CIDR block.
-- Composite threat score and explanation
CALL explain("185.220.101.1")
Sample output:
[{
"indicator": "185.220.101.1",
"type": "ip",
"found": true,
"score": 21.55,
"level": "INFO",
"explanation": "185.220.101.1 is listed in 6 threat feed(s). Score 21.6 (Informational - minimal risk).",
"factors": [
"Listed in 6 source(s) with combined weight 8.20",
"Base score: 8.20 × log₂(6 + 1) = 23.19",
"Recency boost: ×1.2 (last seen just now)"
]
}]
Tip:
CALL explain()works on IPs, domains, ASNs (AS13335), and CIDR ranges (185.220.101.0/24). For network-level assessments, pass the CIDR — it scores the block's listed-IP density.
Deep Dive Investigation
Reverse DNS: What Domains Point Here?
You have an IP from an alert and want to know what else is hosted there.
-- All domains currently resolving to this IP
MATCH (ip:IPV4 {name: "104.16.132.229"})<-[:RESOLVES_TO]-(h:HOSTNAME)
RETURN h.name LIMIT 20
Sample output:
[
{"h.name": "menuchin.app"},
{"h.name": "www.menuchin.app"},
{"h.name": "qapy.com.ar"},
{"h.name": "c-cloudflare-com.4i.am"}
]
Tip: Shared hosting is normal for CDN IPs — a single Cloudflare IP can host thousands of domains. If co-hosted count (see next recipe) is over a few hundred, the IP is likely shared infrastructure rather than a dedicated host.
Count Co-Hosted Domains
Before pivoting on all domains sharing an IP, check how many there are.
-- How many domains share this IP?
MATCH (ip:IPV4 {name: "104.16.132.229"})<-[:RESOLVES_TO]-(h:HOSTNAME)
RETURN count(h) AS cohosted
Sample output:
[{"cohosted": 1491}]
Tip: A count over 500 usually means shared CDN infrastructure. A count under 20 is more interesting for attribution — those domains are likely managed by the same operator.
Look Up GeoIP Location
You need to know the physical location of an IP for a geo-restriction check or incident report.
-- GeoIP city and country for an IP
MATCH (ip:IPV4 {name: "109.111.100.154"})
-[:LOCATED_IN]->(city:CITY)
-[:HAS_COUNTRY]->(co:COUNTRY)
RETURN DISTINCT ip.name, city.name AS city, co.name AS country
Sample output:
[{"ip.name": "109.111.100.154", "city": "Andorra la Vella, AD", "country": "AD"}]
Tip: Well-known anycast IPs (Google, Cloudflare DNS resolvers) may not return city-level GeoIP data because they're served from many locations simultaneously. For those, use the BGP routing chain:
IP -[:ANNOUNCED_BY]-> AP -[:HAS_COUNTRY]-> COUNTRYto get the network's registered country.
IP Geolocation via BGP Country
When GeoIP data is unavailable, get the country from the network's routing allocation.
-- Country via BGP prefix allocation
MATCH (ip:IPV4 {name: "8.8.8.8"})
-[:ANNOUNCED_BY]->(ap:ANNOUNCED_PREFIX)
-[:HAS_COUNTRY]->(co:COUNTRY)
RETURN ip.name, ap.name AS prefix, co.name AS country
Sample output:
[{"ip.name": "8.8.8.8", "prefix": "8.8.8.0/24", "country": "US"}]
Tip: This approach works even when
LOCATED_INreturns nothing. The country reflects where the announcing network is registered, not the physical server location.
Quick WHOIS Check
You need registration details for a suspicious domain — registrar, contact emails, and phone numbers.
-- WHOIS registration profile for a domain
MATCH (h:HOSTNAME {name: "cloudflare.com"})
OPTIONAL MATCH (h)-[:HAS_REGISTRAR]->(r:REGISTRAR)
OPTIONAL MATCH (h)-[:HAS_EMAIL]->(e:EMAIL)
OPTIONAL MATCH (h)-[:HAS_PHONE]->(p:PHONE)
RETURN h.name,
collect(DISTINCT r.name) AS registrars,
collect(DISTINCT e.name) AS emails,
collect(DISTINCT p.name) AS phones
Sample output:
[{
"h.name": "cloudflare.com",
"registrars": ["iana:1910"],
"emails": ["domains@cloudflare.com", "noreply@data-protected.net"],
"phones": ["+10000000000", "+16503198930"]
}]
Tip: Use
OPTIONAL MATCHfor WHOIS fields — not every domain has every field populated. A plainMATCHwould return no results for partially-registered domains.
Who Controls DNS?
Find the authoritative nameservers for a domain.
-- Authoritative nameservers for a domain
MATCH (ns:HOSTNAME)-[:NAMESERVER_FOR]->(h:HOSTNAME {name: "google.com"})
RETURN ns.name LIMIT 10
Sample output:
[
{"ns.name": "ns1.google.com"},
{"ns.name": "ns2.google.com"},
{"ns.name": "ns3.google.com"},
{"ns.name": "ns4.google.com"}
]
Tip: The nameserver that controls DNS for a domain often tells you who's managing the infrastructure. Suspicious domains using free DNS providers or bulletproof hosting nameservers are worth flagging.
Evidence Collection
Full Infrastructure Trace
You need to document the complete path from domain to network owner for an incident report.
-- Full 5-hop chain: domain -> IP -> BGP prefix -> ASN -> network name
MATCH (h:HOSTNAME {name: "cloudflare.com"})
-[:RESOLVES_TO]->(ip:IPV4)
-[:ANNOUNCED_BY]->(ap:ANNOUNCED_PREFIX)
-[:ROUTES]->(a:ASN)
-[:HAS_NAME]->(n:ASN_NAME)
RETURN h.name AS host, ip.name AS ip, ap.name AS prefix,
a.name AS asn, n.name AS network
LIMIT 10
Sample output:
[
{"host": "cloudflare.com", "ip": "104.16.132.229", "prefix": "104.16.128.0/20", "asn": "AS13335", "network": "CLOUDFLARENET - Cloudflare, Inc."},
{"host": "cloudflare.com", "ip": "104.16.133.229", "prefix": "104.16.128.0/20", "asn": "AS13335", "network": "CLOUDFLARENET - Cloudflare, Inc."}
]
Tip: When writing up an incident, include all rows — a domain may resolve to IPs on different ASNs, which can indicate load balancing, multi-CDN setups, or in rarer cases, BGP hijack artifacts.
Batch IOC Enrichment
You have a list of IPs from an alert and want to enrich them all in a single query.
-- Enrich multiple IPs in one request
UNWIND ["185.220.101.1", "104.16.132.229", "8.8.8.8"] AS ip_addr
MATCH (ip:IPV4 {name: ip_addr})
-[:ANNOUNCED_BY]->(ap:ANNOUNCED_PREFIX)
-[:ROUTES]->(a:ASN)
RETURN ip_addr, ap.name AS prefix, a.name AS asn
Sample output:
[
{"ip_addr": "185.220.101.1", "prefix": "185.220.101.0/24", "asn": "AS60729"},
{"ip_addr": "104.16.132.229", "prefix": "104.16.128.0/20", "asn": "AS13335"},
{"ip_addr": "8.8.8.8", "prefix": "8.8.8.0/24", "asn": "AS15169"}
]
Tip:
UNWINDprocesses each value as a separate row, so you can pass up to hundreds of indicators in one query. For scored threat assessments, runCALL explain("indicator")separately per IP — inline procedure chaining is not currently supported.
Splunk equivalents
If you're enriching events inline rather than running ad-hoc Cypher, see the same workflows in SPL: Splunk Use Cases for Infrastructure Intel. For whisperlookup and whisperquery see Search Commands.