Skip to content

实现原理:CT 日志与子域枚举

对应代码:pkg/ctlog.go + pkg/ctenumerate.go · 入口 CTSearch / CTSearchByFingerprint / CTEnumerateSubdomains

证书透明度(Certificate Transparency)日志记录了几乎所有公开 CA 签发的证书。cert-skills 用它做历史检索与子域发现。本页讲数据源、解析与归类的细节。

数据源:crt.sh

cert-skills 的 CT 能力全部走 crt.sh(Sectigo 运营的 CT 搜索服务):

函数URL 模板
CTSearch(domain)https://crt.sh/?q=%25.<domain>&output=json
CTSearchByFingerprint(fp)https://crt.sh/?q=<fingerprint>&output=json
  • %25.%. 的 URL 编码——crt.sh 后缀通配语法,搜该域名下所有子域证书
  • User-Agent:cert-skills/1.0 (certificate security toolkit)
  • HTTP client Timeout:30 秒
  • crtshBaseURL 变量可被测试覆写指向本地 stub

crtshEntry 结构体(8 字段)

go
type crtshEntry struct {
    IssuerCAID        int    `json:"issuer_ca_id"`
    IssuerName        string `json:"issuer_name"`
    CommonName        string `json:"common_name"`
    NameValue         string `json:"name_value"`   // 所有 SAN,换行分隔
    SerialNumber      string `json:"serial_number"`
    NotBefore         string `json:"not_before"`
    NotAfter          string `json:"not_after"`
    FingerprintSHA256 string `json:"sha256"`
}

NameValue 一条记录可能含多个域名(\n 分隔),必须拆开。

解析与去重

CTSearchByFingerprint 不去重

CTSearchByFingerprint 不做去重(L222-239 直接全收)——同一张证书在多个 CT 日志里都有副本,返回条目数会大于 1。需要去重请按 cert_sha256 自行聚合。

子域枚举

CTEnumerateSubdomains(ctenumerate.go L28)在 CTSearch 基础上做归类:

3 种时间格式

NotAfter 逐个尝试(第一个成功即 break):

格式Go layout示例
ISO-like 无时区2006-01-02T15:04:052025-12-31T23:59:59
空格分隔2006-01-02 15:04:052025-12-31 23:59:59
仅日期2006-01-022025-12-31

解析后与 time.Now() 比较:BeforeExpiredCerts++,否则 ActiveCerts++

extractCTOrganization(非正则)

纯字符串分割,非正则。找不到返回 ""

按 issuer 聚合

cleanIssuerName(L154-165):按 , split,TrimSpace 每段,去空,重新用 ", " join。

输出结构

go
type CTEnumerationResult struct {
    TotalCerts        int
    UniqueSubdomains  []string
    WildcardDomains   []string
    SubdomainCount    int
    ByIssuer          map[string][]string
    ByCA              map[string]int
    ActiveCerts       int
    ExpiredCerts      int
    Organizations     []string
}

CTSearchResult{Certificates []CTCert, TotalCount int, Error string}

三种 CT 用法

场景命令用途
资产发现search-ct某域名下所有签发记录
侦察枚举ct-enumerate子域清单 + CA 归类 + 活跃/过期
精确溯源search-ct-fingerprint一张证何时签发、出现在哪些日志

取证场景的串联

CT 日志是公开审计的——攻击者复用一张证到多个钓鱼/C2 域名,CT 会留下全部记录。详见 证书事件应急取证工作流

错误路径

局限

  • 依赖 crt.sh 可用性:crt.sh 偶有不可用或限流,cert-skills 没有备用 CT API(Google/Cloudflare 的 ct-log API 未接入)
  • 仅公开 CA 签发:私有 CA / 内网证书不在 CT 日志里
  • 有签发延迟:证签发后到入 CT 日志有数小时延迟

下一步