find-hidden-subdomains

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Find hidden subdomains

寻找隐藏子域名

The hosts an organization forgot about are the ones worth finding, and most of them announced themselves the moment someone requested a TLS certificate. Certificate Transparency turns that into a searchable, permanent, historical index — free and completely passive. The beginner's mistake is treating a CT hit as a live host: most of what you pull back does not resolve, and that is information too, not noise.
企业遗忘的主机往往是值得挖掘的目标,而其中大多数在申请TLS证书时就已经“暴露”了自己。Certificate Transparency将这些信息转化为可搜索、永久且历史可追溯的索引——完全免费且无需主动交互。初学者常犯的错误是认为CT日志中的记录都是活跃主机:实际上返回的大部分记录无法解析,这同样是有价值的信息,而非干扰项。

Which source first

优先选择的数据源

You holdStart withWhy
An apex domaincrt.sh wildcard queryBroadest free coverage, includes long-dead names
A domain behind a wildcard certPassive DNS, then archivesCT will only show you
*.example.com
A guess at a naming conventionCT to learn the convention, then a wordlistLearn the pattern before brute-forcing anything
An org name, not a domainCertificate search by subject organizationFinds domains you did not know they owned
A cert you already haveIts SANs, then its serial and issuerSANs give siblings; serial finds the exact cert elsewhere
A need for current hosts onlyResolve the candidate listCT is historical by nature; DNS is the liveness oracle
你拥有的信息优先使用的方式原因
顶级域名crt.sh通配符查询免费覆盖范围最广,包含已失效很久的域名
通配符证书下的域名被动DNS,再查归档CT日志只会显示
*.example.com
这类通配符记录
猜测的命名规则先通过CT日志学习规则,再使用字典表在暴力破解前先掌握命名模式
企业名称而非域名按主体组织名称搜索证书发现你不知道的该企业所属域名
已有的证书先看其SAN字段,再查序列号和颁发者SAN字段可找到兄弟域名;序列号能定位该证书在其他地方的记录
仅需要当前活跃主机解析候选域名列表CT日志本质是历史记录;DNS才是判断主机是否活跃的依据

How CT actually works

CT日志的实际工作原理

CAs submit every certificate they issue to append-only, cryptographically verifiable public logs. The log returns a Signed Certificate Timestamp, and mainstream browsers refuse to trust a publicly-trusted certificate that does not carry SCTs from qualified logs. So participation is not voluntary: if the certificate works in a browser, it is in the logs.
Three consequences that matter to you:
  • Nothing is removed. Logs are append-only. A hostname that appeared in a cert five years ago is still there after the host is gone.
  • You see precertificates and certificates. CAs log a precertificate first, then the final cert, so most names appear at least twice. Deduplicate.
  • Only publicly-trusted certs are covered. A private/internal CA, a self-signed cert, or a Cloudflare origin certificate never reaches a log. CT is blind to those hosts entirely.
证书颁发机构(CA)会将其签发的每一张证书提交至仅追加、可加密验证的公共日志。日志会返回一个签名证书时间戳(Signed Certificate Timestamp),主流浏览器会拒绝信任未携带合格日志SCT的公开可信证书。因此参与CT日志并非自愿:若证书能在浏览器中正常使用,它就一定存在于日志中。
对你而言有三个重要结论:
  • 记录永不删除:日志是仅追加模式。五年前出现在证书中的主机名,即使主机已下线,仍会保留在日志中。
  • 会看到预证书和正式证书:CA会先记录预证书,再记录最终证书,因此大多数域名至少会出现两次。需要进行去重处理。
  • 仅覆盖公开可信证书:私有/内部CA签发的证书、自签名证书或Cloudflare源证书永远不会进入CT日志。CT日志完全无法发现这类主机。

crt.sh

crt.sh工具

The web UI takes
?q=
, where
%
is a wildcard, and
output=json
gives you machine-readable results.
bash
undefined
其Web界面使用
?q=
参数进行查询,
%
作为通配符,
output=json
可返回机器可读的结果。
bash
undefined

every name ever seen in a cert covering example.com or a subdomain

获取所有曾出现在覆盖example.com或其子域名的证书中的域名

