Penetration Testers & Red Teams
External recon: subdomain discovery, infrastructure enumeration, exposed services, and lateral pivots through shared hosting.
Penetration Testers & Red Teams Documentation
You're conducting passive reconnaissance on a target. All data here comes from public DNS, BGP, and WHOIS records — no active probing.
Quick Triage
Subdomain Enumeration
Find all indexed subdomains for a target domain.
-- All indexed subdomains of a target
MATCH (h:HOSTNAME) WHERE h.name ENDS WITH ".github.com"
RETURN h.name LIMIT 30
Sample output:
[
{"h.name": "0.github.com"},
{"h.name": "api.github.com"},
{"h.name": "gist.github.com"},
{"h.name": "education.github.com"}
]
Tip: The
ENDS WITH ".target.com"pattern (note the leading dot) returns only subdomains, not the domain itself or domains that merely contain the string. For broad coverage, also run aCHILD_OFquery (see below) which uses the domain hierarchy index.
Count Subdomains Before Enumerating
Before pulling a full subdomain list, check how many exist.
-- How many subdomains are indexed for this target?
MATCH (sub:HOSTNAME)-[:CHILD_OF]->(h:HOSTNAME {name: "github.com"})
RETURN count(sub) AS subdomain_count
Sample output:
[{"subdomain_count": 36131}]
Tip: If subdomain count is in the tens of thousands, the domain is likely a major CDN or hosting provider. Focus on specific interesting prefixes using
STARTS WITHrather than pulling the full list.
Prefix-Based Discovery
Find hosts matching a naming pattern across all domains.
-- All indexed hosts starting with a specific prefix
MATCH (h:HOSTNAME) WHERE h.name STARTS WITH "vpn."
RETURN h.name LIMIT 15
Sample output:
[
{"h.name": "vpn.0--0--0.com"},
{"h.name": "vpn.0--0.uk"},
{"h.name": "vpn.acme-corp.example"}
]
Tip: Combine with domain filtering:
WHERE h.name STARTS WITH "vpn." AND h.name ENDS WITH ".example.com"to target a specific organization's VPN hosts.
Deep Dive Investigation
DNS Hierarchy Walk
Follow the domain tree to understand the full scope of a target's namespace.
-- Full ancestor chain: subdomain -> parent -> TLD
MATCH (h:HOSTNAME {name: "mail.google.com"})-[:CHILD_OF*1..3]->(parent)
RETURN h.name, parent.name LIMIT 10
Sample output:
[
{"h.name": "mail.google.com", "parent.name": "google.com"},
{"h.name": "mail.google.com", "parent.name": "com"}
]
Tip: Use variable-length
[:CHILD_OF*1..3]to walk the hierarchy.*1..3covers up to three levels — enough for most real domain structures.
IP Range Discovery
Collect all IP addresses a target domain resolves to, across all its subdomains.
-- All IPs for all direct children of a target domain
MATCH (sub:HOSTNAME)-[:CHILD_OF]->(h:HOSTNAME {name: "github.com"})
WITH sub LIMIT 5000
MATCH (sub)-[:RESOLVES_TO]->(ip:IPV4)
RETURN DISTINCT ip.name LIMIT 30
Tip: This gives you the IP footprint for a target's first-level subdomains. The
LIMIT 5000on subdomains keeps the query fast while covering enough of the namespace — subdomains are iterated in index order, and many early entries may lack DNS records. Increase the subdomain limit if results are sparse.
Mail Server Discovery
Find the mail servers that handle email for a target domain.
-- MX records: mail servers for a target domain
MATCH (mx:HOSTNAME)-[:MAIL_FOR]->(h:HOSTNAME {name: "cloudflare.com"})
RETURN mx.name
Sample output:
[
{"mx.name": "mxa.global.inbound.cf-emailsecurity.net"},
{"mx.name": "mxa-canary.global.inbound.cf-emailsecurity.net"},
{"mx.name": "mxb.global.inbound.cf-emailsecurity.net"},
{"mx.name": "mxb-canary.global.inbound.cf-emailsecurity.net"}
]
Tip: Mail servers often run on different infrastructure than web servers. This gives you additional IP ranges to scope for the target's attack surface.
CNAME Chain Following
Follow canonical name redirects to find where a subdomain ultimately resolves.
-- Follow CNAME chain to canonical target
MATCH (h:HOSTNAME {name: "www.github.com"})-[:ALIAS_OF*1..5]->(target:HOSTNAME)
RETURN h.name, target.name
Sample output:
[{"h.name": "www.github.com", "target.name": "github.com"}]
Tip: Deep CNAME chains (3+ hops) sometimes reveal cloud provider or CDN vendor relationships that aren't obvious from the surface domain.
SPF Record Mapping
Understand which IP ranges and services are authorized to send email on behalf of a target domain.
-- Full SPF authorization chain for a target domain
MATCH (h:HOSTNAME {name: "google.com"})-[:SPF_INCLUDE]->(spf:HOSTNAME)
OPTIONAL MATCH (spf)-[:SPF_IP]->(range)
RETURN spf.name, collect(range.name) AS authorized_ranges LIMIT 10
Sample output:
[{
"spf.name": "_spf.google.com",
"authorized_ranges": ["74.125.0.0/16", "209.85.128.0/17", "2001:4860:4000::/36", "2404:6800:4000::/36", "2607:f8b0:4000::/36", "2800:3f0:4000::/36", "2a00:1450:4000::/36", "2c0f:fb50:4000::/36"]
}]
Tip: The authorized IP ranges from SPF tell you which cloud providers the target trusts to send email. This is useful for understanding their email vendor relationships.
ASN Prefix Mapping
Enumerate all BGP prefixes announced by a target's ASN.
-- All IP prefixes announced by an ASN
MATCH (a:ASN {name: "AS15169"})-[:ROUTES]->(p)
RETURN a.name, p.name LIMIT 20
Sample output:
[
{"a.name": "AS15169", "p.name": "8.14.69.0/24"},
{"a.name": "AS15169", "p.name": "8.14.84.0/22"},
{"a.name": "AS15169", "p.name": "34.64.68.0/22"}
]
Tip: Count prefixes first with
count(p)before pulling the full list — large ASNs announce thousands of prefixes.
Splunk equivalents
For attack-surface monitoring inside Splunk, see Splunk Use Cases and the owned-domain modular input documented in Modular Inputs.