curl -s 'https://crt.sh/?q=%25.example.com&output=json'
| jq -r '.[].name_value' | sed 's/^*.//' | sort -u
curl -s 'https://crt.sh/?q=%25.example.com&output=json'
| jq -r '.[].name_value' | sed 's/^*.//' | sort -u

skip expired certs when you want a bias toward current infrastructure

当你更关注当前基础设施时,跳过已过期的证书

an identity search on an organization string, which finds unknown domains

通过组织名称进行身份搜索,发现未知域名

curl -s 'https://crt.sh/?q=Example+Corporation&output=json' | jq -r '.[].name_value'

The `q` parameter is an identity search: it matches domain names, and it also
matches subject fields such as the organization name, which is how you find
domains the brief never mentioned.

Useful JSON fields: `name_value` (all names on the cert, newline-separated),
`common_name`, `issuer_name`, `not_before` / `not_after`, `serial_number`,
`entry_timestamp`, and `id` (open `https://crt.sh/?id=<id>` to read the cert).

crt.sh also exposes its database read-only over Postgres — host `crt.sh`, port
5432, user `guest`, database `certwatch`. That lets you write real SQL against
the certificate index instead of paginating JSON. It is a shared free service:
keep queries bounded and expect to be cut off if you hammer it.

Alternatives and other CT front-ends, with their coverage and access models, are
in [reference/subdomain-sources.md](reference/subdomain-sources.md).
curl -s 'https://crt.sh/?q=Example+Corporation&output=json' | jq -r '.[].name_value'

`q`参数是身份搜索:它既匹配域名,也匹配主体字段(如组织名称),这也是你能找到任务简报中未提及的域名的方式。

实用的JSON字段包括:`name_value`(证书上的所有域名,以换行分隔)、`common_name`、`issuer_name`、`not_before`/`not_after`、`serial_number`、`entry_timestamp`和`id`(访问`https://crt.sh/?id=<id>`可查看证书详情)。

crt.sh还通过Postgres提供只读数据库访问——主机`crt.sh`,端口5432,用户`guest`,数据库`certwatch`。这让你可以直接对证书索引编写SQL查询,而无需分页处理JSON。这是一个共享免费服务:请控制查询范围,若频繁请求可能会被限制访问。

其他CT前端工具及其覆盖范围和访问模式可参考[reference/subdomain-sources.md](reference/subdomain-sources.md)。

The SAN field is the prize

SAN字段是核心

Browsers ignore the Common Name; the
subjectAltName
extension holds the real list of covered hostnames. Read it as a statement about what one team deployed together:
  • A cert with a handful of related names is an intentional grouping — those hosts belong to the same service and probably the same admin.
  • A cert with dozens of unrelated names is a hosting provider's or CDN's bundled certificate. Those names are other customers, not your target's assets. This is the single biggest false-positive source in CT-based enumeration.
  • Names from different registrable domains on one cert are the good find: it means one operator manages both, which surfaces acquisitions, rebrands and undisclosed sibling brands. Verify before concluding — see the bundling trap above.
  • Internal names leak here constantly:
    jira
    ,
    owa
    ,
    vpn
    ,
    *.corp.example.com
    , hostnames with rack or datacenter codes, and product codenames that never shipped publicly.
浏览器会忽略通用名称(Common Name);
subjectAltName
(SAN)扩展才包含真实的主机名覆盖列表。可以将其视为同一团队部署的相关主机集合:
  • 包含少量相关域名的证书是有意分组的——这些主机属于同一服务,可能由同一管理员管理。
  • 包含数十个无关域名的证书是托管服务商或CDN的捆绑证书。这些域名属于其他客户,并非你的目标资产。这是基于CT枚举的最大误报来源。
  • 同一证书中包含不同可注册域名的情况是有价值的发现:这意味着同一操作者管理着两者,可揭露收购、品牌重塑和未公开的兄弟品牌。在得出结论前需验证——注意上述捆绑证书的陷阱。
  • 内部域名经常在此泄露:
    jira
    owa
    vpn
    *.corp.example.com
    、带有机柜或数据中心代码的主机名,以及从未公开推出的产品代号。

Wildcards hide, they don't reveal

通配符证书会隐藏信息,而非暴露

*.example.com
covers every subdomain and names none of them. An org that switched to a wildcard, typically alongside DNS-01 ACME automation, effectively went dark in CT from that point. When you see a wildcard:
  • Mine CT for the period before the wildcard, when per-host certs existed.
  • Move to passive DNS, which records answers rather than certificates.
  • Check archives and search indexes for hostnames (
    read-deleted-pages
    ,
    google-like-a-spy
    ).
  • Look for hosts that must still have their own cert for technical reasons: a deeper label than the wildcard covers (
    a.b.example.com
    needs its own), and anything on a different apex.
*.example.com
覆盖所有子域名但不会列出具体域名。切换到通配符证书的企业(通常配合DNS-01 ACME自动化)从那时起在CT日志中就相当于“隐身”了。当你看到通配符证书时:
  • 挖掘通配符证书出现之前的CT日志记录,当时存在按主机颁发的证书。
  • 转向被动DNS,它记录的是DNS查询结果而非证书信息。
  • 检查归档和搜索引擎索引中的主机名(参考
    read-deleted-pages
    google-like-a-spy
    )。
  • 寻找因技术原因仍需单独证书的主机:通配符覆盖范围之外的更深层级域名(如
    a.b.example.com
    需要单独证书),以及不同顶级域名下的主机。

Combining sources, then resolving

整合数据源,然后解析

CT gives you history. Passive DNS gives you observed reality. Wordlists give you names nobody published. Use all three, and keep them labelled by origin, because the confidence you can assign depends on where a name came from.
bash
subfinder -d example.com -all -silent -o passive.txt   # aggregates many passive sources
amass enum -passive -d example.com                     # different source mix, slower
dnsx -l passive.txt -a -resp -silent                   # resolve candidates to A records
Resolution turns candidates into three buckets: resolves to an address, resolves to a CNAME (read the target — it names the vendor, and a dangling one is a takeover candidate to report), or does not resolve at all. Dead names are still findings: they date the infrastructure, expose naming conventions, and sometimes resolve again later.
Detect wildcard DNS before you trust any brute-force result. Resolve a random name that cannot exist, such as
zzq7x-nonexistent.example.com
. If it answers, the zone resolves everything and your entire brute-force list is false positives.
Draw the line clearly: querying CT, passive DNS, search engines and archives never touches the target. Resolving candidate names through a public recursive resolver is effectively invisible but does generate lookups. Wordlist brute-forcing is high-volume DNS traffic, visible to the target's DNS provider and sometimes rate-limited or blocked. HTTP-probing the results with a tool like
httpx
is active — you are connecting to the target's servers. Flag brute-forcing and probing in your scope notes, and skip them if the engagement is passive-only.
CT日志提供历史信息,被动DNS提供已观测到的实际情况,字典表提供未公开的域名。结合使用这三者,并按来源标记,因为你对域名的信任度取决于其来源。
bash
subfinder -d example.com -all -silent -o passive.txt   # 聚合多个被动数据源
amass enum -passive -d example.com                     # 数据源组合不同,速度较慢
dnsx -l passive.txt -a -resp -silent                   # 将候选域名解析为A记录
解析会将候选域名分为三类:解析到IP地址、解析到CNAME(查看目标地址——可识别供应商,悬空的CNAME是可上报的接管候选目标)、完全无法解析。已失效的域名仍有价值:它们能推断基础设施的年代,揭露命名规则,有时后续会再次解析成功。
在信任暴力破解结果前,先检测通配符DNS。解析一个不可能存在的随机域名,如
zzq7x-nonexistent.example.com
。如果能得到响应,说明该区域会解析所有域名,你的整个暴力破解列表都是误报。
需明确区分:查询CT日志、被动DNS、搜索引擎和归档不会触及目标;通过公共递归解析器解析候选域名几乎不可见,但会产生查询请求;字典表暴力破解会产生大量DNS流量,目标的DNS服务商可观测到,有时会被限速或拦截;使用
httpx
等工具对结果进行HTTP探测属于主动操作——你正在连接目标服务器。在范围说明中标记暴力破解和探测操作,如果是仅被动的测试则跳过这些步骤。

What a name pattern implies

域名模式的含义

Do not treat all discovered hosts as equal.
dev
,
staging
,
uat
,
vpn
,
legacy
,
old
, and admin panels carry very different risk and follow-up than
www
. The triage table is in reference/name-pattern-triage.md.
不要将所有发现的主机视为同等风险。
dev
staging
uat
vpn
legacy
old
以及管理面板的风险和后续处理方式与
www
完全不同。分类参考表见reference/name-pattern-triage.md

Where this goes wrong

常见问题

  • Bundled and multi-tenant certs. Shared hosting and CDN certificates put unrelated customers on one cert. Always check whether the other names on a cert plausibly belong to your target before adopting them.
  • CT is not an asset inventory. It is a record of certificate requests. Hosts behind internal CAs, self-signed certs, origin certificates, or plain HTTP are absent. Never report a CT-derived list as complete.
  • Names outlive hosts. Most historical CT names are dead. A list of 400 subdomains, unresolved, is a list of 400 unverified claims.
  • Names outlive ownership. A cert issued for a hostname while the domain belonged to a previous owner still shows up under the current owner's query. Check
    not_before
    against the domain's registration and transfer history via
    who-owns-this-domain
    .
  • CNAME'd third parties are not the target's assets. A hostname the target owns pointing at a SaaS tenant is the target's relationship, not its infrastructure. Do not treat vendor exposure as the target's exposure.
  • Aggregators disagree, and quietly. Each tool queries a different set of sources; free tiers truncate results without telling you. Two tools returning the same 50 names may both be reading the same one source.
  • Deliberate poisoning. Nothing stops anyone from getting a certificate for a name they control on a domain that looks like the target's. Typosquats show up in CT searches looking like the target's own hosts. Check the registrable domain character by character.
  • 捆绑和多租户证书:共享托管和CDN证书会将无关客户的域名放在同一张证书中。在将证书中的其他域名纳入目标前,务必确认它们是否确实属于你的目标。
  • CT日志不是资产清单:它只是证书请求记录。内部CA签发的证书、自签名证书、源证书或纯HTTP的主机不会出现在其中。切勿将基于CT生成的列表报告为完整资产清单。
  • 域名比主机存活时间长:大多数历史CT域名已失效。一个包含400个无法解析的子域名的列表,只是400个未验证的记录。
  • 域名所有权变更后记录仍存在:域名属于前所有者时签发的证书,在当前所有者的查询中仍会显示。通过
    who-owns-this-domain
    工具,将
    not_before
    日期与域名的注册和转移历史进行核对。
  • 指向第三方的CNAME不是目标资产:目标拥有的指向SaaS租户的主机名是目标的合作关系,而非其基础设施。不要将供应商的风险视为目标的风险。
  • 聚合工具结果存在差异:每个工具查询的数据源不同;免费版会在不告知的情况下截断结果。两个工具返回相同的50个域名,可能只是读取了同一个数据源。
  • 故意污染:任何人都可以为自己控制的、类似目标域名的主机名申请证书。仿冒域名会出现在CT搜索结果中,看起来像目标自己的主机。需逐字符检查可注册域名。

Confidence grading

可信度分级

  • Confirmed asset — the name resolves, and it is under a domain whose registration you have verified, on infrastructure consistent with the target's other hosts (same ASN, same cert issuer, same naming convention).
  • Probable asset — a CT name under a verified target domain that no longer resolves, or a name that resolves into a vendor's shared platform. Real name, unproven current state.
  • Unconfirmed — a name from a cert bundled with unrelated customers, a brute-force hit in a wildcard-DNS zone, a name on a different registrable domain with no corroborating link, or an aggregator result you have not seen the underlying cert or DNS answer for.
Record for every host: where the name came from, the cert
id
or passive-DNS source, the
not_before
date, and the resolution result with a timestamp.
  • 已确认资产:域名可解析,且位于你已验证注册信息的域名下,基础设施与目标其他主机一致(相同ASN、相同证书颁发者、相同命名规则)。
  • 疑似资产:已验证目标域名下的CT记录,但域名已无法解析;或解析到供应商的共享平台。域名真实存在,但当前状态未证实。
  • 未确认:来自捆绑了无关客户的证书的域名、通配符DNS区域中的暴力破解结果、无佐证链接的不同可注册域名下的域名,或未查看底层证书或DNS响应的聚合工具结果。
为每个主机记录:域名来源、证书
id
或被动DNS源、
not_before
日期、解析结果及时间戳。

Worked example

实战示例

Target:
example-health.test
, scope is passive-only.
crt.sh with
%25.example-health.test
returns 61 unique names. Deduplicating precert/cert pairs cuts it to 38. Three are interesting immediately:
vpn-uat.example-health.test
,
jira.internal.example-health.test
, and
billing-legacy.example-health.test
.
One cert carries 44 names across nine unrelated companies — a managed hosting provider's bundle. Discard the 43 that are not the target's. That is the dead end, and it would have inflated the report by more than the real findings.
Resolving the 38: 12 answer.
jira.internal
does not resolve publicly, but its existence in a cert confirms an internal naming convention and a Jira instance — worth noting even though there is no host to look at.
vpn-uat
resolves to an appliance vendor's netblock, which goes to
find-exposed-servers
.
An identity search on the organization name from one of the certs returns two certs for
examplehealth-group.test
, a domain nobody mentioned in the brief. WHOIS via
who-owns-this-domain
shows the same registrant organization. That is the pivot that expanded the engagement.
Grade: 12 resolving hosts confirmed,
jira.internal
probable (real name, not publicly reachable), the sibling domain probable pending a corporate filing.
目标:
example-health.test
,测试范围为仅被动操作。
使用
%25.example-health.test
查询crt.sh返回61个唯一域名。对预证书/正式证书对去重后减少到38个。其中三个立即值得关注:
vpn-uat.example-health.test
jira.internal.example-health.test
billing-legacy.example-health.test
某张证书包含来自9家无关公司的44个域名——这是托管服务商的捆绑证书。丢弃其中43个非目标域名。这是无效信息,若纳入报告会远超真实发现数量。
解析38个域名:12个可响应。
jira.internal
无法公开解析,但它出现在证书中证实了内部命名规则和Jira实例的存在——即使没有可访问的主机,也值得记录。
vpn-uat
解析到某设备供应商的网段,需进一步参考
find-exposed-servers
通过其中一张证书的主体组织名称进行身份搜索,返回两张
examplehealth-group.test
的证书,该域名未在任务简报中提及。通过
who-owns-this-domain
工具查询WHOIS信息,显示其注册组织与目标相同。这一发现扩展了测试范围。
分级:12个可解析主机为已确认资产,
jira.internal
疑似资产(域名真实存在,但无法公开访问),兄弟域名为疑似资产(需等待企业备案确认)。

Pivots

后续操作方向

New selectorGoes to
Live hostnames and their IPs
find-exposed-servers
Sibling and acquired domains
who-owns-this-domain
,
who-really-owns-it
Organization name from a cert subject
x-ray-a-company
Dead hostnames with historical content
read-deleted-pages
Dev/staging hostnames, repo-looking names
secrets-in-git-history
Indexed files on newly found hosts
google-like-a-spy
A large host/domain/IP set to structure
graph-the-network
新筛选条件对应操作
活跃主机名及其IP
find-exposed-servers
兄弟域名和收购域名
who-owns-this-domain
,
who-really-owns-it
证书主体中的组织名称
x-ray-a-company
带有历史内容的已失效主机名
read-deleted-pages
开发/预发布主机名、类似仓库的域名
secrets-in-git-history
新发现主机上的已索引文件
google-like-a-spy
需要整理的大量主机/域名/IP集合
graph-the-network

Legal and ToS notes

法律与服务条款说明

Reading CT logs and passive DNS is publishing-by-design: the data exists to be read. Two limits are real. First, free services like crt.sh are shared infrastructure — heavy automated querying gets you blocked and is discourteous; use bounded queries and cache results. Second, DNS brute-forcing and HTTP probing send traffic to the target and, depending on volume and jurisdiction, can be argued as unauthorized activity; keep them inside written scope per ../../ETHICS.md. Discovering a dangling CNAME or an exposed staging host obliges you to report it, not to test it.
读取CT日志和被动DNS是设计允许的公开行为:这些数据就是用于公开读取的。有两个实际限制:首先,crt.sh等免费服务是共享基础设施——大量自动化查询会导致你被封禁,且影响其他用户使用;请使用范围有限的查询并缓存结果。其次,DNS暴力破解和HTTP探测会向目标发送流量,根据流量规模和司法管辖范围,可能会被认定为未经授权的活动;请严格遵循../../ETHICS.md中的书面测试范围进行操作。发现悬空CNAME或暴露的预发布主机时,你有义务上报,而非进行测试。